mirror of
https://github.com/shirou/gopsutil.git
synced 2025-04-26 13:48:59 +08:00

Executing the command does the lookup if needed and returns the same error when not found, no need to do it separately.
128 lines
3.0 KiB
Go
128 lines
3.0 KiB
Go
//go:build darwin && !cgo
|
|
// +build darwin,!cgo
|
|
|
|
package process
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/shirou/gopsutil/v3/cpu"
|
|
"github.com/shirou/gopsutil/v3/internal/common"
|
|
)
|
|
|
|
func (p *Process) CwdWithContext(ctx context.Context) (string, error) {
|
|
return "", common.ErrNotImplementedError
|
|
}
|
|
|
|
func (p *Process) ExeWithContext(ctx context.Context) (string, error) {
|
|
out, err := invoke.CommandWithContext(ctx, "lsof", "-p", strconv.Itoa(int(p.Pid)), "-Fpfn")
|
|
if err != nil {
|
|
return "", fmt.Errorf("bad call to lsof: %s", err)
|
|
}
|
|
txtFound := 0
|
|
lines := strings.Split(string(out), "\n")
|
|
for i := 1; i < len(lines); i++ {
|
|
if lines[i] == "ftxt" {
|
|
txtFound++
|
|
if txtFound == 2 {
|
|
return lines[i-1][1:], nil
|
|
}
|
|
}
|
|
}
|
|
return "", fmt.Errorf("missing txt data returned by lsof")
|
|
}
|
|
|
|
func (p *Process) CmdlineWithContext(ctx context.Context) (string, error) {
|
|
r, err := callPsWithContext(ctx, "command", p.Pid, false, false)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return strings.Join(r[0], " "), err
|
|
}
|
|
|
|
func (p *Process) cmdNameWithContext(ctx context.Context) (string, error) {
|
|
r, err := callPsWithContext(ctx, "command", p.Pid, false, true)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
if len(r) > 0 && len(r[0]) > 0 {
|
|
return r[0][0], err
|
|
}
|
|
|
|
return "", err
|
|
}
|
|
|
|
// CmdlineSliceWithContext returns the command line arguments of the process as a slice with each
|
|
// element being an argument. Because of current deficiencies in the way that the command
|
|
// line arguments are found, single arguments that have spaces in the will actually be
|
|
// reported as two separate items. In order to do something better CGO would be needed
|
|
// to use the native darwin functions.
|
|
func (p *Process) CmdlineSliceWithContext(ctx context.Context) ([]string, error) {
|
|
r, err := callPsWithContext(ctx, "command", p.Pid, false, false)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return r[0], err
|
|
}
|
|
|
|
func (p *Process) NumThreadsWithContext(ctx context.Context) (int32, error) {
|
|
r, err := callPsWithContext(ctx, "utime,stime", p.Pid, true, false)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
return int32(len(r)), nil
|
|
}
|
|
|
|
func (p *Process) TimesWithContext(ctx context.Context) (*cpu.TimesStat, error) {
|
|
r, err := callPsWithContext(ctx, "utime,stime", p.Pid, false, false)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
utime, err := convertCPUTimes(r[0][0])
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
stime, err := convertCPUTimes(r[0][1])
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
ret := &cpu.TimesStat{
|
|
CPU: "cpu",
|
|
User: utime,
|
|
System: stime,
|
|
}
|
|
return ret, nil
|
|
}
|
|
|
|
func (p *Process) MemoryInfoWithContext(ctx context.Context) (*MemoryInfoStat, error) {
|
|
r, err := callPsWithContext(ctx, "rss,vsize,pagein", p.Pid, false, false)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
rss, err := strconv.Atoi(r[0][0])
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
vms, err := strconv.Atoi(r[0][1])
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
pagein, err := strconv.Atoi(r[0][2])
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
ret := &MemoryInfoStat{
|
|
RSS: uint64(rss) * 1024,
|
|
VMS: uint64(vms) * 1024,
|
|
Swap: uint64(pagein),
|
|
}
|
|
|
|
return ret, nil
|
|
}
|