shirou / gopsutil

psutil for golang
Other
10.47k stars 1.58k forks source link

Non-root user can't get process information #1567

Closed stephenzhang0713 closed 8 months ago

stephenzhang0713 commented 8 months ago

Describe the bug Non-root user can't get process information

To Reproduce

type ProcessState struct {
    CpuPercent float64  `json:"CpuPercent"`
    MemPercent float32  `json:"MemPercent"`
    CpuTime    float64  `json:"CpuTime"`
    Status     string   `json:"Status"`
    Ports      []uint32 `json:"Ports"`
    Pid        int32    `json:"Pid"`
    Name       string   `json:"Name"`
    Alive      int8     `json:"Alive"`
}

func collectAllProcessesData() (processStates []*ProcessState, err error) {
    var alive int8
    processes, err := process.Processes()
    if err != nil {
        fmt.Errorf("failed to get all processes: %v", err)
        return nil, err
    }
    seenPorts := make(map[uint32]bool)
    if len(processes) == 0 {
        fmt.Println("collectAllProcessesData process.Processes : %v", processes)
        return
    }
    for _, proc := range processes {
        procConnections, err := proc.Connections()
        if err != nil {
            fmt.Errorf("failed to get connections for pid %d: %v", proc.Pid, err)
            continue
        }

        var ports []uint32

        for _, conn := range procConnections {
            port := conn.Laddr.Port
            if !seenPorts[port] {
                seenPorts[port] = true
                ports = append(ports, port)
            }
        }

        if len(ports) == 0 {
            continue
        }

        isRunning, err := proc.IsRunning()
        if err != nil {
            fmt.Errorf("failed to check if pid %d is running: %v", proc.Pid, err)
            continue
        }

        if isRunning {
            alive = 1
        }

        cpuPercent, err := proc.CPUPercent()
        if err != nil {
            fmt.Errorf("failed to get cpu percent for pid %d: %v", proc.Pid, err)
            continue
        }
        memoryPercent, err := proc.MemoryPercent()
        if err != nil {
            fmt.Errorf("failed to get memory percent for pid %d: %v", proc.Pid, err)
            continue
        }
        procTime, err := proc.Times()
        if err != nil {
            fmt.Errorf("failed to get cpu times for pid %d: %v", proc.Pid, err)
            continue
        }
        cpuTime := procTime.User + procTime.System
        statuses, err := proc.Status()
        if err != nil {
            fmt.Errorf("failed to get status for pid %d: %v", proc.Pid, err)
            continue
        }
        name, err := proc.Name()
        if err != nil {
            fmt.Errorf("failed to get name for pid %d: %v", proc.Pid, err)
            continue
        }

        var currentStatus string
        if len(statuses) > 0 {
            currentStatus = statuses[0]
        }

        state := &ProcessState{
            CpuPercent: cpuPercent,
            MemPercent: memoryPercent,
            CpuTime:    cpuTime,
            Status:     currentStatus,
            Ports:      ports,
            Pid:        proc.Pid,
            Name:       name,
            Alive:      alive,
        }
        fmt.Println("collectAllProcessesData:%v", state)
        processStates = append(processStates, state)
    }
    return processStates, nil
}

func main() {
    _, err := collectAllProcessesData()
    if err != nil {
        fmt.Errorf("error: ", err)
    }
}

Expected behavior

image

I want to collect process information in non-root user

Environment (please complete the following information):

CENTOS_MANTISBT_PROJECT="CentOS-7" CENTOS_MANTISBT_PROJECT_VERSION="7" REDHAT_SUPPORT_PRODUCT="centos" REDHAT_SUPPORT_PRODUCT_VERSION="7" Linux dev-ops-portal-judge-transfer-task-04 3.10.0-1160.71.1.el7.x86_64 #1 SMP Tue Jun 28 15:37:28 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux]

Additional context go version go1.17.13 darwin/arm64 go env -w GOOS=linux GOARCH=amd64

shirou commented 8 months ago

Your code seems checking procConnections on a process. We cannot see the net information of other users' processes. This is a limitation of the Linux proc fs. so procConnections becomes 0, then, nothing printed.