podman

Форк
0
/
container_top_freebsd.go 
135 строк · 3.0 Кб
1
//go:build !remote
2

3
package libpod
4

5
import (
6
	"bufio"
7
	"errors"
8
	"fmt"
9
	"os/exec"
10
	"strings"
11
	"sync"
12

13
	"github.com/containers/podman/v5/libpod/define"
14
	"github.com/containers/podman/v5/pkg/util"
15
	"github.com/google/shlex"
16
	"github.com/sirupsen/logrus"
17
)
18

19
var isDescriptor = map[string]bool{}
20

21
func init() {
22
	allDescriptors, err := util.GetContainerPidInformationDescriptors()
23
	if err != nil {
24
		// Should never happen
25
		logrus.Debugf("failed call to util.GetContainerPidInformationDescriptors()")
26
		return
27
	}
28
	for _, d := range allDescriptors {
29
		isDescriptor[d] = true
30
	}
31
}
32

33
// Top gathers statistics about the running processes in a container. It returns a
34
// []string for output
35
func (c *Container) Top(descriptors []string) ([]string, error) {
36
	conStat, err := c.State()
37
	if err != nil {
38
		return nil, fmt.Errorf("unable to look up state for %s: %w", c.ID(), err)
39
	}
40
	if conStat != define.ContainerStateRunning {
41
		return nil, errors.New("top can only be used on running containers")
42
	}
43

44
	// Default to 'ps -ef' compatible descriptors
45
	if len(strings.Join(descriptors, "")) == 0 {
46
		descriptors = []string{"user", "pid", "ppid", "pcpu", "etime", "tty", "time", "args"}
47
	}
48

49
	// If everything in descriptors is a supported AIX format
50
	// descriptor, we use 'ps -ao <descriptors>', otherwise we pass
51
	// everything straight through to ps.
52
	supportedDescriptors := true
53
	for _, d := range descriptors {
54
		if _, ok := isDescriptor[d]; !ok {
55
			supportedDescriptors = false
56
			break
57
		}
58
	}
59
	if supportedDescriptors {
60
		descriptors = []string{"-ao", strings.Join(descriptors, ",")}
61
	}
62

63
	// Note that the descriptors to ps(1) must be shlexed (see #12452).
64
	psDescriptors := []string{}
65
	for _, d := range descriptors {
66
		shSplit, err := shlex.Split(d)
67
		if err != nil {
68
			return nil, fmt.Errorf("parsing ps args: %w", err)
69
		}
70
		for _, s := range shSplit {
71
			if s != "" {
72
				psDescriptors = append(psDescriptors, s)
73
			}
74
		}
75
	}
76

77
	jailName, err := c.jailName()
78
	if err != nil {
79
		return nil, fmt.Errorf("getting jail name: %w", err)
80
	}
81

82
	args := []string{
83
		"-J",
84
		jailName,
85
	}
86
	args = append(args, psDescriptors...)
87

88
	output, err := execPS(args)
89
	if err != nil {
90
		return nil, fmt.Errorf("executing ps(1): %w", err)
91
	}
92

93
	return output, nil
94
}
95

96
func execPS(args []string) ([]string, error) {
97
	cmd := exec.Command("ps", args...)
98
	stdoutPipe, err := cmd.StdoutPipe()
99
	if err != nil {
100
		return nil, err
101
	}
102
	stderrPipe, err := cmd.StderrPipe()
103
	if err != nil {
104
		return nil, err
105
	}
106

107
	var wg sync.WaitGroup
108
	wg.Add(2)
109
	stdout := []string{}
110
	go func() {
111
		scanner := bufio.NewScanner(stdoutPipe)
112
		for scanner.Scan() {
113
			stdout = append(stdout, scanner.Text())
114
		}
115
		wg.Done()
116
	}()
117
	stderr := []string{}
118
	go func() {
119
		scanner := bufio.NewScanner(stderrPipe)
120
		for scanner.Scan() {
121
			stderr = append(stderr, scanner.Text())
122
		}
123
		wg.Done()
124
	}()
125

126
	if err := cmd.Start(); err != nil {
127
		return nil, err
128
	}
129
	wg.Wait()
130
	if err := cmd.Wait(); err != nil {
131
		return nil, fmt.Errorf("ps(1) command failed: %w, output: %s", err, strings.Join(stderr, " "))
132
	}
133

134
	return stdout, nil
135
}
136

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.