从 exec.Command 逐行捕获 stdout 并通过管道传输到 os.Stdout

Ian*_*son 3 channel go

有人可以帮忙吗?

我有一个通过 exec.CommandContext 运行的应用程序(因此我可以通过 ctx 取消它)。除非出错,否则它通常不会停止。

我目前将其输出中继到 os.stdOut ,效果很好。但我也想通过通道获取每一行 - 这背后的想法是我将在该行上查找正则表达式,如果它为真,那么我将设置一个内部状态“ERROR”,例如。

虽然我无法让它工作,但我尝试了NewSscanner。这是我的代码。

正如我所说,它确实输出到 os.StdOut,这很棒,但我希望接收我设置的频道中发生的每一行。

有任何想法吗 ?

提前致谢。

func (d *Daemon) Start() {
    ctx, cancel := context.WithCancel(context.Background())
    d.cancel = cancel

    go func() {
        args := "-x f -a 1"
        cmd := exec.CommandContext(ctx, "mydaemon", strings.Split(args, " ")...)

        var stdoutBuf, stderrBuf bytes.Buffer

        cmd.Stdout = io.MultiWriter(os.Stdout, &stdoutBuf)
        cmd.Stderr = io.MultiWriter(os.Stderr, &stderrBuf)

        lines := make(chan string)

        go func() {
            scanner := bufio.NewScanner(os.Stdin)
            for scanner.Scan() {
                fmt.Println("I am reading a line!")
                lines <- scanner.Text()
            }
        }()

        err := cmd.Start()
        if err != nil {
            log.Fatal(err)
        }

        select {
        case outputx := <-lines:
            // I will do somethign with this!
            fmt.Println("Hello!!", outputx)

        case <-ctx.Done():
            log.Println("I am done!, probably cancelled!")
        }
    }()
}
Run Code Online (Sandbox Code Playgroud)

也尝试过使用这个

        go func() {
            scanner := bufio.NewScanner(&stdoutBuf)
            for scanner.Scan() {
                fmt.Println("I am reading a line!")
                lines <- scanner.Text()
            }
        }()
Run Code Online (Sandbox Code Playgroud)

即使这样,“我正在读一行”也永远不会出去,我也调试了它,它从来没有进入“用于扫描仪..”

也尝试扫描&stderrBuf,同样,没有输入任何内容。

Kav*_*ian 5

cmd.Start()不等待命令完成。此外,cmd.Wait()需要致电以告知流程结束。

reader, writer := io.Pipe()

cmdCtx, cmdDone := context.WithCancel(context.Background())

scannerStopped := make(chan struct{})
go func() {
    defer close(scannerStopped)

    scanner := bufio.NewScanner(reader)
    for scanner.Scan() {
        fmt.Println(scanner.Text())
    }
}()

cmd := exec.Command("ls")
cmd.Stdout = writer
_ = cmd.Start()
go func() {
    _ = cmd.Wait()
    cmdDone()
    writer.Close()
}()
<-cmdCtx.Done()

<-scannerStopped
Run Code Online (Sandbox Code Playgroud)

scannerStopped添加是为了证明扫描仪 Goroutine 现在停止了。

reader, writer := io.Pipe()

scannerStopped := make(chan struct{})
go func() {
    defer close(scannerStopped)

    scanner := bufio.NewScanner(reader)
    for scanner.Scan() {
        fmt.Println(scanner.Text())
    }
}()

cmd := exec.Command("ls")
cmd.Stdout = writer
_ = cmd.Run()

go func() {
    _ = cmd.Wait()
    writer.Close()
}()

<-scannerStopped
Run Code Online (Sandbox Code Playgroud)

并尽可能处理好线路。

注:写的有点仓促。如果有任何不清楚或不正确的地方,请告诉我。