Golang里实现实时读取shell命令输出
使用golang调用阻塞式shell命令(如ping命令),按普通的调用方法是无法拿到实时输出结果的,这里可以通过异步读取管道输出数据的方式实现,关键代码如下:
package main import ( "bufio" "fmt" "io" "log" "os/exec" "runtime/debug" "sync" ) func readLog(wg *sync.WaitGroup, out chan string, reader io.ReadCloser) { defer func() { if r := recover(); r != nil { log.Println(r, string(debug.Stack())) } }() defer wg.Done() r := bufio.NewReader(reader) for { line, _, err := r.ReadLine() if err == io.EOF || err != nil { return } out <- string(line) } } // RunCommand run shell func RunCommand(out chan string, name string, arg ...string) error { cmd := exec.Command(name, arg...) stdout, _ := cmd.StdoutPipe() stderr, _ := cmd.StderrPipe() if err := cmd.Start(); err != nil { return err } wg := sync.WaitGroup{} defer wg.Wait() wg.Add(2) go readLog(&wg, out, stdout) go readLog(&wg, out, stderr) if err := cmd.Wait(); err != nil { return err } return nil } func main() { out := make(chan string) defer close(out) go func() { for { str, ok := <-out if !ok { break } fmt.Println(str) } }() args := []string{"-c", "ping www.5bug.wang"} if err := RunCommand(out, "bash", args...); err != nil { return } }
执行效果如下: