mirror of
https://github.com/Awuqing/BackupX.git
synced 2026-08-28 19:47:27 +08:00
* chore: ignore web/dist directory in git repository * 功能: 新增 SAP HANA 完整备份支持与 Backint 协议代理 - 修复 service 层校验 bug,使 SAP HANA 类型可正常创建 - 增强 hdbsql Runner:支持完整/增量/差异/日志备份、并行通道、失败重试 - 新增 Backint 协议代理(backupx backint 子命令),HANA 原生接口直连 BackupX 存储后端 - 新增本地 SQLite 目录维护 EBID↔对象键映射 - 前端新增 SAP HANA 扩展字段表单(备份类型/级别/通道数/重试次数/实例编号) - README 中英文补充 SAP HANA 两种模式的使用说明
99 lines
2.6 KiB
Go
99 lines
2.6 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"flag"
|
|
"fmt"
|
|
"os"
|
|
"os/signal"
|
|
"syscall"
|
|
|
|
"backupx/server/internal/backint"
|
|
)
|
|
|
|
// runBackint 是 `backupx backint` 子命令入口。
|
|
//
|
|
// CLI 参数遵循 SAP HANA Backint 规范:
|
|
//
|
|
// backupx backint -f <function> -i <input-file> -o <output-file> -p <param-file>
|
|
// [-u <user>] [-c <config-prefix>] [-l <log-file>] [-v <version>]
|
|
//
|
|
// 除 -f / -i / -o / -p 外其余参数接受但忽略(兼容 SAP 调用约定)。
|
|
func runBackint(args []string) {
|
|
fs := flag.NewFlagSet("backint", flag.ExitOnError)
|
|
fnStr := fs.String("f", "", "function: backup | restore | inquire | delete")
|
|
inputPath := fs.String("i", "", "input file path")
|
|
outputPath := fs.String("o", "", "output file path")
|
|
paramFile := fs.String("p", "", "parameter file path")
|
|
|
|
// 以下参数仅为兼容 SAP 调用约定,当前未使用
|
|
_ = fs.String("u", "", "user (ignored)")
|
|
_ = fs.String("c", "", "config-prefix (ignored)")
|
|
_ = fs.String("l", "", "log file override (ignored, use LOG_FILE in params)")
|
|
_ = fs.String("v", "", "backint version (ignored)")
|
|
|
|
if err := fs.Parse(args); err != nil {
|
|
os.Exit(2)
|
|
}
|
|
|
|
if *fnStr == "" || *inputPath == "" || *outputPath == "" || *paramFile == "" {
|
|
fmt.Fprintln(os.Stderr, "backint: -f, -i, -o, -p are required")
|
|
fs.Usage()
|
|
os.Exit(2)
|
|
}
|
|
|
|
fn, err := backint.ParseFunction(*fnStr)
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "backint: %v\n", err)
|
|
os.Exit(2)
|
|
}
|
|
|
|
cfg, err := backint.LoadConfigFile(*paramFile)
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "backint: load config: %v\n", err)
|
|
os.Exit(2)
|
|
}
|
|
|
|
// 配置日志重定向(如果指定 LOG_FILE)
|
|
restoreLog, err := redirectStderr(cfg.LogFile)
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "backint: open log: %v\n", err)
|
|
os.Exit(2)
|
|
}
|
|
defer restoreLog()
|
|
|
|
ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
|
|
defer stop()
|
|
|
|
agent, err := backint.NewAgent(ctx, cfg)
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "backint: init agent: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
defer func() { _ = agent.Close() }()
|
|
|
|
if err := agent.Run(ctx, fn, *inputPath, *outputPath); err != nil {
|
|
fmt.Fprintf(os.Stderr, "backint: run: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
|
|
// redirectStderr 将 stderr 重定向到指定日志文件,返回恢复函数。
|
|
// 空字符串表示保持原样。
|
|
func redirectStderr(path string) (func(), error) {
|
|
if path == "" {
|
|
return func() {}, nil
|
|
}
|
|
f, err := os.OpenFile(path, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
orig := os.Stderr
|
|
os.Stderr = f
|
|
return func() {
|
|
os.Stderr = orig
|
|
_ = f.Close()
|
|
}, nil
|
|
}
|
|
|