链接 shell 命令 golang
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 数据库就不会关闭,我可以执行其他命令?
您似乎误解了进程(例如解释器和 shell,包括—it appears—mongodb
as well) work with their so-called 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
specifies the process's standard input.
If Stdin
is nil
, the process reads from the null device (os.DevNull
).
If Stdin
is an *os.File
, the process's standard input is connected
directly to that file.
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.
Stdin io.Reader
所以基本上你创建一个对象,它接受一个字符串并提供 一些东西 实现 io.Reader
和 "wire" 它到进程的标准输入被创建。
一旦该过程开始,os/exec
将确保生成一个 goroutine,它将在您的字符串和 运行 mongodb
实例之间铲除数据——就好像您将手动启动 mongodb
并将该字符串直接输入到其标准输入流中。
请注意,您可能还需要检查 mongodb
在其标准 输出 流上生成的内容——尤其是 stderr
,因为如果它遇到任何错误在执行您提交给它的脚本时,它可能会在那里报告它们。
我正在尝试从我的 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 数据库就不会关闭,我可以执行其他命令?
您似乎误解了进程(例如解释器和 shell,包括—it appears—mongodb
as well) work with their so-called 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
specifies the process's standard input.
IfStdin
isnil
, the process reads from the null device (os.DevNull
).
IfStdin
is an*os.File
, the process's standard input is connected directly to that file.
Otherwise, during the execution of the command a separate goroutine reads fromStdin
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 ofStdin
(EOF or a read error) or because writing to the pipe returned an error.
Stdin io.Reader
所以基本上你创建一个对象,它接受一个字符串并提供 一些东西 实现 io.Reader
和 "wire" 它到进程的标准输入被创建。
一旦该过程开始,os/exec
将确保生成一个 goroutine,它将在您的字符串和 运行 mongodb
实例之间铲除数据——就好像您将手动启动 mongodb
并将该字符串直接输入到其标准输入流中。
请注意,您可能还需要检查 mongodb
在其标准 输出 流上生成的内容——尤其是 stderr
,因为如果它遇到任何错误在执行您提交给它的脚本时,它可能会在那里报告它们。