如何将exec函数的stdout传递给另一个函数的读者?

时间:2016-03-10 17:17:33

标签: mongodb go amazon-s3

我试图将标准输出从mongodump流式传输到s3。我已经获得了S3任意长度流的语法,但我不明白如何将这两个函数联系起来。在开始上传到S3之前,我不想处理整个mongodump命令。这就是我到目前为止所做的:

values

不幸的是dumpCmd.Stdout是一个作家,而不是读者,我不知道如何将作者的输出传递给读者。

使用管道后,我现在收到一个新错误,可能属于一个新问题:

dumpCmd := exec.Command("mongodump", "--host", "<host>", "--port", "<port>", "--archive")
dumpCmd.Stdout = os.Stdout


uploader := s3manager.NewUploader(session.New(&aws.Config{Region: aws.String("us-east-1")}))
result, err := uploader.Upload(&s3manager.UploadInput{
    Body:   dumpCmd.Stdout,
    Bucket: aws.String("myBucket"),
    Key:    aws.String("myKey"),
})
if err != nil {
    log.Fatalln("Failed to upload", err)
}

log.Println("Successfully uploaded to", result.Location)

错误:

dumpCmd := exec.Command("mongodump", "--host", "<host>", "--port", "<port>", "--archive")
body, err := dumpCmd.StdoutPipe()
if err != nil {
    // handle error
}

if err := dumpCmd.Start(); err != nil {
    // handle error
}

uploader := s3manager.NewUploader(session.New(&aws.Config{Region: aws.String("us-east-1")}))
result, err := uploader.Upload(&s3manager.UploadInput{
    Body:   body,
    Bucket: aws.String("myBucket"),
    Key:    aws.String("myKey"),
})
if err != nil {
    log.Fatalln("Failed to upload", err)
}

if err := dumpCmd.Wait(); err != nil {
    // handle error
}

log.Println("Successfully uploaded to", result.Location)

2 个答案:

答案 0 :(得分:3)

使用pipe将命令输出连接到上传输入。

这里棘手的问题是上传者seeks on the body,但管道不支持搜索。为了避免这种情况,在管道周围创建一个包装器,以隐藏上传器中的Seek方法。

dumpCmd := exec.Command("mongodump", "--host", "<host>", "--port", "<port>", "--archive")
body, err := dumpCmd.StdoutPipe()
if err != nil {
    // handle error
}

if err := dumpCmd.Start(); err != nil {
    // handle error
}

// Wrap the pipe to hide the seek methods from the uploader
bodyWrap := struct {
    io.Reader
}{body}

uploader := s3manager.NewUploader(session.New(&aws.Config{Region: aws.String("us-east-1")}))
result, err := uploader.Upload(&s3manager.UploadInput{
    Body:   bodyWrap,
    Bucket: aws.String("net-openwhere-mongodb-snapshots-dev"),
    Key:    aws.String("myKey"),
})
if err != nil {
    log.Fatalln("Failed to upload", err)
}

if err := dumpCmd.Wait(); err != nil {
   // handle error
}

log.Println("Successfully uploaded to", result.Location)

答案 1 :(得分:-1)

您可以使用io.Copy方法(godoc),其定义如下:

  

func Copy

     

func Copy(dst Writer,src Reader)(写入int64,错误错误)

     

将副本从src复制到dst,直到在src或a上达到EOF   发生错误。它返回复制的字节数和第一个   复制时遇到错误,如果有的话。

     

成功的复制返回err == nil,而不是err == EOF。因为复制是   定义为从src读取直到EOF,它不会从Read处理EOF   作为要报告的错误。

     

如果src实现了WriterTo接口,则副本由。实现   调用src.WriteTo(dst)。否则,如果dst实现ReaderFrom   接口,通过调用dst.ReadFrom(src)实现副本。