英文:
golang os/exec: get data from stdout in parts
问题
我想在我的Go代码中使用os/exec
来运行一个外部应用程序。这个应用程序是my_external_script.sh
,它将数据输出到stdout
,分为两部分:第一部分非常快(在三秒后向stdout写入"A"),而第二部分("B")只有在10秒后才会被写入。
例如:
./my_external_script.sh
.....
.....
A(经过3秒)
.....
.....
.....
.....
.....
.....
B(经过10秒)
(程序以0状态码退出)
我目前在我的Go代码中这样执行它:
func execMyExternalCmd() (*string, error) {
cmd := exec.Command("my_external_script.sh")
var out bytes.Buffer
cmd.Stdout = &out
err := cmd.Run()
if err != nil {
return nil, err
}
var res = out.String()
return &res, nil
}
问题是,execMyExternalCmd
只有在10秒后才会返回,此时"A"和"B"都已经被写入并且程序已退出。我希望在stdout
上的"A"可用时就开始使用它(但稍后也要使用"B")。我该如何实现这一点?
英文:
I want to run an external application from my go code using os/exec
. The application my_external_script.sh
outputs data to stdout
in two parts: the first part is quite fast (it writes "A" to stdout after three seconds) and the second part ("B) is being written only after 10 seconds.
For example:
./my_external_script.sh
.....
.....
A (3 seconds elapsed)
.....
.....
.....
.....
.....
.....
B (10 seconds elapsed)
(program exits with 0 status code)
I'm currently executing this like so from my go code:
func execMyExternalCmd() (*string, error) {
cmd := exec.Command("my_external_script.sh")
var out bytes.Buffer
cmd.Stdout = &out
err := cmd.Run()
if err != nil {
return nil, err
}
var res = out.String()
return &res, nil
}
The problem is, execMyExternalCmd
will only return after 10 seconds, where both "A" and "B" have been written and the program exited. I would like to use "A" as soon as it's available on the stdout
(but also use "B" later on when it's available). How can I achieve this?
答案1
得分: 1
package main
import (
"bufio"
"log"
"os/exec"
)
func main() {
cmd := exec.Command("sh", "-c", "echo 1;sleep 10;echo 2;")
outPipe, _ := cmd.StdoutPipe()
scanner := bufio.NewScanner(outPipe)
// 创建一个通道用于发送数据
dataChan := make(chan string)
go func() {
for scanner.Scan() {
// 将数据发送到通道
dataChan <- scanner.Text()
}
}()
cmd.Start()
cmd.Wait()
close(dataChan) // 关闭通道
// 从通道中读取数据
for data := range dataChan {
log.Println(data)
}
log.Println("Done")
}
输出:
2016/12/04 17:11:09 1
2016/12/04 17:11:19 2
2016/12/04 17:11:19 Done
使用通道来从函数中发送数据,而不是使用返回值。
英文:
package main
import (
"bufio"
"log"
"os/exec"
)
func main() {
cmd := exec.Command("sh", "-c", "echo 1;sleep 10;echo 2;")
outPipe, _ := cmd.StdoutPipe()
scanner := bufio.NewScanner(outPipe)
go func() {
for scanner.Scan() {
log.Println(scanner.Text())
}
}()
cmd.Start()
cmd.Wait()
log.Println("Done")
}
Output:
2016/12/04 17:11:09 1
2016/12/04 17:11:19 2
2016/12/04 17:11:19 Done
Use channels to send data from the function instead of return.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论