我必须处理脚本的长输出并找到一些数据。这些数据很可能位于输出的几乎一开始。发现数据后,我不再需要处理输出,可以退出。
我无法停止处理输出的问题,因为exec.Cmd
没有任何关闭已打开命令的功能。
以下是一些简化的代码(错误处理被忽略):
func processOutput(r *bufio.Reader)(){
for {
line, _, err := r.ReadLine()
if some_condition_meet {
break
}
......
}
return
}
func execExternalCommand(){
cmdToExecute := "......"
cmd := exec.Command("bash", "-c", cmdToExecute)
output, _ := cmd.StdoutPipe()
cmd.Start()
r := bufio.NewReader(output)
go processOutput(r)
cmd.Wait()
return
}
我应该在processOutput
函数结束时做什么来停止cmd?也许还有另一种解决方法。
由于
答案 0 :(得分:3)
目前,您无法从processOutput
执行此操作,因为它收到的只是bufio.Reader
。您需要将exec.Cmd
传递给它,以便它可以对分叉进程执行任何操作。
要终止分叉过程,您可以向其发送信号,例如:cmd.Process.Kill()
或cmd.Process.Signal(os.SIGINT)
。请参阅exec.Cmd
和os.Process
上的文档。
答案 1 :(得分:1)
您可以使用" context"例如:
package main
import (
"bufio"
"context"
"os/exec"
)
func processOutput(r *bufio.Reader, cancel context.WithCancel) {
for {
line, _, err := r.ReadLine()
if some_condition_meet {
break
}
}
cancel()
return
}
func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
cmdToExecute := "......"
cmd := exec.CommandContext(ctx, "bash", "-c", cmdToExecute)
output, _ := cmd.StdoutPipe()
cmd.Start()
r := bufio.NewReader(output)
go processOutput(r, cancel)
cmd.Wait()
return
}
如果需要以超时结束,这可能有用(例如从这里取得:https://golang.org/src/os/exec/example_test.go)
func ExampleCommandContext() {
ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond)
defer cancel()
if err := exec.CommandContext(ctx, "sleep", "5").Run(); err != nil {
// This will fail after 100 milliseconds. The 5 second sleep
// will be interrupted.
}
}
仅使用睡眠但在1秒后关闭它的基本示例:https://play.golang.org/p/gIXKuf5Oga