当我们想杀死一个进程及其所创建的所有子进程,我们可以使用 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 }