mirror of
https://github.com/containers/podman
synced 2024-10-18 16:24:34 +00:00
libpod: Add support for 'podman top' on FreeBSD
This simply runs ps(1) on the host and filters for processes inside the container. [NO NEW TESTS NEEDED] Signed-off-by: Doug Rabson <dfr@rabson.org>
This commit is contained in:
parent
21081355a7
commit
9e6b37ec1d
131
libpod/container_top_freebsd.go
Normal file
131
libpod/container_top_freebsd.go
Normal file
|
@ -0,0 +1,131 @@
|
|||
//go:build freebsd
|
||||
// +build freebsd
|
||||
|
||||
package libpod
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/containers/podman/v4/libpod/define"
|
||||
"github.com/containers/podman/v4/pkg/util"
|
||||
"github.com/google/shlex"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
var isDescriptor = map[string]bool{}
|
||||
|
||||
func init() {
|
||||
allDescriptors, err := util.GetContainerPidInformationDescriptors()
|
||||
if err != nil {
|
||||
// Should never happen
|
||||
logrus.Debugf("failed call to util.GetContainerPidInformationDescriptors()")
|
||||
return
|
||||
}
|
||||
for _, d := range allDescriptors {
|
||||
isDescriptor[d] = true
|
||||
}
|
||||
}
|
||||
|
||||
// Top gathers statistics about the running processes in a container. It returns a
|
||||
// []string for output
|
||||
func (c *Container) Top(descriptors []string) ([]string, error) {
|
||||
conStat, err := c.State()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to look up state for %s: %w", c.ID(), err)
|
||||
}
|
||||
if conStat != define.ContainerStateRunning {
|
||||
return nil, errors.New("top can only be used on running containers")
|
||||
}
|
||||
|
||||
// Default to 'ps -ef' compatible descriptors
|
||||
if len(descriptors) == 0 {
|
||||
descriptors = []string{"user", "pid", "ppid", "pcpu", "etime", "tty", "time", "args"}
|
||||
}
|
||||
|
||||
// If everything in descriptors is a supported AIX format
|
||||
// descriptor, we use 'ps -ao <descriptors>', otherwise we pass
|
||||
// everything straight through to ps.
|
||||
supportedDescriptors := true
|
||||
for _, d := range descriptors {
|
||||
if _, ok := isDescriptor[d]; !ok {
|
||||
supportedDescriptors = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if supportedDescriptors {
|
||||
descriptors = []string{"-ao", strings.Join(descriptors, ",")}
|
||||
}
|
||||
|
||||
// Note that the descriptors to ps(1) must be shlexed (see #12452).
|
||||
psDescriptors := []string{}
|
||||
for _, d := range descriptors {
|
||||
shSplit, err := shlex.Split(d)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("parsing ps args: %w", err)
|
||||
}
|
||||
for _, s := range shSplit {
|
||||
if s != "" {
|
||||
psDescriptors = append(psDescriptors, s)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
args := []string{
|
||||
"-J",
|
||||
c.jailName(),
|
||||
}
|
||||
args = append(args, psDescriptors...)
|
||||
|
||||
output, err := c.execPS(args)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("executing ps(1): %w", err)
|
||||
}
|
||||
|
||||
return output, nil
|
||||
}
|
||||
|
||||
func (c *Container) execPS(args []string) ([]string, error) {
|
||||
cmd := exec.Command("ps", args...)
|
||||
stdoutPipe, err := cmd.StdoutPipe()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
stderrPipe, err := cmd.StderrPipe()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(2)
|
||||
stdout := []string{}
|
||||
go func() {
|
||||
scanner := bufio.NewScanner(stdoutPipe)
|
||||
for scanner.Scan() {
|
||||
stdout = append(stdout, scanner.Text())
|
||||
}
|
||||
wg.Done()
|
||||
}()
|
||||
stderr := []string{}
|
||||
go func() {
|
||||
scanner := bufio.NewScanner(stderrPipe)
|
||||
for scanner.Scan() {
|
||||
stderr = append(stderr, scanner.Text())
|
||||
}
|
||||
wg.Done()
|
||||
}()
|
||||
|
||||
if err := cmd.Start(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
wg.Wait()
|
||||
if err := cmd.Wait(); err != nil {
|
||||
return nil, fmt.Errorf("ps(1) command failed: %w, output: %s", err, strings.Join(stderr, " "))
|
||||
}
|
||||
|
||||
return stdout, nil
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
//go:build !linux
|
||||
// +build !linux
|
||||
//go:build !linux && !freebsd
|
||||
// +build !linux,!freebsd
|
||||
|
||||
package libpod
|
||||
|
||||
|
|
Loading…
Reference in a new issue