【问题标题】:continuously reading from exec.Cmd output连续读取 exec.Cmd 输出
【发布时间】:2017-04-26 13:26:53
【问题描述】:

伙计们,我正在尝试从命令输出中选择新行,但我总是以同步方式完成(我必须等到脚本完成)。我厌倦了使用 fsnotify 但它仅适用于常规文件,您知道如何完成吗?

package main
import (
   "fmt"
   "os/exec"
   "bytes"
   "os"
)

func main() {
   cmd := exec.Command("scripts/long_script")
   output := new(bytes.Buffer)
   cmd.Stdout = output
   cmd.Stderr = output
   if err := cmd.Start(); err != nil{ // after Start program is continued and script is executing in background
     fmt.Printf("Failed to start " + err.Error())
     os.Exit(1)
   }
   fmt.Printf(" Before WAIT %s \n", output.String())  // script is writing but nothing can be read from output
   cmd.Wait()
   fmt.Printf(" After Wait %s \n", output.String())  // if we wait to finish execution, we can read all output
}

【问题讨论】:

  • 您可以使用cmd.StdoutPipecmd.StderrPipe通过管道获取命令输出,您可以在数据进入时读取它们。如果您想同时读取它们,您需要设置启动 goroutines。

标签: go exec stdout


【解决方案1】:

你应该使用 os.StdoutPipe()

func main() {
    for i := 10; i < 20; i++ {
        go printName(`My name is Bob, I am ` + strconv.Itoa(i) + ` years old`)
        // Adding delay so as to see incremental output
        time.Sleep(60 * time.Millisecond)
    }
    // Adding delay so as to let program complete
    // Please use channels or wait groups
    time.Sleep(100 * time.Millisecond)
}

func printName(jString string) {
    cmd := exec.Command("echo", "-n", jString)
    cmdReader, err := cmd.StdoutPipe()
    if err != nil {
        log.Fatal(err)
    }
    scanner := bufio.NewScanner(cmdReader)
    go func() {
        for scanner.Scan() {
            fmt.Println(scanner.Text())
        }
    }()
    if err := cmd.Start(); err != nil {
        log.Fatal(err)
    }
    if err := cmd.Wait(); err != nil {
        log.Fatal(err)
    }
}

对我有帮助的来源: nathanleclaire.com blog.kowalczyk.info

【讨论】:

    【解决方案2】:

    最终我设法用 []bytes

    做到了
    stdout, err := cmd.StdoutPipe()
    buff := make([]byte,10)
    var n int
    for err == nil {
        n,err = stdout.Read(buff)
        if n > 0{
            fmt.Printf("taken %d chars %s",n,string(buff[:n]))
        }
    }
    cmd.Wait()
    if cmd.ProcessState.Success() {. // ProcessState is set after Wait
        fmt.Println("Script success")  
    } else {
        fmt.Println("Script failed")
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-03-08
      • 1970-01-01
      • 2021-08-03
      • 1970-01-01
      • 2016-11-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多