英文:
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
指定了进程的标准输入。
如果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
——因为如果在执行你提交给它的脚本时遇到任何错误,它很可能会在那里报告这些错误。
英文:
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—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—especially stderr
,—because if it encounters any errors while executing the script you have submitted to it, it will likely report them there.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论