...
1 package main
2
3 import (
4 "encoding/json"
5 "errors"
6 "fmt"
7 "os"
8 "os/exec"
9 "strconv"
10 "strings"
11
12 "github.com/sirupsen/logrus"
13 "github.com/urfave/cli"
14 )
15
16 var psCommand = cli.Command{
17 Name: "ps",
18 Usage: "ps displays the processes running inside a container",
19 ArgsUsage: `<container-id> [ps options]`,
20 Flags: []cli.Flag{
21 cli.StringFlag{
22 Name: "format, f",
23 Value: "table",
24 Usage: `select one of: ` + formatOptions,
25 },
26 },
27 Action: func(context *cli.Context) error {
28 if err := checkArgs(context, 1, minArgs); err != nil {
29 return err
30 }
31 rootlessCg, err := shouldUseRootlessCgroupManager(context)
32 if err != nil {
33 return err
34 }
35 if rootlessCg {
36 logrus.Warn("runc ps may fail if you don't have the full access to cgroups")
37 }
38
39 container, err := getContainer(context)
40 if err != nil {
41 return err
42 }
43
44 pids, err := container.Processes()
45 if err != nil {
46 return err
47 }
48
49 switch context.String("format") {
50 case "table":
51 case "json":
52 return json.NewEncoder(os.Stdout).Encode(pids)
53 default:
54 return errors.New("invalid format option")
55 }
56
57
58
59
60
61 psArgs := context.Args()[1:]
62 if len(psArgs) == 0 {
63 psArgs = []string{"-ef"}
64 }
65
66 cmd := exec.Command("ps", psArgs...)
67 output, err := cmd.CombinedOutput()
68 if err != nil {
69 return fmt.Errorf("%w: %s", err, output)
70 }
71
72 lines := strings.Split(string(output), "\n")
73 pidIndex, err := getPidIndex(lines[0])
74 if err != nil {
75 return err
76 }
77
78 fmt.Println(lines[0])
79 for _, line := range lines[1:] {
80 if len(line) == 0 {
81 continue
82 }
83 fields := strings.Fields(line)
84 p, err := strconv.Atoi(fields[pidIndex])
85 if err != nil {
86 return fmt.Errorf("unable to parse pid: %w", err)
87 }
88
89 for _, pid := range pids {
90 if pid == p {
91 fmt.Println(line)
92 break
93 }
94 }
95 }
96 return nil
97 },
98 SkipArgReorder: true,
99 }
100
101 func getPidIndex(title string) (int, error) {
102 titles := strings.Fields(title)
103
104 pidIndex := -1
105 for i, name := range titles {
106 if name == "PID" {
107 return i, nil
108 }
109 }
110
111 return pidIndex, errors.New("couldn't find PID field in ps output")
112 }
113
View as plain text