我编写了一个小实用程序来将 mysqldump 命令的输出通过管道传输到 golang 中的 s3 存储桶,我打算用它来在端到端测试环境中快照和恢复我们的数据库。当我在本地运行它时,一切都按预期工作:该实用程序正确地将 mysqldump 输出通过管道传输到 s3 存储桶。但是,在 Alpine Linux Docker 映像中运行时,我收到了一个损坏的管道错误。然后,该实用程序将一个空文件发送到 s3 存储桶。
要执行 mysqldump,我只需使用exec
包。mysqldump 的代码:
func (conf *MySQLConfig) DumpDatabases(stdout io.Writer) error {
args := []string{"-u", conf.User, fmt.Sprintf("--password=%s", conf.Password), "-h", conf.Host, "--databases"}
args = append(args, conf.Databases...)
cmd := exec.Command("mysqldump", args...)
cmd.Stdout = stdout
cmd.Stderr = os.Stderr
err := cmd.Start()
if err != nil {
return err
}
cmd.Wait()
return nil
}
上传到 S3 存储桶使用go-cdk
. 它需要一个函数,该函数需要一个io.Writer
作为输入并返回一个error
. 在这种情况下,执行以下代码段以将输出通过管道mysqldump
传输到 s3:
bucket.Upload(func(w io.Writer) error { return mysqlConf.DumpDatabases(w) })
上传代码:
func (b *Bucket) Upload(writeFunc func(io.Writer) error) error {
// Open a connection to the bucket.
ctx := context.Background()
bucket, err := blob.OpenBucket(ctx, b.Url)
if err != nil {
return err
}
defer bucket.Close()
// Add encryption header
beforeWrite := func(asFunc func(interface{}) bool) error {
var input *s3manager.UploadInput
if asFunc(&input) {
input.ServerSideEncryption = aws.String("AES256")
}
return nil
}
opts := &blob.WriterOptions{}
opts.BeforeWrite = beforeWrite
w, err := bucket.NewWriter(ctx, generateKey(), opts)
if err != nil {
return err
}
err = writeFunc(w)
if err != nil {
return err
}
if err := w.Close(); err != nil {
return err
}
return nil
}
任何线索为什么我在 Alpine Linux 上运行此代码时遇到管道损坏错误,而它在本地按预期工作?有关如何调试此问题以弄清楚到底发生了什么的任何建议?我应该使用缓冲 IO 吗?