链接shell命令golang

时间:2016-04-08 15:24:27

标签: mongodb shell go exec mongo-shell

我试图从我的go程序中运行一个shell脚本。我想启动一个mongo实例,然后删除一些数据。所以shell脚本看起来像这样:

mongo

use test-db

db.user.remove({"id": 1})

我最初尝试使用exec.Command包,但它没有链接命令,因此mongo db关闭,我无法运行其他命令:

cmd := exec.Command("mongo", "test-db")
cmd.Start()
cmd1 := exec.Command("db.remove({\"id\": 1})")
cmd1.Run()
cmd.Wait()

我尝试的下一件事是创建一个变量并试图通过sh:

执行它
var script = `
 #!/bin/bash

mongo

use test-db

db.user.remove({"id": 1})
`

并执行exec.Command("sh", script)

我知道我可以创建一个.sh文件,但我不想这样做是否有任何方法可以将命令链接到go,这样mongo db就不会关闭,我可以执行其他命令?

1 个答案:

答案 0 :(得分:3)

您似乎误解了进程(例如解释器和shell,包括 - it appears - mongodb)如何与他们所谓的standard streams一起工作:而“test-db” “确实是传递给要在其命令行上创建的mongodb进程的参数,db.user.remove({"id": 1})是生成mongodb实例应该从其标准输入流中读取的文本

所以基本上你需要这个:

import (
    "os/exec"
    "strings"
)

cmd := exec.Command("mongo", "test-db")
cmd.Stdin = strings.NewReader(`db.user.remove({"id": 1})\n`)
err := cmd.Run()
// Check for an error

为了解释这是如何工作的,让我们引用manual

  

Stdin指定流程的标准输入   如果Stdinnil,则流程从空设备(os.DevNull)读取   如果Stdin*os.File,则会连接流程的标准输入   直接到那个文件。
  否则,在执行命令期间单独执行   goroutine从Stdin读取并将该数据传递给命令   在管道上。在这种情况下,Wait直到goroutine才完成   停止复制,因为它已到达Stdin的末尾   (EOF或读取错误)或因为写入管道返回错误   Stdin io.Reader

所以基本上你创建了一个对象,它接受一个字符串并提供某些实现io.Reader并将其“连接”到即将创建的进程的标准输入。 一旦进程开始,os/exec将确保生成一个goroutine,它会在你的字符串和正在运行的mongodb实例之间挖掘数据 - 就像你手动启动mongodb并键入该字符串一样直接进入其标准输入流。

请注意,您还可能需要检查mongodb在其标准输出流上生成的内容 - 尤其是stderr, - 因为如果在执行脚本时遇到任何错误,已提交给它,它可能会在那里报告。