mirror of
https://github.com/shirou/gopsutil.git
synced 2025-04-26 13:48:59 +08:00
Merge branch 'master' into master
This commit is contained in:
commit
b0469a470b
7
.github/workflows/test.yml
vendored
7
.github/workflows/test.yml
vendored
@ -29,10 +29,3 @@ jobs:
|
||||
- name: Test
|
||||
run: |
|
||||
go test -coverprofile='coverage.out' -covermode=atomic ./...
|
||||
- name: Upload Code Coverage
|
||||
uses: codecov/codecov-action@v2
|
||||
with:
|
||||
fail_ci_if_error: true
|
||||
files: coverage.out
|
||||
flags: ${{ runner.os }},go-${{ matrix.go-version }}
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
|
2
LICENSE
2
LICENSE
@ -28,7 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
-------
|
||||
internal/common/binary.go in the gopsutil is copied and modifid from golang/encoding/binary.go.
|
||||
internal/common/binary.go in the gopsutil is copied and modified from golang/encoding/binary.go.
|
||||
|
||||
|
||||
|
||||
|
@ -7,7 +7,7 @@ challenge is porting all psutil functions on some architectures.
|
||||
|
||||
## v3 migration
|
||||
|
||||
from v3.20.10, gopsutil becomes v3 which breaks backwards compatiblity.
|
||||
from v3.20.10, gopsutil becomes v3 which breaks backwards compatibility.
|
||||
See [v3Changes.md](_tools/v3migration/v3Changes.md) more detail changes.
|
||||
|
||||
## Tag semantics
|
||||
@ -21,7 +21,7 @@ for example, v2.17.04 means
|
||||
- 17: release year, 2017
|
||||
- 04: release month
|
||||
|
||||
gopsutil aims to keep backwards-compatiblity until major version change.
|
||||
gopsutil aims to keep backwards compatibility until major version change.
|
||||
|
||||
Tagged at every end of month, but if there are only a few commits, it
|
||||
can be skipped.
|
||||
@ -130,7 +130,7 @@ will provide useful information.
|
||||
- CacheSize
|
||||
- Flags (ex: "fpu vme de pse tsc msr pae mce cx8 ...")
|
||||
- Microcode
|
||||
- load/LoadAvg() (linux, freebsd)
|
||||
- load/Avg() (linux, freebsd, solaris)
|
||||
- Load1
|
||||
- Load5
|
||||
- Load15
|
||||
@ -229,7 +229,7 @@ Some code is ported from Ohai. many thanks.
|
||||
|**HostInfo** | | | | | | |
|
||||
|hostname |x |x |x |x |x |x |
|
||||
|uptime |x |x |x |x | |x |
|
||||
|proces |x |x |x | | |x |
|
||||
|process |x |x |x | | |x |
|
||||
|os |x |x |x |x |x |x |
|
||||
|platform |x |x |x |x | |x |
|
||||
|platformfamily |x |x |x |x | |x |
|
||||
|
@ -4,10 +4,14 @@
|
||||
package disk
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
|
||||
@ -163,7 +167,29 @@ func getFsType(stat unix.Statfs_t) string {
|
||||
}
|
||||
|
||||
func SerialNumberWithContext(ctx context.Context, name string) (string, error) {
|
||||
return "", common.ErrNotImplementedError
|
||||
geom, err := exec.LookPath("geom")
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("find geom: %w", err)
|
||||
}
|
||||
geomOut, err := invoke.CommandWithContext(ctx, geom, "disk", "list", name)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("exec geom: %w", err)
|
||||
}
|
||||
s := bufio.NewScanner(bytes.NewReader(geomOut))
|
||||
serial := ""
|
||||
for s.Scan() {
|
||||
flds := strings.Fields(s.Text())
|
||||
if len(flds) == 2 && flds[0] == "ident:" {
|
||||
if flds[1] != "(null)" {
|
||||
serial = flds[1]
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
if err = s.Err(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return serial, nil
|
||||
}
|
||||
|
||||
func LabelWithContext(ctx context.Context, name string) (string, error) {
|
||||
|
@ -57,7 +57,7 @@ func GetDockerStatWithContext(ctx context.Context) ([]CgroupDockerStat, error) {
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// GetDockerIDList returnes a list of DockerID.
|
||||
// GetDockerIDList returns a list of DockerID.
|
||||
// This requires certain permission.
|
||||
func GetDockerIDList() ([]string, error) {
|
||||
return GetDockerIDListWithContext(context.Background())
|
||||
@ -86,7 +86,7 @@ func GetDockerIDListWithContext(ctx context.Context) ([]string, error) {
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// CgroupCPU returnes specified cgroup id CPU status.
|
||||
// CgroupCPU returns specified cgroup id CPU status.
|
||||
// containerID is same as docker id if you use docker.
|
||||
// If you use container via systemd.slice, you could use
|
||||
// containerID = docker-<container id>.scope and base=/sys/fs/cgroup/cpuacct/system.slice/
|
||||
@ -94,7 +94,7 @@ func CgroupCPU(containerID string, base string) (*CgroupCPUStat, error) {
|
||||
return CgroupCPUWithContext(context.Background(), containerID, base)
|
||||
}
|
||||
|
||||
// CgroupCPUUsage returnes specified cgroup id CPU usage.
|
||||
// CgroupCPUUsage returns specified cgroup id CPU usage.
|
||||
// containerID is same as docker id if you use docker.
|
||||
// If you use container via systemd.slice, you could use
|
||||
// containerID = docker-<container id>.scope and base=/sys/fs/cgroup/cpuacct/system.slice/
|
||||
|
@ -19,7 +19,7 @@ func GetDockerStatWithContext(ctx context.Context) ([]CgroupDockerStat, error) {
|
||||
return nil, ErrDockerNotAvailable
|
||||
}
|
||||
|
||||
// GetDockerIDList returnes a list of DockerID.
|
||||
// GetDockerIDList returns a list of DockerID.
|
||||
// This requires certain permission.
|
||||
func GetDockerIDList() ([]string, error) {
|
||||
return GetDockerIDListWithContext(context.Background())
|
||||
@ -29,7 +29,7 @@ func GetDockerIDListWithContext(ctx context.Context) ([]string, error) {
|
||||
return nil, ErrDockerNotAvailable
|
||||
}
|
||||
|
||||
// CgroupCPU returnes specified cgroup id CPU status.
|
||||
// CgroupCPU returns specified cgroup id CPU status.
|
||||
// containerid is same as docker id if you use docker.
|
||||
// If you use container via systemd.slice, you could use
|
||||
// containerid = docker-<container id>.scope and base=/sys/fs/cgroup/cpuacct/system.slice/
|
||||
|
4
go.mod
4
go.mod
@ -3,11 +3,11 @@ module github.com/shirou/gopsutil/v3
|
||||
go 1.15
|
||||
|
||||
require (
|
||||
github.com/google/go-cmp v0.5.6
|
||||
github.com/google/go-cmp v0.5.7
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c
|
||||
github.com/stretchr/testify v1.7.0
|
||||
github.com/tklauser/go-sysconf v0.3.9
|
||||
github.com/yusufpapurcu/wmi v1.2.2
|
||||
golang.org/x/sys v0.0.0-20211013075003-97ac67df715c
|
||||
golang.org/x/sys v0.0.0-20220111092808-5a964db01320
|
||||
)
|
||||
|
9
go.sum
9
go.sum
@ -2,12 +2,11 @@ github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
|
||||
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
|
||||
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
|
||||
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
|
||||
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
@ -26,8 +25,8 @@ github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQ
|
||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211013075003-97ac67df715c h1:taxlMj0D/1sOAuv/CbSD+MMDof2vbyPTqz5FNYKpXt8=
|
||||
golang.org/x/sys v0.0.0-20211013075003-97ac67df715c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220111092808-5a964db01320 h1:0jf+tOCoZ3LyutmCOWpVni1chK4VfFLhRsDK7MhqGRY=
|
||||
golang.org/x/sys v0.0.0-20220111092808-5a964db01320/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
|
@ -283,7 +283,7 @@ func PlatformInformationWithContext(ctx context.Context) (platform string, famil
|
||||
family = "debian"
|
||||
case "fedora":
|
||||
family = "fedora"
|
||||
case "oracle", "centos", "redhat", "scientific", "enterpriseenterprise", "amazon", "xenserver", "cloudlinux", "ibm_powerkvm", "rocky":
|
||||
case "oracle", "centos", "redhat", "scientific", "enterpriseenterprise", "amazon", "xenserver", "cloudlinux", "ibm_powerkvm", "rocky", "almalinux":
|
||||
family = "rhel"
|
||||
case "suse", "opensuse", "opensuse-leap", "opensuse-tumbleweed", "opensuse-tumbleweed-kubic", "sles", "sled", "caasp":
|
||||
family = "suse"
|
||||
|
@ -64,7 +64,7 @@ func (i Invoke) CommandWithContext(ctx context.Context, name string, arg ...stri
|
||||
|
||||
type FakeInvoke struct {
|
||||
Suffix string // Suffix species expected file name suffix such as "fail"
|
||||
Error error // If Error specfied, return the error.
|
||||
Error error // If Error specified, return the error.
|
||||
}
|
||||
|
||||
// Command in FakeInvoke returns from expected file if exists.
|
||||
|
@ -100,8 +100,9 @@ func BootTimeWithContext(ctx context.Context) (uint64, error) {
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
t := uint64(time.Now().Unix()) - uint64(b)
|
||||
return t, nil
|
||||
currentTime := float64(time.Now().UnixNano()) / float64(time.Second)
|
||||
t := currentTime - b
|
||||
return uint64(t), nil
|
||||
}
|
||||
|
||||
return 0, fmt.Errorf("could not find btime")
|
||||
|
@ -39,7 +39,7 @@ func AvgWithContext(ctx context.Context) (*AvgStat, error) {
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// Misc returnes miscellaneous host-wide statistics.
|
||||
// Misc returns miscellaneous host-wide statistics.
|
||||
// darwin use ps command to get process running/blocked count.
|
||||
// Almost same as FreeBSD implementation, but state is different.
|
||||
// U means 'Uninterruptible Sleep'.
|
||||
|
@ -68,7 +68,7 @@ func fileAvgWithContext() (*AvgStat, error) {
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// Misc returnes miscellaneous host-wide statistics.
|
||||
// Misc returns miscellaneous host-wide statistics.
|
||||
// Note: the name should be changed near future.
|
||||
func Misc() (*MiscStat, error) {
|
||||
return MiscWithContext(context.Background())
|
||||
|
@ -4,11 +4,12 @@
|
||||
package load
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"context"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
)
|
||||
|
||||
func Avg() (*AvgStat, error) {
|
||||
@ -16,7 +17,45 @@ func Avg() (*AvgStat, error) {
|
||||
}
|
||||
|
||||
func AvgWithContext(ctx context.Context) (*AvgStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
kstat, err := exec.LookPath("kstat")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out, err := invoke.CommandWithContext(ctx, kstat, "-p", "unix:0:system_misc:avenrun_*")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
avg := &AvgStat{}
|
||||
scanner := bufio.NewScanner(bytes.NewReader(out))
|
||||
for scanner.Scan() {
|
||||
flds := strings.Fields(scanner.Text())
|
||||
if len(flds) < 2 {
|
||||
continue
|
||||
}
|
||||
var tgt *float64
|
||||
switch {
|
||||
case strings.HasSuffix(flds[0], ":avenrun_1min"):
|
||||
tgt = &avg.Load1
|
||||
case strings.HasSuffix(flds[0], ":avenrun_5min"):
|
||||
tgt = &avg.Load5
|
||||
case strings.HasSuffix(flds[0], ":avenrun_15min"):
|
||||
tgt = &avg.Load15
|
||||
default:
|
||||
continue
|
||||
}
|
||||
v, err := strconv.ParseInt(flds[1], 10, 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
*tgt = float64(v) / (1 << 8)
|
||||
}
|
||||
if err = scanner.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return avg, nil
|
||||
}
|
||||
|
||||
func Misc() (*MiscStat, error) {
|
||||
|
@ -305,7 +305,7 @@ func fillFromMeminfoWithContext() (*VirtualMemoryStat, *VirtualMemoryExStat, err
|
||||
|
||||
if !memavail {
|
||||
if activeFile && inactiveFile && sReclaimable {
|
||||
ret.Available = calcuateAvailVmem(ret, retEx)
|
||||
ret.Available = calculateAvailVmem(ret, retEx)
|
||||
} else {
|
||||
ret.Available = ret.Cached + ret.Free
|
||||
}
|
||||
@ -387,10 +387,10 @@ func SwapMemoryWithContext(ctx context.Context) (*SwapMemoryStat, error) {
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// calcuateAvailVmem is a fallback under kernel 3.14 where /proc/meminfo does not provide
|
||||
// calculateAvailVmem is a fallback under kernel 3.14 where /proc/meminfo does not provide
|
||||
// "MemAvailable:" column. It reimplements an algorithm from the link below
|
||||
// https://github.com/giampaolo/psutil/pull/890
|
||||
func calcuateAvailVmem(ret *VirtualMemoryStat, retEx *VirtualMemoryExStat) uint64 {
|
||||
func calculateAvailVmem(ret *VirtualMemoryStat, retEx *VirtualMemoryExStat) uint64 {
|
||||
var watermarkLow uint64
|
||||
|
||||
fn := common.HostProc("zoneinfo")
|
||||
|
@ -105,7 +105,7 @@ func IOCountersWithContext(ctx context.Context, pernic bool) ([]IOCountersStat,
|
||||
return iocounters, nil
|
||||
}
|
||||
|
||||
// NetIOCountersByFile is an method which is added just a compatibility for linux.
|
||||
// IOCountersByFile exists just for compatibility with Linux.
|
||||
func IOCountersByFile(pernic bool, filename string) ([]IOCountersStat, error) {
|
||||
return IOCountersByFileWithContext(context.Background(), pernic, filename)
|
||||
}
|
||||
|
@ -257,7 +257,7 @@ func IOCountersWithContext(ctx context.Context, pernic bool) ([]IOCountersStat,
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// NetIOCountersByFile is an method which is added just a compatibility for linux.
|
||||
// IOCountersByFile exists just for compatibility with Linux.
|
||||
func IOCountersByFile(pernic bool, filename string) ([]IOCountersStat, error) {
|
||||
return IOCountersByFileWithContext(context.Background(), pernic, filename)
|
||||
}
|
||||
|
@ -95,7 +95,7 @@ func IOCountersWithContext(ctx context.Context, pernic bool) ([]IOCountersStat,
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// NetIOCountersByFile is an method which is added just a compatibility for linux.
|
||||
// IOCountersByFile exists just for compatibility with Linux.
|
||||
func IOCountersByFile(pernic bool, filename string) ([]IOCountersStat, error) {
|
||||
return IOCountersByFileWithContext(context.Background(), pernic, filename)
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ const ( // Conntrack Column numbers
|
||||
ctSEARCH_RESTART
|
||||
)
|
||||
|
||||
// NetIOCounters returnes network I/O statistics for every network
|
||||
// NetIOCounters returns network I/O statistics for every network
|
||||
// interface installed on the system. If pernic argument is false,
|
||||
// return only sum of all information (which name is 'all'). If true,
|
||||
// every network interface installed on the system is returned
|
||||
@ -188,7 +188,7 @@ func ProtoCountersWithContext(ctx context.Context, protocols []string) ([]ProtoC
|
||||
line := lines[i]
|
||||
r := strings.IndexRune(line, ':')
|
||||
if r == -1 {
|
||||
return nil, errors.New(filename + " is not fomatted correctly, expected ':'.")
|
||||
return nil, errors.New(filename + " is not formatted correctly, expected ':'.")
|
||||
}
|
||||
proto := strings.ToLower(line[:r])
|
||||
if !protos[proto] {
|
||||
@ -204,7 +204,7 @@ func ProtoCountersWithContext(ctx context.Context, protocols []string) ([]ProtoC
|
||||
i++
|
||||
statValues := strings.Split(lines[i][r+2:], " ")
|
||||
if len(statNames) != len(statValues) {
|
||||
return nil, errors.New(filename + " is not fomatted correctly, expected same number of columns.")
|
||||
return nil, errors.New(filename + " is not formatted correctly, expected same number of columns.")
|
||||
}
|
||||
stat := ProtoCountersStat{
|
||||
Protocol: proto,
|
||||
@ -543,7 +543,7 @@ func statsFromInodesWithContext(ctx context.Context, root string, pid int32, tma
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// getProcInodes returnes fd of the pid.
|
||||
// getProcInodes returns fd of the pid.
|
||||
func getProcInodes(root string, pid int32, max int) (map[string][]inodeMap, error) {
|
||||
ret := make(map[string][]inodeMap)
|
||||
|
||||
@ -553,7 +553,7 @@ func getProcInodes(root string, pid int32, max int) (map[string][]inodeMap, erro
|
||||
return ret, err
|
||||
}
|
||||
defer f.Close()
|
||||
dirEntries, err := f.ReadDir(max)
|
||||
dirEntries, err := readDir(f, max)
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
|
12
net/net_linux_111.go
Normal file
12
net/net_linux_111.go
Normal file
@ -0,0 +1,12 @@
|
||||
//go:build !go1.16
|
||||
// +build !go1.16
|
||||
|
||||
package net
|
||||
|
||||
import (
|
||||
"os"
|
||||
)
|
||||
|
||||
func readDir(f *os.File, max int) ([]os.FileInfo, error) {
|
||||
return f.Readdir(max)
|
||||
}
|
12
net/net_linux_116.go
Normal file
12
net/net_linux_116.go
Normal file
@ -0,0 +1,12 @@
|
||||
//go:build go1.16
|
||||
// +build go1.16
|
||||
|
||||
package net
|
||||
|
||||
import (
|
||||
"os"
|
||||
)
|
||||
|
||||
func readDir(f *os.File, max int) ([]os.DirEntry, error) {
|
||||
return f.ReadDir(max)
|
||||
}
|
@ -139,7 +139,7 @@ func IOCountersWithContext(ctx context.Context, pernic bool) ([]IOCountersStat,
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// NetIOCountersByFile is an method which is added just a compatibility for linux.
|
||||
// IOCountersByFile exists just for compatibility with Linux.
|
||||
func IOCountersByFile(pernic bool, filename string) ([]IOCountersStat, error) {
|
||||
return IOCountersByFileWithContext(context.Background(), pernic, filename)
|
||||
}
|
||||
|
@ -200,7 +200,7 @@ func IOCountersWithContext(ctx context.Context, pernic bool) ([]IOCountersStat,
|
||||
return counters, nil
|
||||
}
|
||||
|
||||
// NetIOCountersByFile is an method which is added just a compatibility for linux.
|
||||
// IOCountersByFile exists just for compatibility with Linux.
|
||||
func IOCountersByFile(pernic bool, filename string) ([]IOCountersStat, error) {
|
||||
return IOCountersByFileWithContext(context.Background(), pernic, filename)
|
||||
}
|
||||
|
@ -47,13 +47,13 @@ type Process struct {
|
||||
const (
|
||||
// Running marks a task a running or runnable (on the run queue)
|
||||
Running = "running"
|
||||
// Blocked marks a task waiting on a short, uninterruptable operation (usually IO)
|
||||
// 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, interruptable operation
|
||||
// Sleep marks task waiting for short, interruptible operation
|
||||
Sleep = "sleep"
|
||||
// Stop marks a stopped process
|
||||
Stop = "stop"
|
||||
@ -230,7 +230,7 @@ func (p *Process) BackgroundWithContext(ctx context.Context) (bool, error) {
|
||||
}
|
||||
|
||||
// If interval is 0, return difference from last call(non-blocking).
|
||||
// If interval > 0, wait interval sec and return diffrence between start and end.
|
||||
// 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)
|
||||
}
|
||||
@ -402,6 +402,15 @@ 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
|
||||
|
@ -10,9 +10,7 @@ import (
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/shirou/gopsutil/v3/cpu"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/net"
|
||||
"github.com/tklauser/go-sysconf"
|
||||
@ -46,34 +44,25 @@ type _Ctype_struct___0 struct {
|
||||
func pidsWithContext(ctx context.Context) ([]int32, error) {
|
||||
var ret []int32
|
||||
|
||||
pids, err := callPsWithContext(ctx, "pid", 0, false, false)
|
||||
kprocs, err := unix.SysctlKinfoProcSlice("kern.proc.all")
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
|
||||
for _, pid := range pids {
|
||||
v, err := strconv.Atoi(pid[0])
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
ret = append(ret, int32(v))
|
||||
for _, proc := range kprocs {
|
||||
ret = append(ret, int32(proc.Proc.P_pid))
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (p *Process) PpidWithContext(ctx context.Context) (int32, error) {
|
||||
r, err := callPsWithContext(ctx, "ppid", p.Pid, false, false)
|
||||
k, err := p.getKProc()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
v, err := strconv.Atoi(r[0][0])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return int32(v), err
|
||||
return k.Eproc.Ppid, nil
|
||||
}
|
||||
|
||||
func (p *Process) NameWithContext(ctx context.Context) (string, error) {
|
||||
@ -81,7 +70,8 @@ func (p *Process) NameWithContext(ctx context.Context) (string, error) {
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
name := common.IntToString(k.Proc.P_comm[:])
|
||||
|
||||
name := common.ByteToString(k.Proc.P_comm[:])
|
||||
|
||||
if len(name) >= 15 {
|
||||
cmdName, err := p.cmdNameWithContext(ctx)
|
||||
@ -89,11 +79,11 @@ func (p *Process) NameWithContext(ctx context.Context) (string, error) {
|
||||
return "", err
|
||||
}
|
||||
if len(cmdName) > 0 {
|
||||
extendedName := filepath.Base(cmdName[0])
|
||||
extendedName := filepath.Base(cmdName)
|
||||
if strings.HasPrefix(extendedName, p.name) {
|
||||
name = extendedName
|
||||
} else {
|
||||
name = cmdName[0]
|
||||
name = cmdName
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -101,61 +91,13 @@ func (p *Process) NameWithContext(ctx context.Context) (string, error) {
|
||||
return name, nil
|
||||
}
|
||||
|
||||
// cmdNameWithContext returns the command name (including spaces) without any arguments
|
||||
func (p *Process) cmdNameWithContext(ctx context.Context) ([]string, error) {
|
||||
r, err := callPsWithContext(ctx, "command", p.Pid, false, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return r[0], err
|
||||
}
|
||||
|
||||
func (p *Process) createTimeWithContext(ctx context.Context) (int64, error) {
|
||||
r, err := callPsWithContext(ctx, "etime", p.Pid, false, false)
|
||||
k, err := p.getKProc()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
elapsedSegments := strings.Split(strings.Replace(r[0][0], "-", ":", 1), ":")
|
||||
var elapsedDurations []time.Duration
|
||||
for i := len(elapsedSegments) - 1; i >= 0; i-- {
|
||||
p, err := strconv.ParseInt(elapsedSegments[i], 10, 0)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
elapsedDurations = append(elapsedDurations, time.Duration(p))
|
||||
}
|
||||
|
||||
elapsed := time.Duration(elapsedDurations[0]) * time.Second
|
||||
if len(elapsedDurations) > 1 {
|
||||
elapsed += time.Duration(elapsedDurations[1]) * time.Minute
|
||||
}
|
||||
if len(elapsedDurations) > 2 {
|
||||
elapsed += time.Duration(elapsedDurations[2]) * time.Hour
|
||||
}
|
||||
if len(elapsedDurations) > 3 {
|
||||
elapsed += time.Duration(elapsedDurations[3]) * time.Hour * 24
|
||||
}
|
||||
|
||||
start := time.Now().Add(-elapsed)
|
||||
return start.Unix() * 1000, nil
|
||||
}
|
||||
|
||||
func (p *Process) ParentWithContext(ctx context.Context) (*Process, error) {
|
||||
out, err := common.CallLsofWithContext(ctx, invoke, p.Pid, "-FR")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, line := range out {
|
||||
if len(line) >= 1 && line[0] == 'R' {
|
||||
v, err := strconv.Atoi(line[1:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return NewProcessWithContext(ctx, int32(v))
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("could not find parent line")
|
||||
return k.Proc.P_starttime.Sec*1000 + int64(k.Proc.P_starttime.Usec)/1000, nil
|
||||
}
|
||||
|
||||
func (p *Process) StatusWithContext(ctx context.Context) ([]string, error) {
|
||||
@ -188,7 +130,7 @@ func (p *Process) UidsWithContext(ctx context.Context) ([]int32, error) {
|
||||
}
|
||||
|
||||
// See: http://unix.superglobalmegacorp.com/Net2/newsrc/sys/ucred.h.html
|
||||
userEffectiveUID := int32(k.Eproc.Ucred.UID)
|
||||
userEffectiveUID := int32(k.Eproc.Ucred.Uid)
|
||||
|
||||
return []int32{userEffectiveUID}, nil
|
||||
}
|
||||
@ -200,7 +142,7 @@ func (p *Process) GidsWithContext(ctx context.Context) ([]int32, error) {
|
||||
}
|
||||
|
||||
gids := make([]int32, 0, 3)
|
||||
gids = append(gids, int32(k.Eproc.Pcred.P_rgid), int32(k.Eproc.Ucred.Ngroups), int32(k.Eproc.Pcred.P_svgid))
|
||||
gids = append(gids, int32(k.Eproc.Pcred.P_rgid), int32(k.Eproc.Pcred.P_rgid), int32(k.Eproc.Pcred.P_svgid))
|
||||
|
||||
return gids, nil
|
||||
}
|
||||
@ -250,14 +192,6 @@ func (p *Process) IOCountersWithContext(ctx context.Context) (*IOCountersStat, e
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
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 convertCPUTimes(s string) (ret float64, err error) {
|
||||
var t int
|
||||
var _tmp string
|
||||
@ -304,56 +238,6 @@ func convertCPUTimes(s string) (ret float64, err error) {
|
||||
return float64(t) / float64(clockTicks), 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
|
||||
}
|
||||
|
||||
func (p *Process) ChildrenWithContext(ctx context.Context) ([]*Process, error) {
|
||||
pids, err := common.CallPgrepWithContext(ctx, invoke, p.Pid)
|
||||
if err != nil {
|
||||
@ -399,17 +283,8 @@ func ProcessesWithContext(ctx context.Context) ([]*Process, error) {
|
||||
|
||||
// Returns a proc as defined here:
|
||||
// http://unix.superglobalmegacorp.com/Net2/newsrc/sys/kinfo_proc.h.html
|
||||
func (p *Process) getKProc() (*KinfoProc, error) {
|
||||
buf, err := unix.SysctlRaw("kern.proc.pid", int(p.Pid))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
k, err := parseKinfoProc(buf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &k, nil
|
||||
func (p *Process) getKProc() (*unix.KinfoProc, error) {
|
||||
return unix.SysctlKinfoProc("kern.proc.pid", int(p.Pid))
|
||||
}
|
||||
|
||||
// call ps command.
|
||||
|
@ -9,6 +9,7 @@ package process
|
||||
// #include <sys/errno.h>
|
||||
// #include <sys/proc_info.h>
|
||||
// #include <sys/sysctl.h>
|
||||
// #include <mach/mach_time.h>
|
||||
import "C"
|
||||
|
||||
import (
|
||||
@ -18,12 +19,18 @@ import (
|
||||
"strings"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"github.com/shirou/gopsutil/v3/cpu"
|
||||
)
|
||||
|
||||
var argMax int
|
||||
var (
|
||||
argMax int
|
||||
timescaleToNanoSeconds float64
|
||||
)
|
||||
|
||||
func init() {
|
||||
argMax = getArgMax()
|
||||
timescaleToNanoSeconds = getTimeScaleToNanoSeconds()
|
||||
}
|
||||
|
||||
func getArgMax() int {
|
||||
@ -39,6 +46,14 @@ func getArgMax() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func getTimeScaleToNanoSeconds() float64 {
|
||||
var timeBaseInfo C.struct_mach_timebase_info
|
||||
|
||||
C.mach_timebase_info(&timeBaseInfo)
|
||||
|
||||
return float64(timeBaseInfo.numer) / float64(timeBaseInfo.denom)
|
||||
}
|
||||
|
||||
func (p *Process) ExeWithContext(ctx context.Context) (string, error) {
|
||||
var c C.char // need a var for unsafe.Sizeof need a var
|
||||
const bufsize = C.PROC_PIDPATHINFO_MAXSIZE * unsafe.Sizeof(c)
|
||||
@ -82,7 +97,7 @@ func (p *Process) CwdWithContext(ctx context.Context) (string, error) {
|
||||
return C.GoString(&vpi.pvi_cdir.vip_path[0]), err
|
||||
}
|
||||
|
||||
func procArgs(pid int32) (*[]byte, int, error) {
|
||||
func procArgs(pid int32) ([]byte, int, error) {
|
||||
var (
|
||||
mib = [...]C.int{C.CTL_KERN, C.KERN_PROCARGS2, C.int(pid)}
|
||||
size C.size_t = C.ulong(argMax)
|
||||
@ -91,23 +106,27 @@ func procArgs(pid int32) (*[]byte, int, error) {
|
||||
)
|
||||
procargs := (*C.char)(C.malloc(C.ulong(argMax)))
|
||||
defer C.free(unsafe.Pointer(procargs))
|
||||
retval := C.sysctl(&mib[0], 3, unsafe.Pointer(procargs), &size, C.NULL, 0)
|
||||
retval, err := C.sysctl(&mib[0], 3, unsafe.Pointer(procargs), &size, C.NULL, 0)
|
||||
if retval == 0 {
|
||||
C.memcpy(unsafe.Pointer(&nargs), unsafe.Pointer(procargs), C.sizeof_int)
|
||||
result = C.GoBytes(unsafe.Pointer(procargs), C.int(size))
|
||||
// fmt.Printf("size: %d %d\n%s\n", size, nargs, hex.Dump(result))
|
||||
return &result, int(nargs), nil
|
||||
return result, int(nargs), nil
|
||||
}
|
||||
return nil, 0, fmt.Errorf("error: %d", retval)
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
func (p *Process) CmdlineSliceWithContext(ctx context.Context) ([]string, error) {
|
||||
return p.cmdlineSliceWithContext(ctx, true)
|
||||
}
|
||||
|
||||
func (p *Process) cmdlineSliceWithContext(ctx context.Context, fallback bool) ([]string, error) {
|
||||
pargs, nargs, err := procArgs(p.Pid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// The first bytes hold the nargs int, skip it.
|
||||
args := bytes.Split((*pargs)[C.sizeof_int:], []byte{0})
|
||||
args := bytes.Split((pargs)[C.sizeof_int:], []byte{0})
|
||||
var argStr string
|
||||
// The first element is the actual binary/command path.
|
||||
// command := args[0]
|
||||
@ -131,6 +150,20 @@ func (p *Process) CmdlineSliceWithContext(ctx context.Context) ([]string, error)
|
||||
return argSlice, err
|
||||
}
|
||||
|
||||
// cmdNameWithContext returns the command name (including spaces) without any arguments
|
||||
func (p *Process) cmdNameWithContext(ctx context.Context) (string, error) {
|
||||
r, err := p.cmdlineSliceWithContext(ctx, false)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if len(r) == 0 {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
return r[0], err
|
||||
}
|
||||
|
||||
func (p *Process) CmdlineWithContext(ctx context.Context) (string, error) {
|
||||
r, err := p.CmdlineSliceWithContext(ctx)
|
||||
if err != nil {
|
||||
@ -138,3 +171,49 @@ func (p *Process) CmdlineWithContext(ctx context.Context) (string, error) {
|
||||
}
|
||||
return strings.Join(r, " "), err
|
||||
}
|
||||
|
||||
func (p *Process) NumThreadsWithContext(ctx context.Context) (int32, error) {
|
||||
const tiSize = C.sizeof_struct_proc_taskinfo
|
||||
ti := (*C.struct_proc_taskinfo)(C.malloc(tiSize))
|
||||
|
||||
_, err := C.proc_pidinfo(C.int(p.Pid), C.PROC_PIDTASKINFO, 0, unsafe.Pointer(ti), tiSize)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return int32(ti.pti_threadnum), nil
|
||||
}
|
||||
|
||||
func (p *Process) TimesWithContext(ctx context.Context) (*cpu.TimesStat, error) {
|
||||
const tiSize = C.sizeof_struct_proc_taskinfo
|
||||
ti := (*C.struct_proc_taskinfo)(C.malloc(tiSize))
|
||||
|
||||
_, err := C.proc_pidinfo(C.int(p.Pid), C.PROC_PIDTASKINFO, 0, unsafe.Pointer(ti), tiSize)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ret := &cpu.TimesStat{
|
||||
CPU: "cpu",
|
||||
User: float64(ti.pti_total_user) * timescaleToNanoSeconds / 1e9,
|
||||
System: float64(ti.pti_total_system) * timescaleToNanoSeconds / 1e9,
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (p *Process) MemoryInfoWithContext(ctx context.Context) (*MemoryInfoStat, error) {
|
||||
const tiSize = C.sizeof_struct_proc_taskinfo
|
||||
ti := (*C.struct_proc_taskinfo)(C.malloc(tiSize))
|
||||
|
||||
_, err := C.proc_pidinfo(C.int(p.Pid), C.PROC_PIDTASKINFO, 0, unsafe.Pointer(ti), tiSize)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ret := &MemoryInfoStat{
|
||||
RSS: uint64(ti.pti_resident_size),
|
||||
VMS: uint64(ti.pti_virtual_size),
|
||||
Swap: uint64(ti.pti_pageins),
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/shirou/gopsutil/v3/cpu"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
)
|
||||
|
||||
@ -47,6 +48,18 @@ func (p *Process) CmdlineWithContext(ctx context.Context) (string, error) {
|
||||
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
|
||||
@ -59,3 +72,61 @@ func (p *Process) CmdlineSliceWithContext(ctx context.Context) ([]string, error)
|
||||
}
|
||||
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
|
||||
}
|
||||
|
@ -74,10 +74,6 @@ func (p *Process) CwdWithContext(ctx context.Context) (string, error) {
|
||||
return "", common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) ParentWithContext(ctx context.Context) (*Process, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) StatusWithContext(ctx context.Context) ([]string, error) {
|
||||
return []string{""}, common.ErrNotImplementedError
|
||||
}
|
||||
|
@ -111,11 +111,11 @@ func (p *Process) CmdlineSliceWithContext(ctx context.Context) ([]string, error)
|
||||
}
|
||||
|
||||
func (p *Process) createTimeWithContext(ctx context.Context) (int64, error) {
|
||||
return 0, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) ParentWithContext(ctx context.Context) (*Process, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
k, err := p.getKProc()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return k.Start.Sec*1000 + k.Start.Usec/1000, nil
|
||||
}
|
||||
|
||||
func (p *Process) StatusWithContext(ctx context.Context) ([]string, error) {
|
||||
|
@ -123,17 +123,6 @@ func (p *Process) CwdWithContext(ctx context.Context) (string, error) {
|
||||
return p.fillFromCwdWithContext()
|
||||
}
|
||||
|
||||
func (p *Process) ParentWithContext(ctx context.Context) (*Process, error) {
|
||||
err := p.fillFromStatusWithContext(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if p.parent == 0 {
|
||||
return nil, fmt.Errorf("wrong number of parents")
|
||||
}
|
||||
return NewProcessWithContext(ctx, p.parent)
|
||||
}
|
||||
|
||||
func (p *Process) StatusWithContext(ctx context.Context) ([]string, error) {
|
||||
err := p.fillFromStatusWithContext(ctx)
|
||||
if err != nil {
|
||||
@ -351,11 +340,11 @@ func (p *Process) PageFaultsWithContext(ctx context.Context) (*PageFaultsStat, e
|
||||
func (p *Process) ChildrenWithContext(ctx context.Context) ([]*Process, error) {
|
||||
pids, err := common.CallPgrepWithContext(ctx, invoke, p.Pid)
|
||||
if err != nil {
|
||||
if len(pids) == 0 {
|
||||
return nil, ErrorNoChildren
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
if len(pids) == 0 {
|
||||
return nil, ErrorNoChildren
|
||||
}
|
||||
ret := make([]*Process, 0, len(pids))
|
||||
for _, pid := range pids {
|
||||
np, err := NewProcessWithContext(ctx, pid)
|
||||
@ -537,7 +526,7 @@ func (p *Process) fillFromLimitsWithContext() ([]RlimitStat, error) {
|
||||
// Assert that last item is a Hard limit
|
||||
statItem.Hard, err = limitToUint(str[len(str)-1])
|
||||
if err != nil {
|
||||
// On error remove last item an try once again since it can be unit or header line
|
||||
// On error remove last item and try once again since it can be unit or header line
|
||||
str = str[:len(str)-1]
|
||||
statItem.Hard, err = limitToUint(str[len(str)-1])
|
||||
if err != nil {
|
||||
|
@ -142,10 +142,6 @@ func (p *Process) createTimeWithContext(ctx context.Context) (int64, error) {
|
||||
return 0, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) ParentWithContext(ctx context.Context) (*Process, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) StatusWithContext(ctx context.Context) ([]string, error) {
|
||||
k, err := p.getKProc()
|
||||
if err != nil {
|
||||
|
@ -74,10 +74,6 @@ func (p *Process) CwdWithContext(ctx context.Context) (string, error) {
|
||||
return "", common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) ParentWithContext(ctx context.Context) (*Process, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) StatusWithContext(ctx context.Context) ([]string, error) {
|
||||
return []string{""}, common.ErrNotImplementedError
|
||||
}
|
||||
|
@ -88,10 +88,6 @@ func (p *Process) CwdWithContext(ctx context.Context) (string, error) {
|
||||
return p.fillFromPathCwdWithContext(ctx)
|
||||
}
|
||||
|
||||
func (p *Process) ParentWithContext(ctx context.Context) (*Process, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) StatusWithContext(ctx context.Context) ([]string, error) {
|
||||
return []string{""}, common.ErrNotImplementedError
|
||||
}
|
||||
|
@ -46,26 +46,6 @@ func Test_Pids(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func Test_Pids_Fail(t *testing.T) {
|
||||
if runtime.GOOS != "darwin" {
|
||||
t.Skip("darwin only")
|
||||
}
|
||||
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
|
||||
invoke = common.FakeInvoke{Suffix: "fail"}
|
||||
ret, err := Pids()
|
||||
skipIfNotImplementedErr(t, err)
|
||||
invoke = common.Invoke{}
|
||||
if err != nil {
|
||||
t.Errorf("error %v", err)
|
||||
}
|
||||
if len(ret) != 9 {
|
||||
t.Errorf("wrong getted pid nums: %v/%d", ret, len(ret))
|
||||
}
|
||||
}
|
||||
|
||||
func Test_Pid_exists(t *testing.T) {
|
||||
checkPid := os.Getpid()
|
||||
|
||||
|
@ -189,7 +189,7 @@ type winLUIDAndAttributes struct {
|
||||
}
|
||||
|
||||
// TOKEN_PRIVILEGES
|
||||
type winTokenPriviledges struct {
|
||||
type winTokenPrivileges struct {
|
||||
PrivilegeCount winDWord
|
||||
Privileges [1]winLUIDAndAttributes
|
||||
}
|
||||
@ -218,23 +218,23 @@ func init() {
|
||||
}
|
||||
defer token.Close()
|
||||
|
||||
tokenPriviledges := winTokenPriviledges{PrivilegeCount: 1}
|
||||
tokenPrivileges := winTokenPrivileges{PrivilegeCount: 1}
|
||||
lpName := syscall.StringToUTF16("SeDebugPrivilege")
|
||||
ret, _, _ := procLookupPrivilegeValue.Call(
|
||||
0,
|
||||
uintptr(unsafe.Pointer(&lpName[0])),
|
||||
uintptr(unsafe.Pointer(&tokenPriviledges.Privileges[0].Luid)))
|
||||
uintptr(unsafe.Pointer(&tokenPrivileges.Privileges[0].Luid)))
|
||||
if ret == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
tokenPriviledges.Privileges[0].Attributes = 0x00000002 // SE_PRIVILEGE_ENABLED
|
||||
tokenPrivileges.Privileges[0].Attributes = 0x00000002 // SE_PRIVILEGE_ENABLED
|
||||
|
||||
procAdjustTokenPrivileges.Call(
|
||||
uintptr(token),
|
||||
0,
|
||||
uintptr(unsafe.Pointer(&tokenPriviledges)),
|
||||
uintptr(unsafe.Sizeof(tokenPriviledges)),
|
||||
uintptr(unsafe.Pointer(&tokenPrivileges)),
|
||||
uintptr(unsafe.Sizeof(tokenPrivileges)),
|
||||
0,
|
||||
0)
|
||||
}
|
||||
@ -435,15 +435,6 @@ func (p *Process) CwdWithContext(_ context.Context) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (p *Process) ParentWithContext(ctx context.Context) (*Process, error) {
|
||||
ppid, err := p.PpidWithContext(ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not get ParentProcessID: %s", err)
|
||||
}
|
||||
|
||||
return NewProcessWithContext(ctx, ppid)
|
||||
}
|
||||
|
||||
func (p *Process) StatusWithContext(ctx context.Context) ([]string, error) {
|
||||
return []string{""}, common.ErrNotImplementedError
|
||||
}
|
||||
@ -703,6 +694,9 @@ func (p *Process) OpenFilesWithContext(ctx context.Context) ([]OpenFilesStat, er
|
||||
0, true, windows.DUPLICATE_SAME_ACCESS) != nil {
|
||||
continue
|
||||
}
|
||||
// release the new handle
|
||||
defer windows.CloseHandle(windows.Handle(file))
|
||||
|
||||
fileType, _ := windows.GetFileType(windows.Handle(file))
|
||||
if fileType != windows.FILE_TYPE_DISK {
|
||||
continue
|
||||
|
10
process/testdata/darwin/ps-ax-opid_fail
vendored
10
process/testdata/darwin/ps-ax-opid_fail
vendored
@ -1,10 +0,0 @@
|
||||
PID
|
||||
245
|
||||
247
|
||||
248
|
||||
249
|
||||
254
|
||||
262
|
||||
264
|
||||
265
|
||||
267
|
Loading…
x
Reference in New Issue
Block a user