在Golang中链接shell命令

huangapple go评论107阅读模式
英文:

Chaining shell commands golang

问题

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

mongo

use test-db

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

我最初尝试使用exec.Command包,但它不会链接这些命令,所以mongo数据库会关闭,我无法运行其他命令:

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数据库不关闭,我可以执行其他命令?

英文:

I'm trying to run a shell script from my go program. I want to start up a mongo instance and then remove some data. So the shell script would look something like this:

mongo

use test-db

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

I initially tried just using the exec.Command package but it doesn't chain the commands so the mongo db closes and I can't run the other commands:

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

The next thing I tried is creating a variable and trying to execute that via sh:

var script = `
 #!/bin/bash

mongo

use test-db

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

and executing exec.Command("sh", script)

I know I can create a .sh file but I don't want to do that is there any way to chain commands in go so the mongo db doesn't close and I can execute the other commands?

答案1

得分: 4

你似乎误解了进程(如解释器和shell,包括——似乎是 mongodb)与所谓的标准流的工作方式:虽然"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()
// 检查错误

为了解释这是如何工作的,让我们引用一下手册

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——因为如果在执行你提交给它的脚本时遇到任何错误,它很可能会在那里报告这些错误。

英文:

You seem to misunderstand how processes (such as interpreters and shells, including—it appears—mongodb as well) work with their so-called standard streams: while the "test-db" is indeed an argument to pass to a mongodb process to be created on its command-line, the db.user.remove({"id": 1}) is the text that spawned mongodb instance is supposed to read from its standard input stream.

So basically you need this:

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

To explain how this works, let's cite the manual:

> Stdin specifies the process's standard input.<br/>
> If Stdin is nil, the process reads from the null device (os.DevNull).<br/>
> If Stdin is an *os.File, the process's standard input is connected
> directly to that file.<br/>
> Otherwise, during the execution of the command a separate
> goroutine reads from Stdin and delivers that data to the command
> over a pipe. In this case, Wait does not complete until the goroutine
> stops copying, either because it has reached the end of Stdin
> (EOF or a read error) or because writing to the pipe returned an error.<br/>
> Stdin io.Reader

So basically you create an object which takes a string and provides something implementing io.Reader and "wire" it to the standard input of the process about to be created.
Once the process starts, os/exec will make sure to spawn a goroutine which will shovel data between your string and the running mongodb instance&mdash;as if you would start mongodb by hand and typed that string onto its standard input stream directly.

Note that you also might need to check what mongodb generates on its standard output streams&mdash;especially stderr,&mdash;because if it encounters any errors while executing the script you have submitted to it, it will likely report them there.

huangapple
  • 本文由 发表于 2016年4月8日 23:24:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/36503462.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定