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

示例脚本只是“wc -m”命令的包装器,简单的符号计数器。我尝试只用“teststrings”切片元素输入输入。并在输出侦听器 goroutine 处接收每个字符串的符号数。寻找一种让“wc”永远监听输入的方法。我注意到当我增加睡眠时


time.Sleep(6000 * time.Nanosecond)

wc 不要等待输入。


package main


import (

    "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


}


慕侠2389804
浏览 139回答 1
1回答

慕无忌1623718

如果将 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.WaitGroupwg.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.Bufferc.Stdin = &wc.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())}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go