Golang备份CLI命令的替代方案或API有哪些

Golang备份CLI命令的替代方案或API有哪些 你好!

我正在尝试使用 Go 语言以编程方式将 InfluxDB 备份到另一台服务器。

我可以通过 Go 的命令行功能实现这一点,如下所示:

cmd := exec.Command(configInfluxDB.InfluxdExeutablePath, "backup", "-portable", "-database", configInfluxDB.Database, "-host", configInfluxDB.HostName+":8088", fileStorePath)

但是,我找不到任何用于相同目的的 Go API 函数。

我想了解类似的函数,它可以接收 pathdatabasehostfile path 参数,然后执行备份。

我尝试使用 https://github.com/influxdata/influxdb/blob/master/cmd/influx/backup.go 中定义的后端函数,如下所示:

func newBackupService() (influxdb.BackupService, error) {
	return &http.BackupService{
		Addr:  "http://localhost:8086",
		Token: "admin:admin",
	}, nil
}


func ConnectToDB(fullFileName string) (*InfluxReader, error) { 
	// Read InfluxDB instance's properties from an external file.
	configInfluxDB, err := loadInfluxProperty(fullFileName)

	fmt.Println("hello")

	HTTPAddr := fmt.Sprintf("http://%s:%s",configInfluxDB.HostName, configInfluxDB.PortNumber)
	c, _ := client.NewHTTPClient(client.HTTPConfig{
	    Addr: HTTPAddr,
	    Username: configInfluxDB.UserName,
	    Password: configInfluxDB.Password,
	})
	_, _, err = c.Ping(0)
	if err != nil {
	    log.Fatal("Error creating InfluxDB Client: ", err.Error())
	}
	defer c.Close()

	var slash = ""
	if string(os.TempDir()[0]) == "C" {
		slash = "\\"
	} else {
		slash = "/"
		}
	fileStorePath := os.TempDir() + slash + configInfluxDB.Database
    fmt.Println(fileStorePath)
        
    ctx := context.Background()
        
    err = os.MkdirAll(fileStorePath, 0777)
	if err != nil && !os.IsExist(err) {
		fmt.Println("e1")
		return nil,err
	}

	backupService, err := newBackupService()
	if err != nil {
		fmt.Println("e2")
		return nil,err
	}

	id, backupFilenames, err := backupService.CreateBackup(ctx)
	if err != nil {
		fmt.Println("e3")
		return nil,err
	}

	fmt.Printf("Backup ID %d contains %d files\n", id, len(backupFilenames))
	fmt.Printf("Backup complete")
        
    var files []string
	err = filepath.Walk(fileStorePath, visit(&files))
        if err != nil {
        fmt.Println("Could not store file names:", err)
        return nil, err
	}
	return &InfluxReader{ConfigInfluxDB: configInfluxDB,File: files,Path: fileStorePath}, err
}

运行代码后,输出如下:

hello
(.....some path......)
e3
Failed to establish connection with InfluxDB:2020/05/19 13:47:25 app.Run: 404 page not found

恳请帮助。 谢谢。


更多关于Golang备份CLI命令的替代方案或API有哪些的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于Golang备份CLI命令的替代方案或API有哪些的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


根据你的代码分析,问题在于你使用了错误的备份服务实现。InfluxDB 2.x 的备份API与1.x不同,且需要正确的认证方式。以下是两种解决方案:

方案一:使用InfluxDB 2.x官方Go客户端(推荐)

package main

import (
    "context"
    "fmt"
    "os"
    
    "github.com/influxdata/influxdb-client-go/v2"
    "github.com/influxdata/influxdb-client-go/v2/api"
)

func backupInfluxDB(host, token, org, bucket, backupPath string) error {
    // 创建客户端
    client := influxdb2.NewClient(host, token)
    defer client.Close()
    
    // 获取备份API
    backupAPI := client.BackupAPI()
    
    // 创建备份
    ctx := context.Background()
    backup, err := backupAPI.CreateBackup(ctx, org, bucket)
    if err != nil {
        return fmt.Errorf("创建备份失败: %v", err)
    }
    
    // 下载备份文件
    err = backupAPI.DownloadBackup(ctx, backup, backupPath)
    if err != nil {
        return fmt.Errorf("下载备份失败: %v", err)
    }
    
    fmt.Printf("备份成功保存到: %s\n", backupPath)
    return nil
}

// 使用示例
func main() {
    err := backupInfluxDB(
        "http://localhost:8086",
        "your-token-here",
        "your-org",
        "your-bucket",
        "/path/to/backup.influxdb",
    )
    if err != nil {
        fmt.Printf("备份失败: %v\n", err)
        os.Exit(1)
    }
}

方案二:使用InfluxDB 1.x的备份API

如果你的InfluxDB是1.x版本,可以使用以下方法:

package main

import (
    "context"
    "fmt"
    "io"
    "net/http"
    "os"
    
    "github.com/influxdata/influxdb/client/v2"
)

func backupInfluxDBv1(host, username, password, database, backupPath string) error {
    // 创建HTTP客户端
    httpClient := &http.Client{}
    
    // 构建备份URL
    backupURL := fmt.Sprintf("%s/backup?db=%s", host, database)
    
    // 创建请求
    req, err := http.NewRequest("GET", backupURL, nil)
    if err != nil {
        return err
    }
    
    // 设置认证
    if username != "" && password != "" {
        req.SetBasicAuth(username, password)
    }
    
    // 执行请求
    resp, err := httpClient.Do(req)
    if err != nil {
        return err
    }
    defer resp.Body.Close()
    
    // 检查响应状态
    if resp.StatusCode != http.StatusOK {
        return fmt.Errorf("备份请求失败: %s", resp.Status)
    }
    
    // 创建备份文件
    outFile, err := os.Create(backupPath)
    if err != nil {
        return err
    }
    defer outFile.Close()
    
    // 写入文件
    _, err = io.Copy(outFile, resp.Body)
    return err
}

// 使用示例
func main() {
    err := backupInfluxDBv1(
        "http://localhost:8086",
        "admin",
        "admin",
        "mydb",
        "/tmp/backup.gz",
    )
    if err != nil {
        fmt.Printf("备份失败: %v\n", err)
        os.Exit(1)
    }
    fmt.Println("备份成功")
}

方案三:使用exec.Command但改进错误处理

如果你坚持使用命令行方式,可以改进你的实现:

package main

import (
    "bytes"
    "fmt"
    "os/exec"
    "strings"
)

func backupViaCLI(influxdPath, host, database, backupPath string) error {
    // 构建命令参数
    args := []string{
        "backup",
        "-portable",
        "-database", database,
        "-host", host + ":8088",
        backupPath,
    }
    
    // 执行命令
    cmd := exec.Command(influxdPath, args...)
    
    // 捕获输出
    var stdout, stderr bytes.Buffer
    cmd.Stdout = &stdout
    cmd.Stderr = &stderr
    
    // 运行命令
    err := cmd.Run()
    if err != nil {
        return fmt.Errorf("备份命令执行失败: %v\nSTDOUT: %s\nSTDERR: %s", 
            err, stdout.String(), stderr.String())
    }
    
    // 检查输出
    output := stdout.String()
    if !strings.Contains(output, "backup complete") {
        return fmt.Errorf("备份可能未完成: %s", output)
    }
    
    return nil
}

// 使用示例
func main() {
    err := backupViaCLI(
        "/usr/bin/influxd",
        "localhost",
        "mydatabase",
        "/tmp/backup",
    )
    if err != nil {
        fmt.Printf("备份失败: %v\n", err)
    } else {
        fmt.Println("备份成功")
    }
}

关键问题分析

你遇到的404 page not found错误是因为:

  1. 你使用的http.BackupService是针对InfluxDB 1.x的
  2. 你的InfluxDB可能是2.x版本,API路径不同
  3. 认证方式需要从用户名/密码改为Token

建议先确认你的InfluxDB版本,然后选择对应的API方案。对于生产环境,推荐使用方案一的官方客户端。

回到顶部