mirror of
https://github.com/containers/podman.git
synced 2025-08-06 19:44:14 +08:00
Vendor changes to psgo
Signed-off-by: haircommander <pehunt@redhat.com> Closes: #1298 Approved by: mheon
This commit is contained in:

committed by
Atomic Bot

parent
c32074fa4f
commit
f11020702d
19
vendor/github.com/containers/psgo/README.md
generated
vendored
19
vendor/github.com/containers/psgo/README.md
generated
vendored
@ -10,9 +10,15 @@ This library aims to make things a bit more comfortable, especially for containe
|
|||||||
- `psgo.ProcessInfo(descriptors []string) ([][]string, error)`
|
- `psgo.ProcessInfo(descriptors []string) ([][]string, error)`
|
||||||
- ProcessInfo returns the process information of all processes in the current mount namespace. The input descriptors must be a slice of supported AIX format descriptors in the normal form or in the code form, if supported. If the input descriptor slice is empty, the `psgo.DefaultDescriptors` are used. The return value contains the string slice of process data, one per process.
|
- ProcessInfo returns the process information of all processes in the current mount namespace. The input descriptors must be a slice of supported AIX format descriptors in the normal form or in the code form, if supported. If the input descriptor slice is empty, the `psgo.DefaultDescriptors` are used. The return value contains the string slice of process data, one per process.
|
||||||
|
|
||||||
|
- `psgo.ProcessInfoByPids(pids []string, descriptors []string) ([][]string, error)`
|
||||||
|
- ProcessInfoByPids is similar to `psgo.ProcessInfo`, but limits the return value to a list of specified pids. The pids input must be a slice of PIDs for which process information should be returned. If the input descriptor slice is empty, only the format descriptor headers are returned.
|
||||||
|
|
||||||
- `psgo.JoinNamespaceAndProcessInfo(pid string, descriptors []string) ([][]string, error)`
|
- `psgo.JoinNamespaceAndProcessInfo(pid string, descriptors []string) ([][]string, error)`
|
||||||
- JoinNamespaceAndProcessInfo has the same semantics as ProcessInfo but joins the mount namespace of the specified pid before extracting data from /proc. This way, we can extract the `/proc` data from a container without executing any command inside the container.
|
- JoinNamespaceAndProcessInfo has the same semantics as ProcessInfo but joins the mount namespace of the specified pid before extracting data from /proc. This way, we can extract the `/proc` data from a container without executing any command inside the container.
|
||||||
|
|
||||||
|
- `psgo.JoinNamespaceAndProcessInfoByPids(pids []string, descriptors []string) ([][]string, error)`
|
||||||
|
- JoinNamespaceAndProcessInfoByPids is similar to `psgo.JoinNamespaceAndProcessInfo` but takes a slice of pids as an argument. To avoid duplicate entries (e.g., when two or more containers share the same PID namespace), a given PID namespace will be joined only once.
|
||||||
|
|
||||||
- `psgo.ListDescriptors() []string`
|
- `psgo.ListDescriptors() []string`
|
||||||
- ListDescriptors returns a sorted string slice of all supported AIX format descriptors in the normal form (e.g., "args,comm,user"). It can be useful in the context of bash-completion, help messages, etc.
|
- ListDescriptors returns a sorted string slice of all supported AIX format descriptors in the normal form (e.g., "args,comm,user"). It can be useful in the context of bash-completion, help messages, etc.
|
||||||
|
|
||||||
@ -28,6 +34,17 @@ root 4 2 0.000 6h3m27.678701852s ? 0s
|
|||||||
root 6 2 0.000 6h3m27.678999508s ? 0s [mm_percpu_wq]
|
root 6 2 0.000 6h3m27.678999508s ? 0s [mm_percpu_wq]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Listing processes
|
||||||
|
You can use the `--pids` flag to restrict `psgo` output to a subset of processes. This option accepts a list of comma separate process IDs and will return exactly the same kind of information per process as the default output.
|
||||||
|
|
||||||
|
```
|
||||||
|
$ ./bin/psgo --pids 1,$(pgrep bash | tr "\n" ",")
|
||||||
|
USER PID PPID %CPU ELAPSED TTY TIME COMMAND
|
||||||
|
root 1 0 0.009 128h52m44.193475932s ? 40s systemd
|
||||||
|
root 20830 20827 0.000 105h2m44.19579679s pts/5 0s bash
|
||||||
|
root 25843 25840 0.000 102h56m4.196072027s pts/6 0s bash
|
||||||
|
```
|
||||||
|
|
||||||
### Listing processes within a container
|
### Listing processes within a container
|
||||||
Let's have a look at how we can use this library in the context of containers. As a simple show case, we'll start a Docker container, extract the process ID via `docker-inspect` and run the `psgo` binary to extract the data of running processes within that container.
|
Let's have a look at how we can use this library in the context of containers. As a simple show case, we'll start a Docker container, extract the process ID via `docker-inspect` and run the `psgo` binary to extract the data of running processes within that container.
|
||||||
|
|
||||||
@ -38,7 +55,7 @@ $ docker run -d alpine sleep 100
|
|||||||
$ docker inspect --format '{{.State.Pid}}' 473c9
|
$ docker inspect --format '{{.State.Pid}}' 473c9
|
||||||
5572
|
5572
|
||||||
|
|
||||||
$ sudo ./bin/psgo -pid 5572
|
$ sudo ./bin/psgo -pids 5572 -join
|
||||||
USER PID PPID %CPU ELAPSED TTY TIME COMMAND
|
USER PID PPID %CPU ELAPSED TTY TIME COMMAND
|
||||||
root 1 0 0.000 17.249905587s ? 0s sleep
|
root 1 0 0.000 17.249905587s ? 0s sleep
|
||||||
```
|
```
|
||||||
|
64
vendor/github.com/containers/psgo/psgo.go
generated
vendored
64
vendor/github.com/containers/psgo/psgo.go
generated
vendored
@ -80,7 +80,7 @@ func translateDescriptors(descriptors []string) ([]aixFormatDescriptor, error) {
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
// DefaultDescriptors is the `ps -ef` compatible default format.
|
// DefaultDescriptors is the `ps -ef` compatible default format.
|
||||||
DefaultDescriptors = []string{"user", "pid", "ppid", "pcpu", "etime", "tty", "time", "comm"}
|
DefaultDescriptors = []string{"user", "pid", "ppid", "pcpu", "etime", "tty", "time", "args"}
|
||||||
|
|
||||||
// ErrUnkownDescriptor is returned when an unknown descriptor is parsed.
|
// ErrUnkownDescriptor is returned when an unknown descriptor is parsed.
|
||||||
ErrUnkownDescriptor = errors.New("unknown descriptor")
|
ErrUnkownDescriptor = errors.New("unknown descriptor")
|
||||||
@ -334,6 +334,48 @@ func JoinNamespaceAndProcessInfo(pid string, descriptors []string) ([][]string,
|
|||||||
return data, dataErr
|
return data, dataErr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// JoinNamespaceAndProcessInfoByPids has similar semantics to
|
||||||
|
// JoinNamespaceAndProcessInfo and avoids duplicate entries by joining a giving
|
||||||
|
// PID namepsace only once.
|
||||||
|
func JoinNamespaceAndProcessInfoByPids(pids []string, descriptors []string) ([][]string, error) {
|
||||||
|
// Extracting data from processes that share the same PID namespace
|
||||||
|
// would yield duplicate results. Avoid that by extracting data only
|
||||||
|
// from the first process in `pids` from a given PID namespace.
|
||||||
|
// `nsMap` is used for quick lookups if a given PID namespace is
|
||||||
|
// already covered, `pidList` is used to preserve the order which is
|
||||||
|
// not guaranteed by nondeterministic maps in golang.
|
||||||
|
nsMap := make(map[string]bool)
|
||||||
|
pidList := []string{}
|
||||||
|
for _, pid := range pids {
|
||||||
|
ns, err := proc.ParsePIDNamespace(pid)
|
||||||
|
if err != nil {
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
// catch race conditions
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return nil, errors.Wrapf(err, "error extracing PID namespace")
|
||||||
|
}
|
||||||
|
if _, exists := nsMap[ns]; !exists {
|
||||||
|
nsMap[ns] = true
|
||||||
|
pidList = append(pidList, pid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data := [][]string{}
|
||||||
|
for i, pid := range pidList {
|
||||||
|
pidData, err := JoinNamespaceAndProcessInfo(pid, descriptors)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if i == 0 {
|
||||||
|
data = append(data, pidData[0])
|
||||||
|
}
|
||||||
|
data = append(data, pidData[1:]...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return data, nil
|
||||||
|
}
|
||||||
|
|
||||||
// ProcessInfo returns the process information of all processes in the current
|
// ProcessInfo returns the process information of all processes in the current
|
||||||
// mount namespace. The input format must be a comma-separated list of
|
// mount namespace. The input format must be a comma-separated list of
|
||||||
// supported AIX format descriptors. If the input string is empty, the
|
// supported AIX format descriptors. If the input string is empty, the
|
||||||
@ -341,12 +383,18 @@ func JoinNamespaceAndProcessInfo(pid string, descriptors []string) ([][]string,
|
|||||||
// The return value is an array of tab-separated strings, to easily use the
|
// The return value is an array of tab-separated strings, to easily use the
|
||||||
// output for column-based formatting (e.g., with the `text/tabwriter` package).
|
// output for column-based formatting (e.g., with the `text/tabwriter` package).
|
||||||
func ProcessInfo(descriptors []string) ([][]string, error) {
|
func ProcessInfo(descriptors []string) ([][]string, error) {
|
||||||
aixDescriptors, err := translateDescriptors(descriptors)
|
pids, err := proc.GetPIDs()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
pids, err := proc.GetPIDs()
|
return ProcessInfoByPids(pids, descriptors)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProcessInfoByPids is like ProcessInfo, but the process information returned
|
||||||
|
// is limited to a list of user specified PIDs.
|
||||||
|
func ProcessInfoByPids(pids []string, descriptors []string) ([][]string, error) {
|
||||||
|
aixDescriptors, err := translateDescriptors(descriptors)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -470,22 +518,20 @@ func processName(p *process.Process) (string, error) {
|
|||||||
|
|
||||||
// processARGS returns the command of p with all its arguments.
|
// processARGS returns the command of p with all its arguments.
|
||||||
func processARGS(p *process.Process) (string, error) {
|
func processARGS(p *process.Process) (string, error) {
|
||||||
args := p.CmdLine
|
|
||||||
// ps (1) returns "[$name]" if command/args are empty
|
// ps (1) returns "[$name]" if command/args are empty
|
||||||
if len(args) == 0 {
|
if p.CmdLine[0] == "" {
|
||||||
return processName(p)
|
return processName(p)
|
||||||
}
|
}
|
||||||
return strings.Join(args, " "), nil
|
return strings.Join(p.CmdLine, " "), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// processCOMM returns the command name (i.e., executable name) of process p.
|
// processCOMM returns the command name (i.e., executable name) of process p.
|
||||||
func processCOMM(p *process.Process) (string, error) {
|
func processCOMM(p *process.Process) (string, error) {
|
||||||
args := p.CmdLine
|
|
||||||
// ps (1) returns "[$name]" if command/args are empty
|
// ps (1) returns "[$name]" if command/args are empty
|
||||||
if len(args) == 0 {
|
if p.CmdLine[0] == "" {
|
||||||
return processName(p)
|
return processName(p)
|
||||||
}
|
}
|
||||||
spl := strings.Split(args[0], "/")
|
spl := strings.Split(p.CmdLine[0], "/")
|
||||||
return spl[len(spl)-1], nil
|
return spl[len(spl)-1], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user