登录
首页 >  Golang >  Go问答

保留 os/exec.Cmd.Wait() 后的标准输出

来源:stackoverflow

时间:2024-03-23 21:18:30 500浏览 收藏

本文讨论了如何保留 os/exec.Cmd.Wait() 后 os/exec.Cmd 的剩余标准输出。它指出,直接调用 cmd.wait() 会丢弃剩余的标准输出,并提供了两种解决方法: 1. 在 scanner.scan() 返回 false 后从主 goroutine 调用 cmd.wait()。 2. 从等待的 goroutine 中读取标准输出,并使用 sync.WaitGroup 等待 goroutine 完成。

问题内容

我正在使用 os/exec,在命令运行时发送输入并接收输出。 我需要在命令完成时存储命令的返回代码,因此我有一个带有 err := cmd.wait() 的 goroutine,并且我从 err 中获取任何失败返回代码。 但 wait() 似乎扔掉了我也需要的剩余标准输出。 那么如何在 cmd.wait() 之后保留 os/exec.cmd 的剩余标准输出?

示例代码,使用 unix bc 计算器命令:

package main

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

func main() {
    cmd := exec.command("sh", "-c", "bc")
    stdin, _ := cmd.stdinpipe()
    stdout, _ := cmd.stdoutpipe()
    scanner := bufio.newscanner(stdout)
    cmd.start()

    go func() {
        cmd.wait()
        fmt.println("finished")
    }()

    io.writestring(stdin, "1 + 2\n")
    fmt.println(scanner.scan(), scanner.text())
    io.writestring(stdin, "3 + 4\n")
    fmt.println(scanner.scan(), scanner.text())
    io.writestring(stdin, "5 + 6\n")
    io.writestring(stdin, "quit\n")  // cmd.wait() runs
    time.sleep(time.second)
    // prints false :(
    fmt.println(scanner.scan(), scanner.text())
}

这会打印: 真实3 真实 7 完成的 错误

我想要: 真实3 真实 7 完成的 正确11

我还尝试将 cmd.stdout 设置为 bytes.buffer,例如:

var buf bytes.Buffer
    cmd.Stdout = &buf
    scanner := bufio.NewScanner(&buf)

但这并不可靠。它打印所有错误,除非我添加了 time.sleep() 的延迟。


正确答案


读取到 stdout 末尾后调用 cmd.wait()。

选项 1:在 scanner.scan() 返回 false 后从主 goroutine 调用 cmd.wait。

cmd := exec.command("sh", "-c", "bc")
stdin, _ := cmd.stdinpipe()
stdout, _ := cmd.stdoutpipe()
scanner := bufio.newscanner(stdout)
cmd.start()

io.writestring(stdin, "1 + 2\n")
fmt.println(scanner.scan(), scanner.text())
io.writestring(stdin, "3 + 4\n")
fmt.println(scanner.scan(), scanner.text())
io.writestring(stdin, "5 + 6\n")
io.writestring(stdin, "quit\n") // cmd.wait() runs
fmt.println(scanner.scan(), scanner.text())
fmt.println(scanner.scan(), scanner.text()) // prints false
cmd.wait()

选项2:从等待的goroutine中读取:

cmd := exec.Command("sh", "-c", "bc")
stdin, _ := cmd.StdinPipe()
stdout, _ := cmd.StdoutPipe()
scanner := bufio.NewScanner(stdout)
cmd.Start()

var wg sync.WaitGroup
wg.Add(1)
go func() {
    for scanner.Scan() {
        fmt.Println(scanner.Text())
    }
    cmd.Wait()
    defer wg.Done()
}()

io.WriteString(stdin, "1 + 2\n")
io.WriteString(stdin, "3 + 4\n")
io.WriteString(stdin, "5 + 6\n")
io.WriteString(stdin, "quit\n") // cmd.Wait() runs
wg.Wait()

终于介绍完啦!小伙伴们,这篇关于《保留 os/exec.Cmd.Wait() 后的标准输出》的介绍应该让你收获多多了吧!欢迎大家收藏或分享给更多需要学习的朋友吧~golang学习网公众号也会发布Golang相关知识,快来关注吧!

声明:本文转载于:stackoverflow 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>