1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package server
17
18 import (
19 "context"
20 "fmt"
21 "strings"
22
23 "github.com/pkg/errors"
24 v1 "k8s.io/api/core/v1"
25
26 "github.com/chaos-mesh/chaos-mesh/pkg/bpm"
27 "github.com/chaos-mesh/chaos-mesh/pkg/ctrl/server/model"
28 )
29
30
31 func (r *Resolver) GetPidFromPS(ctx context.Context, pod *v1.Pod) ([]*model.Process, error) {
32 cmd := "ps"
33 out, err := r.ExecBypass(ctx, pod, cmd, bpm.PidNS, bpm.MountNS)
34 if err != nil {
35 return nil, errors.Wrapf(err, "run command %s failed", cmd)
36 }
37 outLines := strings.Split(string(out), "\n")
38 if len(outLines) < 2 {
39 return nil, errors.New("ps returns empty")
40 }
41 titles := strings.Fields(outLines[0])
42 var pidColumn, cmdColumn int
43 for i, t := range titles {
44 if t == "PID" {
45 pidColumn = i
46 }
47 if t == "COMMAND" || t == "CMD" {
48 cmdColumn = i
49 }
50 }
51 if pidColumn == 0 && cmdColumn == 0 {
52 return nil, errors.New("parsing ps error: could not get PID and COMMAND column")
53 }
54
55 var processes []*model.Process
56 for _, line := range outLines[1:] {
57 item := strings.Fields(line)
58
59 if len(item) == 0 {
60 break
61 }
62 if item[cmdColumn] == cmd {
63 continue
64 }
65 processes = append(processes, &model.Process{
66 Pod: pod,
67 Pid: item[pidColumn],
68 Command: item[cmdColumn],
69 })
70 }
71 return processes, nil
72 }
73
74
75 func (r *Resolver) killProcess(ctx context.Context, pod *v1.Pod, pids []string) ([]*model.KillProcessResult, error) {
76 pidSet := make(map[string]bool)
77 for _, pid := range pids {
78 pidSet[pid] = true
79 }
80
81
82 allProcess, err := r.GetPidFromPS(ctx, pod)
83 if err != nil {
84 return nil, errors.Wrapf(err, "get process on pod %s/%s", pod.Namespace, pod.Name)
85 }
86
87
88 var pidList []string
89 var killResults []*model.KillProcessResult
90
91 for _, process := range allProcess {
92 if _, ok := pidSet[process.Pid]; ok {
93 pidList = append(pidList, process.Pid)
94 killResults = append(killResults, &model.KillProcessResult{
95 Pid: process.Pid,
96 Command: process.Command,
97 })
98 }
99 }
100 if len(pidList) == 0 {
101 return nil, nil
102 }
103 cmd := fmt.Sprintf("kill %s", strings.Join(pids, " "))
104 if _, err = r.ExecBypass(ctx, pod, cmd, bpm.PidNS, bpm.MountNS); err != nil {
105 return nil, errors.Wrapf(err, "run command %s", cmd)
106 }
107 return killResults, nil
108 }
109