deps: use upstream gopsutil once more

The PR we needed https://github.com/shirou/gopsutil/pull/889 has been merged
upstream, which means we can use upstream rather than our fork of psutil.
This commit is contained in:
Seth Hoenig
2020-10-17 08:54:50 -05:00
parent 799d3e7df7
commit 10cc366305
47 changed files with 1226 additions and 866 deletions

3
go.mod
View File

@@ -11,7 +11,6 @@ replace (
github.com/hashicorp/go-discover => github.com/hashicorp/go-discover v0.0.0-20200812215701-c4b85f6ed31f
github.com/hashicorp/nomad/api => ./api
github.com/kr/pty => github.com/kr/pty v1.1.5
github.com/shirou/gopsutil => github.com/hashicorp/gopsutil v2.18.13-0.20200531184148-5aca383d4f9d+incompatible
)
require (
@@ -111,7 +110,7 @@ require (
github.com/ryanuber/go-glob v1.0.0
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529
github.com/seccomp/libseccomp-golang v0.9.2-0.20200314001724-bdab42bd5128 // indirect
github.com/shirou/gopsutil v2.20.2+incompatible
github.com/shirou/gopsutil v2.20.9+incompatible
github.com/skratchdot/open-golang v0.0.0-20160302144031-75fb7ed4208c
github.com/stretchr/objx v0.2.0 // indirect
github.com/stretchr/testify v1.6.1

5
go.sum
View File

@@ -415,8 +415,6 @@ github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ
github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/gopsutil v2.18.13-0.20200531184148-5aca383d4f9d+incompatible h1:3dtKc7GWJY4Mm85E1kczAN4JuBFM3kamwt5Zx426Yl8=
github.com/hashicorp/gopsutil v2.18.13-0.20200531184148-5aca383d4f9d+incompatible/go.mod h1:Mz8xr0ujmCW1qsmWMIUDOc+RgaN9QMvrgnBzQF12nYM=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hashicorp/hcl v1.0.1-0.20191016231534-914dc3f8dd7c h1:PdZEHcpa3117kJ1Wa5EYupzCzn9QlBby8Fx2YpZPYvo=
github.com/hashicorp/hcl v1.0.1-0.20191016231534-914dc3f8dd7c/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
@@ -678,6 +676,9 @@ github.com/seccomp/libseccomp-golang v0.9.2-0.20200314001724-bdab42bd5128 h1:vWI
github.com/seccomp/libseccomp-golang v0.9.2-0.20200314001724-bdab42bd5128/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg=
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/shirou/gopsutil v0.0.0-20181107111621-48177ef5f880/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
github.com/shirou/gopsutil v2.20.9+incompatible h1:msXs2frUV+O/JLva9EDLpuJ84PrFsdCTCQex8PUdtkQ=
github.com/shirou/gopsutil v2.20.9+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=

View File

@@ -149,7 +149,9 @@ func PercentWithContext(ctx context.Context, interval time.Duration, percpu bool
return nil, err
}
time.Sleep(interval)
if err := common.Sleep(ctx, interval); err != nil {
return nil, err
}
// And at the end of the interval.
cpuTimes2, err := Times(percpu)

161
vendor/github.com/shirou/gopsutil/cpu/cpu_dragonfly.go generated vendored Normal file
View File

@@ -0,0 +1,161 @@
package cpu
import (
"context"
"fmt"
"os/exec"
"reflect"
"regexp"
"runtime"
"strconv"
"strings"
"unsafe"
"github.com/shirou/gopsutil/internal/common"
"golang.org/x/sys/unix"
)
var ClocksPerSec = float64(128)
var cpuMatch = regexp.MustCompile(`^CPU:`)
var originMatch = regexp.MustCompile(`Origin\s*=\s*"(.+)"\s+Id\s*=\s*(.+)\s+Stepping\s*=\s*(.+)`)
var featuresMatch = regexp.MustCompile(`Features=.+<(.+)>`)
var featuresMatch2 = regexp.MustCompile(`Features2=[a-f\dx]+<(.+)>`)
var cpuEnd = regexp.MustCompile(`^Trying to mount root`)
var cpuTimesSize int
var emptyTimes cpuTimes
func init() {
getconf, err := exec.LookPath("getconf")
if err != nil {
return
}
out, err := invoke.Command(getconf, "CLK_TCK")
// ignore errors
if err == nil {
i, err := strconv.ParseFloat(strings.TrimSpace(string(out)), 64)
if err == nil {
ClocksPerSec = float64(i)
}
}
}
func timeStat(name string, t *cpuTimes) *TimesStat {
return &TimesStat{
User: float64(t.User) / ClocksPerSec,
Nice: float64(t.Nice) / ClocksPerSec,
System: float64(t.Sys) / ClocksPerSec,
Idle: float64(t.Idle) / ClocksPerSec,
Irq: float64(t.Intr) / ClocksPerSec,
CPU: name,
}
}
func Times(percpu bool) ([]TimesStat, error) {
return TimesWithContext(context.Background(), percpu)
}
func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) {
if percpu {
buf, err := unix.SysctlRaw("kern.cp_times")
if err != nil {
return nil, err
}
// We can't do this in init due to the conflict with cpu.init()
if cpuTimesSize == 0 {
cpuTimesSize = int(reflect.TypeOf(cpuTimes{}).Size())
}
ncpus := len(buf) / cpuTimesSize
ret := make([]TimesStat, 0, ncpus)
for i := 0; i < ncpus; i++ {
times := (*cpuTimes)(unsafe.Pointer(&buf[i*cpuTimesSize]))
if *times == emptyTimes {
// CPU not present
continue
}
ret = append(ret, *timeStat(fmt.Sprintf("cpu%d", len(ret)), times))
}
return ret, nil
}
buf, err := unix.SysctlRaw("kern.cp_time")
if err != nil {
return nil, err
}
times := (*cpuTimes)(unsafe.Pointer(&buf[0]))
return []TimesStat{*timeStat("cpu-total", times)}, nil
}
// Returns only one InfoStat on DragonflyBSD. The information regarding core
// count, however is accurate and it is assumed that all InfoStat attributes
// are the same across CPUs.
func Info() ([]InfoStat, error) {
return InfoWithContext(context.Background())
}
func InfoWithContext(ctx context.Context) ([]InfoStat, error) {
const dmesgBoot = "/var/run/dmesg.boot"
c, err := parseDmesgBoot(dmesgBoot)
if err != nil {
return nil, err
}
var u32 uint32
if u32, err = unix.SysctlUint32("hw.clockrate"); err != nil {
return nil, err
}
c.Mhz = float64(u32)
var num int
var buf string
if buf, err = unix.Sysctl("hw.cpu_topology.tree"); err != nil {
return nil, err
}
num = strings.Count(buf, "CHIP")
c.Cores = int32(strings.Count(string(buf), "CORE") / num)
if c.ModelName, err = unix.Sysctl("hw.model"); err != nil {
return nil, err
}
ret := make([]InfoStat, num)
for i := 0; i < num; i++ {
ret[i] = c
}
return ret, nil
}
func parseDmesgBoot(fileName string) (InfoStat, error) {
c := InfoStat{}
lines, _ := common.ReadLines(fileName)
for _, line := range lines {
if matches := cpuEnd.FindStringSubmatch(line); matches != nil {
break
} else if matches := originMatch.FindStringSubmatch(line); matches != nil {
c.VendorID = matches[1]
t, err := strconv.ParseInt(matches[2], 10, 32)
if err != nil {
return c, fmt.Errorf("unable to parse DragonflyBSD CPU stepping information from %q: %v", line, err)
}
c.Stepping = int32(t)
} else if matches := featuresMatch.FindStringSubmatch(line); matches != nil {
for _, v := range strings.Split(matches[1], ",") {
c.Flags = append(c.Flags, strings.ToLower(v))
}
} else if matches := featuresMatch2.FindStringSubmatch(line); matches != nil {
for _, v := range strings.Split(matches[1], ",") {
c.Flags = append(c.Flags, strings.ToLower(v))
}
}
}
return c, nil
}
func CountsWithContext(ctx context.Context, logical bool) (int, error) {
return runtime.NumCPU(), nil
}

View File

@@ -0,0 +1,9 @@
package cpu
type cpuTimes struct {
User uint64
Nice uint64
Sys uint64
Intr uint64
Idle uint64
}

View File

@@ -1,4 +1,4 @@
// +build !darwin,!linux,!freebsd,!openbsd,!solaris,!windows
// +build !darwin,!linux,!freebsd,!openbsd,!solaris,!windows,!dragonfly
package cpu

View File

@@ -7,6 +7,7 @@ import (
"errors"
"fmt"
"os/exec"
"path/filepath"
"strconv"
"strings"
@@ -311,7 +312,23 @@ func CountsWithContext(ctx context.Context, logical bool) (int, error) {
}
return ret, nil
}
// physical cores https://github.com/giampaolo/psutil/blob/d01a9eaa35a8aadf6c519839e987a49d8be2d891/psutil/_pslinux.py#L628
// physical cores
// https://github.com/giampaolo/psutil/blob/122174a10b75c9beebe15f6c07dcf3afbe3b120d/psutil/_pslinux.py#L621-L629
var threadSiblingsLists = make(map[string]bool)
if files, err := filepath.Glob(common.HostSys("devices/system/cpu/cpu[0-9]*/topology/thread_siblings_list")); err == nil {
for _, file := range files {
lines, err := common.ReadLines(file)
if err != nil || len(lines) != 1 {
continue
}
threadSiblingsLists[lines[0]] = true
}
ret := len(threadSiblingsLists)
if ret != 0 {
return ret, nil
}
}
// https://github.com/giampaolo/psutil/blob/122174a10b75c9beebe15f6c07dcf3afbe3b120d/psutil/_pslinux.py#L631-L652
filename := common.HostProc("cpuinfo")
lines, err := common.ReadLines(filename)
if err != nil {

View File

@@ -32,7 +32,6 @@ const (
CTLKern = 1 // "high kernel": proc, limits
CTLHw = 6 // CTL_HW
SMT = 24 // HW_SMT
NCpuOnline = 25 // HW_NCPUONLINE
KernCptime = 40 // KERN_CPTIME
KernCptime2 = 71 // KERN_CPTIME2
)
@@ -163,25 +162,17 @@ func InfoWithContext(ctx context.Context) ([]InfoStat, error) {
c := InfoStat{}
var u32 uint32
if u32, err = unix.SysctlUint32("hw.cpuspeed"); err != nil {
return nil, err
}
c.Mhz = float64(u32)
mib := []int32{CTLHw, NCpuOnline}
buf, _, err := common.CallSyscall(mib)
mhz, err := unix.SysctlUint32("hw.cpuspeed")
if err != nil {
return nil, err
}
c.Mhz = float64(mhz)
var ncpu int32
br := bytes.NewReader(buf)
err = binary.Read(br, binary.LittleEndian, &ncpu)
ncpu, err := unix.SysctlUint32("hw.ncpuonline")
if err != nil {
return nil, err
}
c.Cores = ncpu
c.Cores = int32(ncpu)
if c.ModelName, err = unix.Sysctl("hw.model"); err != nil {
return nil, err

View File

@@ -84,9 +84,9 @@ func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, erro
}
d := PartitionStat{
Device: common.IntToString(stat.Mntfromname[:]),
Mountpoint: common.IntToString(stat.Mntonname[:]),
Fstype: common.IntToString(stat.Fstypename[:]),
Device: common.ByteToString(stat.Mntfromname[:]),
Mountpoint: common.ByteToString(stat.Mntonname[:]),
Fstype: common.ByteToString(stat.Fstypename[:]),
Opts: opts,
}
if all == false {
@@ -170,5 +170,5 @@ func parseDevstat(buf []byte) (Devstat, error) {
}
func getFsType(stat unix.Statfs_t) string {
return common.IntToString(stat.Fstypename[:])
return common.ByteToString(stat.Fstypename[:])
}

View File

@@ -1,5 +1,7 @@
// +build openbsd
// +build 386
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
// cgo -godefs types_openbsd.go
// cgo -godefs disk/types_openbsd.go
package disk

View File

@@ -1,7 +1,11 @@
package host
import (
"context"
"encoding/json"
"os"
"runtime"
"time"
"github.com/shirou/gopsutil/internal/common"
)
@@ -52,3 +56,99 @@ func (t TemperatureStat) String() string {
s, _ := json.Marshal(t)
return string(s)
}
func Info() (*InfoStat, error) {
return InfoWithContext(context.Background())
}
func InfoWithContext(ctx context.Context) (*InfoStat, error) {
var err error
ret := &InfoStat{
OS: runtime.GOOS,
}
ret.Hostname, err = os.Hostname()
if err != nil && err != common.ErrNotImplementedError {
return nil, err
}
ret.Platform, ret.PlatformFamily, ret.PlatformVersion, err = PlatformInformationWithContext(ctx)
if err != nil && err != common.ErrNotImplementedError {
return nil, err
}
ret.KernelVersion, err = KernelVersionWithContext(ctx)
if err != nil && err != common.ErrNotImplementedError {
return nil, err
}
ret.KernelArch, err = KernelArch()
if err != nil && err != common.ErrNotImplementedError {
return nil, err
}
ret.VirtualizationSystem, ret.VirtualizationRole, err = VirtualizationWithContext(ctx)
if err != nil && err != common.ErrNotImplementedError {
return nil, err
}
ret.BootTime, err = BootTimeWithContext(ctx)
if err != nil && err != common.ErrNotImplementedError {
return nil, err
}
ret.Uptime, err = UptimeWithContext(ctx)
if err != nil && err != common.ErrNotImplementedError {
return nil, err
}
ret.Procs, err = numProcs(ctx)
if err != nil && err != common.ErrNotImplementedError {
return nil, err
}
ret.HostID, err = HostIDWithContext(ctx)
if err != nil && err != common.ErrNotImplementedError {
return nil, err
}
return ret, nil
}
// BootTime returns the system boot time expressed in seconds since the epoch.
func BootTime() (uint64, error) {
return BootTimeWithContext(context.Background())
}
func Uptime() (uint64, error) {
return UptimeWithContext(context.Background())
}
func Users() ([]UserStat, error) {
return UsersWithContext(context.Background())
}
func PlatformInformation() (string, string, string, error) {
return PlatformInformationWithContext(context.Background())
}
// HostID returns the unique host ID provided by the OS.
func HostID() (string, error) {
return HostIDWithContext(context.Background())
}
func Virtualization() (string, string, error) {
return VirtualizationWithContext(context.Background())
}
func KernelVersion() (string, error) {
return KernelVersionWithContext(context.Background())
}
func SensorsTemperatures() ([]TemperatureStat, error) {
return SensorsTemperaturesWithContext(context.Background())
}
func timeSince(ts uint64) uint64 {
return uint64(time.Now().Unix()) - ts
}

36
vendor/github.com/shirou/gopsutil/host/host_bsd.go generated vendored Normal file
View File

@@ -0,0 +1,36 @@
// +build darwin freebsd openbsd
package host
import (
"context"
"sync/atomic"
"golang.org/x/sys/unix"
)
// cachedBootTime must be accessed via atomic.Load/StoreUint64
var cachedBootTime uint64
func BootTimeWithContext(ctx context.Context) (uint64, error) {
t := atomic.LoadUint64(&cachedBootTime)
if t != 0 {
return t, nil
}
tv, err := unix.SysctlTimeval("kern.boottime")
if err != nil {
return 0, err
}
atomic.StoreUint64(&cachedBootTime, uint64(tv.Sec))
return uint64(tv.Sec), nil
}
func UptimeWithContext(ctx context.Context) (uint64, error) {
boot, err := BootTimeWithContext(ctx)
if err != nil {
return 0, err
}
return timeSince(boot), nil
}

View File

@@ -9,10 +9,7 @@ import (
"io/ioutil"
"os"
"os/exec"
"runtime"
"strings"
"sync/atomic"
"time"
"unsafe"
"github.com/shirou/gopsutil/internal/common"
@@ -23,107 +20,20 @@ import (
// from utmpx.h
const USER_PROCESS = 7
func Info() (*InfoStat, error) {
return InfoWithContext(context.Background())
}
func InfoWithContext(ctx context.Context) (*InfoStat, error) {
ret := &InfoStat{
OS: runtime.GOOS,
PlatformFamily: "darwin",
}
hostname, err := os.Hostname()
if err == nil {
ret.Hostname = hostname
}
kernelVersion, err := KernelVersionWithContext(ctx)
if err == nil {
ret.KernelVersion = kernelVersion
}
kernelArch, err := kernelArch()
if err == nil {
ret.KernelArch = kernelArch
}
platform, family, pver, err := PlatformInformation()
if err == nil {
ret.Platform = platform
ret.PlatformFamily = family
ret.PlatformVersion = pver
}
system, role, err := Virtualization()
if err == nil {
ret.VirtualizationSystem = system
ret.VirtualizationRole = role
}
boot, err := BootTime()
if err == nil {
ret.BootTime = boot
ret.Uptime = uptime(boot)
}
procs, err := process.Pids()
if err == nil {
ret.Procs = uint64(len(procs))
}
func HostIDWithContext(ctx context.Context) (string, error) {
uuid, err := unix.Sysctl("kern.uuid")
if err == nil && uuid != "" {
ret.HostID = strings.ToLower(uuid)
if err != nil {
return "", err
}
return ret, nil
return strings.ToLower(uuid), err
}
// cachedBootTime must be accessed via atomic.Load/StoreUint64
var cachedBootTime uint64
func BootTime() (uint64, error) {
return BootTimeWithContext(context.Background())
}
func BootTimeWithContext(ctx context.Context) (uint64, error) {
// https://github.com/AaronO/dashd/blob/222e32ef9f7a1f9bea4a8da2c3627c4cb992f860/probe/probe_darwin.go
t := atomic.LoadUint64(&cachedBootTime)
if t != 0 {
return t, nil
}
value, err := unix.Sysctl("kern.boottime")
func numProcs(ctx context.Context) (uint64, error) {
procs, err := process.PidsWithContext(ctx)
if err != nil {
return 0, err
}
bytes := []byte(value[:])
var boottime uint64
boottime = uint64(bytes[0]) + uint64(bytes[1])*256 + uint64(bytes[2])*256*256 + uint64(bytes[3])*256*256*256
atomic.StoreUint64(&cachedBootTime, boottime)
return boottime, nil
}
func uptime(boot uint64) uint64 {
return uint64(time.Now().Unix()) - boot
}
func Uptime() (uint64, error) {
return UptimeWithContext(context.Background())
}
func UptimeWithContext(ctx context.Context) (uint64, error) {
boot, err := BootTimeWithContext(ctx)
if err != nil {
return 0, err
}
return uptime(boot), nil
}
func Users() ([]UserStat, error) {
return UsersWithContext(context.Background())
return uint64(len(procs)), nil
}
func UsersWithContext(ctx context.Context) ([]UserStat, error) {
@@ -170,10 +80,6 @@ func UsersWithContext(ctx context.Context) ([]UserStat, error) {
}
func PlatformInformation() (string, string, string, error) {
return PlatformInformationWithContext(context.Background())
}
func PlatformInformationWithContext(ctx context.Context) (string, string, string, error) {
platform := ""
family := ""
@@ -207,18 +113,10 @@ func PlatformInformationWithContext(ctx context.Context) (string, string, string
return platform, family, pver, nil
}
func Virtualization() (string, string, error) {
return VirtualizationWithContext(context.Background())
}
func VirtualizationWithContext(ctx context.Context) (string, string, error) {
return "", "", common.ErrNotImplementedError
}
func KernelVersion() (string, error) {
return KernelVersionWithContext(context.Background())
}
func KernelVersionWithContext(ctx context.Context) (string, error) {
version, err := unix.Sysctl("kern.osrelease")
return strings.ToLower(version), err

View File

@@ -0,0 +1,22 @@
// +build darwin
// +build arm64
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
// cgo -godefs host/types_darwin.go
package host
type Utmpx struct {
User [256]int8
Id [4]int8
Line [32]int8
Pid int32
Type int16
Tv Timeval
Host [256]int8
Pad [16]uint32
}
type Timeval struct {
Sec int64
Usec int32
Pad_cgo_0 [4]byte
}

View File

@@ -8,10 +8,6 @@ package host
import "C"
import "context"
func SensorsTemperatures() ([]TemperatureStat, error) {
return SensorsTemperaturesWithContext(context.Background())
}
func SensorsTemperaturesWithContext(ctx context.Context) ([]TemperatureStat, error) {
temperatureKeys := []string{
C.AMBIENT_AIR_0,

View File

@@ -9,10 +9,6 @@ import (
"github.com/shirou/gopsutil/internal/common"
)
func SensorsTemperatures() ([]TemperatureStat, error) {
return SensorsTemperaturesWithContext(context.Background())
}
func SensorsTemperaturesWithContext(ctx context.Context) ([]TemperatureStat, error) {
return []TemperatureStat{}, common.ErrNotImplementedError
}

View File

@@ -8,58 +8,42 @@ import (
"github.com/shirou/gopsutil/internal/common"
)
func Info() (*InfoStat, error) {
return InfoWithContext(context.Background())
func HostIDWithContext(ctx context.Context) (string, error) {
return "", common.ErrNotImplementedError
}
func InfoWithContext(ctx context.Context) (*InfoStat, error) {
return nil, common.ErrNotImplementedError
}
func BootTime() (uint64, error) {
return BootTimeWithContext(context.Background())
func numProcs(ctx context.Context) (uint64, error) {
return 0, common.ErrNotImplementedError
}
func BootTimeWithContext(ctx context.Context) (uint64, error) {
return 0, common.ErrNotImplementedError
}
func Uptime() (uint64, error) {
return UptimeWithContext(context.Background())
}
func UptimeWithContext(ctx context.Context) (uint64, error) {
return 0, common.ErrNotImplementedError
}
func Users() ([]UserStat, error) {
return UsersWithContext(context.Background())
}
func UsersWithContext(ctx context.Context) ([]UserStat, error) {
return []UserStat{}, common.ErrNotImplementedError
}
func Virtualization() (string, string, error) {
return VirtualizationWithContext(context.Background())
}
func VirtualizationWithContext(ctx context.Context) (string, string, error) {
return "", "", common.ErrNotImplementedError
}
func KernelVersion() (string, error) {
return KernelVersionWithContext(context.Background())
}
func KernelVersionWithContext(ctx context.Context) (string, error) {
return "", common.ErrNotImplementedError
}
func PlatformInformation() (string, string, string, error) {
return PlatformInformationWithContext(context.Background())
}
func PlatformInformationWithContext(ctx context.Context) (string, string, string, error) {
return "", "", "", common.ErrNotImplementedError
}
func SensorsTemperaturesWithContext(ctx context.Context) ([]TemperatureStat, error) {
return []TemperatureStat{}, common.ErrNotImplementedError
}
func KernelArch() (string, error) {
return "", common.ErrNotImplementedError
}

View File

@@ -9,11 +9,7 @@ import (
"io/ioutil"
"math"
"os"
"runtime"
"strings"
"sync/atomic"
"syscall"
"time"
"unsafe"
"github.com/shirou/gopsutil/internal/common"
@@ -27,100 +23,20 @@ const (
UTHostSize = 16
)
func Info() (*InfoStat, error) {
return InfoWithContext(context.Background())
func HostIDWithContext(ctx context.Context) (string, error) {
uuid, err := unix.Sysctl("kern.hostuuid")
if err != nil {
return "", err
}
return strings.ToLower(uuid), err
}
func InfoWithContext(ctx context.Context) (*InfoStat, error) {
ret := &InfoStat{
OS: runtime.GOOS,
PlatformFamily: "freebsd",
}
hostname, err := os.Hostname()
if err == nil {
ret.Hostname = hostname
}
platform, family, version, err := PlatformInformation()
if err == nil {
ret.Platform = platform
ret.PlatformFamily = family
ret.PlatformVersion = version
ret.KernelVersion = version
}
kernelArch, err := kernelArch()
if err == nil {
ret.KernelArch = kernelArch
}
system, role, err := Virtualization()
if err == nil {
ret.VirtualizationSystem = system
ret.VirtualizationRole = role
}
boot, err := BootTime()
if err == nil {
ret.BootTime = boot
ret.Uptime = uptime(boot)
}
procs, err := process.Pids()
if err == nil {
ret.Procs = uint64(len(procs))
}
hostid, err := unix.Sysctl("kern.hostuuid")
if err == nil && hostid != "" {
ret.HostID = strings.ToLower(hostid)
}
return ret, nil
}
// cachedBootTime must be accessed via atomic.Load/StoreUint64
var cachedBootTime uint64
func BootTime() (uint64, error) {
return BootTimeWithContext(context.Background())
}
func BootTimeWithContext(ctx context.Context) (uint64, error) {
t := atomic.LoadUint64(&cachedBootTime)
if t != 0 {
return t, nil
}
buf, err := unix.SysctlRaw("kern.boottime")
func numProcs(ctx context.Context) (uint64, error) {
procs, err := process.PidsWithContext(ctx)
if err != nil {
return 0, err
}
tv := *(*syscall.Timeval)(unsafe.Pointer((&buf[0])))
atomic.StoreUint64(&cachedBootTime, uint64(tv.Sec))
return t, nil
}
func uptime(boot uint64) uint64 {
return uint64(time.Now().Unix()) - boot
}
func Uptime() (uint64, error) {
return UptimeWithContext(context.Background())
}
func UptimeWithContext(ctx context.Context) (uint64, error) {
boot, err := BootTime()
if err != nil {
return 0, err
}
return uptime(boot), nil
}
func Users() ([]UserStat, error) {
return UsersWithContext(context.Background())
return uint64(len(procs)), nil
}
func UsersWithContext(ctx context.Context) ([]UserStat, error) {
@@ -168,10 +84,6 @@ func UsersWithContext(ctx context.Context) ([]UserStat, error) {
}
func PlatformInformation() (string, string, string, error) {
return PlatformInformationWithContext(context.Background())
}
func PlatformInformationWithContext(ctx context.Context) (string, string, string, error) {
platform, err := unix.Sysctl("kern.ostype")
if err != nil {
@@ -186,10 +98,6 @@ func PlatformInformationWithContext(ctx context.Context) (string, string, string
return strings.ToLower(platform), "", strings.ToLower(version), nil
}
func Virtualization() (string, string, error) {
return VirtualizationWithContext(context.Background())
}
func VirtualizationWithContext(ctx context.Context) (string, string, error) {
return "", "", common.ErrNotImplementedError
}
@@ -233,19 +141,11 @@ func getUsersFromUtmp(utmpfile string) ([]UserStat, error) {
return ret, nil
}
func SensorsTemperatures() ([]TemperatureStat, error) {
return SensorsTemperaturesWithContext(context.Background())
}
func SensorsTemperaturesWithContext(ctx context.Context) ([]TemperatureStat, error) {
return []TemperatureStat{}, common.ErrNotImplementedError
}
func KernelVersion() (string, error) {
return KernelVersionWithContext(context.Background())
}
func KernelVersionWithContext(ctx context.Context) (string, error) {
_, _, version, err := PlatformInformation()
_, _, version, err := PlatformInformationWithContext(ctx)
return version, err
}

View File

@@ -12,10 +12,8 @@ import (
"os/exec"
"path/filepath"
"regexp"
"runtime"
"strconv"
"strings"
"time"
"github.com/shirou/gopsutil/internal/common"
"golang.org/x/sys/unix"
@@ -31,52 +29,7 @@ type LSB struct {
// from utmp.h
const USER_PROCESS = 7
func Info() (*InfoStat, error) {
return InfoWithContext(context.Background())
}
func InfoWithContext(ctx context.Context) (*InfoStat, error) {
ret := &InfoStat{
OS: runtime.GOOS,
}
hostname, err := os.Hostname()
if err == nil {
ret.Hostname = hostname
}
platform, family, version, err := PlatformInformation()
if err == nil {
ret.Platform = platform
ret.PlatformFamily = family
ret.PlatformVersion = version
}
kernelVersion, err := KernelVersion()
if err == nil {
ret.KernelVersion = kernelVersion
}
kernelArch, err := kernelArch()
if err == nil {
ret.KernelArch = kernelArch
}
system, role, err := Virtualization()
if err == nil {
ret.VirtualizationSystem = system
ret.VirtualizationRole = role
}
boot, err := BootTime()
if err == nil {
ret.BootTime = boot
ret.Uptime = uptime(boot)
}
if numProcs, err := common.NumProcs(); err == nil {
ret.Procs = numProcs
}
func HostIDWithContext(ctx context.Context) (string, error) {
sysProductUUID := common.HostSys("class/dmi/id/product_uuid")
machineID := common.HostEtc("machine-id")
procSysKernelRandomBootID := common.HostProc("sys/kernel/random/boot_id")
@@ -86,8 +39,7 @@ func InfoWithContext(ctx context.Context) (*InfoStat, error) {
case common.PathExists(sysProductUUID):
lines, err := common.ReadLines(sysProductUUID)
if err == nil && len(lines) > 0 && lines[0] != "" {
ret.HostID = strings.ToLower(lines[0])
break
return strings.ToLower(lines[0]), nil
}
fallthrough
// Fallback on GNU Linux systems with systemd, readable by everyone
@@ -95,48 +47,34 @@ func InfoWithContext(ctx context.Context) (*InfoStat, error) {
lines, err := common.ReadLines(machineID)
if err == nil && len(lines) > 0 && len(lines[0]) == 32 {
st := lines[0]
ret.HostID = fmt.Sprintf("%s-%s-%s-%s-%s", st[0:8], st[8:12], st[12:16], st[16:20], st[20:32])
break
return fmt.Sprintf("%s-%s-%s-%s-%s", st[0:8], st[8:12], st[12:16], st[16:20], st[20:32]), nil
}
fallthrough
// Not stable between reboot, but better than nothing
default:
lines, err := common.ReadLines(procSysKernelRandomBootID)
if err == nil && len(lines) > 0 && lines[0] != "" {
ret.HostID = strings.ToLower(lines[0])
return strings.ToLower(lines[0]), nil
}
}
return ret, nil
return "", nil
}
// BootTime returns the system boot time expressed in seconds since the epoch.
func BootTime() (uint64, error) {
return BootTimeWithContext(context.Background())
func numProcs(ctx context.Context) (uint64, error) {
return common.NumProcs()
}
func BootTimeWithContext(ctx context.Context) (uint64, error) {
return common.BootTimeWithContext(ctx)
}
func uptime(boot uint64) uint64 {
return uint64(time.Now().Unix()) - boot
}
func Uptime() (uint64, error) {
return UptimeWithContext(context.Background())
}
func UptimeWithContext(ctx context.Context) (uint64, error) {
boot, err := BootTime()
if err != nil {
sysinfo := &unix.Sysinfo_t{}
if err := unix.Sysinfo(sysinfo); err != nil {
return 0, err
}
return uptime(boot), nil
}
func Users() ([]UserStat, error) {
return UsersWithContext(context.Background())
return uint64(sysinfo.Uptime), nil
}
func UsersWithContext(ctx context.Context) ([]UserStat, error) {
@@ -236,12 +174,7 @@ func getLSB() (*LSB, error) {
return ret, nil
}
func PlatformInformation() (platform string, family string, version string, err error) {
return PlatformInformationWithContext(context.Background())
}
func PlatformInformationWithContext(ctx context.Context) (platform string, family string, version string, err error) {
lsb, err := getLSB()
if err != nil {
lsb = &LSB{}
@@ -370,10 +303,6 @@ func PlatformInformationWithContext(ctx context.Context) (platform string, famil
}
func KernelVersion() (version string, err error) {
return KernelVersionWithContext(context.Background())
}
func KernelVersionWithContext(ctx context.Context) (version string, err error) {
var utsname unix.Utsname
err = unix.Uname(&utsname)
@@ -432,18 +361,10 @@ func getSusePlatform(contents []string) string {
return "suse"
}
func Virtualization() (string, string, error) {
return VirtualizationWithContext(context.Background())
}
func VirtualizationWithContext(ctx context.Context) (string, string, error) {
return common.VirtualizationWithContext(ctx)
}
func SensorsTemperatures() ([]TemperatureStat, error) {
return SensorsTemperaturesWithContext(context.Background())
}
func SensorsTemperaturesWithContext(ctx context.Context) ([]TemperatureStat, error) {
var temperatures []TemperatureStat
files, err := filepath.Glob(common.HostSys("/class/hwmon/hwmon*/temp*_*"))

View File

@@ -0,0 +1,47 @@
// Created by cgo -godefs - DO NOT EDIT
// cgo -godefs types_linux.go
package host
const (
sizeofPtr = 0x8
sizeofShort = 0x2
sizeofInt = 0x4
sizeofLong = 0x8
sizeofLongLong = 0x8
sizeOfUtmp = 0x180
)
type (
_C_short int16
_C_int int32
_C_long int64
_C_long_long int64
)
type utmp struct {
Type int16
Pid int32
Line [32]int8
Id [4]int8
User [32]int8
Host [256]int8
Exit exit_status
Session int32
Tv _Ctype_struct___0
Addr_v6 [4]int32
X__glibc_reserved [20]uint8
}
type exit_status struct {
Termination int16
Exit int16
}
type timeval struct {
Sec int64
Usec int64
}
type _Ctype_struct___0 struct {
Sec int32
Usec int32
}

View File

@@ -8,10 +8,7 @@ import (
"encoding/binary"
"io/ioutil"
"os"
"runtime"
"strings"
"sync/atomic"
"time"
"unsafe"
"github.com/shirou/gopsutil/internal/common"
@@ -25,96 +22,16 @@ const (
UTHostSize = 16
)
func Info() (*InfoStat, error) {
return InfoWithContext(context.Background())
func HostIDWithContext(ctx context.Context) (string, error) {
return "", common.ErrNotImplementedError
}
func InfoWithContext(ctx context.Context) (*InfoStat, error) {
ret := &InfoStat{
OS: runtime.GOOS,
PlatformFamily: "openbsd",
}
hostname, err := os.Hostname()
if err == nil {
ret.Hostname = hostname
}
kernelArch, err := kernelArch()
if err == nil {
ret.KernelArch = kernelArch
}
platform, family, version, err := PlatformInformation()
if err == nil {
ret.Platform = platform
ret.PlatformFamily = family
ret.PlatformVersion = version
}
system, role, err := Virtualization()
if err == nil {
ret.VirtualizationSystem = system
ret.VirtualizationRole = role
}
procs, err := process.Pids()
if err == nil {
ret.Procs = uint64(len(procs))
}
boot, err := BootTime()
if err == nil {
ret.BootTime = boot
ret.Uptime = uptime(boot)
}
return ret, nil
}
// cachedBootTime must be accessed via atomic.Load/StoreUint64
var cachedBootTime uint64
func BootTime() (uint64, error) {
return BootTimeWithContext(context.Background())
}
func BootTimeWithContext(ctx context.Context) (uint64, error) {
// https://github.com/AaronO/dashd/blob/222e32ef9f7a1f9bea4a8da2c3627c4cb992f860/probe/probe_darwin.go
t := atomic.LoadUint64(&cachedBootTime)
if t != 0 {
return t, nil
}
value, err := unix.Sysctl("kern.boottime")
func numProcs(ctx context.Context) (uint64, error) {
procs, err := process.PidsWithContext(ctx)
if err != nil {
return 0, err
}
bytes := []byte(value[:])
var boottime uint64
boottime = uint64(bytes[0]) + uint64(bytes[1])*256 + uint64(bytes[2])*256*256 + uint64(bytes[3])*256*256*256
atomic.StoreUint64(&cachedBootTime, boottime)
return boottime, nil
}
func uptime(boot uint64) uint64 {
return uint64(time.Now().Unix()) - boot
}
func Uptime() (uint64, error) {
return UptimeWithContext(context.Background())
}
func UptimeWithContext(ctx context.Context) (uint64, error) {
boot, err := BootTime()
if err != nil {
return 0, err
}
return uptime(boot), nil
}
func PlatformInformation() (string, string, string, error) {
return PlatformInformationWithContext(context.Background())
return uint64(len(procs)), nil
}
func PlatformInformationWithContext(ctx context.Context) (string, string, string, error) {
@@ -134,18 +51,10 @@ func PlatformInformationWithContext(ctx context.Context) (string, string, string
return platform, family, version, nil
}
func Virtualization() (string, string, error) {
return VirtualizationWithContext(context.Background())
}
func VirtualizationWithContext(ctx context.Context) (string, string, error) {
return "", "", common.ErrNotImplementedError
}
func Users() ([]UserStat, error) {
return UsersWithContext(context.Background())
}
func UsersWithContext(ctx context.Context) ([]UserStat, error) {
var ret []UserStat
utmpfile := "/var/run/utmp"
@@ -185,19 +94,11 @@ func UsersWithContext(ctx context.Context) ([]UserStat, error) {
return ret, nil
}
func SensorsTemperatures() ([]TemperatureStat, error) {
return SensorsTemperaturesWithContext(context.Background())
}
func SensorsTemperaturesWithContext(ctx context.Context) ([]TemperatureStat, error) {
return []TemperatureStat{}, common.ErrNotImplementedError
}
func KernelVersion() (string, error) {
return KernelVersionWithContext(context.Background())
}
func KernelVersionWithContext(ctx context.Context) (string, error) {
_, _, version, err := PlatformInformation()
_, _, version, err := PlatformInformationWithContext(ctx)
return version, err
}

View File

@@ -0,0 +1,33 @@
// +build openbsd
// +build 386
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
// cgo -godefs host/types_openbsd.go
package host
const (
sizeofPtr = 0x4
sizeofShort = 0x2
sizeofInt = 0x4
sizeofLong = 0x4
sizeofLongLong = 0x8
sizeOfUtmp = 0x130
)
type (
_C_short int16
_C_int int32
_C_long int32
_C_long_long int64
)
type Utmp struct {
Line [8]int8
Name [32]int8
Host [256]int8
Time int64
}
type Timeval struct {
Sec int64
Usec int32
}

View File

@@ -8,7 +8,7 @@ import (
"golang.org/x/sys/unix"
)
func kernelArch() (string, error) {
func KernelArch() (string, error) {
var utsname unix.Utsname
err := unix.Uname(&utsname)
return string(utsname.Machine[:bytes.IndexByte(utsname.Machine[:], 0)]), err

View File

@@ -9,86 +9,19 @@ import (
"os"
"os/exec"
"regexp"
"runtime"
"strconv"
"strings"
"time"
"github.com/shirou/gopsutil/internal/common"
)
func Info() (*InfoStat, error) {
return InfoWithContext(context.Background())
}
func InfoWithContext(ctx context.Context) (*InfoStat, error) {
result := &InfoStat{
OS: runtime.GOOS,
}
hostname, err := os.Hostname()
func HostIDWithContext(ctx context.Context) (string, error) {
platform, err := parseReleaseFile()
if err != nil {
return nil, err
}
result.Hostname = hostname
// Parse versions from output of `uname(1)`
uname, err := exec.LookPath("uname")
if err != nil {
return nil, err
return "", err
}
out, err := invoke.CommandWithContext(ctx, uname, "-srv")
if err != nil {
return nil, err
}
fields := strings.Fields(string(out))
if len(fields) >= 1 {
result.PlatformFamily = fields[0]
}
if len(fields) >= 2 {
result.KernelVersion = fields[1]
}
if len(fields) == 3 {
result.PlatformVersion = fields[2]
}
kernelArch, err := kernelArch()
if err == nil {
result.KernelArch = kernelArch
}
// Find distribution name from /etc/release
fh, err := os.Open("/etc/release")
if err != nil {
return nil, err
}
defer fh.Close()
sc := bufio.NewScanner(fh)
if sc.Scan() {
line := strings.TrimSpace(sc.Text())
switch {
case strings.HasPrefix(line, "SmartOS"):
result.Platform = "SmartOS"
case strings.HasPrefix(line, "OpenIndiana"):
result.Platform = "OpenIndiana"
case strings.HasPrefix(line, "OmniOS"):
result.Platform = "OmniOS"
case strings.HasPrefix(line, "Open Storage"):
result.Platform = "NexentaStor"
case strings.HasPrefix(line, "Solaris"):
result.Platform = "Solaris"
case strings.HasPrefix(line, "Oracle Solaris"):
result.Platform = "Solaris"
default:
result.Platform = strings.Fields(line)[0]
}
}
switch result.Platform {
case "SmartOS":
if platform == "SmartOS" {
// If everything works, use the current zone ID as the HostID if present.
zonename, err := exec.LookPath("zonename")
if err == nil {
@@ -102,59 +35,45 @@ func InfoWithContext(ctx context.Context) (*InfoStat, error) {
if line == "global" {
hostname, err := os.Hostname()
if err == nil {
result.HostID = hostname
return hostname, nil
}
} else {
result.HostID = strings.TrimSpace(line)
break
return strings.TrimSpace(line), nil
}
}
}
}
}
// If HostID is still empty, use hostid(1), which can lie to callers but at
// If HostID is still unknown, use hostid(1), which can lie to callers but at
// this point there are no hardware facilities available. This behavior
// matches that of other supported OSes.
if result.HostID == "" {
hostID, err := exec.LookPath("hostid")
hostID, err := exec.LookPath("hostid")
if err == nil {
out, err := invoke.CommandWithContext(ctx, hostID)
if err == nil {
out, err := invoke.CommandWithContext(ctx, hostID)
if err == nil {
sc := bufio.NewScanner(bytes.NewReader(out))
for sc.Scan() {
line := sc.Text()
result.HostID = strings.TrimSpace(line)
break
}
sc := bufio.NewScanner(bytes.NewReader(out))
for sc.Scan() {
line := sc.Text()
return strings.TrimSpace(line), nil
}
}
}
// Find the boot time and calculate uptime relative to it
bootTime, err := BootTime()
if err != nil {
return nil, err
}
result.BootTime = bootTime
result.Uptime = uptimeSince(bootTime)
return "", nil
}
// Count number of processes based on the number of entries in /proc
// Count number of processes based on the number of entries in /proc
func numProcs(ctx context.Context) (uint64, error) {
dirs, err := ioutil.ReadDir("/proc")
if err != nil {
return nil, err
return 0, err
}
result.Procs = uint64(len(dirs))
return result, nil
return uint64(len(dirs)), nil
}
var kstatMatch = regexp.MustCompile(`([^\s]+)[\s]+([^\s]*)`)
func BootTime() (uint64, error) {
return BootTimeWithContext(context.Background())
}
func BootTimeWithContext(ctx context.Context) (uint64, error) {
kstat, err := exec.LookPath("kstat")
if err != nil {
@@ -174,80 +93,92 @@ func BootTimeWithContext(ctx context.Context) (uint64, error) {
return strconv.ParseUint(kstats[0][2], 10, 64)
}
func Uptime() (uint64, error) {
return UptimeWithContext(context.Background())
}
func UptimeWithContext(ctx context.Context) (uint64, error) {
bootTime, err := BootTime()
if err != nil {
return 0, err
}
return uptimeSince(bootTime), nil
}
func uptimeSince(since uint64) uint64 {
return uint64(time.Now().Unix()) - since
}
func Users() ([]UserStat, error) {
return UsersWithContext(context.Background())
return timeSince(bootTime), nil
}
func UsersWithContext(ctx context.Context) ([]UserStat, error) {
return []UserStat{}, common.ErrNotImplementedError
}
func SensorsTemperatures() ([]TemperatureStat, error) {
return SensorsTemperaturesWithContext(context.Background())
}
func SensorsTemperaturesWithContext(ctx context.Context) ([]TemperatureStat, error) {
return []TemperatureStat{}, common.ErrNotImplementedError
}
func Virtualization() (string, string, error) {
return VirtualizationWithContext(context.Background())
}
func VirtualizationWithContext(ctx context.Context) (string, string, error) {
return "", "", common.ErrNotImplementedError
}
func KernelVersion() (string, error) {
return KernelVersionWithContext(context.Background())
// Find distribution name from /etc/release
func parseReleaseFile() (string, error) {
b, err := ioutil.ReadFile("/etc/release")
if err != nil {
return "", err
}
s := string(b)
s = strings.TrimSpace(s)
var platform string
switch {
case strings.HasPrefix(s, "SmartOS"):
platform = "SmartOS"
case strings.HasPrefix(s, "OpenIndiana"):
platform = "OpenIndiana"
case strings.HasPrefix(s, "OmniOS"):
platform = "OmniOS"
case strings.HasPrefix(s, "Open Storage"):
platform = "NexentaStor"
case strings.HasPrefix(s, "Solaris"):
platform = "Solaris"
case strings.HasPrefix(s, "Oracle Solaris"):
platform = "Solaris"
default:
platform = strings.Fields(s)[0]
}
return platform, nil
}
func KernelVersionWithContext(ctx context.Context) (string, error) {
// Parse versions from output of `uname(1)`
// parseUnameOutput returns platformFamily, kernelVersion and platformVersion
func parseUnameOutput(ctx context.Context) (string, string, string, error) {
uname, err := exec.LookPath("uname")
if err != nil {
return "", err
}
out, err := invoke.CommandWithContext(ctx, uname, "-srv")
if err != nil {
return "", err
}
fields := strings.Fields(string(out))
if len(fields) >= 2 {
return fields[1], nil
}
return "", fmt.Errorf("could not get kernel version")
}
func PlatformInformation() (platform string, family string, version string, err error) {
return PlatformInformationWithContext(context.Background())
}
func PlatformInformationWithContext(ctx context.Context) (platform string, family string, version string, err error) {
/* This is not finished yet at all. Please contribute! */
version, err = KernelVersion()
if err != nil {
return "", "", "", err
}
return "solaris", "solaris", version, nil
out, err := invoke.CommandWithContext(ctx, uname, "-srv")
if err != nil {
return "", "", "", err
}
fields := strings.Fields(string(out))
if len(fields) < 3 {
return "", "", "", fmt.Errorf("malformed `uname` output")
}
return fields[0], fields[1], fields[2], nil
}
func KernelVersionWithContext(ctx context.Context) (string, error) {
_, kernelVersion, _, err := parseUnameOutput(ctx)
return kernelVersion, err
}
func PlatformInformationWithContext(ctx context.Context) (string, string, string, error) {
platform, err := parseReleaseFile()
if err != nil {
return "", "", "", err
}
platformFamily, _, platformVersion, err := parseUnameOutput(ctx)
if err != nil {
return "", "", "", err
}
return platform, platformFamily, platformVersion, nil
}

View File

@@ -6,8 +6,6 @@ import (
"context"
"fmt"
"math"
"os"
"runtime"
"strings"
"sync/atomic"
"syscall"
@@ -16,7 +14,7 @@ import (
"github.com/StackExchange/wmi"
"github.com/shirou/gopsutil/internal/common"
process "github.com/shirou/gopsutil/process"
"github.com/shirou/gopsutil/process"
"golang.org/x/sys/windows"
)
@@ -64,66 +62,7 @@ type msAcpi_ThermalZoneTemperature struct {
InstanceName string
}
func Info() (*InfoStat, error) {
return InfoWithContext(context.Background())
}
func InfoWithContext(ctx context.Context) (*InfoStat, error) {
ret := &InfoStat{
OS: runtime.GOOS,
}
{
hostname, err := os.Hostname()
if err == nil {
ret.Hostname = hostname
}
}
{
platform, family, version, err := PlatformInformationWithContext(ctx)
if err == nil {
ret.Platform = platform
ret.PlatformFamily = family
ret.PlatformVersion = version
} else {
return ret, err
}
}
{
kernelArch, err := kernelArch()
if err == nil {
ret.KernelArch = kernelArch
}
}
{
boot, err := BootTimeWithContext(ctx)
if err == nil {
ret.BootTime = boot
ret.Uptime, _ = Uptime()
}
}
{
hostID, err := getMachineGuid()
if err == nil {
ret.HostID = hostID
}
}
{
procs, err := process.PidsWithContext(ctx)
if err == nil {
ret.Procs = uint64(len(procs))
}
}
return ret, nil
}
func getMachineGuid() (string, error) {
func HostIDWithContext(ctx context.Context) (string, error) {
// there has been reports of issues on 32bit using golang.org/x/sys/windows/registry, see https://github.com/shirou/gopsutil/pull/312#issuecomment-277422612
// for rationale of using windows.RegOpenKeyEx/RegQueryValueEx instead of registry.OpenKey/GetStringValue
var h windows.Handle
@@ -153,8 +92,12 @@ func getMachineGuid() (string, error) {
return strings.ToLower(hostID), nil
}
func Uptime() (uint64, error) {
return UptimeWithContext(context.Background())
func numProcs(ctx context.Context) (uint64, error) {
procs, err := process.PidsWithContext(ctx)
if err != nil {
return 0, err
}
return uint64(len(procs)), nil
}
func UptimeWithContext(ctx context.Context) (uint64, error) {
@@ -170,17 +113,9 @@ func UptimeWithContext(ctx context.Context) (uint64, error) {
return uint64((time.Duration(r1) * time.Millisecond).Seconds()), nil
}
func bootTimeFromUptime(up uint64) uint64 {
return uint64(time.Now().Unix()) - up
}
// cachedBootTime must be accessed via atomic.Load/StoreUint64
var cachedBootTime uint64
func BootTime() (uint64, error) {
return BootTimeWithContext(context.Background())
}
func BootTimeWithContext(ctx context.Context) (uint64, error) {
t := atomic.LoadUint64(&cachedBootTime)
if t != 0 {
@@ -190,15 +125,11 @@ func BootTimeWithContext(ctx context.Context) (uint64, error) {
if err != nil {
return 0, err
}
t = bootTimeFromUptime(up)
t = timeSince(up)
atomic.StoreUint64(&cachedBootTime, t)
return t, nil
}
func PlatformInformation() (platform string, family string, version string, err error) {
return PlatformInformationWithContext(context.Background())
}
func PlatformInformationWithContext(ctx context.Context) (platform string, family string, version string, err error) {
// GetVersionEx lies on Windows 8.1 and returns as Windows 8 if we don't declare compatibility in manifest
// RtlGetVersion bypasses this lying layer and returns the true Windows version
@@ -212,7 +143,7 @@ func PlatformInformationWithContext(ctx context.Context) (platform string, famil
}
// Platform
var h windows.Handle // like getMachineGuid(), we query the registry using the raw windows.RegOpenKeyEx/RegQueryValueEx
var h windows.Handle // like HostIDWithContext(), we query the registry using the raw windows.RegOpenKeyEx/RegQueryValueEx
err = windows.RegOpenKeyEx(windows.HKEY_LOCAL_MACHINE, windows.StringToUTF16Ptr(`SOFTWARE\Microsoft\Windows NT\CurrentVersion`), 0, windows.KEY_READ|windows.KEY_WOW64_64KEY, &h)
if err != nil {
return
@@ -258,18 +189,10 @@ func PlatformInformationWithContext(ctx context.Context) (platform string, famil
return platform, family, version, nil
}
func Users() ([]UserStat, error) {
return UsersWithContext(context.Background())
}
func UsersWithContext(ctx context.Context) ([]UserStat, error) {
var ret []UserStat
return ret, nil
}
func SensorsTemperatures() ([]TemperatureStat, error) {
return SensorsTemperaturesWithContext(context.Background())
return ret, common.ErrNotImplementedError
}
func SensorsTemperaturesWithContext(ctx context.Context) ([]TemperatureStat, error) {
@@ -299,24 +222,16 @@ func kelvinToCelsius(temp uint32, n int) float64 {
return math.Trunc((t+0.5/n10)*n10) / n10
}
func Virtualization() (string, string, error) {
return VirtualizationWithContext(context.Background())
}
func VirtualizationWithContext(ctx context.Context) (string, string, error) {
return "", "", common.ErrNotImplementedError
}
func KernelVersion() (string, error) {
return KernelVersionWithContext(context.Background())
}
func KernelVersionWithContext(ctx context.Context) (string, error) {
_, _, version, err := PlatformInformation()
_, _, version, err := PlatformInformationWithContext(ctx)
return version, err
}
func kernelArch() (string, error) {
func KernelArch() (string, error) {
var systemInfo systemInfo
procGetNativeSystemInfo.Call(uintptr(unsafe.Pointer(&systemInfo)))

View File

@@ -94,6 +94,17 @@ func (i FakeInvoke) CommandWithContext(ctx context.Context, name string, arg ...
var ErrNotImplementedError = errors.New("not implemented yet")
// ReadFile reads contents from a file
func ReadFile(filename string) (string, error) {
content, err := ioutil.ReadFile(filename)
if err != nil {
return "", err
}
return string(content), nil
}
// ReadLines reads contents from a file and splits them by new lines.
// A convenience wrapper to ReadLinesOffsetN(filename, 0, -1).
func ReadLines(filename string) ([]string, error) {

View File

@@ -36,7 +36,7 @@ func CallSyscall(mib []int32) ([]byte, uint64, error) {
// get required buffer size
length := uint64(0)
_, _, err := unix.Syscall6(
unix.SYS___SYSCTL,
202, // unix.SYS___SYSCTL https://github.com/golang/sys/blob/76b94024e4b621e672466e8db3d7f084e7ddcad2/unix/zsysnum_darwin_amd64.go#L146
uintptr(unsafe.Pointer(&mib[0])),
uintptr(miblen),
0,
@@ -54,7 +54,7 @@ func CallSyscall(mib []int32) ([]byte, uint64, error) {
// get proc info itself
buf := make([]byte, length)
_, _, err = unix.Syscall6(
unix.SYS___SYSCTL,
202, // unix.SYS___SYSCTL https://github.com/golang/sys/blob/76b94024e4b621e672466e8db3d7f084e7ddcad2/unix/zsysnum_darwin_amd64.go#L146
uintptr(unsafe.Pointer(&mib[0])),
uintptr(miblen),
uintptr(unsafe.Pointer(&buf[0])),

View File

@@ -110,7 +110,14 @@ func Virtualization() (string, string, error) {
return VirtualizationWithContext(context.Background())
}
var virtualizationCache map[string]string
func VirtualizationWithContext(ctx context.Context) (string, string, error) {
// if cached already, return from cache
if virtualizationCache != nil {
return virtualizationCache["system"], virtualizationCache["role"], nil
}
var system string
var role string
@@ -194,6 +201,17 @@ func VirtualizationWithContext(ctx context.Context) (string, string, error) {
}
}
if PathExists(filepath.Join(filename, "1", "environ")) {
contents, err := ReadFile(filepath.Join(filename, "1", "environ"))
if err == nil {
if strings.Contains(contents, "container=lxc") {
system = "lxc"
role = "guest"
}
}
}
if PathExists(filepath.Join(filename, "self", "cgroup")) {
contents, err := ReadLines(filepath.Join(filename, "self", "cgroup"))
if err == nil {
@@ -220,6 +238,13 @@ func VirtualizationWithContext(ctx context.Context) (string, string, error) {
role = "host"
}
}
// before returning for the first time, cache the system and role
virtualizationCache = map[string]string{
"system": system,
"role": role,
}
return system, role, nil
}

View File

@@ -0,0 +1,18 @@
package common
import (
"context"
"time"
)
// Sleep awaits for provided interval.
// Can be interrupted by context cancelation.
func Sleep(ctx context.Context, interval time.Duration) error {
var timer = time.NewTimer(interval)
select {
case <-ctx.Done():
return ctx.Err()
case <-timer.C:
return nil
}
}

View File

@@ -88,6 +88,10 @@ type SwapMemoryStat struct {
PgIn uint64 `json:"pgin"`
PgOut uint64 `json:"pgout"`
PgFault uint64 `json:"pgfault"`
// Linux specific numbers
// https://www.kernel.org/doc/Documentation/cgroup-v2.txt
PgMajFault uint64 `json:"pgmajfault"`
}
func (m VirtualMemoryStat) String() string {

View File

@@ -232,6 +232,12 @@ func SwapMemoryWithContext(ctx context.Context) (*SwapMemoryStat, error) {
continue
}
ret.PgFault = value * 4 * 1024
case "pgmajfault":
value, err := strconv.ParseUint(fields[1], 10, 64)
if err != nil {
continue
}
ret.PgMajFault = value * 4 * 1024
}
}
return ret, nil

View File

@@ -11,6 +11,7 @@ import (
"os/exec"
"github.com/shirou/gopsutil/internal/common"
"golang.org/x/sys/unix"
)
func GetPageSize() (uint64, error) {
@@ -18,17 +19,7 @@ func GetPageSize() (uint64, error) {
}
func GetPageSizeWithContext(ctx context.Context) (uint64, error) {
mib := []int32{CTLVm, VmUvmexp}
buf, length, err := common.CallSyscall(mib)
if err != nil {
return 0, err
}
if length < sizeOfUvmexp {
return 0, fmt.Errorf("short syscall ret %d bytes", length)
}
var uvmexp Uvmexp
br := bytes.NewReader(buf)
err = common.Read(br, binary.LittleEndian, &uvmexp)
uvmexp, err := unix.SysctlUvmexp("vm.uvmexp")
if err != nil {
return 0, err
}
@@ -40,17 +31,7 @@ func VirtualMemory() (*VirtualMemoryStat, error) {
}
func VirtualMemoryWithContext(ctx context.Context) (*VirtualMemoryStat, error) {
mib := []int32{CTLVm, VmUvmexp}
buf, length, err := common.CallSyscall(mib)
if err != nil {
return nil, err
}
if length < sizeOfUvmexp {
return nil, fmt.Errorf("short syscall ret %d bytes", length)
}
var uvmexp Uvmexp
br := bytes.NewReader(buf)
err = common.Read(br, binary.LittleEndian, &uvmexp)
uvmexp, err := unix.SysctlUvmexp("vm.uvmexp")
if err != nil {
return nil, err
}
@@ -69,8 +50,8 @@ func VirtualMemoryWithContext(ctx context.Context) (*VirtualMemoryStat, error) {
ret.Used = ret.Total - ret.Available
ret.UsedPercent = float64(ret.Used) / float64(ret.Total) * 100.0
mib = []int32{CTLVfs, VfsGeneric, VfsBcacheStat}
buf, length, err = common.CallSyscall(mib)
mib := []int32{CTLVfs, VfsGeneric, VfsBcacheStat}
buf, length, err := common.CallSyscall(mib)
if err != nil {
return nil, err
}
@@ -78,7 +59,7 @@ func VirtualMemoryWithContext(ctx context.Context) (*VirtualMemoryStat, error) {
return nil, fmt.Errorf("short syscall ret %d bytes", length)
}
var bcs Bcachestats
br = bytes.NewReader(buf)
br := bytes.NewReader(buf)
err = common.Read(br, binary.LittleEndian, &bcs)
if err != nil {
return nil, err

View File

@@ -0,0 +1,37 @@
// +build openbsd
// +build 386
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
// cgo -godefs mem/types_openbsd.go
package mem
const (
CTLVfs = 10
VfsGeneric = 0
VfsBcacheStat = 3
)
const (
sizeOfBcachestats = 0x90
)
type Bcachestats struct {
Numbufs int64
Numbufpages int64
Numdirtypages int64
Numcleanpages int64
Pendingwrites int64
Pendingreads int64
Numwrites int64
Numreads int64
Cachehits int64
Busymapped int64
Dmapages int64
Highpages int64
Delwribufs int64
Kvaslots int64
Avail int64
Highflips int64
Highflops int64
Dmaflips int64
}

View File

@@ -4,105 +4,15 @@
package mem
const (
CTLVm = 2
CTLVfs = 10
VmUvmexp = 4
VfsGeneric = 0
VfsBcacheStat = 3
)
const (
sizeOfUvmexp = 0x154
sizeOfBcachestats = 0x78
)
type Uvmexp struct {
Pagesize int32
Pagemask int32
Pageshift int32
Npages int32
Free int32
Active int32
Inactive int32
Paging int32
Wired int32
Zeropages int32
Reserve_pagedaemon int32
Reserve_kernel int32
Anonpages int32
Vnodepages int32
Vtextpages int32
Freemin int32
Freetarg int32
Inactarg int32
Wiredmax int32
Anonmin int32
Vtextmin int32
Vnodemin int32
Anonminpct int32
Vtextminpct int32
Vnodeminpct int32
Nswapdev int32
Swpages int32
Swpginuse int32
Swpgonly int32
Nswget int32
Nanon int32
Nanonneeded int32
Nfreeanon int32
Faults int32
Traps int32
Intrs int32
Swtch int32
Softs int32
Syscalls int32
Pageins int32
Obsolete_swapins int32
Obsolete_swapouts int32
Pgswapin int32
Pgswapout int32
Forks int32
Forks_ppwait int32
Forks_sharevm int32
Pga_zerohit int32
Pga_zeromiss int32
Zeroaborts int32
Fltnoram int32
Fltnoanon int32
Fltpgwait int32
Fltpgrele int32
Fltrelck int32
Fltrelckok int32
Fltanget int32
Fltanretry int32
Fltamcopy int32
Fltnamap int32
Fltnomap int32
Fltlget int32
Fltget int32
Flt_anon int32
Flt_acow int32
Flt_obj int32
Flt_prcopy int32
Flt_przero int32
Pdwoke int32
Pdrevs int32
Pdswout int32
Pdfreed int32
Pdscans int32
Pdanscan int32
Pdobscan int32
Pdreact int32
Pdbusy int32
Pdpageouts int32
Pdpending int32
Pddeact int32
Pdreanon int32
Pdrevnode int32
Pdrevtext int32
Fpswtch int32
Kmapent int32
}
type Bcachestats struct {
Numbufs int64
Numbufpages int64

View File

@@ -42,6 +42,7 @@ func VirtualMemoryWithContext(ctx context.Context) (*VirtualMemoryStat, error) {
ret := &VirtualMemoryStat{
Total: memInfo.ullTotalPhys,
Available: memInfo.ullAvailPhys,
Free: memInfo.ullAvailPhys,
UsedPercent: float64(memInfo.dwMemoryLoad),
}

View File

@@ -696,7 +696,7 @@ func decodeAddress(family uint32, src string) (Addr, error) {
return Addr{}, fmt.Errorf("does not contain port, %s", src)
}
addr := t[0]
port, err := strconv.ParseInt("0x"+t[1], 0, 64)
port, err := strconv.ParseUint(t[1], 16, 16)
if err != nil {
return Addr{}, fmt.Errorf("invalid port, %s", src)
}

View File

@@ -4,7 +4,6 @@ package net
import (
"context"
"errors"
"fmt"
"net"
"os"
@@ -323,7 +322,7 @@ func FilterCounters() ([]FilterStat, error) {
}
func FilterCountersWithContext(ctx context.Context) ([]FilterStat, error) {
return nil, errors.New("NetFilterCounters not implemented for windows")
return nil, common.ErrNotImplementedError
}
func ConntrackStats(percpu bool) ([]ConntrackStat, error) {
@@ -344,7 +343,7 @@ func ProtoCounters(protocols []string) ([]ProtoCountersStat, error) {
}
func ProtoCountersWithContext(ctx context.Context, protocols []string) ([]ProtoCountersStat, error) {
return nil, errors.New("NetProtoCounters not implemented for windows")
return nil, common.ErrNotImplementedError
}
func getTableUintptr(family uint32, buf []byte) uintptr {

View File

@@ -27,6 +27,7 @@ type Process struct {
numCtxSwitches *NumCtxSwitchesStat
uids []int32
gids []int32
groups []int32
numThreads int32
memInfo *MemoryInfoStat
sigInfo *SignalInfoStat
@@ -200,7 +201,9 @@ func (p *Process) PercentWithContext(ctx context.Context, interval time.Duration
if interval > 0 {
p.lastCPUTimes = cpuTimes
p.lastCPUTime = now
time.Sleep(interval)
if err := common.Sleep(ctx, interval); err != nil {
return 0, err
}
cpuTimes, err = p.Times()
now = time.Now()
if err != nil {
@@ -312,3 +315,8 @@ func (p *Process) CPUPercentWithContext(ctx context.Context) (float64, error) {
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() ([]int32, error) {
return p.GroupsWithContext(context.Background())
}

View File

@@ -267,6 +267,20 @@ func (p *Process) GidsWithContext(ctx context.Context) ([]int32, error) {
return gids, nil
}
func (p *Process) GroupsWithContext(ctx context.Context) ([]int32, error) {
k, err := p.getKProc()
if err != nil {
return nil, err
}
groups := make([]int32, k.Eproc.Ucred.Ngroups)
for i := int16(0); i < k.Eproc.Ucred.Ngroups; i++ {
groups[i] = int32(k.Eproc.Ucred.Groups[i])
}
return groups, nil
}
func (p *Process) Terminal() (string, error) {
return p.TerminalWithContext(context.Background())
}
@@ -597,7 +611,7 @@ func (p *Process) getKProcWithContext(ctx context.Context) (*KinfoProc, error) {
length := uint64(unsafe.Sizeof(procK))
buf := make([]byte, length)
_, _, syserr := unix.Syscall6(
unix.SYS___SYSCTL,
202, // unix.SYS___SYSCTL https://github.com/golang/sys/blob/76b94024e4b621e672466e8db3d7f084e7ddcad2/unix/zsysnum_darwin_amd64.go#L146
uintptr(unsafe.Pointer(&mib[0])),
uintptr(len(mib)),
uintptr(unsafe.Pointer(&buf[0])),

View File

@@ -0,0 +1,205 @@
// +build darwin
// +build arm64
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
// cgo -godefs process/types_darwin.go
package process
const (
sizeofPtr = 0x8
sizeofShort = 0x2
sizeofInt = 0x4
sizeofLong = 0x8
sizeofLongLong = 0x8
)
type (
_C_short int16
_C_int int32
_C_long int64
_C_long_long int64
)
type Timespec struct {
Sec int64
Nsec int64
}
type Timeval struct {
Sec int64
Usec int32
Pad_cgo_0 [4]byte
}
type Rusage struct {
Utime Timeval
Stime Timeval
Maxrss int64
Ixrss int64
Idrss int64
Isrss int64
Minflt int64
Majflt int64
Nswap int64
Inblock int64
Oublock int64
Msgsnd int64
Msgrcv int64
Nsignals int64
Nvcsw int64
Nivcsw int64
}
type Rlimit struct {
Cur uint64
Max uint64
}
type UGid_t uint32
type KinfoProc struct {
Proc ExternProc
Eproc Eproc
}
type Eproc struct {
Paddr *Proc
Sess *Session
Pcred Upcred
Ucred Uucred
Vm Vmspace
Ppid int32
Pgid int32
Jobc int16
Tdev int32
Tpgid int32
Tsess *Session
Wmesg [8]int8
Xsize int32
Xrssize int16
Xccount int16
Xswrss int16
Flag int32
Login [12]int8
Spare [4]int32
Pad_cgo_0 [4]byte
}
type Proc struct{}
type Session struct{}
type ucred struct{}
type Uucred struct {
Ref int32
UID uint32
Ngroups int16
Groups [16]uint32
}
type Upcred struct {
Pc_lock [72]int8
Pc_ucred *ucred
P_ruid uint32
P_svuid uint32
P_rgid uint32
P_svgid uint32
P_refcnt int32
Pad_cgo_0 [4]byte
}
type Vmspace struct {
Dummy int32
Dummy2 *int8
Dummy3 [5]int32
Dummy4 [3]*int8
}
type Sigacts struct{}
type ExternProc struct {
P_un [16]byte
P_vmspace *Vmspace
P_sigacts *Sigacts
P_flag int32
P_stat int8
P_pid int32
P_oppid int32
P_dupfd int32
User_stack *int8
Exit_thread *byte
P_debugger int32
Sigwait int32
P_estcpu uint32
P_cpticks int32
P_pctcpu uint32
P_wchan *byte
P_wmesg *int8
P_swtime uint32
P_slptime uint32
P_realtimer Itimerval
P_rtime Timeval
P_uticks uint64
P_sticks uint64
P_iticks uint64
P_traceflag int32
P_tracep *Vnode
P_siglist int32
P_textvp *Vnode
P_holdcnt int32
P_sigmask uint32
P_sigignore uint32
P_sigcatch uint32
P_priority uint8
P_usrpri uint8
P_nice int8
P_comm [17]int8
P_pgrp *Pgrp
P_addr *UserStruct
P_xstat uint16
P_acflag uint16
P_ru *Rusage
}
type Itimerval struct {
Interval Timeval
Value Timeval
}
type Vnode struct{}
type Pgrp struct{}
type UserStruct struct{}
type Au_session struct {
Aia_p *AuditinfoAddr
Mask AuMask
}
type Posix_cred struct{}
type Label struct{}
type AuditinfoAddr struct {
Auid uint32
Mask AuMask
Termid AuTidAddr
Asid int32
Flags uint64
}
type AuMask struct {
Success uint32
Failure uint32
}
type AuTidAddr struct {
Port int32
Type uint32
Addr [4]uint32
}
type UcredQueue struct {
Next *ucred
Prev **ucred
}

View File

@@ -139,6 +139,10 @@ func (p *Process) Gids() ([]int32, error) {
func (p *Process) GidsWithContext(ctx context.Context) ([]int32, error) {
return []int32{}, common.ErrNotImplementedError
}
func (p *Process) GroupsWithContext(ctx context.Context) ([]int32, error) {
return []int32{}, common.ErrNotImplementedError
}
func (p *Process) Terminal() (string, error) {
return p.TerminalWithContext(context.Background())
}

View File

@@ -230,6 +230,20 @@ func (p *Process) GidsWithContext(ctx context.Context) ([]int32, error) {
return gids, nil
}
func (p *Process) GroupsWithContext(ctx context.Context) ([]int32, error) {
k, err := p.getKProc()
if err != nil {
return nil, err
}
groups := make([]int32, k.Ngroups)
for i := int16(0); i < k.Ngroups; i++ {
groups[i] = int32(k.Groups[i])
}
return groups, nil
}
func (p *Process) Terminal() (string, error) {
return p.TerminalWithContext(context.Background())
}

View File

@@ -228,6 +228,14 @@ func (p *Process) GidsWithContext(ctx context.Context) ([]int32, error) {
return p.gids, nil
}
func (p *Process) GroupsWithContext(ctx context.Context) ([]int32, error) {
err := p.fillFromStatusWithContext(ctx)
if err != nil {
return []int32{}, err
}
return p.groups, nil
}
// Terminal returns a terminal which is associated with the process.
func (p *Process) Terminal() (string, error) {
return p.TerminalWithContext(context.Background())
@@ -576,7 +584,8 @@ func (p *Process) MemoryMapsWithContext(ctx context.Context, grouped bool) (*[]M
if len(field) < 2 {
continue
}
v := strings.Trim(field[1], " kB") // remove last "kB"
v := strings.Trim(field[1], "kB") // remove last "kB"
v = strings.TrimSpace(v)
t, err := strconv.ParseUint(v, 10, 64)
if err != nil {
return m, err
@@ -610,11 +619,11 @@ func (p *Process) MemoryMapsWithContext(ctx context.Context, grouped bool) (*[]M
blocks := make([]string, 16)
for _, line := range lines {
field := strings.Split(line, " ")
if strings.HasSuffix(field[0], ":") == false {
fields := strings.Fields(line)
if len(fields) > 0 && !strings.HasSuffix(fields[0], ":") {
// new block section
if len(blocks) > 0 {
g, err := getBlock(field, blocks)
g, err := getBlock(fields, blocks)
if err != nil {
return &ret, err
}
@@ -1014,6 +1023,16 @@ func (p *Process) fillFromStatusWithContext(ctx context.Context) error {
}
p.gids = append(p.gids, int32(v))
}
case "Groups":
groups := strings.Fields(value)
p.groups = make([]int32, 0, len(groups))
for _, i := range groups {
v, err := strconv.ParseInt(i, 10, 32)
if err != nil {
return err
}
p.groups = append(p.groups, int32(v))
}
case "Threads":
v, err := strconv.ParseInt(value, 10, 32)
if err != nil {

View File

@@ -221,6 +221,14 @@ func (p *Process) GidsWithContext(ctx context.Context) ([]int32, error) {
return gids, nil
}
func (p *Process) GroupsWithContext(ctx context.Context) ([]int32, error) {
k, err := p.getKProc()
if err != nil {
return nil, err
}
return k.Groups, nil
}
func (p *Process) Terminal() (string, error) {
return p.TerminalWithContext(context.Background())
}

View File

@@ -0,0 +1,201 @@
// +build openbsd
// +build 386
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
// cgo -godefs process/types_openbsd.go
package process
const (
CTLKern = 1
KernProc = 66
KernProcAll = 0
KernProcPID = 1
KernProcProc = 8
KernProcPathname = 12
KernProcArgs = 55
KernProcArgv = 1
KernProcEnv = 3
)
const (
ArgMax = 256 * 1024
)
const (
sizeofPtr = 0x4
sizeofShort = 0x2
sizeofInt = 0x4
sizeofLong = 0x4
sizeofLongLong = 0x8
)
const (
sizeOfKinfoVmentry = 0x38
sizeOfKinfoProc = 0x264
)
const (
SIDL = 1
SRUN = 2
SSLEEP = 3
SSTOP = 4
SZOMB = 5
SDEAD = 6
SONPROC = 7
)
type (
_C_short int16
_C_int int32
_C_long int32
_C_long_long int64
)
type Timespec struct {
Sec int64
Nsec int32
}
type Timeval struct {
Sec int64
Usec int32
}
type Rusage struct {
Utime Timeval
Stime Timeval
Maxrss int32
Ixrss int32
Idrss int32
Isrss int32
Minflt int32
Majflt int32
Nswap int32
Inblock int32
Oublock int32
Msgsnd int32
Msgrcv int32
Nsignals int32
Nvcsw int32
Nivcsw int32
}
type Rlimit struct {
Cur uint64
Max uint64
}
type KinfoProc struct {
Forw uint64
Back uint64
Paddr uint64
Addr uint64
Fd uint64
Stats uint64
Limit uint64
Vmspace uint64
Sigacts uint64
Sess uint64
Tsess uint64
Ru uint64
Eflag int32
Exitsig int32
Flag int32
Pid int32
Ppid int32
Sid int32
X_pgid int32
Tpgid int32
Uid uint32
Ruid uint32
Gid uint32
Rgid uint32
Groups [16]uint32
Ngroups int16
Jobc int16
Tdev uint32
Estcpu uint32
Rtime_sec uint32
Rtime_usec uint32
Cpticks int32
Pctcpu uint32
Swtime uint32
Slptime uint32
Schedflags int32
Uticks uint64
Sticks uint64
Iticks uint64
Tracep uint64
Traceflag int32
Holdcnt int32
Siglist int32
Sigmask uint32
Sigignore uint32
Sigcatch uint32
Stat int8
Priority uint8
Usrpri uint8
Nice uint8
Xstat uint16
Acflag uint16
Comm [24]int8
Wmesg [8]int8
Wchan uint64
Login [32]int8
Vm_rssize int32
Vm_tsize int32
Vm_dsize int32
Vm_ssize int32
Uvalid int64
Ustart_sec uint64
Ustart_usec uint32
Uutime_sec uint32
Uutime_usec uint32
Ustime_sec uint32
Ustime_usec uint32
Uru_maxrss uint64
Uru_ixrss uint64
Uru_idrss uint64
Uru_isrss uint64
Uru_minflt uint64
Uru_majflt uint64
Uru_nswap uint64
Uru_inblock uint64
Uru_oublock uint64
Uru_msgsnd uint64
Uru_msgrcv uint64
Uru_nsignals uint64
Uru_nvcsw uint64
Uru_nivcsw uint64
Uctime_sec uint32
Uctime_usec uint32
Psflags int32
Spare int32
Svuid uint32
Svgid uint32
Emul [8]int8
Rlim_rss_cur uint64
Cpuid uint64
Vm_map_size uint64
Tid int32
Rtableid uint32
}
type Priority struct{}
type KinfoVmentry struct {
Start uint32
End uint32
Guard uint32
Fspace uint32
Fspace_augment uint32
Offset uint64
Wired_count int32
Etype int32
Protection int32
Max_protection int32
Advice int32
Inheritance int32
Flags uint8
Pad_cgo_0 [3]byte
}

View File

@@ -18,6 +18,10 @@ import (
)
var (
modntdll = windows.NewLazySystemDLL("ntdll.dll")
procNtResumeProcess = modntdll.NewProc("NtResumeProcess")
procNtSuspendProcess = modntdll.NewProc("NtSuspendProcess")
modpsapi = windows.NewLazySystemDLL("psapi.dll")
procGetProcessMemoryInfo = modpsapi.NewProc("GetProcessMemoryInfo")
procGetProcessImageFileNameW = modpsapi.NewProc("GetProcessImageFileNameW")
@@ -51,10 +55,10 @@ type SystemProcessInformation struct {
type systemProcessorInformation struct {
ProcessorArchitecture uint16
ProcessorLevel uint16
ProcessorRevision uint16
Reserved uint16
ProcessorFeatureBits uint16
ProcessorLevel uint16
ProcessorRevision uint16
Reserved uint16
ProcessorFeatureBits uint16
}
type systemInfo struct {
@@ -405,6 +409,11 @@ func (p *Process) GidsWithContext(ctx context.Context) ([]int32, error) {
var gids []int32
return gids, common.ErrNotImplementedError
}
func (p *Process) GroupsWithContext(ctx context.Context) ([]int32, error) {
var groups []int32
return groups, common.ErrNotImplementedError
}
func (p *Process) Terminal() (string, error) {
return p.TerminalWithContext(context.Background())
}
@@ -680,14 +689,39 @@ func (p *Process) Suspend() error {
}
func (p *Process) SuspendWithContext(ctx context.Context) error {
return common.ErrNotImplementedError
c, err := windows.OpenProcess(windows.PROCESS_SUSPEND_RESUME, false, uint32(p.Pid))
if err != nil {
return err
}
defer windows.CloseHandle(c)
r1, _, _ := procNtSuspendProcess.Call(uintptr(unsafe.Pointer(c)))
if r1 != 0 {
// See https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/596a1078-e883-4972-9bbc-49e60bebca55
return fmt.Errorf("NtStatus='0x%.8X'", r1)
}
return nil
}
func (p *Process) Resume() error {
return p.ResumeWithContext(context.Background())
}
func (p *Process) ResumeWithContext(ctx context.Context) error {
return common.ErrNotImplementedError
c, err := windows.OpenProcess(windows.PROCESS_SUSPEND_RESUME, false, uint32(p.Pid))
if err != nil {
return err
}
defer windows.CloseHandle(c)
r1, _, _ := procNtResumeProcess.Call(uintptr(unsafe.Pointer(c)))
if r1 != 0 {
// See https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/596a1078-e883-4972-9bbc-49e60bebca55
return fmt.Errorf("NtStatus='0x%.8X'", r1)
}
return nil
}
func (p *Process) Terminate() error {
@@ -853,7 +887,7 @@ func is32BitProcess(procHandle syscall.Handle) bool {
}
func getProcessCommandLine(pid int32) (string, error) {
h, err := windows.OpenProcess(windows.PROCESS_QUERY_LIMITED_INFORMATION | windows.PROCESS_VM_READ, false, uint32(pid))
h, err := windows.OpenProcess(windows.PROCESS_QUERY_LIMITED_INFORMATION|windows.PROCESS_VM_READ, false, uint32(pid))
if err == windows.ERROR_ACCESS_DENIED || err == windows.ERROR_INVALID_PARAMETER {
return "", nil
}
@@ -897,14 +931,14 @@ func getProcessCommandLine(pid int32) (string, error) {
}
if procIs32Bits {
buf := readProcessMemory(syscall.Handle(h), procIs32Bits, pebAddress + uint64(16), 4)
buf := readProcessMemory(syscall.Handle(h), procIs32Bits, pebAddress+uint64(16), 4)
if len(buf) != 4 {
return "", errors.New("cannot locate process user parameters")
}
userProcParams := uint64(buf[0]) | (uint64(buf[1]) << 8) | (uint64(buf[2]) << 16) | (uint64(buf[3]) << 24)
//read CommandLine field from PRTL_USER_PROCESS_PARAMETERS
remoteCmdLine := readProcessMemory(syscall.Handle(h), procIs32Bits, userProcParams + uint64(64), 8)
remoteCmdLine := readProcessMemory(syscall.Handle(h), procIs32Bits, userProcParams+uint64(64), 8)
if len(remoteCmdLine) != 8 {
return "", errors.New("cannot read cmdline field")
}
@@ -925,15 +959,15 @@ func getProcessCommandLine(pid int32) (string, error) {
return convertUTF16ToString(cmdLine), nil
}
} else {
buf := readProcessMemory(syscall.Handle(h), procIs32Bits, pebAddress + uint64(32), 8)
buf := readProcessMemory(syscall.Handle(h), procIs32Bits, pebAddress+uint64(32), 8)
if len(buf) != 8 {
return "", errors.New("cannot locate process user parameters")
}
userProcParams := uint64(buf[0]) | (uint64(buf[1]) << 8) | (uint64(buf[2]) << 16) | (uint64(buf[3]) << 24) |
userProcParams := uint64(buf[0]) | (uint64(buf[1]) << 8) | (uint64(buf[2]) << 16) | (uint64(buf[3]) << 24) |
(uint64(buf[4]) << 32) | (uint64(buf[5]) << 40) | (uint64(buf[6]) << 48) | (uint64(buf[7]) << 56)
//read CommandLine field from PRTL_USER_PROCESS_PARAMETERS
remoteCmdLine := readProcessMemory(syscall.Handle(h), procIs32Bits, userProcParams + uint64(112), 16)
remoteCmdLine := readProcessMemory(syscall.Handle(h), procIs32Bits, userProcParams+uint64(112), 16)
if len(remoteCmdLine) != 16 {
return "", errors.New("cannot read cmdline field")
}
@@ -968,7 +1002,7 @@ func convertUTF16ToString(src []byte) string {
srcIdx := 0
for i := 0; i < srcLen; i++ {
codePoints[i] = uint16(src[srcIdx]) | uint16(src[srcIdx + 1] << 8)
codePoints[i] = uint16(src[srcIdx]) | uint16(src[srcIdx+1])<<8
srcIdx += 2
}
return syscall.UTF16ToString(codePoints)

3
vendor/modules.txt vendored
View File

@@ -680,7 +680,7 @@ github.com/sean-/seed
# github.com/seccomp/libseccomp-golang v0.9.2-0.20200314001724-bdab42bd5128
## explicit
github.com/seccomp/libseccomp-golang
# github.com/shirou/gopsutil v2.20.2+incompatible => github.com/hashicorp/gopsutil v2.18.13-0.20200531184148-5aca383d4f9d+incompatible
# github.com/shirou/gopsutil v2.20.9+incompatible
## explicit
github.com/shirou/gopsutil/cpu
github.com/shirou/gopsutil/disk
@@ -1021,4 +1021,3 @@ honnef.co/go/tools/version
# github.com/hashicorp/go-discover => github.com/hashicorp/go-discover v0.0.0-20200812215701-c4b85f6ed31f
# github.com/hashicorp/nomad/api => ./api
# github.com/kr/pty => github.com/kr/pty v1.1.5
# github.com/shirou/gopsutil => github.com/hashicorp/gopsutil v2.18.13-0.20200531184148-5aca383d4f9d+incompatible