为了账号安全,请及时绑定邮箱和手机立即绑定

Os/exec 优雅,循环兼容 stdin 和 stdout 输入/输出

Os/exec 优雅,循环兼容 stdin 和 stdout 输入/输出

Go
慕侠2389804 2022-01-04 14:40:49
示例脚本只是“wc -m”命令的包装器,简单的符号计数器。我尝试只用“teststrings”切片元素输入输入。并在输出侦听器 goroutine 处接收每个字符串的符号数。寻找一种让“wc”永远监听输入的方法。我注意到当我增加睡眠时time.Sleep(6000 * time.Nanosecond)wc 不要等待输入。package mainimport (    "bytes"    "fmt"    "os/exec"    "time")func main() {    BashCommand := exec.Command("wc", "-m")    InputBytes := &bytes.Buffer{}    OutputBytes := &bytes.Buffer{}    BashCommand.Stdin = InputBytes    BashCommand.Stdout = OutputBytes    e := BashCommand.Start()    time.Sleep(1 * time.Nanosecond)    _, _ = InputBytes.Write([]byte("13symbolsting"))    if e != nil {        fmt.Println(e)    }    fmt.Println("after run")    teststrings := []string{        "one",        "twoo",        "threeeee",    }    for _, s := range teststrings {        _, _ = InputBytes.Write([]byte(s))    }    //result printer    go func() {        for {            line, _ := OutputBytes.ReadString('\n')            if line != "" {                fmt.Println(line)            }        }    }()    var input string    fmt.Scanln(&input) //dont exit until keypress}
查看完整描述

1 回答

?
慕无忌1623718

TA贡献1744条经验 获得超4个赞

如果将 sleep 增加到一个较大的值,则由命令启动的 goroutine 会InputBytes在数据写入InputBytes. goroutine 关闭通向子进程的管道并在没有读取任何数据的情况下退出。


使用管道代替 bytes.Buffer:


c := exec.Command("wc", "-m")

w, _ := c.StdinPipe()

r, _ := c.StdoutPipe()

if err := c.Start(); err != nil {

    log.Fatal(err)

}


w.Write([]byte("13symbolsting"))

teststrings := []string{

    "one",

    "twoo",

    "threeeee",

}

for _, s := range teststrings {

    w.Write([]byte(s))


}

w.Close() // Close pipe to indicate input is done.


var wg sync.WaitGroup

wg.Add(1)


go func() {

    s := bufio.NewScanner(r)

    for s.Scan() {

        fmt.Println(s.Text())

    }

    wg.Done()

}()


wg.Wait()

另一种选择是在启动命令之前写入 bytes.Buffer 并在读取输出之前等待命令完成:


c := exec.Command("wc", "-m")

var w, r bytes.Buffer

c.Stdin = &w

c.Stdout = &r


// Write data before starting command.


w.Write([]byte("13symbolsting"))

teststrings := []string{

    "one",

    "twoo",

    "threeeee",

}

for _, s := range teststrings {

    w.Write([]byte(s))


}


if err := c.Start(); err != nil {

    log.Fatal(err)

}


// Wait for command to complete before reading data.


if err := c.Wait(); err != nil {

    log.Fatal(err)

}


s := bufio.NewScanner(&r)

for s.Scan() {

    fmt.Println(s.Text())

}


查看完整回答
反对 回复 2022-01-04
  • 1 回答
  • 0 关注
  • 138 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信