mirror of
https://github.com/Awuqing/BackupX.git
synced 2026-05-07 06:12:56 +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
|
||
}
|
||
|