github.com/vmware/govmomi@v0.51.0/cli/vm/guest/ps.go (about) 1 // © Broadcom. All Rights Reserved. 2 // The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. 3 // SPDX-License-Identifier: Apache-2.0 4 5 package guest 6 7 import ( 8 "context" 9 "flag" 10 "fmt" 11 "io" 12 "strconv" 13 "strings" 14 "text/tabwriter" 15 "time" 16 17 "github.com/vmware/govmomi/cli" 18 "github.com/vmware/govmomi/cli/flags" 19 "github.com/vmware/govmomi/vim25/types" 20 ) 21 22 type ps struct { 23 *flags.OutputFlag 24 *GuestFlag 25 26 every bool 27 exit bool 28 wait bool 29 30 pids pidSelector 31 uids uidSelector 32 } 33 34 type pidSelector []int64 35 36 func (s *pidSelector) String() string { 37 return fmt.Sprint(*s) 38 } 39 40 func (s *pidSelector) Set(value string) error { 41 v, err := strconv.ParseInt(value, 0, 64) 42 if err != nil { 43 return err 44 } 45 *s = append(*s, v) 46 return nil 47 } 48 49 type uidSelector map[string]bool 50 51 func (s uidSelector) String() string { 52 return "" 53 } 54 55 func (s uidSelector) Set(value string) error { 56 s[value] = true 57 return nil 58 } 59 60 func init() { 61 cli.Register("guest.ps", &ps{}) 62 } 63 64 func (cmd *ps) Register(ctx context.Context, f *flag.FlagSet) { 65 cmd.OutputFlag, ctx = flags.NewOutputFlag(ctx) 66 cmd.OutputFlag.Register(ctx, f) 67 68 cmd.GuestFlag, ctx = newGuestProcessFlag(ctx) 69 cmd.GuestFlag.Register(ctx, f) 70 71 cmd.uids = make(map[string]bool) 72 f.BoolVar(&cmd.every, "e", false, "Select all processes") 73 f.BoolVar(&cmd.exit, "x", false, "Output exit time and code") 74 f.BoolVar(&cmd.wait, "X", false, "Wait for process to exit") 75 f.Var(&cmd.pids, "p", "Select by process ID") 76 f.Var(&cmd.uids, "U", "Select by process UID") 77 } 78 79 func (cmd *ps) Process(ctx context.Context) error { 80 if err := cmd.OutputFlag.Process(ctx); err != nil { 81 return err 82 } 83 if err := cmd.GuestFlag.Process(ctx); err != nil { 84 return err 85 } 86 return nil 87 } 88 89 func (cmd *ps) Description() string { 90 return `List processes in VM. 91 92 By default, unless the '-e', '-p' or '-U' flag is specified, only processes owned 93 by the '-l' flag user are displayed. 94 95 The '-x' and '-X' flags only apply to processes started by vmware-tools, 96 such as those started with the govc guest.start command. 97 98 Examples: 99 govc guest.ps -vm $name 100 govc guest.ps -vm $name -e 101 govc guest.ps -vm $name -p 12345 102 govc guest.ps -vm $name -U root` 103 } 104 105 func running(procs []types.GuestProcessInfo) bool { 106 for _, p := range procs { 107 if p.EndTime == nil { 108 return true 109 } 110 } 111 return false 112 } 113 114 func (cmd *ps) list(ctx context.Context) ([]types.GuestProcessInfo, error) { 115 m, err := cmd.ProcessManager() 116 if err != nil { 117 return nil, err 118 } 119 120 auth := cmd.Auth() 121 122 for { 123 procs, err := m.ListProcesses(ctx, auth, cmd.pids) 124 if err != nil { 125 return nil, err 126 } 127 128 if cmd.wait && running(procs) { 129 <-time.After(time.Second) 130 continue 131 } 132 133 return procs, nil 134 } 135 } 136 137 func (cmd *ps) Run(ctx context.Context, f *flag.FlagSet) error { 138 procs, err := cmd.list(ctx) 139 if err != nil { 140 return err 141 } 142 143 r := &psResult{cmd, procs} 144 145 return cmd.WriteResult(r) 146 } 147 148 type psResult struct { 149 cmd *ps 150 ProcessInfo []types.GuestProcessInfo `json:"processInfo"` 151 } 152 153 func (r *psResult) Write(w io.Writer) error { 154 tw := tabwriter.NewWriter(w, 2, 0, 2, ' ', 0) 155 156 fmt.Fprintf(tw, "%s\t%s\t%s", "UID", "PID", "STIME") 157 if r.cmd.exit { 158 fmt.Fprintf(tw, "\t%s\t%s", "XTIME", "XCODE") 159 } 160 fmt.Fprint(tw, "\tCMD\n") 161 162 if len(r.cmd.pids) != 0 { 163 r.cmd.every = true 164 } 165 166 if !r.cmd.every && len(r.cmd.uids) == 0 { 167 r.cmd.uids[r.cmd.auth.Username] = true 168 } 169 170 for _, p := range r.ProcessInfo { 171 if r.cmd.every || r.cmd.uids[p.Owner] { 172 fmt.Fprintf(tw, "%s\t%d\t%s", p.Owner, p.Pid, p.StartTime.Format("15:04")) 173 if r.cmd.exit { 174 etime := "-" 175 ecode := "-" 176 if p.EndTime != nil { 177 etime = p.EndTime.Format("15:04") 178 ecode = strconv.Itoa(int(p.ExitCode)) 179 } 180 fmt.Fprintf(tw, "\t%s\t%s", etime, ecode) 181 } 182 fmt.Fprintf(tw, "\t%s\n", strings.TrimSpace(p.CmdLine)) 183 } 184 } 185 186 return tw.Flush() 187 }