这里用ping进程为例,在main函数中创建一个并发ping程序,然后将ping的执行结果通过管道(pipe)传递给主程序,主程序读取结果,然后打印,最后通过主程序发送系统信号(syscall.Signal)来结束ping。
创建子进程(并发 用IO口进行通信 走二进制码流)
cmd1 := exec.Command("ping", "www.baidu.com") //创建子进程
ppReader, err := cmd1.StdoutPipe()
//创建管道,ppReader为io.ReaderCloser类型
var bufReader = bufio.NewReader(ppReader) //创建带缓冲的Reader
if err != nil {
fmt.Printf("create cmd stdoutpipe failed,error:%s\n", err)
os.Exit(1) // 中断整个程序 属于异常处理
}
err = cmd1.Start() //启动cmd1
if err != nil {
fmt.Printf("cannot start cmd1,error:%s\n", 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 Closed\n")
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", "www.baidu.com")
ppReader, err := cmd1.StdoutPipe()
defer ppReader.Close()
var bufReader = bufio.NewReader(ppReader)
if err != nil {
fmt.Printf("create cmd stdoutpipe failed,error:%s\n", err)
os.Exit(1)
}
err = cmd1.Start()
if err != nil {
fmt.Printf("cannot start cmd1,error:%s\n", 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 Closed\n")
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 www.a.shifen.com (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 ms
64 bytes from 180.97.33.107 (180.97.33.107): icmp_seq=2 ttl=55 time=34.7 ms
64 bytes from 180.97.33.107 (180.97.33.107): icmp_seq=3 ttl=55 time=34.2 ms
64 bytes from 180.97.33.107 (180.97.33.107): icmp_seq=4 ttl=55 time=39.6 ms
64 bytes from 180.97.33.107 (180.97.33.107): icmp_seq=5 ttl=55 time=34.4 ms
64 bytes from 180.97.33.107 (180.97.33.107): icmp_seq=6 ttl=55 time=34.2 ms
64 bytes from 180.97.33.107 (180.97.33.107): icmp_seq=7 ttl=55 time=34.2 ms
64 bytes from 180.97.33.107 (180.97.33.107): icmp_seq=8 ttl=55 time=34.2 ms
64 bytes from 180.97.33.107 (180.97.33.107): icmp_seq=9 ttl=55 time=34.2 ms
64 bytes from 180.97.33.107 (180.97.33.107): icmp_seq=10 ttl=55 time=34.2 ms
结束子进程/bin/ping成功
--- www.a.shifen.com 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