如何让stdin在golang中执行cmd

use*_*961 14 go

我有这个代码

subProcess := exec.Cmd{
    Path: execAble,
    Args: []string{
        fmt.Sprintf("-config=%s", *configPath),
        fmt.Sprintf("-serverType=%s", *serverType),
        fmt.Sprintf("-reload=%t", *reload),
        fmt.Sprintf("-listenFD=%d", fd),
    },
    Dir: here,
}
subProcess.Stdout = os.Stdout
subProcess.Stderr = os.Stderr
logger.Info("starting  subProcess:%s ", subProcess.Args)

if err := subProcess.Run(); err != nil {
    logger.Fatal(err)
}
Run Code Online (Sandbox Code Playgroud)

然后我做os.Exit(1)来停止主进程

我可以从子进程获得输出

但我也想把stdin放进去

我试试

subProcess.Stdin = os.Stdin
Run Code Online (Sandbox Code Playgroud)

但它不起作用

mra*_*ron 24

我制作了一个简单的程序(用于测试).它读取一个数字并写出给定的数字.

package main

import (
    "fmt"
)

func main() {
    fmt.Println("Hello, What's your favorite number?")
    var i int
    fmt.Scanf("%d\n", &i)
    fmt.Println("Ah I like ", i, " too.")
}
Run Code Online (Sandbox Code Playgroud)

这是修改后的代码

package main

import (
    "fmt"
    "io"
    "os"
    "os/exec"
)

func main() {
    subProcess := exec.Command("go", "run", "./helper/main.go") //Just for testing, replace with your subProcess

    stdin, err := subProcess.StdinPipe()
    if err != nil {
        fmt.Println(err) //replace with logger, or anything you want
    }
    defer stdin.Close() // the doc says subProcess.Wait will close it, but I'm not sure, so I kept this line

    subProcess.Stdout = os.Stdout
    subProcess.Stderr = os.Stderr

    fmt.Println("START") //for debug
    if err = subProcess.Start(); err != nil { //Use start, not run
        fmt.Println("An error occured: ", err) //replace with logger, or anything you want
    }

    io.WriteString(stdin, "4\n")
    subProcess.Wait()
    fmt.Println("END") //for debug
}
Run Code Online (Sandbox Code Playgroud)

你对这些线感兴趣

stdin, err := subProcess.StdinPipe()
if err != nil {
    fmt.Println(err)
}
defer stdin.Close()
//...
io.WriteString(stdin, "4\n")
//...
subProcess.Wait()
Run Code Online (Sandbox Code Playgroud)

以上行的说明

  1. 我们获得了子进程'stdin,现在我们可以写它了
  2. 我们使用我们的力量,我们写了一个数字
  3. 我们等待我们的子流程完成

产量

开始
你好,你最喜欢的号码是什么?
啊我也喜欢4.
结束

为了更好地理解


Pet*_*epo 8

Go 文档中现在提供了一个更新的示例:https ://golang.org/pkg/os/exec/#Cmd.StdinPipe

如果子进程在标准输入关闭之前没有继续,则io.WriteString()需要将调用包装在匿名函数中:

func main() {
    cmd := exec.Command("cat")
    stdin, err := cmd.StdinPipe()
    if err != nil {
        log.Fatal(err)
    }

    go func() {
        defer stdin.Close()
        io.WriteString(stdin, "values written to stdin are passed to cmd's standard input")
    }()

    out, err := cmd.CombinedOutput()
    if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("%s\n", out)
}
Run Code Online (Sandbox Code Playgroud)