我试图从我的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就不会关闭,我可以执行其他命令?
答案 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
指定流程的标准输入 如果Stdin
为nil
,则流程从空设备(os.DevNull
)读取 如果Stdin
是*os.File
,则会连接流程的标准输入 直接到那个文件。
否则,在执行命令期间单独执行 goroutine从Stdin
读取并将该数据传递给命令 在管道上。在这种情况下,Wait
直到goroutine才完成 停止复制,因为它已到达Stdin
的末尾 (EOF或读取错误)或因为写入管道返回错误Stdin io.Reader
所以基本上你创建了一个对象,它接受一个字符串并提供某些实现io.Reader
并将其“连接”到即将创建的进程的标准输入。
一旦进程开始,os/exec
将确保生成一个goroutine,它会在你的字符串和正在运行的mongodb
实例之间挖掘数据 - 就像你手动启动mongodb
并键入该字符串一样直接进入其标准输入流。
请注意,您还可能需要检查mongodb
在其标准输出流上生成的内容 - 尤其是stderr
, - 因为如果在执行脚本时遇到任何错误,已提交给它,它可能会在那里报告。