里用ping进程为例,在main函数中创建ping程序,然后将ping的执行结果通过管道(pipe)传递给主程序.主程序读取结果,然后打印,最后通过主程序发送系统信号(syscall.Signal)来结束ping.
cmd1 := exec.Command("ping", "") //创建子进程 ppReader, err := cmd1.StdoutPipe() //创建管道,ppReader为io.ReaderCloser类型 var bufReader = bufio.NewReader(ppReader) //创建带缓冲的Reader if err != nil { fmt.Printf("create cmd stdoutpipe failed,error:%sn", err) os.Exit(1) } err = cmd1.Start() //启动cmd1 if err != nil { fmt.Printf("cannot start cmd1,error:%sn", err) os.Exit(1) }
创建协程读取输出通过管道传输的数据
go func() { var buffer []byte = make([]byte, 4096) for { n, err := bufReader.Read(buffer) //读取数据到buffer中 if err != nil { if err == io.EOF { //管道关闭后会出现io.EOF错误 fmt.Printf("pipi has Closedn") break } else { fmt.Println("Read content failed") } } fmt.Print(string(buffer[:n])) } }()
主程序发送信号给子进程,停止cmd1的运行
time.Sleep(10 * time.Second) //让子进程运行10秒 err = stopProcess(cmd1) // 停止子进程 if err != nil { fmt.Printf("stop child process failed,error:%s", err) os.Exit(1) } cmd1.Wait() //能让cmd1执行到结束,测试stopProcess是否成功,如果没有stopProcess,程序和子进程会一直执行 time.Sleep(1 * time.Second) //让协程能读取关闭子进程时最后一次传输的数据
stopProcess的内容
func stopProcess(cmd *exec.Cmd) error { pro, err := os.FindProcess(cmd.Process.Pid) //通过pid获取子进程 if err != nil { return err } err = pro.Signal(syscall.SIGINT) //给子进程发送信号使之结束 if err != nil { return err } fmt.Printf("结束子进程%s成功n", cmd.Path) return nil}
完整代码段
package main import ( "bufio" "fmt" "io" "os" "os/exec" "time" "syscall") func main() { cmd1 := exec.Command("ping", "") ppReader, err := cmd1.StdoutPipe() defer ppReader.Close() var bufReader = bufio.NewReader(ppReader) if err != nil { fmt.Printf("create cmd stdoutpipe failed,error:%sn", err) os.Exit(1) } err = cmd1.Start() if err != nil { fmt.Printf("cannot start cmd1,error:%sn", err) os.Exit(1) } go func() { var buffer []byte = make([]byte, 4096) for { n, err := bufReader.Read(buffer) if err != nil { if err == io.EOF { fmt.Printf("pipi has Closedn") break } else { fmt.Println("Read content failed") } } fmt.Print(string(buffer[:n])) } }() time.Sleep(10 * time.Second) err = stopProcess(cmd1) if err != nil { fmt.Printf("stop child process failed,error:%s", err) os.Exit(1) } cmd1.Wait() time.Sleep(1 * time.Second) } func stopProcess(cmd *exec.Cmd) error { pro, err := os.FindProcess(cmd.Process.Pid) if err != nil { return err } err = pro.Signal(syscall.SIGINT) if err != nil { return err } fmt.Printf("结束子进程%s成功n", cmd.Path) return nil}
运行结果:
PING (180.97.33.107) 56(84) bytes of data.64 bytes from 180.97.33.107 (180.97.33.107): icmp_seq=1 ttl=55 time=35.3 ms64 bytes from 180.97.33.107 (180.97.33.107): icmp_seq=2 ttl=55 time=34.7 ms64 bytes from 180.97.33.107 (180.97.33.107): icmp_seq=3 ttl=55 time=34.2 ms64 bytes from 180.97.33.107 (180.97.33.107): icmp_seq=4 ttl=55 time=39.6 ms64 bytes from 180.97.33.107 (180.97.33.107): icmp_seq=5 ttl=55 time=34.4 ms64 bytes from 180.97.33.107 (180.97.33.107): icmp_seq=6 ttl=55 time=34.2 ms64 bytes from 180.97.33.107 (180.97.33.107): icmp_seq=7 ttl=55 time=34.2 ms64 bytes from 180.97.33.107 (180.97.33.107): icmp_seq=8 ttl=55 time=34.2 ms64 bytes from 180.97.33.107 (180.97.33.107): icmp_seq=9 ttl=55 time=34.2 ms64 bytes from 180.97.33.107 (180.97.33.107): icmp_seq=10 ttl=55 time=34.2 ms 结束子进程/bin/ping成功 --- ping statistics ---10 packets transmitted, 10 received, 0% packet loss, time 9012ms rtt min/avg/max/mdev = 34.206/34.967/39.689/1.632 ms pipi has Closed Process finished with exit code 0