summaryrefslogtreecommitdiff
path: root/vendor/github.com/shirou/gopsutil/v4/process/process.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/shirou/gopsutil/v4/process/process.go')
-rw-r--r--vendor/github.com/shirou/gopsutil/v4/process/process.go640
1 files changed, 640 insertions, 0 deletions
diff --git a/vendor/github.com/shirou/gopsutil/v4/process/process.go b/vendor/github.com/shirou/gopsutil/v4/process/process.go
new file mode 100644
index 0000000..70411c6
--- /dev/null
+++ b/vendor/github.com/shirou/gopsutil/v4/process/process.go
@@ -0,0 +1,640 @@
+// SPDX-License-Identifier: BSD-3-Clause
+package process
+
+import (
+ "context"
+ "encoding/json"
+ "errors"
+ "runtime"
+ "sort"
+ "sync"
+ "time"
+
+ "github.com/shirou/gopsutil/v4/cpu"
+ "github.com/shirou/gopsutil/v4/internal/common"
+ "github.com/shirou/gopsutil/v4/mem"
+ "github.com/shirou/gopsutil/v4/net"
+)
+
+var (
+ invoke common.Invoker = common.Invoke{}
+ ErrorNoChildren = errors.New("process does not have children") // Deprecated: ErrorNoChildren is never returned by process.Children(), check its returned []*Process slice length instead
+ ErrorProcessNotRunning = errors.New("process does not exist")
+ ErrorNotPermitted = errors.New("operation not permitted")
+)
+
+type Process struct {
+ Pid int32 `json:"pid"`
+ name string
+ status string
+ parent int32
+ parentMutex sync.RWMutex // for windows ppid cache
+ numCtxSwitches *NumCtxSwitchesStat
+ uids []uint32
+ gids []uint32
+ groups []uint32
+ numThreads int32
+ memInfo *MemoryInfoStat
+ sigInfo *SignalInfoStat
+ createTime int64
+
+ lastCPUTimes *cpu.TimesStat
+ lastCPUTime time.Time
+
+ tgid int32
+}
+
+// Process status
+const (
+ // Running marks a task a running or runnable (on the run queue)
+ Running = "running"
+ // Blocked marks a task waiting on a short, uninterruptible operation (usually I/O)
+ Blocked = "blocked"
+ // Idle marks a task sleeping for more than about 20 seconds
+ Idle = "idle"
+ // Lock marks a task waiting to acquire a lock
+ Lock = "lock"
+ // Sleep marks task waiting for short, interruptible operation
+ Sleep = "sleep"
+ // Stop marks a stopped process
+ Stop = "stop"
+ // Wait marks an idle interrupt thread (or paging in pre 2.6.xx Linux)
+ Wait = "wait"
+ // Zombie marks a defunct process, terminated but not reaped by its parent
+ Zombie = "zombie"
+
+ // Solaris states. See https://github.com/collectd/collectd/blob/1da3305c10c8ff9a63081284cf3d4bb0f6daffd8/src/processes.c#L2115
+ Daemon = "daemon"
+ Detached = "detached"
+ System = "system"
+ Orphan = "orphan"
+
+ UnknownState = ""
+)
+
+type OpenFilesStat struct {
+ Path string `json:"path"`
+ Fd uint64 `json:"fd"`
+}
+
+type MemoryInfoStat struct {
+ RSS uint64 `json:"rss"` // bytes
+ VMS uint64 `json:"vms"` // bytes
+ HWM uint64 `json:"hwm"` // bytes
+ Data uint64 `json:"data"` // bytes
+ Stack uint64 `json:"stack"` // bytes
+ Locked uint64 `json:"locked"` // bytes
+ Swap uint64 `json:"swap"` // bytes
+}
+
+type SignalInfoStat struct {
+ PendingProcess uint64 `json:"pending_process"`
+ PendingThread uint64 `json:"pending_thread"`
+ Blocked uint64 `json:"blocked"`
+ Ignored uint64 `json:"ignored"`
+ Caught uint64 `json:"caught"`
+}
+
+type RlimitStat struct {
+ Resource int32 `json:"resource"`
+ Soft uint64 `json:"soft"`
+ Hard uint64 `json:"hard"`
+ Used uint64 `json:"used"`
+}
+
+type IOCountersStat struct {
+ // ReadCount is a number of read I/O operations such as syscalls.
+ ReadCount uint64 `json:"readCount"`
+ // WriteCount is a number of read I/O operations such as syscalls.
+ WriteCount uint64 `json:"writeCount"`
+ // ReadBytes is a number of all I/O read in bytes. This includes disk I/O on Linux and Windows.
+ ReadBytes uint64 `json:"readBytes"`
+ // WriteBytes is a number of all I/O write in bytes. This includes disk I/O on Linux and Windows.
+ WriteBytes uint64 `json:"writeBytes"`
+ // DiskReadBytes is a number of disk I/O write in bytes. Currently only Linux has this value.
+ DiskReadBytes uint64 `json:"diskReadBytes"`
+ // DiskWriteBytes is a number of disk I/O read in bytes. Currently only Linux has this value.
+ DiskWriteBytes uint64 `json:"diskWriteBytes"`
+}
+
+type NumCtxSwitchesStat struct {
+ Voluntary int64 `json:"voluntary"`
+ Involuntary int64 `json:"involuntary"`
+}
+
+type PageFaultsStat struct {
+ MinorFaults uint64 `json:"minorFaults"`
+ MajorFaults uint64 `json:"majorFaults"`
+ ChildMinorFaults uint64 `json:"childMinorFaults"`
+ ChildMajorFaults uint64 `json:"childMajorFaults"`
+}
+
+// Resource limit constants are from /usr/include/x86_64-linux-gnu/bits/resource.h
+// from libc6-dev package in Ubuntu 16.10
+const (
+ RLIMIT_CPU int32 = 0
+ RLIMIT_FSIZE int32 = 1
+ RLIMIT_DATA int32 = 2
+ RLIMIT_STACK int32 = 3
+ RLIMIT_CORE int32 = 4
+ RLIMIT_RSS int32 = 5
+ RLIMIT_NPROC int32 = 6
+ RLIMIT_NOFILE int32 = 7
+ RLIMIT_MEMLOCK int32 = 8
+ RLIMIT_AS int32 = 9
+ RLIMIT_LOCKS int32 = 10
+ RLIMIT_SIGPENDING int32 = 11
+ RLIMIT_MSGQUEUE int32 = 12
+ RLIMIT_NICE int32 = 13
+ RLIMIT_RTPRIO int32 = 14
+ RLIMIT_RTTIME int32 = 15
+)
+
+func (p Process) String() string {
+ s, _ := json.Marshal(p)
+ return string(s)
+}
+
+func (o OpenFilesStat) String() string {
+ s, _ := json.Marshal(o)
+ return string(s)
+}
+
+func (m MemoryInfoStat) String() string {
+ s, _ := json.Marshal(m)
+ return string(s)
+}
+
+func (r RlimitStat) String() string {
+ s, _ := json.Marshal(r)
+ return string(s)
+}
+
+func (i IOCountersStat) String() string {
+ s, _ := json.Marshal(i)
+ return string(s)
+}
+
+func (p NumCtxSwitchesStat) String() string {
+ s, _ := json.Marshal(p)
+ return string(s)
+}
+
+var enableBootTimeCache bool
+
+// EnableBootTimeCache change cache behavior of BootTime. If true, cache BootTime value. Default is false.
+func EnableBootTimeCache(enable bool) {
+ enableBootTimeCache = enable
+}
+
+// Pids returns a slice of process ID list which are running now.
+func Pids() ([]int32, error) {
+ return PidsWithContext(context.Background())
+}
+
+func PidsWithContext(ctx context.Context) ([]int32, error) {
+ pids, err := pidsWithContext(ctx)
+ sort.Slice(pids, func(i, j int) bool { return pids[i] < pids[j] })
+ return pids, err
+}
+
+// Processes returns a slice of pointers to Process structs for all
+// currently running processes.
+func Processes() ([]*Process, error) {
+ return ProcessesWithContext(context.Background())
+}
+
+// NewProcess creates a new Process instance, it only stores the pid and
+// checks that the process exists. Other method on Process can be used
+// to get more information about the process. An error will be returned
+// if the process does not exist.
+func NewProcess(pid int32) (*Process, error) {
+ return NewProcessWithContext(context.Background(), pid)
+}
+
+func NewProcessWithContext(ctx context.Context, pid int32) (*Process, error) {
+ p := &Process{
+ Pid: pid,
+ }
+
+ exists, err := PidExistsWithContext(ctx, pid)
+ if err != nil {
+ return p, err
+ }
+ if !exists {
+ return p, ErrorProcessNotRunning
+ }
+ p.CreateTimeWithContext(ctx)
+ return p, nil
+}
+
+func PidExists(pid int32) (bool, error) {
+ return PidExistsWithContext(context.Background(), pid)
+}
+
+// Background returns true if the process is in background, false otherwise.
+func (p *Process) Background() (bool, error) {
+ return p.BackgroundWithContext(context.Background())
+}
+
+func (p *Process) BackgroundWithContext(ctx context.Context) (bool, error) {
+ fg, err := p.ForegroundWithContext(ctx)
+ if err != nil {
+ return false, err
+ }
+ return !fg, err
+}
+
+// If interval is 0, return difference from last call(non-blocking).
+// If interval > 0, wait interval sec and return difference between start and end.
+func (p *Process) Percent(interval time.Duration) (float64, error) {
+ return p.PercentWithContext(context.Background(), interval)
+}
+
+func (p *Process) PercentWithContext(ctx context.Context, interval time.Duration) (float64, error) {
+ cpuTimes, err := p.TimesWithContext(ctx)
+ if err != nil {
+ return 0, err
+ }
+ now := time.Now()
+
+ if interval > 0 {
+ p.lastCPUTimes = cpuTimes
+ p.lastCPUTime = now
+ if err := common.Sleep(ctx, interval); err != nil {
+ return 0, err
+ }
+ cpuTimes, err = p.TimesWithContext(ctx)
+ now = time.Now()
+ if err != nil {
+ return 0, err
+ }
+ } else {
+ if p.lastCPUTimes == nil {
+ // invoked first time
+ p.lastCPUTimes = cpuTimes
+ p.lastCPUTime = now
+ return 0, nil
+ }
+ }
+
+ numcpu := runtime.NumCPU()
+ delta := (now.Sub(p.lastCPUTime).Seconds()) * float64(numcpu)
+ ret := calculatePercent(p.lastCPUTimes, cpuTimes, delta, numcpu)
+ p.lastCPUTimes = cpuTimes
+ p.lastCPUTime = now
+ return ret, nil
+}
+
+// IsRunning returns whether the process is still running or not.
+func (p *Process) IsRunning() (bool, error) {
+ return p.IsRunningWithContext(context.Background())
+}
+
+func (p *Process) IsRunningWithContext(ctx context.Context) (bool, error) {
+ createTime, err := p.CreateTimeWithContext(ctx)
+ if err != nil {
+ return false, err
+ }
+ p2, err := NewProcessWithContext(ctx, p.Pid)
+ if errors.Is(err, ErrorProcessNotRunning) {
+ return false, nil
+ }
+ createTime2, err := p2.CreateTimeWithContext(ctx)
+ if err != nil {
+ return false, err
+ }
+ return createTime == createTime2, nil
+}
+
+// CreateTime returns created time of the process in milliseconds since the epoch, in UTC.
+func (p *Process) CreateTime() (int64, error) {
+ return p.CreateTimeWithContext(context.Background())
+}
+
+func (p *Process) CreateTimeWithContext(ctx context.Context) (int64, error) {
+ if p.createTime != 0 {
+ return p.createTime, nil
+ }
+ createTime, err := p.createTimeWithContext(ctx)
+ p.createTime = createTime
+ return p.createTime, err
+}
+
+func calculatePercent(t1, t2 *cpu.TimesStat, delta float64, numcpu int) float64 {
+ if delta == 0 {
+ return 0
+ }
+ // https://github.com/giampaolo/psutil/blob/c034e6692cf736b5e87d14418a8153bb03f6cf42/psutil/__init__.py#L1064
+ delta_proc := (t2.User - t1.User) + (t2.System - t1.System)
+ if delta_proc <= 0 {
+ return 0
+ }
+ overall_percent := ((delta_proc / delta) * 100) * float64(numcpu)
+ return overall_percent
+}
+
+// MemoryPercent returns how many percent of the total RAM this process uses
+func (p *Process) MemoryPercent() (float32, error) {
+ return p.MemoryPercentWithContext(context.Background())
+}
+
+func (p *Process) MemoryPercentWithContext(ctx context.Context) (float32, error) {
+ machineMemory, err := mem.VirtualMemoryWithContext(ctx)
+ if err != nil {
+ return 0, err
+ }
+ total := machineMemory.Total
+
+ processMemory, err := p.MemoryInfoWithContext(ctx)
+ if err != nil {
+ return 0, err
+ }
+ used := processMemory.RSS
+
+ return (100 * float32(used) / float32(total)), nil
+}
+
+// CPUPercent returns how many percent of the CPU time this process uses
+func (p *Process) CPUPercent() (float64, error) {
+ return p.CPUPercentWithContext(context.Background())
+}
+
+func (p *Process) CPUPercentWithContext(ctx context.Context) (float64, error) {
+ crt_time, err := p.createTimeWithContext(ctx)
+ if err != nil {
+ return 0, err
+ }
+
+ cput, err := p.TimesWithContext(ctx)
+ if err != nil {
+ return 0, err
+ }
+
+ created := time.Unix(0, crt_time*int64(time.Millisecond))
+ totalTime := time.Since(created).Seconds()
+ if totalTime <= 0 {
+ return 0, nil
+ }
+
+ return 100 * cput.Total() / totalTime, nil
+}
+
+// Groups returns all group IDs(include supplementary groups) of the process as a slice of the int
+func (p *Process) Groups() ([]uint32, error) {
+ return p.GroupsWithContext(context.Background())
+}
+
+// Ppid returns Parent Process ID of the process.
+func (p *Process) Ppid() (int32, error) {
+ return p.PpidWithContext(context.Background())
+}
+
+// Name returns name of the process.
+func (p *Process) Name() (string, error) {
+ return p.NameWithContext(context.Background())
+}
+
+// Exe returns executable path of the process.
+func (p *Process) Exe() (string, error) {
+ return p.ExeWithContext(context.Background())
+}
+
+// Cmdline returns the command line arguments of the process as a string with
+// each argument separated by 0x20 ascii character.
+func (p *Process) Cmdline() (string, error) {
+ return p.CmdlineWithContext(context.Background())
+}
+
+// CmdlineSlice returns the command line arguments of the process as a slice with each
+// element being an argument.
+func (p *Process) CmdlineSlice() ([]string, error) {
+ return p.CmdlineSliceWithContext(context.Background())
+}
+
+// Cwd returns current working directory of the process.
+func (p *Process) Cwd() (string, error) {
+ return p.CwdWithContext(context.Background())
+}
+
+// Parent returns parent Process of the process.
+func (p *Process) Parent() (*Process, error) {
+ return p.ParentWithContext(context.Background())
+}
+
+// ParentWithContext returns parent Process of the process.
+func (p *Process) ParentWithContext(ctx context.Context) (*Process, error) {
+ ppid, err := p.PpidWithContext(ctx)
+ if err != nil {
+ return nil, err
+ }
+ return NewProcessWithContext(ctx, ppid)
+}
+
+// Status returns the process status.
+// Return value could be one of these.
+// R: Running S: Sleep T: Stop I: Idle
+// Z: Zombie W: Wait L: Lock
+// The character is same within all supported platforms.
+func (p *Process) Status() ([]string, error) {
+ return p.StatusWithContext(context.Background())
+}
+
+// Foreground returns true if the process is in foreground, false otherwise.
+func (p *Process) Foreground() (bool, error) {
+ return p.ForegroundWithContext(context.Background())
+}
+
+// Uids returns user ids of the process as a slice of the int
+func (p *Process) Uids() ([]uint32, error) {
+ return p.UidsWithContext(context.Background())
+}
+
+// Gids returns group ids of the process as a slice of the int
+func (p *Process) Gids() ([]uint32, error) {
+ return p.GidsWithContext(context.Background())
+}
+
+// Terminal returns a terminal which is associated with the process.
+func (p *Process) Terminal() (string, error) {
+ return p.TerminalWithContext(context.Background())
+}
+
+// Nice returns a nice value (priority).
+func (p *Process) Nice() (int32, error) {
+ return p.NiceWithContext(context.Background())
+}
+
+// IOnice returns process I/O nice value (priority).
+func (p *Process) IOnice() (int32, error) {
+ return p.IOniceWithContext(context.Background())
+}
+
+// Rlimit returns Resource Limits.
+func (p *Process) Rlimit() ([]RlimitStat, error) {
+ return p.RlimitWithContext(context.Background())
+}
+
+// RlimitUsage returns Resource Limits.
+// If gatherUsed is true, the currently used value will be gathered and added
+// to the resulting RlimitStat.
+func (p *Process) RlimitUsage(gatherUsed bool) ([]RlimitStat, error) {
+ return p.RlimitUsageWithContext(context.Background(), gatherUsed)
+}
+
+// IOCounters returns IO Counters.
+func (p *Process) IOCounters() (*IOCountersStat, error) {
+ return p.IOCountersWithContext(context.Background())
+}
+
+// NumCtxSwitches returns the number of the context switches of the process.
+func (p *Process) NumCtxSwitches() (*NumCtxSwitchesStat, error) {
+ return p.NumCtxSwitchesWithContext(context.Background())
+}
+
+// NumFDs returns the number of File Descriptors used by the process.
+func (p *Process) NumFDs() (int32, error) {
+ return p.NumFDsWithContext(context.Background())
+}
+
+// NumThreads returns the number of threads used by the process.
+func (p *Process) NumThreads() (int32, error) {
+ return p.NumThreadsWithContext(context.Background())
+}
+
+func (p *Process) Threads() (map[int32]*cpu.TimesStat, error) {
+ return p.ThreadsWithContext(context.Background())
+}
+
+// Times returns CPU times of the process.
+func (p *Process) Times() (*cpu.TimesStat, error) {
+ return p.TimesWithContext(context.Background())
+}
+
+// CPUAffinity returns CPU affinity of the process.
+func (p *Process) CPUAffinity() ([]int32, error) {
+ return p.CPUAffinityWithContext(context.Background())
+}
+
+// MemoryInfo returns generic process memory information,
+// such as RSS and VMS.
+func (p *Process) MemoryInfo() (*MemoryInfoStat, error) {
+ return p.MemoryInfoWithContext(context.Background())
+}
+
+// MemoryInfoEx returns platform-specific process memory information.
+func (p *Process) MemoryInfoEx() (*MemoryInfoExStat, error) {
+ return p.MemoryInfoExWithContext(context.Background())
+}
+
+// PageFaults returns the process's page fault counters.
+func (p *Process) PageFaults() (*PageFaultsStat, error) {
+ return p.PageFaultsWithContext(context.Background())
+}
+
+// Children returns the children of the process represented as a slice
+// of pointers to Process type.
+func (p *Process) Children() ([]*Process, error) {
+ return p.ChildrenWithContext(context.Background())
+}
+
+// OpenFiles returns a slice of OpenFilesStat opend by the process.
+// OpenFilesStat includes a file path and file descriptor.
+func (p *Process) OpenFiles() ([]OpenFilesStat, error) {
+ return p.OpenFilesWithContext(context.Background())
+}
+
+// Connections returns a slice of net.ConnectionStat used by the process.
+// This returns all kind of the connection. This means TCP, UDP or UNIX.
+func (p *Process) Connections() ([]net.ConnectionStat, error) {
+ return p.ConnectionsWithContext(context.Background())
+}
+
+// ConnectionsMax returns a slice of net.ConnectionStat used by the process at most `max`.
+func (p *Process) ConnectionsMax(maxConn int) ([]net.ConnectionStat, error) {
+ return p.ConnectionsMaxWithContext(context.Background(), maxConn)
+}
+
+// MemoryMaps get memory maps from /proc/(pid)/smaps
+func (p *Process) MemoryMaps(grouped bool) (*[]MemoryMapsStat, error) {
+ return p.MemoryMapsWithContext(context.Background(), grouped)
+}
+
+// Tgid returns thread group id of the process.
+func (p *Process) Tgid() (int32, error) {
+ return p.TgidWithContext(context.Background())
+}
+
+// SendSignal sends a unix.Signal to the process.
+func (p *Process) SendSignal(sig Signal) error {
+ return p.SendSignalWithContext(context.Background(), sig)
+}
+
+// Suspend sends SIGSTOP to the process.
+func (p *Process) Suspend() error {
+ return p.SuspendWithContext(context.Background())
+}
+
+// Resume sends SIGCONT to the process.
+func (p *Process) Resume() error {
+ return p.ResumeWithContext(context.Background())
+}
+
+// Terminate sends SIGTERM to the process.
+func (p *Process) Terminate() error {
+ return p.TerminateWithContext(context.Background())
+}
+
+// Kill sends SIGKILL to the process.
+func (p *Process) Kill() error {
+ return p.KillWithContext(context.Background())
+}
+
+// Username returns a username of the process.
+func (p *Process) Username() (string, error) {
+ return p.UsernameWithContext(context.Background())
+}
+
+// Environ returns the environment variables of the process.
+func (p *Process) Environ() ([]string, error) {
+ return p.EnvironWithContext(context.Background())
+}
+
+// convertStatusChar as reported by the ps command across different platforms.
+func convertStatusChar(letter string) string {
+ // Sources
+ // Darwin: http://www.mywebuniversity.com/Man_Pages/Darwin/man_ps.html
+ // FreeBSD: https://www.freebsd.org/cgi/man.cgi?ps
+ // Linux https://man7.org/linux/man-pages/man1/ps.1.html
+ // OpenBSD: https://man.openbsd.org/ps.1#state
+ // Solaris: https://github.com/collectd/collectd/blob/1da3305c10c8ff9a63081284cf3d4bb0f6daffd8/src/processes.c#L2115
+ switch letter {
+ case "A":
+ return Daemon
+ case "D", "U":
+ return Blocked
+ case "E":
+ return Detached
+ case "I":
+ return Idle
+ case "L":
+ return Lock
+ case "O":
+ return Orphan
+ case "R":
+ return Running
+ case "S":
+ return Sleep
+ case "T", "t":
+ // "t" is used by Linux to signal stopped by the debugger during tracing
+ return Stop
+ case "W":
+ return Wait
+ case "Y":
+ return System
+ case "Z":
+ return Zombie
+ default:
+ return UnknownState
+ }
+}