-3

curl我的应用程序适用于从控制台( 、、、date等等ping)提供的所有类型的 shell 命令。现在我想用交互式 shell 命令(如 mongo shell)来覆盖这个案例,使用os/exec.

  • 例如,作为第一步,连接到 mongodb: mongo --quiet --host=localhost blog

  • 然后执行任意数量的命令,每一步都得到结果 db.getCollection('posts').find({status:'INACTIVE'})

  • 进而 exit

我尝试了以下方法,但它允许我每个 mongo 连接只执行一个命令:

func main() {

    cmd := exec.Command("sh", "-c", "mongo --quiet --host=localhost blog")

    cmd.Stdout = os.Stdout
    cmd.Stderr = os.Stderr

    stdin, _ := cmd.StdinPipe()

    go func() {
        defer stdin.Close()
        io.WriteString(stdin, "db.getCollection('posts').find({status:'INACTIVE'}).itcount()")
        // fails, if I'll do one more here
    }()

    cmd.Run()
    cmd.Wait()
}

有没有办法运行多个命令,获得每个执行命令的标准输出结果?

4

1 回答 1

1

正如 Flimzy 所指出的,您绝对应该使用 mongo 驱动程序来使用 mongo,而不是尝试通过 shell exec 与之交互。

但是,要回答根本问题,您当然可以执行多个命令——没有理由不能。每次您写入进程的标准输入时,就像您在终端上输入它一样。除了专门检测它们是否连接到 TTY 的进程外,对此没有任何秘密限制。

但是,您的代码有几个问题 - 您绝对应该查看os/exec包文档。您正在调用cmd.Run,其中:

启动指定的命令并等待它完成。

然后调用cmd.Wait, 其中...也等待命令完成。您正在 goroutine 中写入标准输入管道,即使这是一个非常序列化的过程:您想写入管道以执行命令,获取结果,编写另一个命令,获取另一个结果......并发只会混淆很重要,不应该在这里使用。而且您不会发送换行符来告诉 Mongo 您已完成编写命令(就像您在 shell 中所做的那样 - Mongo 不会在您输入结束括号后立即开始执行,您必须按 Enter 键) .

您想要通过 stdin/stdout 与进程进行交互的操作(再次注意,这绝对不是与数据库交互的方式,但可能对其他外部命令有效):

cmd := exec.Command("sh", "-c", "mongo --quiet --host=localhost blog")

cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr

stdin, _ := cmd.StdinPipe()

// Start command but don't wait for it to exit (yet) so we can interact with it
cmd.Start()

// Newlines, like hitting enter in a terminal, tell Mongo you're done writing a command
io.WriteString(stdin, "db.getCollection('posts').find({status:'INACTIVE'}).itcount()\n")
io.WriteString(stdin, "db.getCollection('posts').find({status:'ACTIVE'}).itcount()\n")

// Quit tells it you're done interacting with it, otherwise it won't exit
io.WriteString(stdin, "quit()\n")

stdin.Close()

// Lastly, wait for the process to exit
cmd.Wait()
于 2019-04-02T13:44:15.863 回答