当我们想杀死一个进程及其所创建的所有子进程,我们可以使用 linux 命令 kill -- -pid
执行 tail -f ./text.log| grep -a "5t6hwhu1" >../a330fec0-f946-5e47-1be3-5c42ef040c78.tmp
⇒ ps -lf UID PID PPID F CPU PRI NI SZ RSS WCHAN S ADDR TTY TIME CMD STIME 501 407 323 4006 0 31 0 4337800 14192 - Ss 0 ttys000 0:00.03 /Applications/iT 8:45上午 501 411 409 4006 0 31 0 4334036 2472 - S+ 0 ttys000 0:00.85 -zsh 8:45上午 501 1421 1418 4006 0 31 0 4334036 1412 - Ss+ 0 ttys001 0:00.31 zsh -l 9:28上午 501 635 630 4006 0 31 0 4334036 1396 - Ss+ 0 ttys002 0:00.38 zsh -l 8:45上午 501 1517 323 4006 0 31 0 4347016 14192 - Ss 0 ttys003 0:00.04 /Applications/iT 9:33上午 501 1519 1518 4006 0 31 0 4337016 4088 - S 0 ttys003 0:01.25 -zsh 9:33上午 501 3919 1418 4006 0 31 0 4334036 3972 - Ss 0 ttys004 0:00.56 zsh -l 11:48上午 501 6550 3919 4006 0 31 0 4277244 700 - S+ 0 ttys004 0:00.00 tail -f ./text.l 12:33下午 501 6551 3919 4006 0 31 0 4268036 812 - S+ 0 ttys004 0:00.00 grep --color=aut 12:33下午
会发现生成了两个进程,一个是tail(pid:6550),另一个是grep(pid:6551),我们想杀死这两个进程, kill -- -6550
golang中我们想执行 tail -f ./text.log| grep -a "5t6hwhu1" >../a330fec0-f946-5e47-1be3-5c42ef040c78.tmp,发现会生成三个进程
⇒ ps -lf UID PID PPID F CPU PRI NI SZ RSS WCHAN S ADDR TTY TIME CMD STIME 501 407 323 4006 0 31 0 4337800 14192 - Ss 0 ttys000 0:00.03 /Applications/iT 8:45上午 501 411 409 4006 0 31 0 4334036 1440 - S+ 0 ttys000 0:00.85 -zsh 8:45上午 501 1421 1418 4006 0 31 0 4334036 1412 - Ss+ 0 ttys001 0:00.31 zsh -l 9:28上午 501 635 630 4006 0 31 0 4334036 1396 - Ss+ 0 ttys002 0:00.38 zsh -l 8:45上午 501 1517 323 4006 0 31 0 4347016 14192 - Ss 0 ttys003 0:00.04 /Applications/iT 9:33上午 501 1519 1518 4006 0 31 0 4337016 4012 - S 0 ttys003 0:01.34 -zsh 9:33上午 501 3919 1418 4006 0 31 0 4334036 3944 - Ss 0 ttys004 0:00.61 zsh -l 11:48上午 501 6715 3919 4006 0 31 0 4371416 2344 - S+ 0 ttys004 0:00.01 ./test 12:40下午 501 6716 6715 4006 0 31 0 4268616 1100 - S 0 ttys004 0:00.00 bash -c tail -f 12:40下午 501 6717 6716 4006 0 31 0 4268028 684 - S 0 ttys004 0:00.00 tail -f ./text.l 12:40下午 501 6718 6716 4006 0 31 0 4277252 824 - S 0 ttys004 0:00.00 grep -a 5t6hwhu1 12:40下午
./test 进程生成了6716进程,6716生成了6717和6718进程,可以使用golang中syscall.Kill()
1 package main 2 3 import ( 4 "bytes" 5 "fmt" 6 "log" 7 "os" 8 "os/exec" 9 "strconv" 10 "syscall" 11 "time" 12 ) 13 14 func main() { 15 go Write() 16 go Process() 17 18 fmt.Println("goroutine is ok.") 19 time.Sleep(time.Second * 100) 20 } 21 22 // 非阻塞模式执行bash 23 func Process() { 24 // "bash", "-c", "./1.sh" 25 // 会启动两个进程 tail 和 一个 grep 进程,kill只会杀掉 3190 进程 26 // 501 3987 3986 4006 0 31 0 4268616 1100 - S 0 ttys004 0:00.00 bash -c tail -f 11:48上午 27 // 501 3988 3987 4006 0 31 0 4268028 684 - S 0 ttys004 0:00.00 tail -f ./text.l 11:48上午 28 // 501 3989 3987 4006 0 31 0 4270084 832 - S 0 ttys004 0:00.00 grep -a 5t6hwhu1 11:48上午 29 30 s := ` tail -f ./text.log| grep -a "5t6hwhu1" >../a330fec0-f946-5e47-1be3-5c42ef040c78.tmp` 31 cmd := exec.Command("bash", "-c", s) 32 33 // Go会将PGID设置成与PID相同的值 34 cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true} 35 36 r, err := cmd.StdoutPipe() 37 if err != nil { 38 fmt.Println("stdout pipe is failed, err:", err) 39 } 40 41 err = cmd.Start() 42 if err != nil { 43 log.Fatal(err) 44 } 45 46 go KillProcess(cmd) 47 48 p := make([]byte, 1024*4) 49 for { 50 time.Sleep(time.Second * 1) 51 n, err := r.Read(p) 52 if err != nil { 53 fmt.Println("read is failed, err:", err) 54 break 55 } 56 57 // 如果分隔符的为最后一位,则会分割出来两个数组,第二个数组长度为0 58 lines := bytes.Split(p[0:n], []byte("\n")) 59 for _, line := range lines { 60 if len(line) <= 0 { 61 continue 62 } 63 64 // 新的一行内容 65 } 66 67 fmt.Println("---n=", n, cmd.Process.Pid, "read=", string(p[0:n]), "len(line)=", len(lines)) 68 } 69 70 // 可用 wait 等待 shell 执行结果 71 err = cmd.Wait() 72 } 73 74 func KillProcess(cmd *exec.Cmd) { 75 fmt.Println("sleep ~~~~") 76 time.Sleep(time.Second * 15) 77 78 err := syscall.Kill(-cmd.Process.Pid, syscall.SIGKILL) 79 if err != nil { 80 fmt.Println("kill process team is failed, err:", err) 81 } 82 fmt.Println("kill process team is ok") 83 84 // time.Sleep(time.Second * 10) 85 // 如果执行下面只会杀死 3987 进程, 3988、3989 还会存活 86 // err := cmd.Process.Kill() 87 // if err != nil { 88 // fmt.Println("kill is failed, err:", err) 89 // } 90 91 fmt.Println("kill tail. ") 92 } 93 94 func Write() { 95 f, err := os.OpenFile("./text.log", os.O_TRUNC|os.O_CREATE|os.O_RDWR, 0644) 96 if err != nil { 97 fmt.Println("open file is failed,err:", err) 98 } 99 100 for i := 0; i <= 100; i++ { 101 time.Sleep(time.Second * 2) 102 f.WriteString("write log " + strconv.Itoa(i) + "----------------------------------------cc\n") 103 } 104 }