func()

in manager/container.go [343:422]


func (cd *containerData) parsePsLine(line, cadvisorContainer string, inHostNamespace bool) (*v2.ProcessInfo, error) {
	const expectedFields = 13
	if len(line) == 0 {
		return nil, nil
	}

	info := v2.ProcessInfo{}
	var err error

	fields := strings.Fields(line)
	if len(fields) < expectedFields {
		return nil, fmt.Errorf("expected at least %d fields, found %d: output: %q", expectedFields, len(fields), line)
	}
	info.User = fields[0]
	info.StartTime = fields[3]
	info.Status = fields[8]
	info.RunningTime = fields[9]

	info.Pid, err = strconv.Atoi(fields[1])
	if err != nil {
		return nil, fmt.Errorf("invalid pid %q: %v", fields[1], err)
	}
	info.Ppid, err = strconv.Atoi(fields[2])
	if err != nil {
		return nil, fmt.Errorf("invalid ppid %q: %v", fields[2], err)
	}

	percentCPU, err := strconv.ParseFloat(fields[4], 32)
	if err != nil {
		return nil, fmt.Errorf("invalid cpu percent %q: %v", fields[4], err)
	}
	info.PercentCpu = float32(percentCPU)
	percentMem, err := strconv.ParseFloat(fields[5], 32)
	if err != nil {
		return nil, fmt.Errorf("invalid memory percent %q: %v", fields[5], err)
	}
	info.PercentMemory = float32(percentMem)

	info.RSS, err = strconv.ParseUint(fields[6], 0, 64)
	if err != nil {
		return nil, fmt.Errorf("invalid rss %q: %v", fields[6], err)
	}
	info.VirtualSize, err = strconv.ParseUint(fields[7], 0, 64)
	if err != nil {
		return nil, fmt.Errorf("invalid virtual size %q: %v", fields[7], err)
	}
	// convert to bytes
	info.RSS *= 1024
	info.VirtualSize *= 1024

	// According to `man ps`: The following user-defined format specifiers may contain spaces: args, cmd, comm, command,
	// fname, ucmd, ucomm, lstart, bsdstart, start.
	// Therefore we need to be able to parse comm that consists of multiple space-separated parts.
	info.Cmd = strings.Join(fields[10:len(fields)-2], " ")

	// These are last two parts of the line. We create a subslice of `fields` to handle comm that includes spaces.
	lastTwoFields := fields[len(fields)-2:]
	info.Psr, err = strconv.Atoi(lastTwoFields[0])
	if err != nil {
		return nil, fmt.Errorf("invalid psr %q: %v", lastTwoFields[0], err)
	}
	info.CgroupPath = cd.getCgroupPath(lastTwoFields[1])

	// Remove the ps command we just ran from cadvisor container.
	// Not necessary, but makes the cadvisor page look cleaner.
	if !inHostNamespace && cadvisorContainer == info.CgroupPath && info.Cmd == "ps" {
		return nil, nil
	}

	// Do not report processes from other containers when non-root container requested.
	if !cd.isRoot() && info.CgroupPath != cd.info.Name {
		return nil, nil
	}

	// Remove cgroup information when non-root container requested.
	if !cd.isRoot() {
		info.CgroupPath = ""
	}
	return &info, nil
}