链接 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 appearsmongodb 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,因为如果它遇到任何错误在执行您提交给它的脚本时,它可能会在那里报告它们。