mirror of
https://github.com/kemko/nomad.git
synced 2026-01-05 18:05:42 +03:00
@@ -275,7 +275,7 @@ func (h *HostCpuStatsCalculator) Calculate(times cpu.TimesStat) (idle float64, u
|
||||
currentSystem := times.System
|
||||
currentTotal := times.Total()
|
||||
currentBusy := times.User + times.System + times.Nice + times.Iowait + times.Irq +
|
||||
times.Softirq + times.Steal + times.Guest + times.GuestNice + times.Stolen
|
||||
times.Softirq + times.Steal + times.Guest + times.GuestNice
|
||||
|
||||
deltaTotal := currentTotal - h.prevTotal
|
||||
idle = ((currentIdle - h.prevIdle) / deltaTotal) * 100
|
||||
|
||||
22
vendor/github.com/shirou/gopsutil/cpu/cpu.go
generated
vendored
22
vendor/github.com/shirou/gopsutil/cpu/cpu.go
generated
vendored
@@ -4,7 +4,7 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"runtime"
|
||||
"math"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
@@ -28,7 +28,6 @@ type TimesStat struct {
|
||||
Steal float64 `json:"steal"`
|
||||
Guest float64 `json:"guest"`
|
||||
GuestNice float64 `json:"guestNice"`
|
||||
Stolen float64 `json:"stolen"`
|
||||
}
|
||||
|
||||
type InfoStat struct {
|
||||
@@ -54,24 +53,20 @@ type lastPercent struct {
|
||||
}
|
||||
|
||||
var lastCPUPercent lastPercent
|
||||
var invoke common.Invoker
|
||||
var invoke common.Invoker = common.Invoke{}
|
||||
|
||||
func init() {
|
||||
invoke = common.Invoke{}
|
||||
lastCPUPercent.Lock()
|
||||
lastCPUPercent.lastCPUTimes, _ = Times(false)
|
||||
lastCPUPercent.lastPerCPUTimes, _ = Times(true)
|
||||
lastCPUPercent.Unlock()
|
||||
}
|
||||
|
||||
// Counts returns the number of physical or logical cores in the system
|
||||
func Counts(logical bool) (int, error) {
|
||||
return CountsWithContext(context.Background(), logical)
|
||||
}
|
||||
|
||||
func CountsWithContext(ctx context.Context, logical bool) (int, error) {
|
||||
return runtime.NumCPU(), nil
|
||||
}
|
||||
|
||||
func (c TimesStat) String() string {
|
||||
v := []string{
|
||||
`"cpu":"` + c.CPU + `"`,
|
||||
@@ -85,7 +80,6 @@ func (c TimesStat) String() string {
|
||||
`"steal":` + strconv.FormatFloat(c.Steal, 'f', 1, 64),
|
||||
`"guest":` + strconv.FormatFloat(c.Guest, 'f', 1, 64),
|
||||
`"guestNice":` + strconv.FormatFloat(c.GuestNice, 'f', 1, 64),
|
||||
`"stolen":` + strconv.FormatFloat(c.Stolen, 'f', 1, 64),
|
||||
}
|
||||
|
||||
return `{` + strings.Join(v, ",") + `}`
|
||||
@@ -93,8 +87,8 @@ func (c TimesStat) String() string {
|
||||
|
||||
// Total returns the total number of seconds in a CPUTimesStat
|
||||
func (c TimesStat) Total() float64 {
|
||||
total := c.User + c.System + c.Nice + c.Iowait + c.Irq + c.Softirq + c.Steal +
|
||||
c.Guest + c.GuestNice + c.Idle + c.Stolen
|
||||
total := c.User + c.System + c.Nice + c.Iowait + c.Irq + c.Softirq +
|
||||
c.Steal + c.Idle
|
||||
return total
|
||||
}
|
||||
|
||||
@@ -105,7 +99,7 @@ func (c InfoStat) String() string {
|
||||
|
||||
func getAllBusy(t TimesStat) (float64, float64) {
|
||||
busy := t.User + t.System + t.Nice + t.Iowait + t.Irq +
|
||||
t.Softirq + t.Steal + t.Guest + t.GuestNice + t.Stolen
|
||||
t.Softirq + t.Steal
|
||||
return busy + t.Idle, busy
|
||||
}
|
||||
|
||||
@@ -117,9 +111,9 @@ func calculateBusy(t1, t2 TimesStat) float64 {
|
||||
return 0
|
||||
}
|
||||
if t2All <= t1All {
|
||||
return 1
|
||||
return 100
|
||||
}
|
||||
return (t2Busy - t1Busy) / (t2All - t1All) * 100
|
||||
return math.Min(100, math.Max(0, (t2Busy-t1Busy)/(t2All-t1All)*100))
|
||||
}
|
||||
|
||||
func calculateAllBusy(t1, t2 []TimesStat) ([]float64, error) {
|
||||
|
||||
108
vendor/github.com/shirou/gopsutil/cpu/cpu_darwin.go
generated
vendored
108
vendor/github.com/shirou/gopsutil/cpu/cpu_darwin.go
generated
vendored
@@ -4,9 +4,10 @@ package cpu
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// sys/resource.h
|
||||
@@ -41,75 +42,62 @@ func Info() ([]InfoStat, error) {
|
||||
|
||||
func InfoWithContext(ctx context.Context) ([]InfoStat, error) {
|
||||
var ret []InfoStat
|
||||
sysctl, err := exec.LookPath("/usr/sbin/sysctl")
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
out, err := invoke.Command(sysctl, "machdep.cpu")
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
|
||||
c := InfoStat{}
|
||||
for _, line := range strings.Split(string(out), "\n") {
|
||||
values := strings.Fields(line)
|
||||
if len(values) < 1 {
|
||||
continue
|
||||
}
|
||||
|
||||
t, err := strconv.ParseInt(values[1], 10, 64)
|
||||
// err is not checked here because some value is string.
|
||||
if strings.HasPrefix(line, "machdep.cpu.brand_string") {
|
||||
c.ModelName = strings.Join(values[1:], " ")
|
||||
} else if strings.HasPrefix(line, "machdep.cpu.family") {
|
||||
c.Family = values[1]
|
||||
} else if strings.HasPrefix(line, "machdep.cpu.model") {
|
||||
c.Model = values[1]
|
||||
} else if strings.HasPrefix(line, "machdep.cpu.stepping") {
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
c.Stepping = int32(t)
|
||||
} else if strings.HasPrefix(line, "machdep.cpu.features") {
|
||||
for _, v := range values[1:] {
|
||||
c.Flags = append(c.Flags, strings.ToLower(v))
|
||||
}
|
||||
} else if strings.HasPrefix(line, "machdep.cpu.leaf7_features") {
|
||||
for _, v := range values[1:] {
|
||||
c.Flags = append(c.Flags, strings.ToLower(v))
|
||||
}
|
||||
} else if strings.HasPrefix(line, "machdep.cpu.extfeatures") {
|
||||
for _, v := range values[1:] {
|
||||
c.Flags = append(c.Flags, strings.ToLower(v))
|
||||
}
|
||||
} else if strings.HasPrefix(line, "machdep.cpu.core_count") {
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
c.Cores = int32(t)
|
||||
} else if strings.HasPrefix(line, "machdep.cpu.cache.size") {
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
c.CacheSize = int32(t)
|
||||
} else if strings.HasPrefix(line, "machdep.cpu.vendor") {
|
||||
c.VendorID = values[1]
|
||||
c.ModelName, _ = unix.Sysctl("machdep.cpu.brand_string")
|
||||
family, _ := unix.SysctlUint32("machdep.cpu.family")
|
||||
c.Family = strconv.FormatUint(uint64(family), 10)
|
||||
model, _ := unix.SysctlUint32("machdep.cpu.model")
|
||||
c.Model = strconv.FormatUint(uint64(model), 10)
|
||||
stepping, _ := unix.SysctlUint32("machdep.cpu.stepping")
|
||||
c.Stepping = int32(stepping)
|
||||
features, err := unix.Sysctl("machdep.cpu.features")
|
||||
if err == nil {
|
||||
for _, v := range strings.Fields(features) {
|
||||
c.Flags = append(c.Flags, strings.ToLower(v))
|
||||
}
|
||||
}
|
||||
leaf7Features, err := unix.Sysctl("machdep.cpu.leaf7_features")
|
||||
if err == nil {
|
||||
for _, v := range strings.Fields(leaf7Features) {
|
||||
c.Flags = append(c.Flags, strings.ToLower(v))
|
||||
}
|
||||
}
|
||||
extfeatures, err := unix.Sysctl("machdep.cpu.extfeatures")
|
||||
if err == nil {
|
||||
for _, v := range strings.Fields(extfeatures) {
|
||||
c.Flags = append(c.Flags, strings.ToLower(v))
|
||||
}
|
||||
}
|
||||
cores, _ := unix.SysctlUint32("machdep.cpu.core_count")
|
||||
c.Cores = int32(cores)
|
||||
cacheSize, _ := unix.SysctlUint32("machdep.cpu.cache.size")
|
||||
c.CacheSize = int32(cacheSize)
|
||||
c.VendorID, _ = unix.Sysctl("machdep.cpu.vendor")
|
||||
|
||||
// Use the rated frequency of the CPU. This is a static value and does not
|
||||
// account for low power or Turbo Boost modes.
|
||||
out, err = invoke.Command(sysctl, "hw.cpufrequency")
|
||||
cpuFrequency, err := unix.SysctlUint64("hw.cpufrequency")
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
|
||||
values := strings.Fields(string(out))
|
||||
hz, err := strconv.ParseFloat(values[1], 64)
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
c.Mhz = hz / 1000000.0
|
||||
c.Mhz = float64(cpuFrequency) / 1000000.0
|
||||
|
||||
return append(ret, c), nil
|
||||
}
|
||||
|
||||
func CountsWithContext(ctx context.Context, logical bool) (int, error) {
|
||||
var cpuArgument string
|
||||
if logical {
|
||||
cpuArgument = "hw.logicalcpu"
|
||||
} else {
|
||||
cpuArgument = "hw.physicalcpu"
|
||||
}
|
||||
|
||||
count, err := unix.SysctlUint32(cpuArgument)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return int(count), nil
|
||||
}
|
||||
|
||||
5
vendor/github.com/shirou/gopsutil/cpu/cpu_fallback.go
generated
vendored
5
vendor/github.com/shirou/gopsutil/cpu/cpu_fallback.go
generated
vendored
@@ -4,6 +4,7 @@ package cpu
|
||||
|
||||
import (
|
||||
"context"
|
||||
"runtime"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
)
|
||||
@@ -23,3 +24,7 @@ func Info() ([]InfoStat, error) {
|
||||
func InfoWithContext(ctx context.Context) ([]InfoStat, error) {
|
||||
return []InfoStat{}, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func CountsWithContext(ctx context.Context, logical bool) (int, error) {
|
||||
return runtime.NumCPU(), nil
|
||||
}
|
||||
|
||||
7
vendor/github.com/shirou/gopsutil/cpu/cpu_freebsd.go
generated
vendored
7
vendor/github.com/shirou/gopsutil/cpu/cpu_freebsd.go
generated
vendored
@@ -6,6 +6,7 @@ import (
|
||||
"os/exec"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unsafe"
|
||||
@@ -25,7 +26,7 @@ var cpuTimesSize int
|
||||
var emptyTimes cpuTimes
|
||||
|
||||
func init() {
|
||||
getconf, err := exec.LookPath("/usr/bin/getconf")
|
||||
getconf, err := exec.LookPath("getconf")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -166,3 +167,7 @@ func parseDmesgBoot(fileName string) (InfoStat, int, error) {
|
||||
|
||||
return c, cpuNum, nil
|
||||
}
|
||||
|
||||
func CountsWithContext(ctx context.Context, logical bool) (int, error) {
|
||||
return runtime.NumCPU(), nil
|
||||
}
|
||||
|
||||
9
vendor/github.com/shirou/gopsutil/cpu/cpu_freebsd_arm.go
generated
vendored
Normal file
9
vendor/github.com/shirou/gopsutil/cpu/cpu_freebsd_arm.go
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
package cpu
|
||||
|
||||
type cpuTimes struct {
|
||||
User uint32
|
||||
Nice uint32
|
||||
Sys uint32
|
||||
Intr uint32
|
||||
Idle uint32
|
||||
}
|
||||
9
vendor/github.com/shirou/gopsutil/cpu/cpu_freebsd_arm64.go
generated
vendored
Normal file
9
vendor/github.com/shirou/gopsutil/cpu/cpu_freebsd_arm64.go
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
package cpu
|
||||
|
||||
type cpuTimes struct {
|
||||
User uint64
|
||||
Nice uint64
|
||||
Sys uint64
|
||||
Intr uint64
|
||||
Idle uint64
|
||||
}
|
||||
40
vendor/github.com/shirou/gopsutil/cpu/cpu_freebsd_test.go
generated
vendored
40
vendor/github.com/shirou/gopsutil/cpu/cpu_freebsd_test.go
generated
vendored
@@ -1,40 +0,0 @@
|
||||
package cpu
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
)
|
||||
|
||||
func TestParseDmesgBoot(t *testing.T) {
|
||||
if runtime.GOOS != "freebsd" {
|
||||
t.SkipNow()
|
||||
}
|
||||
|
||||
var cpuTests = []struct {
|
||||
file string
|
||||
cpuNum int
|
||||
cores int32
|
||||
}{
|
||||
{"1cpu_2core.txt", 1, 2},
|
||||
{"1cpu_4core.txt", 1, 4},
|
||||
{"2cpu_4core.txt", 2, 4},
|
||||
}
|
||||
for _, tt := range cpuTests {
|
||||
v, num, err := parseDmesgBoot(filepath.Join("testdata", "freebsd", tt.file))
|
||||
if err != nil {
|
||||
t.Errorf("parseDmesgBoot failed(%s), %v", tt.file, err)
|
||||
}
|
||||
if num != tt.cpuNum {
|
||||
t.Errorf("parseDmesgBoot wrong length(%s), %v", tt.file, err)
|
||||
}
|
||||
if v.Cores != tt.cores {
|
||||
t.Errorf("parseDmesgBoot wrong core(%s), %v", tt.file, err)
|
||||
}
|
||||
if !common.StringsContains(v.Flags, "fpu") {
|
||||
t.Errorf("parseDmesgBoot fail to parse features(%s), %v", tt.file, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
99
vendor/github.com/shirou/gopsutil/cpu/cpu_linux.go
generated
vendored
99
vendor/github.com/shirou/gopsutil/cpu/cpu_linux.go
generated
vendored
@@ -13,19 +13,19 @@ import (
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
)
|
||||
|
||||
var cpu_tick = float64(100)
|
||||
var CPUTick = float64(100)
|
||||
|
||||
func init() {
|
||||
getconf, err := exec.LookPath("/usr/bin/getconf")
|
||||
getconf, err := exec.LookPath("getconf")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
out, err := invoke.Command(getconf, "CLK_TCK")
|
||||
out, err := invoke.CommandWithContext(context.Background(), getconf, "CLK_TCK")
|
||||
// ignore errors
|
||||
if err == nil {
|
||||
i, err := strconv.ParseFloat(strings.TrimSpace(string(out)), 64)
|
||||
if err == nil {
|
||||
cpu_tick = float64(i)
|
||||
CPUTick = i
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -87,7 +87,7 @@ func finishCPUInfo(c *InfoStat) error {
|
||||
lines, err = common.ReadLines(sysCPUPath(c.CPU, "cpufreq/cpuinfo_max_freq"))
|
||||
// if we encounter errors below such as there are no cpuinfo_max_freq file,
|
||||
// we just ignore. so let Mhz is 0.
|
||||
if err != nil {
|
||||
if err != nil || len(lines) == 0 {
|
||||
return nil
|
||||
}
|
||||
value, err = strconv.ParseFloat(lines[0], 64)
|
||||
@@ -212,7 +212,6 @@ func parseStatLine(line string) (*TimesStat, error) {
|
||||
}
|
||||
|
||||
if strings.HasPrefix(fields[0], "cpu") == false {
|
||||
// return CPUTimesStat{}, e
|
||||
return nil, errors.New("not contain cpu")
|
||||
}
|
||||
|
||||
@@ -251,35 +250,103 @@ func parseStatLine(line string) (*TimesStat, error) {
|
||||
|
||||
ct := &TimesStat{
|
||||
CPU: cpu,
|
||||
User: float64(user) / cpu_tick,
|
||||
Nice: float64(nice) / cpu_tick,
|
||||
System: float64(system) / cpu_tick,
|
||||
Idle: float64(idle) / cpu_tick,
|
||||
Iowait: float64(iowait) / cpu_tick,
|
||||
Irq: float64(irq) / cpu_tick,
|
||||
Softirq: float64(softirq) / cpu_tick,
|
||||
User: user / CPUTick,
|
||||
Nice: nice / CPUTick,
|
||||
System: system / CPUTick,
|
||||
Idle: idle / CPUTick,
|
||||
Iowait: iowait / CPUTick,
|
||||
Irq: irq / CPUTick,
|
||||
Softirq: softirq / CPUTick,
|
||||
}
|
||||
if len(fields) > 8 { // Linux >= 2.6.11
|
||||
steal, err := strconv.ParseFloat(fields[8], 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ct.Steal = float64(steal) / cpu_tick
|
||||
ct.Steal = steal / CPUTick
|
||||
}
|
||||
if len(fields) > 9 { // Linux >= 2.6.24
|
||||
guest, err := strconv.ParseFloat(fields[9], 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ct.Guest = float64(guest) / cpu_tick
|
||||
ct.Guest = guest / CPUTick
|
||||
}
|
||||
if len(fields) > 10 { // Linux >= 3.2.0
|
||||
guestNice, err := strconv.ParseFloat(fields[10], 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ct.GuestNice = float64(guestNice) / cpu_tick
|
||||
ct.GuestNice = guestNice / CPUTick
|
||||
}
|
||||
|
||||
return ct, nil
|
||||
}
|
||||
|
||||
func CountsWithContext(ctx context.Context, logical bool) (int, error) {
|
||||
if logical {
|
||||
ret := 0
|
||||
// https://github.com/giampaolo/psutil/blob/d01a9eaa35a8aadf6c519839e987a49d8be2d891/psutil/_pslinux.py#L599
|
||||
procCpuinfo := common.HostProc("cpuinfo")
|
||||
lines, err := common.ReadLines(procCpuinfo)
|
||||
if err == nil {
|
||||
for _, line := range lines {
|
||||
line = strings.ToLower(line)
|
||||
if strings.HasPrefix(line, "processor") {
|
||||
ret++
|
||||
}
|
||||
}
|
||||
}
|
||||
if ret == 0 {
|
||||
procStat := common.HostProc("stat")
|
||||
lines, err = common.ReadLines(procStat)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
for _, line := range lines {
|
||||
if len(line) >= 4 && strings.HasPrefix(line, "cpu") && '0' <= line[3] && line[3] <= '9' { // `^cpu\d` regexp matching
|
||||
ret++
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
// physical cores https://github.com/giampaolo/psutil/blob/d01a9eaa35a8aadf6c519839e987a49d8be2d891/psutil/_pslinux.py#L628
|
||||
filename := common.HostProc("cpuinfo")
|
||||
lines, err := common.ReadLines(filename)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
mapping := make(map[int]int)
|
||||
currentInfo := make(map[string]int)
|
||||
for _, line := range lines {
|
||||
line = strings.ToLower(strings.TrimSpace(line))
|
||||
if line == "" {
|
||||
// new section
|
||||
id, okID := currentInfo["physical id"]
|
||||
cores, okCores := currentInfo["cpu cores"]
|
||||
if okID && okCores {
|
||||
mapping[id] = cores
|
||||
}
|
||||
currentInfo = make(map[string]int)
|
||||
continue
|
||||
}
|
||||
fields := strings.Split(line, ":")
|
||||
if len(fields) < 2 {
|
||||
continue
|
||||
}
|
||||
fields[0] = strings.TrimSpace(fields[0])
|
||||
if fields[0] == "physical id" || fields[0] == "cpu cores" {
|
||||
val, err := strconv.Atoi(strings.TrimSpace(fields[1]))
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
currentInfo[fields[0]] = val
|
||||
}
|
||||
}
|
||||
ret := 0
|
||||
for _, v := range mapping {
|
||||
ret += v
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
40
vendor/github.com/shirou/gopsutil/cpu/cpu_linux_test.go
generated
vendored
40
vendor/github.com/shirou/gopsutil/cpu/cpu_linux_test.go
generated
vendored
@@ -1,40 +0,0 @@
|
||||
package cpu
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestTimesEmpty(t *testing.T) {
|
||||
orig := os.Getenv("HOST_PROC")
|
||||
os.Setenv("HOST_PROC", "testdata/linux/times_empty")
|
||||
_, err := Times(true)
|
||||
if err != nil {
|
||||
t.Error("Times(true) failed")
|
||||
}
|
||||
_, err = Times(false)
|
||||
if err != nil {
|
||||
t.Error("Times(false) failed")
|
||||
}
|
||||
os.Setenv("HOST_PROC", orig)
|
||||
}
|
||||
|
||||
func TestCPUparseStatLine_424(t *testing.T) {
|
||||
orig := os.Getenv("HOST_PROC")
|
||||
os.Setenv("HOST_PROC", "testdata/linux/424/proc")
|
||||
{
|
||||
l, err := Times(true)
|
||||
if err != nil || len(l) == 0 {
|
||||
t.Error("Times(true) failed")
|
||||
}
|
||||
t.Logf("Times(true): %#v", l)
|
||||
}
|
||||
{
|
||||
l, err := Times(false)
|
||||
if err != nil || len(l) == 0 {
|
||||
t.Error("Times(false) failed")
|
||||
}
|
||||
t.Logf("Times(false): %#v", l)
|
||||
}
|
||||
os.Setenv("HOST_PROC", orig)
|
||||
}
|
||||
114
vendor/github.com/shirou/gopsutil/cpu/cpu_openbsd.go
generated
vendored
114
vendor/github.com/shirou/gopsutil/cpu/cpu_openbsd.go
generated
vendored
@@ -8,15 +8,17 @@ import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// sys/sched.h
|
||||
const (
|
||||
var (
|
||||
CPUser = 0
|
||||
CPNice = 1
|
||||
CPSys = 2
|
||||
@@ -28,6 +30,9 @@ const (
|
||||
// sys/sysctl.h
|
||||
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
|
||||
)
|
||||
@@ -35,18 +40,52 @@ const (
|
||||
var ClocksPerSec = float64(128)
|
||||
|
||||
func init() {
|
||||
getconf, err := exec.LookPath("/usr/bin/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() {
|
||||
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() {
|
||||
v, err := unix.Sysctl("kern.osrelease") // can't reuse host.PlatformInformation because of circular import
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
v = strings.ToLower(v)
|
||||
version, err := strconv.ParseFloat(v, 64)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if version >= 6.4 {
|
||||
CPIntr = 4
|
||||
CPIdle = 5
|
||||
CPUStates = 6
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func smt() (bool, error) {
|
||||
mib := []int32{CTLHw, SMT}
|
||||
buf, _, err := common.CallSyscall(mib)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
var ret bool
|
||||
br := bytes.NewReader(buf)
|
||||
if err := binary.Read(br, binary.LittleEndian, &ret); err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func Times(percpu bool) ([]TimesStat, error) {
|
||||
@@ -63,13 +102,27 @@ func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) {
|
||||
ncpu = 1
|
||||
}
|
||||
|
||||
smt, err := smt()
|
||||
if err == syscall.EOPNOTSUPP {
|
||||
// if hw.smt is not applicable for this platform (e.g. i386),
|
||||
// pretend it's enabled
|
||||
smt = true
|
||||
} else if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for i := 0; i < ncpu; i++ {
|
||||
var cpuTimes [CPUStates]int64
|
||||
j := i
|
||||
if !smt {
|
||||
j *= 2
|
||||
}
|
||||
|
||||
var cpuTimes = make([]int32, CPUStates)
|
||||
var mib []int32
|
||||
if percpu {
|
||||
mib = []int32{CTLKern, KernCptime}
|
||||
mib = []int32{CTLKern, KernCptime2, int32(j)}
|
||||
} else {
|
||||
mib = []int32{CTLKern, KernCptime2, int32(i)}
|
||||
mib = []int32{CTLKern, KernCptime}
|
||||
}
|
||||
buf, _, err := common.CallSyscall(mib)
|
||||
if err != nil {
|
||||
@@ -88,10 +141,10 @@ func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) {
|
||||
Idle: float64(cpuTimes[CPIdle]) / ClocksPerSec,
|
||||
Irq: float64(cpuTimes[CPIntr]) / ClocksPerSec,
|
||||
}
|
||||
if !percpu {
|
||||
c.CPU = "cpu-total"
|
||||
if percpu {
|
||||
c.CPU = fmt.Sprintf("cpu%d", j)
|
||||
} else {
|
||||
c.CPU = fmt.Sprintf("cpu%d", i)
|
||||
c.CPU = "cpu-total"
|
||||
}
|
||||
ret = append(ret, c)
|
||||
}
|
||||
@@ -106,14 +159,37 @@ func Info() ([]InfoStat, error) {
|
||||
|
||||
func InfoWithContext(ctx context.Context) ([]InfoStat, error) {
|
||||
var ret []InfoStat
|
||||
var err error
|
||||
|
||||
c := InfoStat{}
|
||||
|
||||
v, err := unix.Sysctl("hw.model")
|
||||
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)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
c.ModelName = v
|
||||
|
||||
var ncpu int32
|
||||
br := bytes.NewReader(buf)
|
||||
err = binary.Read(br, binary.LittleEndian, &ncpu)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
c.Cores = ncpu
|
||||
|
||||
if c.ModelName, err = unix.Sysctl("hw.model"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return append(ret, c), nil
|
||||
}
|
||||
|
||||
func CountsWithContext(ctx context.Context, logical bool) (int, error) {
|
||||
return runtime.NumCPU(), nil
|
||||
}
|
||||
|
||||
104
vendor/github.com/shirou/gopsutil/cpu/cpu_solaris.go
generated
vendored
104
vendor/github.com/shirou/gopsutil/cpu/cpu_solaris.go
generated
vendored
@@ -6,17 +6,16 @@ import (
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
)
|
||||
|
||||
var ClocksPerSec = float64(128)
|
||||
|
||||
func init() {
|
||||
getconf, err := exec.LookPath("/usr/bin/getconf")
|
||||
getconf, err := exec.LookPath("getconf")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -30,12 +29,97 @@ func init() {
|
||||
}
|
||||
}
|
||||
|
||||
//sum all values in a float64 map with float64 keys
|
||||
func msum(x map[float64]float64) float64 {
|
||||
total := 0.0
|
||||
for _, y := range x {
|
||||
total += y
|
||||
}
|
||||
return total
|
||||
}
|
||||
|
||||
func Times(percpu bool) ([]TimesStat, error) {
|
||||
return TimesWithContext(context.Background(), percpu)
|
||||
}
|
||||
|
||||
func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) {
|
||||
return []TimesStat{}, common.ErrNotImplementedError
|
||||
kstatSys, err := exec.LookPath("kstat")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot find kstat: %s", err)
|
||||
}
|
||||
cpu := make(map[float64]float64)
|
||||
idle := make(map[float64]float64)
|
||||
user := make(map[float64]float64)
|
||||
kern := make(map[float64]float64)
|
||||
iowt := make(map[float64]float64)
|
||||
//swap := make(map[float64]float64)
|
||||
kstatSysOut, err := invoke.CommandWithContext(ctx, kstatSys, "-p", "cpu_stat:*:*:/^idle$|^user$|^kernel$|^iowait$|^swap$/")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot execute kstat: %s", err)
|
||||
}
|
||||
re := regexp.MustCompile(`[:\s]+`)
|
||||
for _, line := range strings.Split(string(kstatSysOut), "\n") {
|
||||
fields := re.Split(line, -1)
|
||||
if fields[0] != "cpu_stat" {
|
||||
continue
|
||||
}
|
||||
cpuNumber, err := strconv.ParseFloat(fields[1], 64)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot parse cpu number: %s", err)
|
||||
}
|
||||
cpu[cpuNumber] = cpuNumber
|
||||
switch fields[3] {
|
||||
case "idle":
|
||||
idle[cpuNumber], err = strconv.ParseFloat(fields[4], 64)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot parse idle: %s", err)
|
||||
}
|
||||
case "user":
|
||||
user[cpuNumber], err = strconv.ParseFloat(fields[4], 64)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot parse user: %s", err)
|
||||
}
|
||||
case "kernel":
|
||||
kern[cpuNumber], err = strconv.ParseFloat(fields[4], 64)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot parse kernel: %s", err)
|
||||
}
|
||||
case "iowait":
|
||||
iowt[cpuNumber], err = strconv.ParseFloat(fields[4], 64)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot parse iowait: %s", err)
|
||||
}
|
||||
//not sure how this translates, don't report, add to kernel, something else?
|
||||
/*case "swap":
|
||||
swap[cpuNumber], err = strconv.ParseFloat(fields[4], 64)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot parse swap: %s", err)
|
||||
} */
|
||||
}
|
||||
}
|
||||
ret := make([]TimesStat, 0, len(cpu))
|
||||
if percpu {
|
||||
for _, c := range cpu {
|
||||
ct := &TimesStat{
|
||||
CPU: fmt.Sprintf("cpu%d", int(cpu[c])),
|
||||
Idle: idle[c] / ClocksPerSec,
|
||||
User: user[c] / ClocksPerSec,
|
||||
System: kern[c] / ClocksPerSec,
|
||||
Iowait: iowt[c] / ClocksPerSec,
|
||||
}
|
||||
ret = append(ret, *ct)
|
||||
}
|
||||
} else {
|
||||
ct := &TimesStat{
|
||||
CPU: "cpu-total",
|
||||
Idle: msum(idle) / ClocksPerSec,
|
||||
User: msum(user) / ClocksPerSec,
|
||||
System: msum(kern) / ClocksPerSec,
|
||||
Iowait: msum(iowt) / ClocksPerSec,
|
||||
}
|
||||
ret = append(ret, *ct)
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func Info() ([]InfoStat, error) {
|
||||
@@ -43,20 +127,20 @@ func Info() ([]InfoStat, error) {
|
||||
}
|
||||
|
||||
func InfoWithContext(ctx context.Context) ([]InfoStat, error) {
|
||||
psrInfo, err := exec.LookPath("/usr/sbin/psrinfo")
|
||||
psrInfo, err := exec.LookPath("psrinfo")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot find psrinfo: %s", err)
|
||||
}
|
||||
psrInfoOut, err := invoke.Command(psrInfo, "-p", "-v")
|
||||
psrInfoOut, err := invoke.CommandWithContext(ctx, psrInfo, "-p", "-v")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot execute psrinfo: %s", err)
|
||||
}
|
||||
|
||||
isaInfo, err := exec.LookPath("/usr/bin/isainfo")
|
||||
isaInfo, err := exec.LookPath("isainfo")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot find isainfo: %s", err)
|
||||
}
|
||||
isaInfoOut, err := invoke.Command(isaInfo, "-b", "-v")
|
||||
isaInfoOut, err := invoke.CommandWithContext(ctx, isaInfo, "-b", "-v")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot execute isainfo: %s", err)
|
||||
}
|
||||
@@ -196,3 +280,7 @@ func parseProcessorInfo(cmdOutput string) ([]InfoStat, error) {
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func CountsWithContext(ctx context.Context, logical bool) (int, error) {
|
||||
return runtime.NumCPU(), nil
|
||||
}
|
||||
|
||||
110
vendor/github.com/shirou/gopsutil/cpu/cpu_solaris_test.go
generated
vendored
110
vendor/github.com/shirou/gopsutil/cpu/cpu_solaris_test.go
generated
vendored
@@ -1,110 +0,0 @@
|
||||
package cpu
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"sort"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestParseISAInfo(t *testing.T) {
|
||||
cases := []struct {
|
||||
filename string
|
||||
expected []string
|
||||
}{
|
||||
{
|
||||
"1cpu_1core_isainfo.txt",
|
||||
[]string{"rdseed", "adx", "avx2", "fma", "bmi2", "bmi1", "rdrand", "f16c", "vmx",
|
||||
"avx", "xsave", "pclmulqdq", "aes", "movbe", "sse4.2", "sse4.1", "ssse3", "popcnt",
|
||||
"tscp", "cx16", "sse3", "sse2", "sse", "fxsr", "mmx", "cmov", "amd_sysc", "cx8",
|
||||
"tsc", "fpu"},
|
||||
},
|
||||
{
|
||||
"2cpu_1core_isainfo.txt",
|
||||
[]string{"rdseed", "adx", "avx2", "fma", "bmi2", "bmi1", "rdrand", "f16c", "vmx",
|
||||
"avx", "xsave", "pclmulqdq", "aes", "movbe", "sse4.2", "sse4.1", "ssse3", "popcnt",
|
||||
"tscp", "cx16", "sse3", "sse2", "sse", "fxsr", "mmx", "cmov", "amd_sysc", "cx8",
|
||||
"tsc", "fpu"},
|
||||
},
|
||||
{
|
||||
"2cpu_8core_isainfo.txt",
|
||||
[]string{"vmx", "avx", "xsave", "pclmulqdq", "aes", "sse4.2", "sse4.1", "ssse3", "popcnt",
|
||||
"tscp", "cx16", "sse3", "sse2", "sse", "fxsr", "mmx", "cmov", "amd_sysc", "cx8",
|
||||
"tsc", "fpu"},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
content, err := ioutil.ReadFile(filepath.Join("testdata", "solaris", tc.filename))
|
||||
if err != nil {
|
||||
t.Errorf("cannot read test case: %s", err)
|
||||
}
|
||||
|
||||
sort.Strings(tc.expected)
|
||||
|
||||
flags, err := parseISAInfo(string(content))
|
||||
if err != nil {
|
||||
t.Fatalf("parseISAInfo: %s", err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(tc.expected, flags) {
|
||||
t.Fatalf("Bad flags\nExpected: %v\n Actual: %v", tc.expected, flags)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseProcessorInfo(t *testing.T) {
|
||||
cases := []struct {
|
||||
filename string
|
||||
expected []InfoStat
|
||||
}{
|
||||
{
|
||||
"1cpu_1core_psrinfo.txt",
|
||||
[]InfoStat{
|
||||
{CPU: 0, VendorID: "GenuineIntel", Family: "6", Model: "78", Stepping: 3, PhysicalID: "0", CoreID: "0", Cores: 1, ModelName: "Intel(r) Core(tm) i7-6567U CPU @ 3.30GHz", Mhz: 3312},
|
||||
},
|
||||
},
|
||||
{
|
||||
"2cpu_1core_psrinfo.txt",
|
||||
[]InfoStat{
|
||||
{CPU: 0, VendorID: "GenuineIntel", Family: "6", Model: "78", Stepping: 3, PhysicalID: "0", CoreID: "0", Cores: 1, ModelName: "Intel(r) Core(tm) i7-6567U CPU @ 3.30GHz", Mhz: 3312},
|
||||
{CPU: 1, VendorID: "GenuineIntel", Family: "6", Model: "78", Stepping: 3, PhysicalID: "1", CoreID: "0", Cores: 1, ModelName: "Intel(r) Core(tm) i7-6567U CPU @ 3.30GHz", Mhz: 3312},
|
||||
},
|
||||
},
|
||||
{
|
||||
"2cpu_8core_psrinfo.txt",
|
||||
[]InfoStat{
|
||||
{CPU: 0, VendorID: "GenuineIntel", Family: "6", Model: "45", Stepping: 7, PhysicalID: "0", CoreID: "0", Cores: 2, ModelName: "Intel(r) Xeon(r) CPU E5-2670 0 @ 2.60GHz", Mhz: 2600},
|
||||
{CPU: 1, VendorID: "GenuineIntel", Family: "6", Model: "45", Stepping: 7, PhysicalID: "0", CoreID: "1", Cores: 2, ModelName: "Intel(r) Xeon(r) CPU E5-2670 0 @ 2.60GHz", Mhz: 2600},
|
||||
{CPU: 2, VendorID: "GenuineIntel", Family: "6", Model: "45", Stepping: 7, PhysicalID: "0", CoreID: "2", Cores: 2, ModelName: "Intel(r) Xeon(r) CPU E5-2670 0 @ 2.60GHz", Mhz: 2600},
|
||||
{CPU: 3, VendorID: "GenuineIntel", Family: "6", Model: "45", Stepping: 7, PhysicalID: "0", CoreID: "3", Cores: 2, ModelName: "Intel(r) Xeon(r) CPU E5-2670 0 @ 2.60GHz", Mhz: 2600},
|
||||
{CPU: 4, VendorID: "GenuineIntel", Family: "6", Model: "45", Stepping: 7, PhysicalID: "0", CoreID: "4", Cores: 2, ModelName: "Intel(r) Xeon(r) CPU E5-2670 0 @ 2.60GHz", Mhz: 2600},
|
||||
{CPU: 5, VendorID: "GenuineIntel", Family: "6", Model: "45", Stepping: 7, PhysicalID: "0", CoreID: "5", Cores: 2, ModelName: "Intel(r) Xeon(r) CPU E5-2670 0 @ 2.60GHz", Mhz: 2600},
|
||||
{CPU: 6, VendorID: "GenuineIntel", Family: "6", Model: "45", Stepping: 7, PhysicalID: "0", CoreID: "6", Cores: 2, ModelName: "Intel(r) Xeon(r) CPU E5-2670 0 @ 2.60GHz", Mhz: 2600},
|
||||
{CPU: 7, VendorID: "GenuineIntel", Family: "6", Model: "45", Stepping: 7, PhysicalID: "0", CoreID: "7", Cores: 2, ModelName: "Intel(r) Xeon(r) CPU E5-2670 0 @ 2.60GHz", Mhz: 2600},
|
||||
{CPU: 8, VendorID: "GenuineIntel", Family: "6", Model: "45", Stepping: 7, PhysicalID: "1", CoreID: "0", Cores: 2, ModelName: "Intel(r) Xeon(r) CPU E5-2670 0 @ 2.60GHz", Mhz: 2600},
|
||||
{CPU: 9, VendorID: "GenuineIntel", Family: "6", Model: "45", Stepping: 7, PhysicalID: "1", CoreID: "1", Cores: 2, ModelName: "Intel(r) Xeon(r) CPU E5-2670 0 @ 2.60GHz", Mhz: 2600},
|
||||
{CPU: 10, VendorID: "GenuineIntel", Family: "6", Model: "45", Stepping: 7, PhysicalID: "1", CoreID: "2", Cores: 2, ModelName: "Intel(r) Xeon(r) CPU E5-2670 0 @ 2.60GHz", Mhz: 2600},
|
||||
{CPU: 11, VendorID: "GenuineIntel", Family: "6", Model: "45", Stepping: 7, PhysicalID: "1", CoreID: "3", Cores: 2, ModelName: "Intel(r) Xeon(r) CPU E5-2670 0 @ 2.60GHz", Mhz: 2600},
|
||||
{CPU: 12, VendorID: "GenuineIntel", Family: "6", Model: "45", Stepping: 7, PhysicalID: "1", CoreID: "4", Cores: 2, ModelName: "Intel(r) Xeon(r) CPU E5-2670 0 @ 2.60GHz", Mhz: 2600},
|
||||
{CPU: 13, VendorID: "GenuineIntel", Family: "6", Model: "45", Stepping: 7, PhysicalID: "1", CoreID: "5", Cores: 2, ModelName: "Intel(r) Xeon(r) CPU E5-2670 0 @ 2.60GHz", Mhz: 2600},
|
||||
{CPU: 14, VendorID: "GenuineIntel", Family: "6", Model: "45", Stepping: 7, PhysicalID: "1", CoreID: "6", Cores: 2, ModelName: "Intel(r) Xeon(r) CPU E5-2670 0 @ 2.60GHz", Mhz: 2600},
|
||||
{CPU: 15, VendorID: "GenuineIntel", Family: "6", Model: "45", Stepping: 7, PhysicalID: "1", CoreID: "7", Cores: 2, ModelName: "Intel(r) Xeon(r) CPU E5-2670 0 @ 2.60GHz", Mhz: 2600},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
content, err := ioutil.ReadFile(filepath.Join("testdata", "solaris", tc.filename))
|
||||
if err != nil {
|
||||
t.Errorf("cannot read test case: %s", err)
|
||||
}
|
||||
|
||||
cpus, err := parseProcessorInfo(string(content))
|
||||
|
||||
if !reflect.DeepEqual(tc.expected, cpus) {
|
||||
t.Fatalf("Bad Processor Info\nExpected: %v\n Actual: %v", tc.expected, cpus)
|
||||
}
|
||||
}
|
||||
}
|
||||
145
vendor/github.com/shirou/gopsutil/cpu/cpu_test.go
generated
vendored
145
vendor/github.com/shirou/gopsutil/cpu/cpu_test.go
generated
vendored
@@ -1,145 +0,0 @@
|
||||
package cpu
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestCpu_times(t *testing.T) {
|
||||
v, err := Times(false)
|
||||
if err != nil {
|
||||
t.Errorf("error %v", err)
|
||||
}
|
||||
if len(v) == 0 {
|
||||
t.Error("could not get CPUs ", err)
|
||||
}
|
||||
empty := TimesStat{}
|
||||
for _, vv := range v {
|
||||
if vv == empty {
|
||||
t.Errorf("could not get CPU User: %v", vv)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCpu_counts(t *testing.T) {
|
||||
v, err := Counts(true)
|
||||
if err != nil {
|
||||
t.Errorf("error %v", err)
|
||||
}
|
||||
if v == 0 {
|
||||
t.Errorf("could not get CPU counts: %v", v)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCPUTimeStat_String(t *testing.T) {
|
||||
v := TimesStat{
|
||||
CPU: "cpu0",
|
||||
User: 100.1,
|
||||
System: 200.1,
|
||||
Idle: 300.1,
|
||||
}
|
||||
e := `{"cpu":"cpu0","user":100.1,"system":200.1,"idle":300.1,"nice":0.0,"iowait":0.0,"irq":0.0,"softirq":0.0,"steal":0.0,"guest":0.0,"guestNice":0.0,"stolen":0.0}`
|
||||
if e != fmt.Sprintf("%v", v) {
|
||||
t.Errorf("CPUTimesStat string is invalid: %v", v)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCpuInfo(t *testing.T) {
|
||||
v, err := Info()
|
||||
if err != nil {
|
||||
t.Errorf("error %v", err)
|
||||
}
|
||||
if len(v) == 0 {
|
||||
t.Errorf("could not get CPU Info")
|
||||
}
|
||||
for _, vv := range v {
|
||||
if vv.ModelName == "" {
|
||||
t.Errorf("could not get CPU Info: %v", vv)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func testCPUPercent(t *testing.T, percpu bool) {
|
||||
numcpu := runtime.NumCPU()
|
||||
testCount := 3
|
||||
|
||||
if runtime.GOOS != "windows" {
|
||||
testCount = 100
|
||||
v, err := Percent(time.Millisecond, percpu)
|
||||
if err != nil {
|
||||
t.Errorf("error %v", err)
|
||||
}
|
||||
// Skip CircleCI which CPU num is different
|
||||
if os.Getenv("CIRCLECI") != "true" {
|
||||
if (percpu && len(v) != numcpu) || (!percpu && len(v) != 1) {
|
||||
t.Fatalf("wrong number of entries from CPUPercent: %v", v)
|
||||
}
|
||||
}
|
||||
}
|
||||
for i := 0; i < testCount; i++ {
|
||||
duration := time.Duration(10) * time.Microsecond
|
||||
v, err := Percent(duration, percpu)
|
||||
if err != nil {
|
||||
t.Errorf("error %v", err)
|
||||
}
|
||||
for _, percent := range v {
|
||||
// Check for slightly greater then 100% to account for any rounding issues.
|
||||
if percent < 0.0 || percent > 100.0001*float64(numcpu) {
|
||||
t.Fatalf("CPUPercent value is invalid: %f", percent)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func testCPUPercentLastUsed(t *testing.T, percpu bool) {
|
||||
|
||||
numcpu := runtime.NumCPU()
|
||||
testCount := 10
|
||||
|
||||
if runtime.GOOS != "windows" {
|
||||
testCount = 2
|
||||
v, err := Percent(time.Millisecond, percpu)
|
||||
if err != nil {
|
||||
t.Errorf("error %v", err)
|
||||
}
|
||||
// Skip CircleCI which CPU num is different
|
||||
if os.Getenv("CIRCLECI") != "true" {
|
||||
if (percpu && len(v) != numcpu) || (!percpu && len(v) != 1) {
|
||||
t.Fatalf("wrong number of entries from CPUPercent: %v", v)
|
||||
}
|
||||
}
|
||||
}
|
||||
for i := 0; i < testCount; i++ {
|
||||
v, err := Percent(0, percpu)
|
||||
if err != nil {
|
||||
t.Errorf("error %v", err)
|
||||
}
|
||||
time.Sleep(1 * time.Millisecond)
|
||||
for _, percent := range v {
|
||||
// Check for slightly greater then 100% to account for any rounding issues.
|
||||
if percent < 0.0 || percent > 100.0001*float64(numcpu) {
|
||||
t.Fatalf("CPUPercent value is invalid: %f", percent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestCPUPercent(t *testing.T) {
|
||||
testCPUPercent(t, false)
|
||||
}
|
||||
|
||||
func TestCPUPercentPerCpu(t *testing.T) {
|
||||
testCPUPercent(t, true)
|
||||
}
|
||||
|
||||
func TestCPUPercentIntervalZero(t *testing.T) {
|
||||
testCPUPercentLastUsed(t, false)
|
||||
}
|
||||
|
||||
func TestCPUPercentIntervalZeroPerCPU(t *testing.T) {
|
||||
testCPUPercentLastUsed(t, true)
|
||||
}
|
||||
159
vendor/github.com/shirou/gopsutil/cpu/cpu_windows.go
generated
vendored
159
vendor/github.com/shirou/gopsutil/cpu/cpu_windows.go
generated
vendored
@@ -12,30 +12,35 @@ import (
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
var (
|
||||
procGetActiveProcessorCount = common.Modkernel32.NewProc("GetActiveProcessorCount")
|
||||
procGetNativeSystemInfo = common.Modkernel32.NewProc("GetNativeSystemInfo")
|
||||
)
|
||||
|
||||
type Win32_Processor struct {
|
||||
LoadPercentage *uint16
|
||||
Family uint16
|
||||
Manufacturer string
|
||||
Name string
|
||||
NumberOfLogicalProcessors uint32
|
||||
NumberOfCores uint32
|
||||
ProcessorID *string
|
||||
Stepping *string
|
||||
MaxClockSpeed uint32
|
||||
}
|
||||
|
||||
// Win32_PerfFormattedData_Counters_ProcessorInformation stores instance value of the perf counters
|
||||
type Win32_PerfFormattedData_Counters_ProcessorInformation struct {
|
||||
Name string
|
||||
PercentDPCTime uint64
|
||||
PercentIdleTime uint64
|
||||
PercentUserTime uint64
|
||||
PercentProcessorTime uint64
|
||||
PercentInterruptTime uint64
|
||||
PercentPriorityTime uint64
|
||||
PercentPrivilegedTime uint64
|
||||
InterruptsPerSec uint32
|
||||
ProcessorFrequency uint32
|
||||
DPCRate uint32
|
||||
// SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
|
||||
// defined in windows api doc with the following
|
||||
// https://docs.microsoft.com/en-us/windows/desktop/api/winternl/nf-winternl-ntquerysysteminformation#system_processor_performance_information
|
||||
// additional fields documented here
|
||||
// https://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/ex/sysinfo/processor_performance.htm
|
||||
type win32_SystemProcessorPerformanceInformation struct {
|
||||
IdleTime int64 // idle time in 100ns (this is not a filetime).
|
||||
KernelTime int64 // kernel time in 100ns. kernel time includes idle time. (this is not a filetime).
|
||||
UserTime int64 // usertime in 100ns (this is not a filetime).
|
||||
DpcTime int64 // dpc time in 100ns (this is not a filetime).
|
||||
InterruptTime int64 // interrupt time in 100ns
|
||||
InterruptCount uint32
|
||||
}
|
||||
|
||||
// Win32_PerfFormattedData_PerfOS_System struct to have count of processes and processor queue length
|
||||
@@ -44,6 +49,17 @@ type Win32_PerfFormattedData_PerfOS_System struct {
|
||||
ProcessorQueueLength uint32
|
||||
}
|
||||
|
||||
const (
|
||||
win32_TicksPerSecond = 10000000.0
|
||||
|
||||
// systemProcessorPerformanceInformationClass information class to query with NTQuerySystemInformation
|
||||
// https://processhacker.sourceforge.io/doc/ntexapi_8h.html#ad5d815b48e8f4da1ef2eb7a2f18a54e0
|
||||
win32_SystemProcessorPerformanceInformationClass = 8
|
||||
|
||||
// size of systemProcessorPerformanceInfoSize in memory
|
||||
win32_SystemProcessorPerformanceInfoSize = uint32(unsafe.Sizeof(win32_SystemProcessorPerformanceInformation{}))
|
||||
)
|
||||
|
||||
// Times returns times stat per cpu and combined for all CPUs
|
||||
func Times(percpu bool) ([]TimesStat, error) {
|
||||
return TimesWithContext(context.Background(), percpu)
|
||||
@@ -117,24 +133,6 @@ func InfoWithContext(ctx context.Context) ([]InfoStat, error) {
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// PerfInfo returns the performance counter's instance value for ProcessorInformation.
|
||||
// Name property is the key by which overall, per cpu and per core metric is known.
|
||||
func PerfInfo() ([]Win32_PerfFormattedData_Counters_ProcessorInformation, error) {
|
||||
return PerfInfoWithContext(context.Background())
|
||||
}
|
||||
|
||||
func PerfInfoWithContext(ctx context.Context) ([]Win32_PerfFormattedData_Counters_ProcessorInformation, error) {
|
||||
var ret []Win32_PerfFormattedData_Counters_ProcessorInformation
|
||||
|
||||
q := wmi.CreateQuery(&ret, "")
|
||||
err := common.WMIQueryWithContext(ctx, q, &ret)
|
||||
if err != nil {
|
||||
return []Win32_PerfFormattedData_Counters_ProcessorInformation{}, err
|
||||
}
|
||||
|
||||
return ret, err
|
||||
}
|
||||
|
||||
// ProcInfo returns processes count and processor queue length in the system.
|
||||
// There is a single queue for processor even on multiprocessors systems.
|
||||
func ProcInfo() ([]Win32_PerfFormattedData_PerfOS_System, error) {
|
||||
@@ -154,19 +152,104 @@ func ProcInfoWithContext(ctx context.Context) ([]Win32_PerfFormattedData_PerfOS_
|
||||
// perCPUTimes returns times stat per cpu, per core and overall for all CPUs
|
||||
func perCPUTimes() ([]TimesStat, error) {
|
||||
var ret []TimesStat
|
||||
stats, err := PerfInfo()
|
||||
stats, err := perfInfo()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, v := range stats {
|
||||
for core, v := range stats {
|
||||
c := TimesStat{
|
||||
CPU: v.Name,
|
||||
User: float64(v.PercentUserTime),
|
||||
System: float64(v.PercentPrivilegedTime),
|
||||
Idle: float64(v.PercentIdleTime),
|
||||
Irq: float64(v.PercentInterruptTime),
|
||||
CPU: fmt.Sprintf("cpu%d", core),
|
||||
User: float64(v.UserTime) / win32_TicksPerSecond,
|
||||
System: float64(v.KernelTime-v.IdleTime) / win32_TicksPerSecond,
|
||||
Idle: float64(v.IdleTime) / win32_TicksPerSecond,
|
||||
Irq: float64(v.InterruptTime) / win32_TicksPerSecond,
|
||||
}
|
||||
ret = append(ret, c)
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// makes call to Windows API function to retrieve performance information for each core
|
||||
func perfInfo() ([]win32_SystemProcessorPerformanceInformation, error) {
|
||||
// Make maxResults large for safety.
|
||||
// We can't invoke the api call with a results array that's too small.
|
||||
// If we have more than 2056 cores on a single host, then it's probably the future.
|
||||
maxBuffer := 2056
|
||||
// buffer for results from the windows proc
|
||||
resultBuffer := make([]win32_SystemProcessorPerformanceInformation, maxBuffer)
|
||||
// size of the buffer in memory
|
||||
bufferSize := uintptr(win32_SystemProcessorPerformanceInfoSize) * uintptr(maxBuffer)
|
||||
// size of the returned response
|
||||
var retSize uint32
|
||||
|
||||
// Invoke windows api proc.
|
||||
// The returned err from the windows dll proc will always be non-nil even when successful.
|
||||
// See https://godoc.org/golang.org/x/sys/windows#LazyProc.Call for more information
|
||||
retCode, _, err := common.ProcNtQuerySystemInformation.Call(
|
||||
win32_SystemProcessorPerformanceInformationClass, // System Information Class -> SystemProcessorPerformanceInformation
|
||||
uintptr(unsafe.Pointer(&resultBuffer[0])), // pointer to first element in result buffer
|
||||
bufferSize, // size of the buffer in memory
|
||||
uintptr(unsafe.Pointer(&retSize)), // pointer to the size of the returned results the windows proc will set this
|
||||
)
|
||||
|
||||
// check return code for errors
|
||||
if retCode != 0 {
|
||||
return nil, fmt.Errorf("call to NtQuerySystemInformation returned %d. err: %s", retCode, err.Error())
|
||||
}
|
||||
|
||||
// calculate the number of returned elements based on the returned size
|
||||
numReturnedElements := retSize / win32_SystemProcessorPerformanceInfoSize
|
||||
|
||||
// trim results to the number of returned elements
|
||||
resultBuffer = resultBuffer[:numReturnedElements]
|
||||
|
||||
return resultBuffer, nil
|
||||
}
|
||||
|
||||
// SystemInfo is an equivalent representation of SYSTEM_INFO in the Windows API.
|
||||
// https://msdn.microsoft.com/en-us/library/ms724958%28VS.85%29.aspx?f=255&MSPPError=-2147217396
|
||||
// https://github.com/elastic/go-windows/blob/bb1581babc04d5cb29a2bfa7a9ac6781c730c8dd/kernel32.go#L43
|
||||
type systemInfo struct {
|
||||
wProcessorArchitecture uint16
|
||||
wReserved uint16
|
||||
dwPageSize uint32
|
||||
lpMinimumApplicationAddress uintptr
|
||||
lpMaximumApplicationAddress uintptr
|
||||
dwActiveProcessorMask uintptr
|
||||
dwNumberOfProcessors uint32
|
||||
dwProcessorType uint32
|
||||
dwAllocationGranularity uint32
|
||||
wProcessorLevel uint16
|
||||
wProcessorRevision uint16
|
||||
}
|
||||
|
||||
func CountsWithContext(ctx context.Context, logical bool) (int, error) {
|
||||
if logical {
|
||||
// https://github.com/giampaolo/psutil/blob/d01a9eaa35a8aadf6c519839e987a49d8be2d891/psutil/_psutil_windows.c#L97
|
||||
err := procGetActiveProcessorCount.Find()
|
||||
if err == nil { // Win7+
|
||||
ret, _, _ := procGetActiveProcessorCount.Call(uintptr(0xffff)) // ALL_PROCESSOR_GROUPS is 0xffff according to Rust's winapi lib https://docs.rs/winapi/*/x86_64-pc-windows-msvc/src/winapi/shared/ntdef.rs.html#120
|
||||
if ret != 0 {
|
||||
return int(ret), nil
|
||||
}
|
||||
}
|
||||
var systemInfo systemInfo
|
||||
_, _, err = procGetNativeSystemInfo.Call(uintptr(unsafe.Pointer(&systemInfo)))
|
||||
if systemInfo.dwNumberOfProcessors == 0 {
|
||||
return 0, err
|
||||
}
|
||||
return int(systemInfo.dwNumberOfProcessors), nil
|
||||
}
|
||||
// physical cores https://github.com/giampaolo/psutil/blob/d01a9eaa35a8aadf6c519839e987a49d8be2d891/psutil/_psutil_windows.c#L499
|
||||
// for the time being, try with unreliable and slow WMI call…
|
||||
var dst []Win32_Processor
|
||||
q := wmi.CreateQuery(&dst, "")
|
||||
if err := common.WMIQueryWithContext(ctx, q, &dst); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
var count uint32
|
||||
for _, d := range dst {
|
||||
count += d.NumberOfCores
|
||||
}
|
||||
return int(count), nil
|
||||
}
|
||||
|
||||
7
vendor/github.com/shirou/gopsutil/disk/disk.go
generated
vendored
7
vendor/github.com/shirou/gopsutil/disk/disk.go
generated
vendored
@@ -6,11 +6,7 @@ import (
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
)
|
||||
|
||||
var invoke common.Invoker
|
||||
|
||||
func init() {
|
||||
invoke = common.Invoke{}
|
||||
}
|
||||
var invoke common.Invoker = common.Invoke{}
|
||||
|
||||
type UsageStat struct {
|
||||
Path string `json:"path"`
|
||||
@@ -46,6 +42,7 @@ type IOCountersStat struct {
|
||||
WeightedIO uint64 `json:"weightedIO"`
|
||||
Name string `json:"name"`
|
||||
SerialNumber string `json:"serialNumber"`
|
||||
Label string `json:"label"`
|
||||
}
|
||||
|
||||
func (d UsageStat) String() string {
|
||||
|
||||
131
vendor/github.com/shirou/gopsutil/disk/disk_darwin.c
generated
vendored
Normal file
131
vendor/github.com/shirou/gopsutil/disk/disk_darwin.c
generated
vendored
Normal file
@@ -0,0 +1,131 @@
|
||||
// https://github.com/lufia/iostat/blob/9f7362b77ad333b26c01c99de52a11bdb650ded2/iostat_darwin.c
|
||||
#include <stdint.h>
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include "disk_darwin.h"
|
||||
|
||||
#define IOKIT 1 /* to get io_name_t in device_types.h */
|
||||
|
||||
#include <IOKit/IOKitLib.h>
|
||||
#include <IOKit/storage/IOBlockStorageDriver.h>
|
||||
#include <IOKit/storage/IOMedia.h>
|
||||
#include <IOKit/IOBSD.h>
|
||||
|
||||
#include <mach/mach_host.h>
|
||||
|
||||
static int getdrivestat(io_registry_entry_t d, DriveStats *stat);
|
||||
static int fillstat(io_registry_entry_t d, DriveStats *stat);
|
||||
|
||||
int
|
||||
readdrivestat(DriveStats a[], int n)
|
||||
{
|
||||
mach_port_t port;
|
||||
CFMutableDictionaryRef match;
|
||||
io_iterator_t drives;
|
||||
io_registry_entry_t d;
|
||||
kern_return_t status;
|
||||
int na, rv;
|
||||
|
||||
IOMasterPort(bootstrap_port, &port);
|
||||
match = IOServiceMatching("IOMedia");
|
||||
CFDictionaryAddValue(match, CFSTR(kIOMediaWholeKey), kCFBooleanTrue);
|
||||
status = IOServiceGetMatchingServices(port, match, &drives);
|
||||
if(status != KERN_SUCCESS)
|
||||
return -1;
|
||||
|
||||
na = 0;
|
||||
while(na < n && (d=IOIteratorNext(drives)) > 0){
|
||||
rv = getdrivestat(d, &a[na]);
|
||||
if(rv < 0)
|
||||
return -1;
|
||||
if(rv > 0)
|
||||
na++;
|
||||
IOObjectRelease(d);
|
||||
}
|
||||
IOObjectRelease(drives);
|
||||
return na;
|
||||
}
|
||||
|
||||
static int
|
||||
getdrivestat(io_registry_entry_t d, DriveStats *stat)
|
||||
{
|
||||
io_registry_entry_t parent;
|
||||
kern_return_t status;
|
||||
CFDictionaryRef props;
|
||||
CFStringRef name;
|
||||
CFNumberRef num;
|
||||
int rv;
|
||||
|
||||
memset(stat, 0, sizeof *stat);
|
||||
status = IORegistryEntryGetParentEntry(d, kIOServicePlane, &parent);
|
||||
if(status != KERN_SUCCESS)
|
||||
return -1;
|
||||
if(!IOObjectConformsTo(parent, "IOBlockStorageDriver")){
|
||||
IOObjectRelease(parent);
|
||||
return 0;
|
||||
}
|
||||
|
||||
status = IORegistryEntryCreateCFProperties(d, (CFMutableDictionaryRef *)&props, kCFAllocatorDefault, kNilOptions);
|
||||
if(status != KERN_SUCCESS){
|
||||
IOObjectRelease(parent);
|
||||
return -1;
|
||||
}
|
||||
name = (CFStringRef)CFDictionaryGetValue(props, CFSTR(kIOBSDNameKey));
|
||||
CFStringGetCString(name, stat->name, NAMELEN, CFStringGetSystemEncoding());
|
||||
num = (CFNumberRef)CFDictionaryGetValue(props, CFSTR(kIOMediaSizeKey));
|
||||
CFNumberGetValue(num, kCFNumberSInt64Type, &stat->size);
|
||||
num = (CFNumberRef)CFDictionaryGetValue(props, CFSTR(kIOMediaPreferredBlockSizeKey));
|
||||
CFNumberGetValue(num, kCFNumberSInt64Type, &stat->blocksize);
|
||||
CFRelease(props);
|
||||
|
||||
rv = fillstat(parent, stat);
|
||||
IOObjectRelease(parent);
|
||||
if(rv < 0)
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct {
|
||||
char *key;
|
||||
size_t off;
|
||||
} statstab[] = {
|
||||
{kIOBlockStorageDriverStatisticsBytesReadKey, offsetof(DriveStats, read)},
|
||||
{kIOBlockStorageDriverStatisticsBytesWrittenKey, offsetof(DriveStats, written)},
|
||||
{kIOBlockStorageDriverStatisticsReadsKey, offsetof(DriveStats, nread)},
|
||||
{kIOBlockStorageDriverStatisticsWritesKey, offsetof(DriveStats, nwrite)},
|
||||
{kIOBlockStorageDriverStatisticsTotalReadTimeKey, offsetof(DriveStats, readtime)},
|
||||
{kIOBlockStorageDriverStatisticsTotalWriteTimeKey, offsetof(DriveStats, writetime)},
|
||||
{kIOBlockStorageDriverStatisticsLatentReadTimeKey, offsetof(DriveStats, readlat)},
|
||||
{kIOBlockStorageDriverStatisticsLatentWriteTimeKey, offsetof(DriveStats, writelat)},
|
||||
};
|
||||
|
||||
static int
|
||||
fillstat(io_registry_entry_t d, DriveStats *stat)
|
||||
{
|
||||
CFDictionaryRef props, v;
|
||||
CFNumberRef num;
|
||||
kern_return_t status;
|
||||
typeof(statstab[0]) *bp, *ep;
|
||||
|
||||
status = IORegistryEntryCreateCFProperties(d, (CFMutableDictionaryRef *)&props, kCFAllocatorDefault, kNilOptions);
|
||||
if(status != KERN_SUCCESS)
|
||||
return -1;
|
||||
v = (CFDictionaryRef)CFDictionaryGetValue(props, CFSTR(kIOBlockStorageDriverStatisticsKey));
|
||||
if(v == NULL){
|
||||
CFRelease(props);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ep = &statstab[sizeof(statstab)/sizeof(statstab[0])];
|
||||
for(bp = &statstab[0]; bp < ep; bp++){
|
||||
CFStringRef s;
|
||||
|
||||
s = CFStringCreateWithCString(kCFAllocatorDefault, bp->key, CFStringGetSystemEncoding());
|
||||
num = (CFNumberRef)CFDictionaryGetValue(v, s);
|
||||
if(num)
|
||||
CFNumberGetValue(num, kCFNumberSInt64Type, ((char*)stat)+bp->off);
|
||||
CFRelease(s);
|
||||
}
|
||||
|
||||
CFRelease(props);
|
||||
return 0;
|
||||
}
|
||||
74
vendor/github.com/shirou/gopsutil/disk/disk_darwin.go
generated
vendored
74
vendor/github.com/shirou/gopsutil/disk/disk_darwin.go
generated
vendored
@@ -5,7 +5,6 @@ package disk
|
||||
import (
|
||||
"context"
|
||||
"path"
|
||||
"unsafe"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"golang.org/x/sys/unix"
|
||||
@@ -18,61 +17,51 @@ func Partitions(all bool) ([]PartitionStat, error) {
|
||||
func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, error) {
|
||||
var ret []PartitionStat
|
||||
|
||||
count, err := Getfsstat(nil, MntWait)
|
||||
count, err := unix.Getfsstat(nil, unix.MNT_WAIT)
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
fs := make([]Statfs_t, count)
|
||||
_, err = Getfsstat(fs, MntWait)
|
||||
fs := make([]unix.Statfs_t, count)
|
||||
if _, err = unix.Getfsstat(fs, unix.MNT_WAIT); err != nil {
|
||||
return ret, err
|
||||
}
|
||||
for _, stat := range fs {
|
||||
opts := "rw"
|
||||
if stat.Flags&MntReadOnly != 0 {
|
||||
if stat.Flags&unix.MNT_RDONLY != 0 {
|
||||
opts = "ro"
|
||||
}
|
||||
if stat.Flags&MntSynchronous != 0 {
|
||||
if stat.Flags&unix.MNT_SYNCHRONOUS != 0 {
|
||||
opts += ",sync"
|
||||
}
|
||||
if stat.Flags&MntNoExec != 0 {
|
||||
if stat.Flags&unix.MNT_NOEXEC != 0 {
|
||||
opts += ",noexec"
|
||||
}
|
||||
if stat.Flags&MntNoSuid != 0 {
|
||||
if stat.Flags&unix.MNT_NOSUID != 0 {
|
||||
opts += ",nosuid"
|
||||
}
|
||||
if stat.Flags&MntUnion != 0 {
|
||||
if stat.Flags&unix.MNT_UNION != 0 {
|
||||
opts += ",union"
|
||||
}
|
||||
if stat.Flags&MntAsync != 0 {
|
||||
if stat.Flags&unix.MNT_ASYNC != 0 {
|
||||
opts += ",async"
|
||||
}
|
||||
if stat.Flags&MntSuidDir != 0 {
|
||||
opts += ",suiddir"
|
||||
if stat.Flags&unix.MNT_DONTBROWSE != 0 {
|
||||
opts += ",nobrowse"
|
||||
}
|
||||
if stat.Flags&MntSoftDep != 0 {
|
||||
opts += ",softdep"
|
||||
if stat.Flags&unix.MNT_AUTOMOUNTED != 0 {
|
||||
opts += ",automounted"
|
||||
}
|
||||
if stat.Flags&MntNoSymFollow != 0 {
|
||||
opts += ",nosymfollow"
|
||||
if stat.Flags&unix.MNT_JOURNALED != 0 {
|
||||
opts += ",journaled"
|
||||
}
|
||||
if stat.Flags&MntGEOMJournal != 0 {
|
||||
opts += ",gjounalc"
|
||||
}
|
||||
if stat.Flags&MntMultilabel != 0 {
|
||||
if stat.Flags&unix.MNT_MULTILABEL != 0 {
|
||||
opts += ",multilabel"
|
||||
}
|
||||
if stat.Flags&MntACLs != 0 {
|
||||
opts += ",acls"
|
||||
if stat.Flags&unix.MNT_NOATIME != 0 {
|
||||
opts += ",noatime"
|
||||
}
|
||||
if stat.Flags&MntNoATime != 0 {
|
||||
opts += ",noattime"
|
||||
}
|
||||
if stat.Flags&MntClusterRead != 0 {
|
||||
opts += ",nocluster"
|
||||
}
|
||||
if stat.Flags&MntClusterWrite != 0 {
|
||||
opts += ",noclusterw"
|
||||
}
|
||||
if stat.Flags&MntNFS4ACLs != 0 {
|
||||
opts += ",nfs4acls"
|
||||
if stat.Flags&unix.MNT_NODEV != 0 {
|
||||
opts += ",nodev"
|
||||
}
|
||||
d := PartitionStat{
|
||||
Device: common.IntToString(stat.Mntfromname[:]),
|
||||
@@ -92,25 +81,6 @@ func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, erro
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
|
||||
return GetfsstatWithContext(context.Background(), buf, flags)
|
||||
}
|
||||
|
||||
func GetfsstatWithContext(ctx context.Context, buf []Statfs_t, flags int) (n int, err error) {
|
||||
var _p0 unsafe.Pointer
|
||||
var bufsize uintptr
|
||||
if len(buf) > 0 {
|
||||
_p0 = unsafe.Pointer(&buf[0])
|
||||
bufsize = unsafe.Sizeof(Statfs_t{}) * uintptr(len(buf))
|
||||
}
|
||||
r0, _, e1 := unix.Syscall(SYS_GETFSSTAT64, uintptr(_p0), bufsize, uintptr(flags))
|
||||
n = int(r0)
|
||||
if e1 != 0 {
|
||||
err = e1
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func getFsType(stat unix.Statfs_t) string {
|
||||
return common.IntToString(stat.Fstypename[:])
|
||||
}
|
||||
|
||||
187
vendor/github.com/shirou/gopsutil/disk/disk_darwin.h
generated
vendored
187
vendor/github.com/shirou/gopsutil/disk/disk_darwin.h
generated
vendored
@@ -1,164 +1,33 @@
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <IOKit/IOKitLib.h>
|
||||
#include <IOKit/storage/IOBlockStorageDriver.h>
|
||||
#include <IOKit/storage/IOMedia.h>
|
||||
#include <IOKit/IOBSD.h>
|
||||
// https://github.com/lufia/iostat/blob/9f7362b77ad333b26c01c99de52a11bdb650ded2/iostat_darwin.h
|
||||
typedef struct DriveStats DriveStats;
|
||||
typedef struct CPUStats CPUStats;
|
||||
|
||||
// The iterator of all things disk. Allocated by StartIOCounterFetch, released
|
||||
// by EndIOCounterFetch.
|
||||
static io_iterator_t diskIter;
|
||||
enum {
|
||||
NDRIVE = 16,
|
||||
NAMELEN = 31
|
||||
};
|
||||
|
||||
// Begins fetching IO counters.
|
||||
//
|
||||
// Returns 1 if the fetch started successfully, false otherwise.
|
||||
//
|
||||
// If the fetch was started successfully, you must call EndIOCounterFetch once
|
||||
// done to release resources.
|
||||
int StartIOCounterFetch()
|
||||
{
|
||||
if (IOServiceGetMatchingServices(kIOMasterPortDefault,
|
||||
IOServiceMatching(kIOMediaClass),
|
||||
&diskIter) != kIOReturnSuccess) {
|
||||
return 0;
|
||||
}
|
||||
struct DriveStats {
|
||||
char name[NAMELEN+1];
|
||||
int64_t size;
|
||||
int64_t blocksize;
|
||||
|
||||
return 1;
|
||||
}
|
||||
int64_t read;
|
||||
int64_t written;
|
||||
int64_t nread;
|
||||
int64_t nwrite;
|
||||
int64_t readtime;
|
||||
int64_t writetime;
|
||||
int64_t readlat;
|
||||
int64_t writelat;
|
||||
};
|
||||
|
||||
// Releases resources from fetching IO counters.
|
||||
void EndIOCounterFetch()
|
||||
{
|
||||
IOObjectRelease(diskIter);
|
||||
}
|
||||
|
||||
// The current disk entry of interest. Allocated by FetchNextDisk(), released by
|
||||
// ReadDiskInfo().
|
||||
static io_registry_entry_t diskEntry;
|
||||
|
||||
// The parent of diskEntry. Same lifetimes.
|
||||
static io_registry_entry_t parentEntry;
|
||||
|
||||
// Fetches the next disk. Note that a disk entry is allocated, and will be held
|
||||
// until it is processed and freed by ReadDiskInfo.
|
||||
int FetchNextDisk()
|
||||
{
|
||||
while ((diskEntry = IOIteratorNext(diskIter)) != 0) {
|
||||
// We are iterating IOMedia. We need to get the parent too (IOBSD).
|
||||
if (IORegistryEntryGetParentEntry(diskEntry, kIOServicePlane, &parentEntry) != kIOReturnSuccess) {
|
||||
// something is wrong...
|
||||
IOObjectRelease(diskEntry);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!IOObjectConformsTo(parentEntry, "IOBlockStorageDriver")) {
|
||||
// no use to us, try the next disk
|
||||
IOObjectRelease(diskEntry);
|
||||
IOObjectRelease(parentEntry);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Got a disk OK.
|
||||
return 1;
|
||||
}
|
||||
|
||||
// No more disks.
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Reads the current disk (from iteration) info into DiskInfo struct.
|
||||
// Once done, all resources from the current iteration of reading are freed,
|
||||
// ready for FetchNextDisk() to be called again.
|
||||
int ReadDiskInfo(DiskInfo *info)
|
||||
{
|
||||
// Parent props. Allocated by us.
|
||||
CFDictionaryRef parentProps = NULL;
|
||||
|
||||
// Disk props. Allocated by us.
|
||||
CFDictionaryRef diskProps = NULL;
|
||||
|
||||
// Disk stats, fetched by us, but not allocated by us.
|
||||
CFDictionaryRef stats = NULL;
|
||||
|
||||
if (IORegistryEntryCreateCFProperties(diskEntry, (CFMutableDictionaryRef *)&parentProps,
|
||||
kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess)
|
||||
{
|
||||
// can't get parent props, give up
|
||||
CFRelease(parentProps);
|
||||
IOObjectRelease(diskEntry);
|
||||
IOObjectRelease(parentEntry);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (IORegistryEntryCreateCFProperties(parentEntry, (CFMutableDictionaryRef *)&diskProps,
|
||||
kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess)
|
||||
{
|
||||
// can't get disk props, give up
|
||||
CFRelease(parentProps);
|
||||
CFRelease(diskProps);
|
||||
IOObjectRelease(diskEntry);
|
||||
IOObjectRelease(parentEntry);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Start fetching
|
||||
CFStringRef cfDiskName = (CFStringRef)CFDictionaryGetValue(parentProps, CFSTR(kIOBSDNameKey));
|
||||
CFStringGetCString(cfDiskName, info->DiskName, MAX_DISK_NAME, CFStringGetSystemEncoding());
|
||||
stats = (CFDictionaryRef)CFDictionaryGetValue( diskProps, CFSTR(kIOBlockStorageDriverStatisticsKey));
|
||||
|
||||
if (stats == NULL) {
|
||||
// stat fetch failed...
|
||||
CFRelease(parentProps);
|
||||
CFRelease(diskProps);
|
||||
IOObjectRelease(parentEntry);
|
||||
IOObjectRelease(diskEntry);
|
||||
return -1;
|
||||
}
|
||||
|
||||
CFNumberRef cfnum;
|
||||
|
||||
if ((cfnum = (CFNumberRef)CFDictionaryGetValue(stats, CFSTR(kIOBlockStorageDriverStatisticsReadsKey)))) {
|
||||
CFNumberGetValue(cfnum, kCFNumberSInt64Type, &info->Reads);
|
||||
} else {
|
||||
info->Reads = 0;
|
||||
}
|
||||
|
||||
if ((cfnum = (CFNumberRef)CFDictionaryGetValue(stats, CFSTR(kIOBlockStorageDriverStatisticsWritesKey)))) {
|
||||
CFNumberGetValue(cfnum, kCFNumberSInt64Type, &info->Writes);
|
||||
} else {
|
||||
info->Writes = 0;
|
||||
}
|
||||
|
||||
if ((cfnum = (CFNumberRef)CFDictionaryGetValue(stats, CFSTR(kIOBlockStorageDriverStatisticsBytesReadKey)))) {
|
||||
CFNumberGetValue(cfnum, kCFNumberSInt64Type, &info->ReadBytes);
|
||||
} else {
|
||||
info->ReadBytes = 0;
|
||||
}
|
||||
|
||||
if ((cfnum = (CFNumberRef)CFDictionaryGetValue(stats, CFSTR(kIOBlockStorageDriverStatisticsBytesWrittenKey)))) {
|
||||
CFNumberGetValue(cfnum, kCFNumberSInt64Type, &info->WriteBytes);
|
||||
} else {
|
||||
info->WriteBytes = 0;
|
||||
}
|
||||
|
||||
if ((cfnum = (CFNumberRef)CFDictionaryGetValue(stats, CFSTR(kIOBlockStorageDriverStatisticsTotalReadTimeKey)))) {
|
||||
CFNumberGetValue(cfnum, kCFNumberSInt64Type, &info->ReadTime);
|
||||
} else {
|
||||
info->ReadTime = 0;
|
||||
}
|
||||
if ((cfnum = (CFNumberRef)CFDictionaryGetValue(stats, CFSTR(kIOBlockStorageDriverStatisticsTotalWriteTimeKey)))) {
|
||||
CFNumberGetValue(cfnum, kCFNumberSInt64Type, &info->WriteTime);
|
||||
} else {
|
||||
info->WriteTime = 0;
|
||||
}
|
||||
|
||||
// note: read/write time are in ns, but we want ms.
|
||||
info->ReadTime = info->ReadTime / 1000 / 1000;
|
||||
info->WriteTime = info->WriteTime / 1000 / 1000;
|
||||
|
||||
CFRelease(parentProps);
|
||||
CFRelease(diskProps);
|
||||
IOObjectRelease(parentEntry);
|
||||
IOObjectRelease(diskEntry);
|
||||
return 0;
|
||||
}
|
||||
struct CPUStats {
|
||||
natural_t user;
|
||||
natural_t nice;
|
||||
natural_t sys;
|
||||
natural_t idle;
|
||||
};
|
||||
|
||||
extern int readdrivestat(DriveStats a[], int n);
|
||||
extern int readcpustat(CPUStats *cpu);
|
||||
|
||||
58
vendor/github.com/shirou/gopsutil/disk/disk_darwin_amd64.go
generated
vendored
58
vendor/github.com/shirou/gopsutil/disk/disk_darwin_amd64.go
generated
vendored
@@ -1,58 +0,0 @@
|
||||
// +build darwin
|
||||
// +build amd64
|
||||
|
||||
package disk
|
||||
|
||||
const (
|
||||
MntWait = 1
|
||||
MfsNameLen = 15 /* length of fs type name, not inc. nul */
|
||||
MNameLen = 90 /* length of buffer for returned name */
|
||||
|
||||
MFSTYPENAMELEN = 16 /* length of fs type name including null */
|
||||
MAXPATHLEN = 1024
|
||||
MNAMELEN = MAXPATHLEN
|
||||
|
||||
SYS_GETFSSTAT64 = 347
|
||||
)
|
||||
|
||||
type Fsid struct{ val [2]int32 } /* file system id type */
|
||||
type uid_t int32
|
||||
|
||||
// sys/mount.h
|
||||
const (
|
||||
MntReadOnly = 0x00000001 /* read only filesystem */
|
||||
MntSynchronous = 0x00000002 /* filesystem written synchronously */
|
||||
MntNoExec = 0x00000004 /* can't exec from filesystem */
|
||||
MntNoSuid = 0x00000008 /* don't honor setuid bits on fs */
|
||||
MntUnion = 0x00000020 /* union with underlying filesystem */
|
||||
MntAsync = 0x00000040 /* filesystem written asynchronously */
|
||||
MntSuidDir = 0x00100000 /* special handling of SUID on dirs */
|
||||
MntSoftDep = 0x00200000 /* soft updates being done */
|
||||
MntNoSymFollow = 0x00400000 /* do not follow symlinks */
|
||||
MntGEOMJournal = 0x02000000 /* GEOM journal support enabled */
|
||||
MntMultilabel = 0x04000000 /* MAC support for individual objects */
|
||||
MntACLs = 0x08000000 /* ACL support enabled */
|
||||
MntNoATime = 0x10000000 /* disable update of file access time */
|
||||
MntClusterRead = 0x40000000 /* disable cluster read */
|
||||
MntClusterWrite = 0x80000000 /* disable cluster write */
|
||||
MntNFS4ACLs = 0x00000010
|
||||
)
|
||||
|
||||
type Statfs_t struct {
|
||||
Bsize uint32
|
||||
Iosize int32
|
||||
Blocks uint64
|
||||
Bfree uint64
|
||||
Bavail uint64
|
||||
Files uint64
|
||||
Ffree uint64
|
||||
Fsid Fsid
|
||||
Owner uint32
|
||||
Type uint32
|
||||
Flags uint32
|
||||
Fssubtype uint32
|
||||
Fstypename [16]int8
|
||||
Mntonname [1024]int8
|
||||
Mntfromname [1024]int8
|
||||
Reserved [8]uint32
|
||||
}
|
||||
58
vendor/github.com/shirou/gopsutil/disk/disk_darwin_arm64.go
generated
vendored
58
vendor/github.com/shirou/gopsutil/disk/disk_darwin_arm64.go
generated
vendored
@@ -1,58 +0,0 @@
|
||||
// +build darwin
|
||||
// +build arm64
|
||||
|
||||
package disk
|
||||
|
||||
const (
|
||||
MntWait = 1
|
||||
MfsNameLen = 15 /* length of fs type name, not inc. nul */
|
||||
MNameLen = 90 /* length of buffer for returned name */
|
||||
|
||||
MFSTYPENAMELEN = 16 /* length of fs type name including null */
|
||||
MAXPATHLEN = 1024
|
||||
MNAMELEN = MAXPATHLEN
|
||||
|
||||
SYS_GETFSSTAT64 = 347
|
||||
)
|
||||
|
||||
type Fsid struct{ val [2]int32 } /* file system id type */
|
||||
type uid_t int32
|
||||
|
||||
// sys/mount.h
|
||||
const (
|
||||
MntReadOnly = 0x00000001 /* read only filesystem */
|
||||
MntSynchronous = 0x00000002 /* filesystem written synchronously */
|
||||
MntNoExec = 0x00000004 /* can't exec from filesystem */
|
||||
MntNoSuid = 0x00000008 /* don't honor setuid bits on fs */
|
||||
MntUnion = 0x00000020 /* union with underlying filesystem */
|
||||
MntAsync = 0x00000040 /* filesystem written asynchronously */
|
||||
MntSuidDir = 0x00100000 /* special handling of SUID on dirs */
|
||||
MntSoftDep = 0x00200000 /* soft updates being done */
|
||||
MntNoSymFollow = 0x00400000 /* do not follow symlinks */
|
||||
MntGEOMJournal = 0x02000000 /* GEOM journal support enabled */
|
||||
MntMultilabel = 0x04000000 /* MAC support for individual objects */
|
||||
MntACLs = 0x08000000 /* ACL support enabled */
|
||||
MntNoATime = 0x10000000 /* disable update of file access time */
|
||||
MntClusterRead = 0x40000000 /* disable cluster read */
|
||||
MntClusterWrite = 0x80000000 /* disable cluster write */
|
||||
MntNFS4ACLs = 0x00000010
|
||||
)
|
||||
|
||||
type Statfs_t struct {
|
||||
Bsize uint32
|
||||
Iosize int32
|
||||
Blocks uint64
|
||||
Bfree uint64
|
||||
Bavail uint64
|
||||
Files uint64
|
||||
Ffree uint64
|
||||
Fsid Fsid
|
||||
Owner uint32
|
||||
Type uint32
|
||||
Flags uint32
|
||||
Fssubtype uint32
|
||||
Fstypename [16]int8
|
||||
Mntonname [1024]int8
|
||||
Mntfromname [1024]int8
|
||||
Reserved [8]uint32
|
||||
}
|
||||
76
vendor/github.com/shirou/gopsutil/disk/disk_darwin_cgo.go
generated
vendored
76
vendor/github.com/shirou/gopsutil/disk/disk_darwin_cgo.go
generated
vendored
@@ -4,32 +4,15 @@
|
||||
package disk
|
||||
|
||||
/*
|
||||
#cgo LDFLAGS: -lobjc -framework Foundation -framework IOKit
|
||||
#cgo LDFLAGS: -framework CoreFoundation -framework IOKit
|
||||
#include <stdint.h>
|
||||
|
||||
// ### enough?
|
||||
const int MAX_DISK_NAME = 100;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char DiskName[MAX_DISK_NAME];
|
||||
int64_t Reads;
|
||||
int64_t Writes;
|
||||
int64_t ReadBytes;
|
||||
int64_t WriteBytes;
|
||||
int64_t ReadTime;
|
||||
int64_t WriteTime;
|
||||
} DiskInfo;
|
||||
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include "disk_darwin.h"
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"strings"
|
||||
"unsafe"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
)
|
||||
@@ -39,57 +22,28 @@ func IOCounters(names ...string) (map[string]IOCountersStat, error) {
|
||||
}
|
||||
|
||||
func IOCountersWithContext(ctx context.Context, names ...string) (map[string]IOCountersStat, error) {
|
||||
if C.StartIOCounterFetch() == 0 {
|
||||
return nil, errors.New("Unable to fetch disk list")
|
||||
var buf [C.NDRIVE]C.DriveStats
|
||||
n, err := C.readdrivestat(&buf[0], C.int(len(buf)))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Clean up when we are done.
|
||||
defer C.EndIOCounterFetch()
|
||||
ret := make(map[string]IOCountersStat, 0)
|
||||
|
||||
for {
|
||||
res := C.FetchNextDisk()
|
||||
if res == -1 {
|
||||
return nil, errors.New("Unable to fetch disk information")
|
||||
} else if res == 0 {
|
||||
break // done
|
||||
}
|
||||
|
||||
di := C.DiskInfo{}
|
||||
if C.ReadDiskInfo((*C.DiskInfo)(unsafe.Pointer(&di))) == -1 {
|
||||
return nil, errors.New("Unable to fetch disk properties")
|
||||
}
|
||||
|
||||
// Used to only get the necessary part of the C string.
|
||||
isRuneNull := func(r rune) bool {
|
||||
return r == '\u0000'
|
||||
}
|
||||
|
||||
// Map from the darwin-specific C struct to the Go type
|
||||
//
|
||||
// ### missing: IopsInProgress, WeightedIO, MergedReadCount,
|
||||
// MergedWriteCount, SerialNumber
|
||||
// IOKit can give us at least the serial number I think...
|
||||
for i := 0; i < int(n); i++ {
|
||||
d := IOCountersStat{
|
||||
// Note: The Go type wants unsigned values, but CFNumberGetValue
|
||||
// doesn't appear to be able to give us unsigned values. So, we
|
||||
// cast, and hope for the best.
|
||||
ReadBytes: uint64(di.ReadBytes),
|
||||
WriteBytes: uint64(di.WriteBytes),
|
||||
ReadCount: uint64(di.Reads),
|
||||
WriteCount: uint64(di.Writes),
|
||||
ReadTime: uint64(di.ReadTime),
|
||||
WriteTime: uint64(di.WriteTime),
|
||||
IoTime: uint64(di.ReadTime + di.WriteTime),
|
||||
Name: strings.TrimFunc(C.GoStringN(&di.DiskName[0], C.MAX_DISK_NAME), isRuneNull),
|
||||
ReadBytes: uint64(buf[i].read),
|
||||
WriteBytes: uint64(buf[i].written),
|
||||
ReadCount: uint64(buf[i].nread),
|
||||
WriteCount: uint64(buf[i].nwrite),
|
||||
ReadTime: uint64(buf[i].readtime / 1000 / 1000), // note: read/write time are in ns, but we want ms.
|
||||
WriteTime: uint64(buf[i].writetime / 1000 / 1000),
|
||||
IoTime: uint64((buf[i].readtime + buf[i].writetime) / 1000 / 1000),
|
||||
Name: C.GoString(&buf[i].name[0]),
|
||||
}
|
||||
|
||||
if len(names) > 0 && !common.StringsHas(names, d.Name) {
|
||||
continue
|
||||
}
|
||||
|
||||
ret[d.Name] = d
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
70
vendor/github.com/shirou/gopsutil/disk/disk_freebsd.go
generated
vendored
70
vendor/github.com/shirou/gopsutil/disk/disk_freebsd.go
generated
vendored
@@ -8,7 +8,6 @@ import (
|
||||
"encoding/binary"
|
||||
"path"
|
||||
"strconv"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
|
||||
@@ -23,63 +22,65 @@ func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, erro
|
||||
var ret []PartitionStat
|
||||
|
||||
// get length
|
||||
count, err := unix.Getfsstat(nil, MNT_WAIT)
|
||||
count, err := unix.Getfsstat(nil, unix.MNT_WAIT)
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
|
||||
fs := make([]Statfs, count)
|
||||
_, err = Getfsstat(fs, MNT_WAIT)
|
||||
fs := make([]unix.Statfs_t, count)
|
||||
if _, err = unix.Getfsstat(fs, unix.MNT_WAIT); err != nil {
|
||||
return ret, err
|
||||
}
|
||||
|
||||
for _, stat := range fs {
|
||||
opts := "rw"
|
||||
if stat.Flags&MNT_RDONLY != 0 {
|
||||
if stat.Flags&unix.MNT_RDONLY != 0 {
|
||||
opts = "ro"
|
||||
}
|
||||
if stat.Flags&MNT_SYNCHRONOUS != 0 {
|
||||
if stat.Flags&unix.MNT_SYNCHRONOUS != 0 {
|
||||
opts += ",sync"
|
||||
}
|
||||
if stat.Flags&MNT_NOEXEC != 0 {
|
||||
if stat.Flags&unix.MNT_NOEXEC != 0 {
|
||||
opts += ",noexec"
|
||||
}
|
||||
if stat.Flags&MNT_NOSUID != 0 {
|
||||
if stat.Flags&unix.MNT_NOSUID != 0 {
|
||||
opts += ",nosuid"
|
||||
}
|
||||
if stat.Flags&MNT_UNION != 0 {
|
||||
if stat.Flags&unix.MNT_UNION != 0 {
|
||||
opts += ",union"
|
||||
}
|
||||
if stat.Flags&MNT_ASYNC != 0 {
|
||||
if stat.Flags&unix.MNT_ASYNC != 0 {
|
||||
opts += ",async"
|
||||
}
|
||||
if stat.Flags&MNT_SUIDDIR != 0 {
|
||||
if stat.Flags&unix.MNT_SUIDDIR != 0 {
|
||||
opts += ",suiddir"
|
||||
}
|
||||
if stat.Flags&MNT_SOFTDEP != 0 {
|
||||
if stat.Flags&unix.MNT_SOFTDEP != 0 {
|
||||
opts += ",softdep"
|
||||
}
|
||||
if stat.Flags&MNT_NOSYMFOLLOW != 0 {
|
||||
if stat.Flags&unix.MNT_NOSYMFOLLOW != 0 {
|
||||
opts += ",nosymfollow"
|
||||
}
|
||||
if stat.Flags&MNT_GJOURNAL != 0 {
|
||||
opts += ",gjounalc"
|
||||
if stat.Flags&unix.MNT_GJOURNAL != 0 {
|
||||
opts += ",gjournal"
|
||||
}
|
||||
if stat.Flags&MNT_MULTILABEL != 0 {
|
||||
if stat.Flags&unix.MNT_MULTILABEL != 0 {
|
||||
opts += ",multilabel"
|
||||
}
|
||||
if stat.Flags&MNT_ACLS != 0 {
|
||||
if stat.Flags&unix.MNT_ACLS != 0 {
|
||||
opts += ",acls"
|
||||
}
|
||||
if stat.Flags&MNT_NOATIME != 0 {
|
||||
opts += ",noattime"
|
||||
if stat.Flags&unix.MNT_NOATIME != 0 {
|
||||
opts += ",noatime"
|
||||
}
|
||||
if stat.Flags&MNT_NOCLUSTERR != 0 {
|
||||
opts += ",nocluster"
|
||||
if stat.Flags&unix.MNT_NOCLUSTERR != 0 {
|
||||
opts += ",noclusterr"
|
||||
}
|
||||
if stat.Flags&MNT_NOCLUSTERW != 0 {
|
||||
if stat.Flags&unix.MNT_NOCLUSTERW != 0 {
|
||||
opts += ",noclusterw"
|
||||
}
|
||||
if stat.Flags&MNT_NFS4ACLS != 0 {
|
||||
opts += ",nfs4acls"
|
||||
if stat.Flags&unix.MNT_NFS4ACLS != 0 {
|
||||
opts += ",nfsv4acls"
|
||||
}
|
||||
|
||||
d := PartitionStat{
|
||||
@@ -156,27 +157,6 @@ func (b Bintime) Compute() float64 {
|
||||
|
||||
// BT2LD(time) ((long double)(time).sec + (time).frac * BINTIME_SCALE)
|
||||
|
||||
// Getfsstat is borrowed from pkg/syscall/syscall_freebsd.go
|
||||
// change Statfs_t to Statfs in order to get more information
|
||||
func Getfsstat(buf []Statfs, flags int) (n int, err error) {
|
||||
return GetfsstatWithContext(context.Background(), buf, flags)
|
||||
}
|
||||
|
||||
func GetfsstatWithContext(ctx context.Context, buf []Statfs, flags int) (n int, err error) {
|
||||
var _p0 unsafe.Pointer
|
||||
var bufsize uintptr
|
||||
if len(buf) > 0 {
|
||||
_p0 = unsafe.Pointer(&buf[0])
|
||||
bufsize = unsafe.Sizeof(Statfs{}) * uintptr(len(buf))
|
||||
}
|
||||
r0, _, e1 := unix.Syscall(unix.SYS_GETFSSTAT, uintptr(_p0), bufsize, uintptr(flags))
|
||||
n = int(r0)
|
||||
if e1 != 0 {
|
||||
err = e1
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func parseDevstat(buf []byte) (Devstat, error) {
|
||||
var ds Devstat
|
||||
br := bytes.NewReader(buf)
|
||||
|
||||
50
vendor/github.com/shirou/gopsutil/disk/disk_freebsd_386.go
generated
vendored
50
vendor/github.com/shirou/gopsutil/disk/disk_freebsd_386.go
generated
vendored
@@ -15,28 +15,6 @@ const (
|
||||
DEVSTAT_READ = 0x01
|
||||
DEVSTAT_WRITE = 0x02
|
||||
DEVSTAT_FREE = 0x03
|
||||
|
||||
MNT_RDONLY = 0x00000001
|
||||
MNT_SYNCHRONOUS = 0x00000002
|
||||
MNT_NOEXEC = 0x00000004
|
||||
MNT_NOSUID = 0x00000008
|
||||
MNT_UNION = 0x00000020
|
||||
MNT_ASYNC = 0x00000040
|
||||
MNT_SUIDDIR = 0x00100000
|
||||
MNT_SOFTDEP = 0x00200000
|
||||
MNT_NOSYMFOLLOW = 0x00400000
|
||||
MNT_GJOURNAL = 0x02000000
|
||||
MNT_MULTILABEL = 0x04000000
|
||||
MNT_ACLS = 0x08000000
|
||||
MNT_NOATIME = 0x10000000
|
||||
MNT_NOCLUSTERR = 0x40000000
|
||||
MNT_NOCLUSTERW = 0x80000000
|
||||
MNT_NFS4ACLS = 0x00000010
|
||||
|
||||
MNT_WAIT = 1
|
||||
MNT_NOWAIT = 2
|
||||
MNT_LAZY = 3
|
||||
MNT_SUSPEND = 4
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -51,34 +29,6 @@ type (
|
||||
_C_long_double int64
|
||||
)
|
||||
|
||||
type Statfs struct {
|
||||
Version uint32
|
||||
Type uint32
|
||||
Flags uint64
|
||||
Bsize uint64
|
||||
Iosize uint64
|
||||
Blocks uint64
|
||||
Bfree uint64
|
||||
Bavail int64
|
||||
Files uint64
|
||||
Ffree int64
|
||||
Syncwrites uint64
|
||||
Asyncwrites uint64
|
||||
Syncreads uint64
|
||||
Asyncreads uint64
|
||||
Spare [10]uint64
|
||||
Namemax uint32
|
||||
Owner uint32
|
||||
Fsid Fsid
|
||||
Charspare [80]int8
|
||||
Fstypename [16]int8
|
||||
Mntfromname [88]int8
|
||||
Mntonname [88]int8
|
||||
}
|
||||
type Fsid struct {
|
||||
Val [2]int32
|
||||
}
|
||||
|
||||
type Devstat struct {
|
||||
Sequence0 uint32
|
||||
Allocated int32
|
||||
|
||||
50
vendor/github.com/shirou/gopsutil/disk/disk_freebsd_amd64.go
generated
vendored
50
vendor/github.com/shirou/gopsutil/disk/disk_freebsd_amd64.go
generated
vendored
@@ -15,28 +15,6 @@ const (
|
||||
DEVSTAT_READ = 0x01
|
||||
DEVSTAT_WRITE = 0x02
|
||||
DEVSTAT_FREE = 0x03
|
||||
|
||||
MNT_RDONLY = 0x00000001
|
||||
MNT_SYNCHRONOUS = 0x00000002
|
||||
MNT_NOEXEC = 0x00000004
|
||||
MNT_NOSUID = 0x00000008
|
||||
MNT_UNION = 0x00000020
|
||||
MNT_ASYNC = 0x00000040
|
||||
MNT_SUIDDIR = 0x00100000
|
||||
MNT_SOFTDEP = 0x00200000
|
||||
MNT_NOSYMFOLLOW = 0x00400000
|
||||
MNT_GJOURNAL = 0x02000000
|
||||
MNT_MULTILABEL = 0x04000000
|
||||
MNT_ACLS = 0x08000000
|
||||
MNT_NOATIME = 0x10000000
|
||||
MNT_NOCLUSTERR = 0x40000000
|
||||
MNT_NOCLUSTERW = 0x80000000
|
||||
MNT_NFS4ACLS = 0x00000010
|
||||
|
||||
MNT_WAIT = 1
|
||||
MNT_NOWAIT = 2
|
||||
MNT_LAZY = 3
|
||||
MNT_SUSPEND = 4
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -51,34 +29,6 @@ type (
|
||||
_C_long_double int64
|
||||
)
|
||||
|
||||
type Statfs struct {
|
||||
Version uint32
|
||||
Type uint32
|
||||
Flags uint64
|
||||
Bsize uint64
|
||||
Iosize uint64
|
||||
Blocks uint64
|
||||
Bfree uint64
|
||||
Bavail int64
|
||||
Files uint64
|
||||
Ffree int64
|
||||
Syncwrites uint64
|
||||
Asyncwrites uint64
|
||||
Syncreads uint64
|
||||
Asyncreads uint64
|
||||
Spare [10]uint64
|
||||
Namemax uint32
|
||||
Owner uint32
|
||||
Fsid Fsid
|
||||
Charspare [80]int8
|
||||
Fstypename [16]int8
|
||||
Mntfromname [88]int8
|
||||
Mntonname [88]int8
|
||||
}
|
||||
type Fsid struct {
|
||||
Val [2]int32
|
||||
}
|
||||
|
||||
type Devstat struct {
|
||||
Sequence0 uint32
|
||||
Allocated int32
|
||||
|
||||
62
vendor/github.com/shirou/gopsutil/disk/disk_freebsd_arm.go
generated
vendored
Normal file
62
vendor/github.com/shirou/gopsutil/disk/disk_freebsd_arm.go
generated
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// cgo -godefs types_freebsd.go
|
||||
|
||||
package disk
|
||||
|
||||
const (
|
||||
sizeofPtr = 0x4
|
||||
sizeofShort = 0x2
|
||||
sizeofInt = 0x4
|
||||
sizeofLong = 0x4
|
||||
sizeofLongLong = 0x8
|
||||
sizeofLongDouble = 0x8
|
||||
|
||||
DEVSTAT_NO_DATA = 0x00
|
||||
DEVSTAT_READ = 0x01
|
||||
DEVSTAT_WRITE = 0x02
|
||||
DEVSTAT_FREE = 0x03
|
||||
)
|
||||
|
||||
const (
|
||||
sizeOfDevstat = 0xf0
|
||||
)
|
||||
|
||||
type (
|
||||
_C_short int16
|
||||
_C_int int32
|
||||
_C_long int32
|
||||
_C_long_long int64
|
||||
_C_long_double int64
|
||||
)
|
||||
|
||||
type Devstat struct {
|
||||
Sequence0 uint32
|
||||
Allocated int32
|
||||
Start_count uint32
|
||||
End_count uint32
|
||||
Busy_from Bintime
|
||||
Dev_links _Ctype_struct___0
|
||||
Device_number uint32
|
||||
Device_name [16]int8
|
||||
Unit_number int32
|
||||
Bytes [4]uint64
|
||||
Operations [4]uint64
|
||||
Duration [4]Bintime
|
||||
Busy_time Bintime
|
||||
Creation_time Bintime
|
||||
Block_size uint32
|
||||
Tag_types [3]uint64
|
||||
Flags uint32
|
||||
Device_type uint32
|
||||
Priority uint32
|
||||
Id *byte
|
||||
Sequence1 uint32
|
||||
}
|
||||
type Bintime struct {
|
||||
Sec int32
|
||||
Frac uint64
|
||||
}
|
||||
|
||||
type _Ctype_struct___0 struct {
|
||||
Empty uint32
|
||||
}
|
||||
65
vendor/github.com/shirou/gopsutil/disk/disk_freebsd_arm64.go
generated
vendored
Normal file
65
vendor/github.com/shirou/gopsutil/disk/disk_freebsd_arm64.go
generated
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
// +build freebsd
|
||||
// +build arm64
|
||||
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
|
||||
// cgo -godefs disk/types_freebsd.go
|
||||
|
||||
package disk
|
||||
|
||||
const (
|
||||
sizeofPtr = 0x8
|
||||
sizeofShort = 0x2
|
||||
sizeofInt = 0x4
|
||||
sizeofLong = 0x8
|
||||
sizeofLongLong = 0x8
|
||||
sizeofLongDouble = 0x8
|
||||
|
||||
DEVSTAT_NO_DATA = 0x00
|
||||
DEVSTAT_READ = 0x01
|
||||
DEVSTAT_WRITE = 0x02
|
||||
DEVSTAT_FREE = 0x03
|
||||
)
|
||||
|
||||
const (
|
||||
sizeOfDevstat = 0x120
|
||||
)
|
||||
|
||||
type (
|
||||
_C_short int16
|
||||
_C_int int32
|
||||
_C_long int64
|
||||
_C_long_long int64
|
||||
_C_long_double int64
|
||||
)
|
||||
|
||||
type Devstat struct {
|
||||
Sequence0 uint32
|
||||
Allocated int32
|
||||
Start_count uint32
|
||||
End_count uint32
|
||||
Busy_from Bintime
|
||||
Dev_links _Ctype_struct___0
|
||||
Device_number uint32
|
||||
Device_name [16]int8
|
||||
Unit_number int32
|
||||
Bytes [4]uint64
|
||||
Operations [4]uint64
|
||||
Duration [4]Bintime
|
||||
Busy_time Bintime
|
||||
Creation_time Bintime
|
||||
Block_size uint32
|
||||
Tag_types [3]uint64
|
||||
Flags uint32
|
||||
Device_type uint32
|
||||
Priority uint32
|
||||
Id *byte
|
||||
Sequence1 uint32
|
||||
Pad_cgo_0 [4]byte
|
||||
}
|
||||
type Bintime struct {
|
||||
Sec int64
|
||||
Frac uint64
|
||||
}
|
||||
|
||||
type _Ctype_struct___0 struct {
|
||||
Empty uint64
|
||||
}
|
||||
160
vendor/github.com/shirou/gopsutil/disk/disk_linux.go
generated
vendored
160
vendor/github.com/shirou/gopsutil/disk/disk_linux.go
generated
vendored
@@ -3,16 +3,18 @@
|
||||
package disk
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -45,6 +47,7 @@ const (
|
||||
FUSE_SUPER_MAGIC = 0x65735546
|
||||
FUTEXFS_SUPER_MAGIC = 0xBAD1DEA
|
||||
HFS_SUPER_MAGIC = 0x4244
|
||||
HFSPLUS_SUPER_MAGIC = 0x482b
|
||||
HOSTFS_SUPER_MAGIC = 0x00c0ffee
|
||||
HPFS_SUPER_MAGIC = 0xF995E849
|
||||
HUGETLBFS_MAGIC = 0x958458f6
|
||||
@@ -154,6 +157,7 @@ var fsTypeMap = map[int64]string{
|
||||
GFS_SUPER_MAGIC: "gfs/gfs2", /* 0x1161970 remote */
|
||||
GPFS_SUPER_MAGIC: "gpfs", /* 0x47504653 remote */
|
||||
HFS_SUPER_MAGIC: "hfs", /* 0x4244 local */
|
||||
HFSPLUS_SUPER_MAGIC: "hfsplus", /* 0x482b local */
|
||||
HPFS_SUPER_MAGIC: "hpfs", /* 0xF995E849 local */
|
||||
HUGETLBFS_MAGIC: "hugetlbfs", /* 0x958458F6 local */
|
||||
MTD_INODE_FS_SUPER_MAGIC: "inodefs", /* 0x11307854 local */
|
||||
@@ -222,30 +226,95 @@ func Partitions(all bool) ([]PartitionStat, error) {
|
||||
}
|
||||
|
||||
func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, error) {
|
||||
filename := common.HostProc("self/mounts")
|
||||
useMounts := false
|
||||
|
||||
filename := common.HostProc("self/mountinfo")
|
||||
lines, err := common.ReadLines(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
if err != err.(*os.PathError) {
|
||||
return nil, err
|
||||
}
|
||||
// if kernel does not support self/mountinfo, fallback to self/mounts (<2.6.26)
|
||||
useMounts = true
|
||||
filename = common.HostProc("self/mounts")
|
||||
lines, err = common.ReadLines(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
fs, err := getFileSystems()
|
||||
if err != nil {
|
||||
if err != nil && !all {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ret := make([]PartitionStat, 0, len(lines))
|
||||
|
||||
for _, line := range lines {
|
||||
fields := strings.Fields(line)
|
||||
d := PartitionStat{
|
||||
Device: fields[0],
|
||||
Mountpoint: fields[1],
|
||||
Fstype: fields[2],
|
||||
Opts: fields[3],
|
||||
}
|
||||
if all == false {
|
||||
if d.Device == "none" || !common.StringsHas(fs, d.Fstype) {
|
||||
continue
|
||||
var d PartitionStat
|
||||
if useMounts {
|
||||
fields := strings.Fields(line)
|
||||
|
||||
d = PartitionStat{
|
||||
Device: fields[0],
|
||||
Mountpoint: unescapeFstab(fields[1]),
|
||||
Fstype: fields[2],
|
||||
Opts: fields[3],
|
||||
}
|
||||
|
||||
if !all {
|
||||
if d.Device == "none" || !common.StringsHas(fs, d.Fstype) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// a line of self/mountinfo has the following structure:
|
||||
// 36 35 98:0 /mnt1 /mnt2 rw,noatime master:1 - ext3 /dev/root rw,errors=continue
|
||||
// (1) (2) (3) (4) (5) (6) (7) (8) (9) (10) (11)
|
||||
|
||||
// split the mountinfo line by the separator hyphen
|
||||
parts := strings.Split(line, " - ")
|
||||
if len(parts) != 2 {
|
||||
return nil, fmt.Errorf("found invalid mountinfo line in file %s: %s ", filename, line)
|
||||
}
|
||||
|
||||
fields := strings.Fields(parts[0])
|
||||
blockDeviceID := fields[2]
|
||||
mountPoint := fields[4]
|
||||
mountOpts := fields[5]
|
||||
|
||||
fields = strings.Fields(parts[1])
|
||||
fstype := fields[0]
|
||||
device := fields[1]
|
||||
|
||||
d = PartitionStat{
|
||||
Device: device,
|
||||
Mountpoint: unescapeFstab(mountPoint),
|
||||
Fstype: fstype,
|
||||
Opts: mountOpts,
|
||||
}
|
||||
|
||||
if !all {
|
||||
if d.Device == "none" || !common.StringsHas(fs, d.Fstype) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if strings.HasPrefix(d.Device, "/dev/mapper/") {
|
||||
devpath, err := filepath.EvalSymlinks(common.HostDev(strings.Replace(d.Device, "/dev", "", -1)))
|
||||
if err == nil {
|
||||
d.Device = devpath
|
||||
}
|
||||
}
|
||||
|
||||
// /dev/root is not the real device name
|
||||
// so we get the real device name from its major/minor number
|
||||
if d.Device == "/dev/root" {
|
||||
devpath, err := os.Readlink(common.HostSys("/dev/block/" + blockDeviceID))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
d.Device = strings.Replace(d.Device, "root", filepath.Base(devpath), 1)
|
||||
}
|
||||
}
|
||||
ret = append(ret, d)
|
||||
@@ -370,6 +439,8 @@ func IOCountersWithContext(ctx context.Context, names ...string) (map[string]IOC
|
||||
d.Name = name
|
||||
|
||||
d.SerialNumber = GetDiskSerialNumber(name)
|
||||
d.Label = GetLabel(name)
|
||||
|
||||
ret[name] = d
|
||||
}
|
||||
return ret, nil
|
||||
@@ -382,30 +453,57 @@ func GetDiskSerialNumber(name string) string {
|
||||
}
|
||||
|
||||
func GetDiskSerialNumberWithContext(ctx context.Context, name string) string {
|
||||
n := fmt.Sprintf("--name=%s", name)
|
||||
udevadm, err := exec.LookPath("/sbin/udevadm")
|
||||
var stat unix.Stat_t
|
||||
err := unix.Stat(name, &stat)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
major := unix.Major(uint64(stat.Rdev))
|
||||
minor := unix.Minor(uint64(stat.Rdev))
|
||||
|
||||
out, err := invoke.Command(udevadm, "info", "--query=property", n)
|
||||
|
||||
// does not return error, just an empty string
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
lines := strings.Split(string(out), "\n")
|
||||
for _, line := range lines {
|
||||
values := strings.Split(line, "=")
|
||||
if len(values) < 2 || values[0] != "ID_SERIAL" {
|
||||
// only get ID_SERIAL, not ID_SERIAL_SHORT
|
||||
continue
|
||||
// Try to get the serial from udev data
|
||||
udevDataPath := common.HostRun(fmt.Sprintf("udev/data/b%d:%d", major, minor))
|
||||
if udevdata, err := ioutil.ReadFile(udevDataPath); err == nil {
|
||||
scanner := bufio.NewScanner(bytes.NewReader(udevdata))
|
||||
for scanner.Scan() {
|
||||
values := strings.Split(scanner.Text(), "=")
|
||||
if len(values) == 2 && values[0] == "E:ID_SERIAL" {
|
||||
return values[1]
|
||||
}
|
||||
}
|
||||
return values[1]
|
||||
}
|
||||
|
||||
// Try to get the serial from sysfs, look at the disk device (minor 0) directly
|
||||
// because if it is a partition it is not going to contain any device information
|
||||
devicePath := common.HostSys(fmt.Sprintf("dev/block/%d:0/device", major))
|
||||
model, _ := ioutil.ReadFile(filepath.Join(devicePath, "model"))
|
||||
serial, _ := ioutil.ReadFile(filepath.Join(devicePath, "serial"))
|
||||
if len(model) > 0 && len(serial) > 0 {
|
||||
return fmt.Sprintf("%s_%s", string(model), string(serial))
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// GetLabel returns label of given device or empty string on error.
|
||||
// Name of device is expected, eg. /dev/sda
|
||||
// Supports label based on devicemapper name
|
||||
// See https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-block-dm
|
||||
func GetLabel(name string) string {
|
||||
// Try label based on devicemapper name
|
||||
dmname_filename := common.HostSys(fmt.Sprintf("block/%s/dm/name", name))
|
||||
|
||||
if !common.PathExists(dmname_filename) {
|
||||
return ""
|
||||
}
|
||||
|
||||
dmname, err := ioutil.ReadFile(dmname_filename)
|
||||
if err != nil {
|
||||
return ""
|
||||
} else {
|
||||
return strings.TrimSpace(string(dmname))
|
||||
}
|
||||
}
|
||||
|
||||
func getFsType(stat unix.Statfs_t) string {
|
||||
t := int64(stat.Type)
|
||||
ret, ok := fsTypeMap[t]
|
||||
|
||||
51
vendor/github.com/shirou/gopsutil/disk/disk_openbsd.go
generated
vendored
51
vendor/github.com/shirou/gopsutil/disk/disk_openbsd.go
generated
vendored
@@ -7,7 +7,6 @@ import (
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"path"
|
||||
"unsafe"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"golang.org/x/sys/unix"
|
||||
@@ -21,34 +20,45 @@ func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, erro
|
||||
var ret []PartitionStat
|
||||
|
||||
// get length
|
||||
count, err := unix.Getfsstat(nil, MNT_WAIT)
|
||||
count, err := unix.Getfsstat(nil, unix.MNT_WAIT)
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
|
||||
fs := make([]Statfs, count)
|
||||
_, err = Getfsstat(fs, MNT_WAIT)
|
||||
fs := make([]unix.Statfs_t, count)
|
||||
if _, err = unix.Getfsstat(fs, unix.MNT_WAIT); err != nil {
|
||||
return ret, err
|
||||
}
|
||||
|
||||
for _, stat := range fs {
|
||||
opts := "rw"
|
||||
if stat.F_flags&MNT_RDONLY != 0 {
|
||||
if stat.F_flags&unix.MNT_RDONLY != 0 {
|
||||
opts = "ro"
|
||||
}
|
||||
if stat.F_flags&MNT_SYNCHRONOUS != 0 {
|
||||
if stat.F_flags&unix.MNT_SYNCHRONOUS != 0 {
|
||||
opts += ",sync"
|
||||
}
|
||||
if stat.F_flags&MNT_NOEXEC != 0 {
|
||||
if stat.F_flags&unix.MNT_NOEXEC != 0 {
|
||||
opts += ",noexec"
|
||||
}
|
||||
if stat.F_flags&MNT_NOSUID != 0 {
|
||||
if stat.F_flags&unix.MNT_NOSUID != 0 {
|
||||
opts += ",nosuid"
|
||||
}
|
||||
if stat.F_flags&MNT_NODEV != 0 {
|
||||
if stat.F_flags&unix.MNT_NODEV != 0 {
|
||||
opts += ",nodev"
|
||||
}
|
||||
if stat.F_flags&MNT_ASYNC != 0 {
|
||||
if stat.F_flags&unix.MNT_ASYNC != 0 {
|
||||
opts += ",async"
|
||||
}
|
||||
if stat.F_flags&unix.MNT_SOFTDEP != 0 {
|
||||
opts += ",softdep"
|
||||
}
|
||||
if stat.F_flags&unix.MNT_NOATIME != 0 {
|
||||
opts += ",noatime"
|
||||
}
|
||||
if stat.F_flags&unix.MNT_WXALLOWED != 0 {
|
||||
opts += ",wxallowed"
|
||||
}
|
||||
|
||||
d := PartitionStat{
|
||||
Device: common.IntToString(stat.F_mntfromname[:]),
|
||||
@@ -112,27 +122,6 @@ func IOCountersWithContext(ctx context.Context, names ...string) (map[string]IOC
|
||||
|
||||
// BT2LD(time) ((long double)(time).sec + (time).frac * BINTIME_SCALE)
|
||||
|
||||
// Getfsstat is borrowed from pkg/syscall/syscall_freebsd.go
|
||||
// change Statfs_t to Statfs in order to get more information
|
||||
func Getfsstat(buf []Statfs, flags int) (n int, err error) {
|
||||
return GetfsstatWithContext(context.Background(), buf, flags)
|
||||
}
|
||||
|
||||
func GetfsstatWithContext(ctx context.Context, buf []Statfs, flags int) (n int, err error) {
|
||||
var _p0 unsafe.Pointer
|
||||
var bufsize uintptr
|
||||
if len(buf) > 0 {
|
||||
_p0 = unsafe.Pointer(&buf[0])
|
||||
bufsize = unsafe.Sizeof(Statfs{}) * uintptr(len(buf))
|
||||
}
|
||||
r0, _, e1 := unix.Syscall(unix.SYS_GETFSSTAT, uintptr(_p0), bufsize, uintptr(flags))
|
||||
n = int(r0)
|
||||
if e1 != 0 {
|
||||
err = e1
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func parseDiskstats(buf []byte) (Diskstats, error) {
|
||||
var ds Diskstats
|
||||
br := bytes.NewReader(buf)
|
||||
|
||||
35
vendor/github.com/shirou/gopsutil/disk/disk_openbsd_386.go
generated
vendored
Normal file
35
vendor/github.com/shirou/gopsutil/disk/disk_openbsd_386.go
generated
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
|
||||
// cgo -godefs types_openbsd.go
|
||||
|
||||
package disk
|
||||
|
||||
const (
|
||||
DEVSTAT_NO_DATA = 0x00
|
||||
DEVSTAT_READ = 0x01
|
||||
DEVSTAT_WRITE = 0x02
|
||||
DEVSTAT_FREE = 0x03
|
||||
)
|
||||
|
||||
const (
|
||||
sizeOfDiskstats = 0x60
|
||||
)
|
||||
|
||||
type Diskstats struct {
|
||||
Name [16]int8
|
||||
Busy int32
|
||||
Rxfer uint64
|
||||
Wxfer uint64
|
||||
Seek uint64
|
||||
Rbytes uint64
|
||||
Wbytes uint64
|
||||
Attachtime Timeval
|
||||
Timestamp Timeval
|
||||
Time Timeval
|
||||
}
|
||||
type Timeval struct {
|
||||
Sec int64
|
||||
Usec int32
|
||||
}
|
||||
|
||||
type Diskstat struct{}
|
||||
type Bintime struct{}
|
||||
57
vendor/github.com/shirou/gopsutil/disk/disk_openbsd_amd64.go
generated
vendored
57
vendor/github.com/shirou/gopsutil/disk/disk_openbsd_amd64.go
generated
vendored
@@ -1,71 +1,19 @@
|
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
|
||||
// cgo -godefs types_openbsd.go
|
||||
|
||||
package disk
|
||||
|
||||
const (
|
||||
sizeofPtr = 0x8
|
||||
sizeofShort = 0x2
|
||||
sizeofInt = 0x4
|
||||
sizeofLong = 0x8
|
||||
sizeofLongLong = 0x8
|
||||
sizeofLongDouble = 0x8
|
||||
|
||||
DEVSTAT_NO_DATA = 0x00
|
||||
DEVSTAT_READ = 0x01
|
||||
DEVSTAT_WRITE = 0x02
|
||||
DEVSTAT_FREE = 0x03
|
||||
|
||||
MNT_RDONLY = 0x00000001
|
||||
MNT_SYNCHRONOUS = 0x00000002
|
||||
MNT_NOEXEC = 0x00000004
|
||||
MNT_NOSUID = 0x00000008
|
||||
MNT_NODEV = 0x00000010
|
||||
MNT_ASYNC = 0x00000040
|
||||
|
||||
MNT_WAIT = 1
|
||||
MNT_NOWAIT = 2
|
||||
MNT_LAZY = 3
|
||||
)
|
||||
|
||||
const (
|
||||
sizeOfDiskstats = 0x70
|
||||
)
|
||||
|
||||
type (
|
||||
_C_short int16
|
||||
_C_int int32
|
||||
_C_long int64
|
||||
_C_long_long int64
|
||||
_C_long_double int64
|
||||
)
|
||||
|
||||
type Statfs struct {
|
||||
F_flags uint32
|
||||
F_bsize uint32
|
||||
F_iosize uint32
|
||||
Pad_cgo_0 [4]byte
|
||||
F_blocks uint64
|
||||
F_bfree uint64
|
||||
F_bavail int64
|
||||
F_files uint64
|
||||
F_ffree uint64
|
||||
F_favail int64
|
||||
F_syncwrites uint64
|
||||
F_syncreads uint64
|
||||
F_asyncwrites uint64
|
||||
F_asyncreads uint64
|
||||
F_fsid Fsid
|
||||
F_namemax uint32
|
||||
F_owner uint32
|
||||
F_ctime uint64
|
||||
F_fstypename [16]int8
|
||||
F_mntonname [90]int8
|
||||
F_mntfromname [90]int8
|
||||
F_mntfromspec [90]int8
|
||||
Pad_cgo_1 [2]byte
|
||||
Mount_info [160]byte
|
||||
}
|
||||
type Diskstats struct {
|
||||
Name [16]int8
|
||||
Busy int32
|
||||
@@ -79,9 +27,6 @@ type Diskstats struct {
|
||||
Timestamp Timeval
|
||||
Time Timeval
|
||||
}
|
||||
type Fsid struct {
|
||||
Val [2]int32
|
||||
}
|
||||
type Timeval struct {
|
||||
Sec int64
|
||||
Usec int64
|
||||
|
||||
20
vendor/github.com/shirou/gopsutil/disk/disk_unix.go
generated
vendored
20
vendor/github.com/shirou/gopsutil/disk/disk_unix.go
generated
vendored
@@ -4,11 +4,12 @@ package disk
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// Usage returns a file system usage. path is a filessytem path such
|
||||
// Usage returns a file system usage. path is a filesystem path such
|
||||
// as "/", not device file path like "/dev/vda1". If you want to use
|
||||
// a return value of disk.Partitions, use "Mountpoint" not "Device".
|
||||
func Usage(path string) (*UsageStat, error) {
|
||||
@@ -24,7 +25,7 @@ func UsageWithContext(ctx context.Context, path string) (*UsageStat, error) {
|
||||
bsize := stat.Bsize
|
||||
|
||||
ret := &UsageStat{
|
||||
Path: path,
|
||||
Path: unescapeFstab(path),
|
||||
Fstype: getFsType(stat),
|
||||
Total: (uint64(stat.Blocks) * uint64(bsize)),
|
||||
Free: (uint64(stat.Bavail) * uint64(bsize)),
|
||||
@@ -46,11 +47,22 @@ func UsageWithContext(ctx context.Context, path string) (*UsageStat, error) {
|
||||
ret.InodesUsedPercent = (float64(ret.InodesUsed) / float64(ret.InodesTotal)) * 100.0
|
||||
}
|
||||
|
||||
if ret.Total == 0 {
|
||||
if (ret.Used + ret.Free) == 0 {
|
||||
ret.UsedPercent = 0
|
||||
} else {
|
||||
ret.UsedPercent = (float64(ret.Used) / float64(ret.Total)) * 100.0
|
||||
// We don't use ret.Total to calculate percent.
|
||||
// see https://github.com/shirou/gopsutil/issues/562
|
||||
ret.UsedPercent = (float64(ret.Used) / float64(ret.Used+ret.Free)) * 100.0
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// Unescape escaped octal chars (like space 040, ampersand 046 and backslash 134) to their real value in fstab fields issue#555
|
||||
func unescapeFstab(path string) string {
|
||||
escaped, err := strconv.Unquote(`"` + path + `"`)
|
||||
if err != nil {
|
||||
return path
|
||||
}
|
||||
return escaped
|
||||
}
|
||||
|
||||
11
vendor/github.com/shirou/gopsutil/disk/disk_windows.go
generated
vendored
11
vendor/github.com/shirou/gopsutil/disk/disk_windows.go
generated
vendored
@@ -15,7 +15,7 @@ var (
|
||||
procGetDiskFreeSpaceExW = common.Modkernel32.NewProc("GetDiskFreeSpaceExW")
|
||||
procGetLogicalDriveStringsW = common.Modkernel32.NewProc("GetLogicalDriveStringsW")
|
||||
procGetDriveType = common.Modkernel32.NewProc("GetDriveTypeW")
|
||||
provGetVolumeInformation = common.Modkernel32.NewProc("GetVolumeInformationW")
|
||||
procGetVolumeInformation = common.Modkernel32.NewProc("GetVolumeInformationW")
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -40,8 +40,6 @@ func Usage(path string) (*UsageStat, error) {
|
||||
}
|
||||
|
||||
func UsageWithContext(ctx context.Context, path string) (*UsageStat, error) {
|
||||
ret := &UsageStat{}
|
||||
|
||||
lpFreeBytesAvailable := int64(0)
|
||||
lpTotalNumberOfBytes := int64(0)
|
||||
lpTotalNumberOfFreeBytes := int64(0)
|
||||
@@ -53,7 +51,7 @@ func UsageWithContext(ctx context.Context, path string) (*UsageStat, error) {
|
||||
if diskret == 0 {
|
||||
return nil, err
|
||||
}
|
||||
ret = &UsageStat{
|
||||
ret := &UsageStat{
|
||||
Path: path,
|
||||
Total: uint64(lpTotalNumberOfBytes),
|
||||
Free: uint64(lpTotalNumberOfFreeBytes),
|
||||
@@ -83,9 +81,6 @@ func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, erro
|
||||
for _, v := range lpBuffer {
|
||||
if v >= 65 && v <= 90 {
|
||||
path := string(v) + ":"
|
||||
if path == "A:" || path == "B:" { // skip floppy drives
|
||||
continue
|
||||
}
|
||||
typepath, _ := windows.UTF16PtrFromString(path)
|
||||
typeret, _, _ := procGetDriveType.Call(uintptr(unsafe.Pointer(typepath)))
|
||||
if typeret == 0 {
|
||||
@@ -100,7 +95,7 @@ func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, erro
|
||||
lpFileSystemFlags := int64(0)
|
||||
lpFileSystemNameBuffer := make([]byte, 256)
|
||||
volpath, _ := windows.UTF16PtrFromString(string(v) + ":/")
|
||||
driveret, _, err := provGetVolumeInformation.Call(
|
||||
driveret, _, err := procGetVolumeInformation.Call(
|
||||
uintptr(unsafe.Pointer(volpath)),
|
||||
uintptr(unsafe.Pointer(&lpVolumeNameBuffer[0])),
|
||||
uintptr(len(lpVolumeNameBuffer)),
|
||||
|
||||
7
vendor/github.com/shirou/gopsutil/host/host.go
generated
vendored
7
vendor/github.com/shirou/gopsutil/host/host.go
generated
vendored
@@ -6,11 +6,7 @@ import (
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
)
|
||||
|
||||
var invoke common.Invoker
|
||||
|
||||
func init() {
|
||||
invoke = common.Invoke{}
|
||||
}
|
||||
var invoke common.Invoker = common.Invoke{}
|
||||
|
||||
// A HostInfoStat describes the host status.
|
||||
// This is not in the psutil but it useful.
|
||||
@@ -24,6 +20,7 @@ type InfoStat struct {
|
||||
PlatformFamily string `json:"platformFamily"` // ex: debian, rhel
|
||||
PlatformVersion string `json:"platformVersion"` // version of the complete OS
|
||||
KernelVersion string `json:"kernelVersion"` // version of the OS kernel (if available)
|
||||
KernelArch string `json:"kernelArch"` // native cpu architecture queried at runtime, as returned by `uname -m` or empty string in case of error
|
||||
VirtualizationSystem string `json:"virtualizationSystem"`
|
||||
VirtualizationRole string `json:"virtualizationRole"` // guest or host
|
||||
HostID string `json:"hostid"` // ex: uuid
|
||||
|
||||
72
vendor/github.com/shirou/gopsutil/host/host_darwin.go
generated
vendored
72
vendor/github.com/shirou/gopsutil/host/host_darwin.go
generated
vendored
@@ -10,7 +10,6 @@ import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
@@ -18,6 +17,7 @@ import (
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/process"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// from utmpx.h
|
||||
@@ -38,12 +38,14 @@ func InfoWithContext(ctx context.Context) (*InfoStat, error) {
|
||||
ret.Hostname = hostname
|
||||
}
|
||||
|
||||
uname, err := exec.LookPath("uname")
|
||||
kernelVersion, err := KernelVersionWithContext(ctx)
|
||||
if err == nil {
|
||||
out, err := invoke.Command(uname, "-r")
|
||||
if err == nil {
|
||||
ret.KernelVersion = strings.ToLower(strings.TrimSpace(string(out)))
|
||||
}
|
||||
ret.KernelVersion = kernelVersion
|
||||
}
|
||||
|
||||
kernelArch, err := kernelArch()
|
||||
if err == nil {
|
||||
ret.KernelArch = kernelArch
|
||||
}
|
||||
|
||||
platform, family, pver, err := PlatformInformation()
|
||||
@@ -70,9 +72,9 @@ func InfoWithContext(ctx context.Context) (*InfoStat, error) {
|
||||
ret.Procs = uint64(len(procs))
|
||||
}
|
||||
|
||||
values, err := common.DoSysctrl("kern.uuid")
|
||||
if err == nil && len(values) == 1 && values[0] != "" {
|
||||
ret.HostID = strings.ToLower(values[0])
|
||||
uuid, err := unix.Sysctl("kern.uuid")
|
||||
if err == nil && uuid != "" {
|
||||
ret.HostID = strings.ToLower(uuid)
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
@@ -86,24 +88,22 @@ func BootTime() (uint64, error) {
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
values, err := common.DoSysctrl("kern.boottime")
|
||||
value, err := unix.Sysctl("kern.boottime")
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
// ex: { sec = 1392261637, usec = 627534 } Thu Feb 13 12:20:37 2014
|
||||
v := strings.Replace(values[2], ",", "", 1)
|
||||
boottime, err := strconv.ParseInt(v, 10, 64)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
t = uint64(boottime)
|
||||
atomic.StoreUint64(&cachedBootTime, t)
|
||||
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
|
||||
|
||||
return t, nil
|
||||
atomic.StoreUint64(&cachedBootTime, boottime)
|
||||
|
||||
return boottime, nil
|
||||
}
|
||||
|
||||
func uptime(boot uint64) uint64 {
|
||||
@@ -115,7 +115,7 @@ func Uptime() (uint64, error) {
|
||||
}
|
||||
|
||||
func UptimeWithContext(ctx context.Context) (uint64, error) {
|
||||
boot, err := BootTime()
|
||||
boot, err := BootTimeWithContext(ctx)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@@ -183,21 +183,27 @@ func PlatformInformationWithContext(ctx context.Context) (string, string, string
|
||||
if err != nil {
|
||||
return "", "", "", err
|
||||
}
|
||||
uname, err := exec.LookPath("uname")
|
||||
if err != nil {
|
||||
return "", "", "", err
|
||||
}
|
||||
|
||||
out, err := invoke.Command(uname, "-s")
|
||||
p, err := unix.Sysctl("kern.ostype")
|
||||
if err == nil {
|
||||
platform = strings.ToLower(strings.TrimSpace(string(out)))
|
||||
platform = strings.ToLower(p)
|
||||
}
|
||||
|
||||
out, err = invoke.Command(sw_vers, "-productVersion")
|
||||
out, err := invoke.CommandWithContext(ctx, sw_vers, "-productVersion")
|
||||
if err == nil {
|
||||
pver = strings.ToLower(strings.TrimSpace(string(out)))
|
||||
}
|
||||
|
||||
// check if the macos server version file exists
|
||||
_, err = os.Stat("/System/Library/CoreServices/ServerVersion.plist")
|
||||
|
||||
// server file doesn't exist
|
||||
if os.IsNotExist(err) {
|
||||
family = "Standalone Workstation"
|
||||
} else {
|
||||
family = "Server"
|
||||
}
|
||||
|
||||
return platform, family, pver, nil
|
||||
}
|
||||
|
||||
@@ -214,14 +220,6 @@ func KernelVersion() (string, error) {
|
||||
}
|
||||
|
||||
func KernelVersionWithContext(ctx context.Context) (string, error) {
|
||||
_, _, version, err := PlatformInformation()
|
||||
return version, err
|
||||
}
|
||||
|
||||
func SensorsTemperatures() ([]TemperatureStat, error) {
|
||||
return SensorsTemperaturesWithContext(context.Background())
|
||||
}
|
||||
|
||||
func SensorsTemperaturesWithContext(ctx context.Context) ([]TemperatureStat, error) {
|
||||
return []TemperatureStat{}, common.ErrNotImplementedError
|
||||
version, err := unix.Sysctl("kern.osrelease")
|
||||
return strings.ToLower(version), err
|
||||
}
|
||||
|
||||
53
vendor/github.com/shirou/gopsutil/host/host_darwin_cgo.go
generated
vendored
Normal file
53
vendor/github.com/shirou/gopsutil/host/host_darwin_cgo.go
generated
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
// +build darwin
|
||||
// +build cgo
|
||||
|
||||
package host
|
||||
|
||||
// #cgo LDFLAGS: -framework IOKit
|
||||
// #include <stdio.h>
|
||||
// #include <string.h>
|
||||
// #include "include/smc.c"
|
||||
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,
|
||||
C.AMBIENT_AIR_1,
|
||||
C.CPU_0_DIODE,
|
||||
C.CPU_0_HEATSINK,
|
||||
C.CPU_0_PROXIMITY,
|
||||
C.ENCLOSURE_BASE_0,
|
||||
C.ENCLOSURE_BASE_1,
|
||||
C.ENCLOSURE_BASE_2,
|
||||
C.ENCLOSURE_BASE_3,
|
||||
C.GPU_0_DIODE,
|
||||
C.GPU_0_HEATSINK,
|
||||
C.GPU_0_PROXIMITY,
|
||||
C.HARD_DRIVE_BAY,
|
||||
C.MEMORY_SLOT_0,
|
||||
C.MEMORY_SLOTS_PROXIMITY,
|
||||
C.NORTHBRIDGE,
|
||||
C.NORTHBRIDGE_DIODE,
|
||||
C.NORTHBRIDGE_PROXIMITY,
|
||||
C.THUNDERBOLT_0,
|
||||
C.THUNDERBOLT_1,
|
||||
C.WIRELESS_MODULE,
|
||||
}
|
||||
var temperatures []TemperatureStat
|
||||
|
||||
C.open_smc()
|
||||
defer C.close_smc()
|
||||
|
||||
for _, key := range temperatureKeys {
|
||||
temperatures = append(temperatures, TemperatureStat{
|
||||
SensorKey: key,
|
||||
Temperature: float64(C.get_temperature(C.CString(key))),
|
||||
})
|
||||
}
|
||||
return temperatures, nil
|
||||
}
|
||||
18
vendor/github.com/shirou/gopsutil/host/host_darwin_nocgo.go
generated
vendored
Normal file
18
vendor/github.com/shirou/gopsutil/host/host_darwin_nocgo.go
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
// +build darwin
|
||||
// +build !cgo
|
||||
|
||||
package host
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"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
|
||||
}
|
||||
8
vendor/github.com/shirou/gopsutil/host/host_fallback.go
generated
vendored
8
vendor/github.com/shirou/gopsutil/host/host_fallback.go
generated
vendored
@@ -55,3 +55,11 @@ func KernelVersion() (string, error) {
|
||||
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
|
||||
}
|
||||
|
||||
29
vendor/github.com/shirou/gopsutil/host/host_freebsd.go
generated
vendored
29
vendor/github.com/shirou/gopsutil/host/host_freebsd.go
generated
vendored
@@ -7,8 +7,8 @@ import (
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"io/ioutil"
|
||||
"math"
|
||||
"os"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
@@ -50,6 +50,11 @@ func InfoWithContext(ctx context.Context) (*InfoStat, error) {
|
||||
ret.KernelVersion = version
|
||||
}
|
||||
|
||||
kernelArch, err := kernelArch()
|
||||
if err == nil {
|
||||
ret.KernelArch = kernelArch
|
||||
}
|
||||
|
||||
system, role, err := Virtualization()
|
||||
if err == nil {
|
||||
ret.VirtualizationSystem = system
|
||||
@@ -144,11 +149,11 @@ func UsersWithContext(ctx context.Context) ([]UserStat, error) {
|
||||
b := buf[i*sizeOfUtmpx : (i+1)*sizeOfUtmpx]
|
||||
var u Utmpx
|
||||
br := bytes.NewReader(b)
|
||||
err := binary.Read(br, binary.LittleEndian, &u)
|
||||
err := binary.Read(br, binary.BigEndian, &u)
|
||||
if err != nil || u.Type != 4 {
|
||||
continue
|
||||
}
|
||||
sec := (binary.LittleEndian.Uint32(u.Tv.Sec[:])) / 2 // TODO:
|
||||
sec := math.Floor(float64(u.Tv) / 1000000)
|
||||
user := UserStat{
|
||||
User: common.IntToString(u.User[:]),
|
||||
Terminal: common.IntToString(u.Line[:]),
|
||||
@@ -168,25 +173,17 @@ func PlatformInformation() (string, string, string, error) {
|
||||
}
|
||||
|
||||
func PlatformInformationWithContext(ctx context.Context) (string, string, string, error) {
|
||||
platform := ""
|
||||
family := ""
|
||||
version := ""
|
||||
uname, err := exec.LookPath("uname")
|
||||
platform, err := unix.Sysctl("kern.ostype")
|
||||
if err != nil {
|
||||
return "", "", "", err
|
||||
}
|
||||
|
||||
out, err := invoke.Command(uname, "-s")
|
||||
if err == nil {
|
||||
platform = strings.ToLower(strings.TrimSpace(string(out)))
|
||||
version, err := unix.Sysctl("kern.osrelease")
|
||||
if err != nil {
|
||||
return "", "", "", err
|
||||
}
|
||||
|
||||
out, err = invoke.Command(uname, "-r")
|
||||
if err == nil {
|
||||
version = strings.ToLower(strings.TrimSpace(string(out)))
|
||||
}
|
||||
|
||||
return platform, family, version, nil
|
||||
return strings.ToLower(platform), "", strings.ToLower(version), nil
|
||||
}
|
||||
|
||||
func Virtualization() (string, string, error) {
|
||||
|
||||
18
vendor/github.com/shirou/gopsutil/host/host_freebsd_386.go
generated
vendored
18
vendor/github.com/shirou/gopsutil/host/host_freebsd_386.go
generated
vendored
@@ -1,4 +1,4 @@
|
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
|
||||
// cgo -godefs types_freebsd.go
|
||||
|
||||
package host
|
||||
@@ -9,7 +9,7 @@ const (
|
||||
sizeofInt = 0x4
|
||||
sizeofLong = 0x4
|
||||
sizeofLongLong = 0x8
|
||||
sizeOfUtmpx = 197 // TODO why should 197
|
||||
sizeOfUtmpx = 0xc5
|
||||
)
|
||||
|
||||
type (
|
||||
@@ -27,17 +27,11 @@ type Utmp struct {
|
||||
}
|
||||
|
||||
type Utmpx struct {
|
||||
Type int16
|
||||
Tv Timeval
|
||||
Type uint8
|
||||
Tv uint64
|
||||
Id [8]int8
|
||||
Pid int32
|
||||
Pid uint32
|
||||
User [32]int8
|
||||
Line [16]int8
|
||||
Host [125]int8
|
||||
// X__ut_spare [64]int8
|
||||
}
|
||||
|
||||
type Timeval struct {
|
||||
Sec [4]byte
|
||||
Usec [3]byte
|
||||
Host [128]int8
|
||||
}
|
||||
|
||||
19
vendor/github.com/shirou/gopsutil/host/host_freebsd_amd64.go
generated
vendored
19
vendor/github.com/shirou/gopsutil/host/host_freebsd_amd64.go
generated
vendored
@@ -1,4 +1,4 @@
|
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
|
||||
// cgo -godefs types_freebsd.go
|
||||
|
||||
package host
|
||||
@@ -9,7 +9,7 @@ const (
|
||||
sizeofInt = 0x4
|
||||
sizeofLong = 0x8
|
||||
sizeofLongLong = 0x8
|
||||
sizeOfUtmpx = 197 // TODO: why should 197, not 0x118
|
||||
sizeOfUtmpx = 0xc5
|
||||
)
|
||||
|
||||
type (
|
||||
@@ -27,18 +27,11 @@ type Utmp struct {
|
||||
}
|
||||
|
||||
type Utmpx struct {
|
||||
Type int16
|
||||
Tv Timeval
|
||||
Type uint8
|
||||
Tv uint64
|
||||
Id [8]int8
|
||||
Pid int32
|
||||
Pid uint32
|
||||
User [32]int8
|
||||
Line [16]int8
|
||||
Host [125]int8
|
||||
// Host [128]int8
|
||||
// X__ut_spare [64]int8
|
||||
}
|
||||
|
||||
type Timeval struct {
|
||||
Sec [4]byte
|
||||
Usec [3]byte
|
||||
Host [128]int8
|
||||
}
|
||||
|
||||
19
vendor/github.com/shirou/gopsutil/host/host_freebsd_arm.go
generated
vendored
19
vendor/github.com/shirou/gopsutil/host/host_freebsd_arm.go
generated
vendored
@@ -1,4 +1,4 @@
|
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
|
||||
// cgo -godefs types_freebsd.go
|
||||
|
||||
package host
|
||||
@@ -9,7 +9,7 @@ const (
|
||||
sizeofInt = 0x4
|
||||
sizeofLong = 0x8
|
||||
sizeofLongLong = 0x8
|
||||
sizeOfUtmpx = 197 // TODO: why should 197, not 0x118
|
||||
sizeOfUtmpx = 0xc5
|
||||
)
|
||||
|
||||
type (
|
||||
@@ -27,18 +27,11 @@ type Utmp struct {
|
||||
}
|
||||
|
||||
type Utmpx struct {
|
||||
Type int16
|
||||
Tv Timeval
|
||||
Type uint8
|
||||
Tv uint64
|
||||
Id [8]int8
|
||||
Pid int32
|
||||
Pid uint32
|
||||
User [32]int8
|
||||
Line [16]int8
|
||||
Host [125]int8
|
||||
// Host [128]int8
|
||||
// X__ut_spare [64]int8
|
||||
}
|
||||
|
||||
type Timeval struct {
|
||||
Sec [4]byte
|
||||
Usec [3]byte
|
||||
Host [128]int8
|
||||
}
|
||||
|
||||
39
vendor/github.com/shirou/gopsutil/host/host_freebsd_arm64.go
generated
vendored
Normal file
39
vendor/github.com/shirou/gopsutil/host/host_freebsd_arm64.go
generated
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
// +build freebsd
|
||||
// +build arm64
|
||||
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
|
||||
// cgo -godefs host/types_freebsd.go
|
||||
|
||||
package host
|
||||
|
||||
const (
|
||||
sizeofPtr = 0x8
|
||||
sizeofShort = 0x2
|
||||
sizeofInt = 0x4
|
||||
sizeofLong = 0x8
|
||||
sizeofLongLong = 0x8
|
||||
sizeOfUtmpx = 0xc5
|
||||
)
|
||||
|
||||
type (
|
||||
_C_short int16
|
||||
_C_int int32
|
||||
_C_long int64
|
||||
_C_long_long int64
|
||||
)
|
||||
|
||||
type Utmp struct {
|
||||
Line [8]int8
|
||||
Name [16]int8
|
||||
Host [16]int8
|
||||
Time int32
|
||||
}
|
||||
|
||||
type Utmpx struct {
|
||||
Type uint8
|
||||
Tv uint64
|
||||
Id [8]int8
|
||||
Pid uint32
|
||||
User [32]int8
|
||||
Line [16]int8
|
||||
Host [128]int8
|
||||
}
|
||||
240
vendor/github.com/shirou/gopsutil/host/host_linux.go
generated
vendored
240
vendor/github.com/shirou/gopsutil/host/host_linux.go
generated
vendored
@@ -15,10 +15,10 @@ import (
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
type LSB struct {
|
||||
@@ -56,6 +56,11 @@ func InfoWithContext(ctx context.Context) (*InfoStat, error) {
|
||||
ret.KernelVersion = kernelVersion
|
||||
}
|
||||
|
||||
kernelArch, err := kernelArch()
|
||||
if err == nil {
|
||||
ret.KernelArch = kernelArch
|
||||
}
|
||||
|
||||
system, role, err := Virtualization()
|
||||
if err == nil {
|
||||
ret.VirtualizationSystem = system
|
||||
@@ -73,7 +78,11 @@ func InfoWithContext(ctx context.Context) (*InfoStat, error) {
|
||||
}
|
||||
|
||||
sysProductUUID := common.HostSys("class/dmi/id/product_uuid")
|
||||
machineID := common.HostEtc("machine-id")
|
||||
procSysKernelRandomBootID := common.HostProc("sys/kernel/random/boot_id")
|
||||
switch {
|
||||
// In order to read this file, needs to be supported by kernel/arch and run as root
|
||||
// so having fallback is important
|
||||
case common.PathExists(sysProductUUID):
|
||||
lines, err := common.ReadLines(sysProductUUID)
|
||||
if err == nil && len(lines) > 0 && lines[0] != "" {
|
||||
@@ -81,62 +90,33 @@ func InfoWithContext(ctx context.Context) (*InfoStat, error) {
|
||||
break
|
||||
}
|
||||
fallthrough
|
||||
// Fallback on GNU Linux systems with systemd, readable by everyone
|
||||
case common.PathExists(machineID):
|
||||
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
|
||||
}
|
||||
fallthrough
|
||||
// Not stable between reboot, but better than nothing
|
||||
default:
|
||||
values, err := common.DoSysctrl("kernel.random.boot_id")
|
||||
if err == nil && len(values) == 1 && values[0] != "" {
|
||||
ret.HostID = strings.ToLower(values[0])
|
||||
lines, err := common.ReadLines(procSysKernelRandomBootID)
|
||||
if err == nil && len(lines) > 0 && lines[0] != "" {
|
||||
ret.HostID = strings.ToLower(lines[0])
|
||||
}
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// cachedBootTime must be accessed via atomic.Load/StoreUint64
|
||||
var cachedBootTime uint64
|
||||
|
||||
// BootTime returns the system boot time expressed in seconds since the epoch.
|
||||
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
|
||||
}
|
||||
|
||||
system, role, err := Virtualization()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
statFile := "stat"
|
||||
if system == "lxc" && role == "guest" {
|
||||
// if lxc, /proc/uptime is used.
|
||||
statFile = "uptime"
|
||||
}
|
||||
|
||||
filename := common.HostProc(statFile)
|
||||
lines, err := common.ReadLines(filename)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
for _, line := range lines {
|
||||
if strings.HasPrefix(line, "btime") {
|
||||
f := strings.Fields(line)
|
||||
if len(f) != 2 {
|
||||
return 0, fmt.Errorf("wrong btime format")
|
||||
}
|
||||
b, err := strconv.ParseInt(f[1], 10, 64)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
t = uint64(b)
|
||||
atomic.StoreUint64(&cachedBootTime, t)
|
||||
return t, nil
|
||||
}
|
||||
}
|
||||
|
||||
return 0, fmt.Errorf("could not find btime")
|
||||
return common.BootTimeWithContext(ctx)
|
||||
}
|
||||
|
||||
func uptime(boot uint64) uint64 {
|
||||
@@ -202,26 +182,6 @@ func UsersWithContext(ctx context.Context) ([]UserStat, error) {
|
||||
|
||||
}
|
||||
|
||||
func getOSRelease() (platform string, version string, err error) {
|
||||
contents, err := common.ReadLines(common.HostEtc("os-release"))
|
||||
if err != nil {
|
||||
return "", "", nil // return empty
|
||||
}
|
||||
for _, line := range contents {
|
||||
field := strings.Split(line, "=")
|
||||
if len(field) < 2 {
|
||||
continue
|
||||
}
|
||||
switch field[0] {
|
||||
case "ID": // use ID for lowercase
|
||||
platform = field[1]
|
||||
case "VERSION":
|
||||
version = field[1]
|
||||
}
|
||||
}
|
||||
return platform, version, nil
|
||||
}
|
||||
|
||||
func getLSB() (*LSB, error) {
|
||||
ret := &LSB{}
|
||||
if common.PathExists(common.HostEtc("lsb-release")) {
|
||||
@@ -246,7 +206,7 @@ func getLSB() (*LSB, error) {
|
||||
}
|
||||
}
|
||||
} else if common.PathExists("/usr/bin/lsb_release") {
|
||||
lsb_release, err := exec.LookPath("/usr/bin/lsb_release")
|
||||
lsb_release, err := exec.LookPath("lsb_release")
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
@@ -300,6 +260,12 @@ func PlatformInformationWithContext(ctx context.Context) (platform string, famil
|
||||
if err == nil {
|
||||
version = getRedhatishVersion(contents)
|
||||
}
|
||||
} else if common.PathExists(common.HostEtc("slackware-version")) {
|
||||
platform = "slackware"
|
||||
contents, err := common.ReadLines(common.HostEtc("slackware-version"))
|
||||
if err == nil {
|
||||
version = getSlackwareVersion(contents)
|
||||
}
|
||||
} else if common.PathExists(common.HostEtc("debian_version")) {
|
||||
if lsb.ID == "Ubuntu" {
|
||||
platform = "ubuntu"
|
||||
@@ -314,7 +280,7 @@ func PlatformInformationWithContext(ctx context.Context) (platform string, famil
|
||||
platform = "debian"
|
||||
}
|
||||
contents, err := common.ReadLines(common.HostEtc("debian_version"))
|
||||
if err == nil {
|
||||
if err == nil && len(contents) > 0 && contents[0] != "" {
|
||||
version = contents[0]
|
||||
}
|
||||
}
|
||||
@@ -349,11 +315,11 @@ func PlatformInformationWithContext(ctx context.Context) (platform string, famil
|
||||
} else if common.PathExists(common.HostEtc("alpine-release")) {
|
||||
platform = "alpine"
|
||||
contents, err := common.ReadLines(common.HostEtc("alpine-release"))
|
||||
if err == nil && len(contents) > 0 {
|
||||
if err == nil && len(contents) > 0 && contents[0] != "" {
|
||||
version = contents[0]
|
||||
}
|
||||
} else if common.PathExists(common.HostEtc("os-release")) {
|
||||
p, v, err := getOSRelease()
|
||||
p, v, err := common.GetOSRelease()
|
||||
if err == nil {
|
||||
platform = p
|
||||
version = v
|
||||
@@ -382,7 +348,7 @@ func PlatformInformationWithContext(ctx context.Context) (platform string, famil
|
||||
family = "fedora"
|
||||
case "oracle", "centos", "redhat", "scientific", "enterpriseenterprise", "amazon", "xenserver", "cloudlinux", "ibm_powerkvm":
|
||||
family = "rhel"
|
||||
case "suse", "opensuse":
|
||||
case "suse", "opensuse", "sles":
|
||||
family = "suse"
|
||||
case "gentoo":
|
||||
family = "gentoo"
|
||||
@@ -396,6 +362,8 @@ func PlatformInformationWithContext(ctx context.Context) (platform string, famil
|
||||
family = "alpine"
|
||||
case "coreos":
|
||||
family = "coreos"
|
||||
case "solus":
|
||||
family = "solus"
|
||||
}
|
||||
|
||||
return platform, family, version, nil
|
||||
@@ -407,19 +375,18 @@ func KernelVersion() (version string, err error) {
|
||||
}
|
||||
|
||||
func KernelVersionWithContext(ctx context.Context) (version string, err error) {
|
||||
filename := common.HostProc("sys/kernel/osrelease")
|
||||
if common.PathExists(filename) {
|
||||
contents, err := common.ReadLines(filename)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if len(contents) > 0 {
|
||||
version = contents[0]
|
||||
}
|
||||
var utsname unix.Utsname
|
||||
err = unix.Uname(&utsname)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(utsname.Release[:bytes.IndexByte(utsname.Release[:], 0)]), nil
|
||||
}
|
||||
|
||||
return version, nil
|
||||
func getSlackwareVersion(contents []string) string {
|
||||
c := strings.ToLower(strings.Join(contents, ""))
|
||||
c = strings.Replace(c, "slackware ", "", 1)
|
||||
return c
|
||||
}
|
||||
|
||||
func getRedhatishVersion(contents []string) string {
|
||||
@@ -470,106 +437,7 @@ func Virtualization() (string, string, error) {
|
||||
}
|
||||
|
||||
func VirtualizationWithContext(ctx context.Context) (string, string, error) {
|
||||
var system string
|
||||
var role string
|
||||
|
||||
filename := common.HostProc("xen")
|
||||
if common.PathExists(filename) {
|
||||
system = "xen"
|
||||
role = "guest" // assume guest
|
||||
|
||||
if common.PathExists(filepath.Join(filename, "capabilities")) {
|
||||
contents, err := common.ReadLines(filepath.Join(filename, "capabilities"))
|
||||
if err == nil {
|
||||
if common.StringsContains(contents, "control_d") {
|
||||
role = "host"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
filename = common.HostProc("modules")
|
||||
if common.PathExists(filename) {
|
||||
contents, err := common.ReadLines(filename)
|
||||
if err == nil {
|
||||
if common.StringsContains(contents, "kvm") {
|
||||
system = "kvm"
|
||||
role = "host"
|
||||
} else if common.StringsContains(contents, "vboxdrv") {
|
||||
system = "vbox"
|
||||
role = "host"
|
||||
} else if common.StringsContains(contents, "vboxguest") {
|
||||
system = "vbox"
|
||||
role = "guest"
|
||||
} else if common.StringsContains(contents, "vmware") {
|
||||
system = "vmware"
|
||||
role = "guest"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
filename = common.HostProc("cpuinfo")
|
||||
if common.PathExists(filename) {
|
||||
contents, err := common.ReadLines(filename)
|
||||
if err == nil {
|
||||
if common.StringsContains(contents, "QEMU Virtual CPU") ||
|
||||
common.StringsContains(contents, "Common KVM processor") ||
|
||||
common.StringsContains(contents, "Common 32-bit KVM processor") {
|
||||
system = "kvm"
|
||||
role = "guest"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
filename = common.HostProc()
|
||||
if common.PathExists(filepath.Join(filename, "bc", "0")) {
|
||||
system = "openvz"
|
||||
role = "host"
|
||||
} else if common.PathExists(filepath.Join(filename, "vz")) {
|
||||
system = "openvz"
|
||||
role = "guest"
|
||||
}
|
||||
|
||||
// not use dmidecode because it requires root
|
||||
if common.PathExists(filepath.Join(filename, "self", "status")) {
|
||||
contents, err := common.ReadLines(filepath.Join(filename, "self", "status"))
|
||||
if err == nil {
|
||||
|
||||
if common.StringsContains(contents, "s_context:") ||
|
||||
common.StringsContains(contents, "VxID:") {
|
||||
system = "linux-vserver"
|
||||
}
|
||||
// TODO: guest or host
|
||||
}
|
||||
}
|
||||
|
||||
if common.PathExists(filepath.Join(filename, "self", "cgroup")) {
|
||||
contents, err := common.ReadLines(filepath.Join(filename, "self", "cgroup"))
|
||||
if err == nil {
|
||||
if common.StringsContains(contents, "lxc") {
|
||||
system = "lxc"
|
||||
role = "guest"
|
||||
} else if common.StringsContains(contents, "docker") {
|
||||
system = "docker"
|
||||
role = "guest"
|
||||
} else if common.StringsContains(contents, "machine-rkt") {
|
||||
system = "rkt"
|
||||
role = "guest"
|
||||
} else if common.PathExists("/usr/bin/lxc-version") {
|
||||
system = "lxc"
|
||||
role = "host"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if common.PathExists(common.HostEtc("os-release")) {
|
||||
p, _, err := getOSRelease()
|
||||
if err == nil && p == "coreos" {
|
||||
system = "rkt" // Is it true?
|
||||
role = "host"
|
||||
}
|
||||
}
|
||||
return system, role, nil
|
||||
return common.VirtualizationWithContext(ctx)
|
||||
}
|
||||
|
||||
func SensorsTemperatures() ([]TemperatureStat, error) {
|
||||
@@ -590,6 +458,7 @@ func SensorsTemperaturesWithContext(ctx context.Context) ([]TemperatureStat, err
|
||||
return temperatures, err
|
||||
}
|
||||
}
|
||||
var warns Warnings
|
||||
|
||||
// example directory
|
||||
// device/ temp1_crit_alarm temp2_crit_alarm temp3_crit_alarm temp4_crit_alarm temp5_crit_alarm temp6_crit_alarm temp7_crit_alarm
|
||||
@@ -612,19 +481,22 @@ func SensorsTemperaturesWithContext(ctx context.Context) ([]TemperatureStat, err
|
||||
label = fmt.Sprintf("%s_", strings.Join(strings.Split(strings.TrimSpace(strings.ToLower(string(c))), " "), ""))
|
||||
}
|
||||
|
||||
// Get the name of the tempearture you are reading
|
||||
// Get the name of the temperature you are reading
|
||||
name, err := ioutil.ReadFile(filepath.Join(filepath.Dir(file), "name"))
|
||||
if err != nil {
|
||||
return temperatures, err
|
||||
warns.Add(err)
|
||||
continue
|
||||
}
|
||||
|
||||
// Get the temperature reading
|
||||
current, err := ioutil.ReadFile(file)
|
||||
if err != nil {
|
||||
return temperatures, err
|
||||
warns.Add(err)
|
||||
continue
|
||||
}
|
||||
temperature, err := strconv.ParseFloat(strings.TrimSpace(string(current)), 64)
|
||||
if err != nil {
|
||||
warns.Add(err)
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -634,5 +506,5 @@ func SensorsTemperaturesWithContext(ctx context.Context) ([]TemperatureStat, err
|
||||
Temperature: temperature / 1000.0,
|
||||
})
|
||||
}
|
||||
return temperatures, nil
|
||||
return temperatures, warns.Reference()
|
||||
}
|
||||
|
||||
43
vendor/github.com/shirou/gopsutil/host/host_linux_mips64.go
generated
vendored
Normal file
43
vendor/github.com/shirou/gopsutil/host/host_linux_mips64.go
generated
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// cgo -godefs types_linux.go
|
||||
|
||||
package host
|
||||
|
||||
const (
|
||||
sizeofPtr = 0x4
|
||||
sizeofShort = 0x2
|
||||
sizeofInt = 0x4
|
||||
sizeofLong = 0x4
|
||||
sizeofLongLong = 0x8
|
||||
sizeOfUtmp = 0x180
|
||||
)
|
||||
|
||||
type (
|
||||
_C_short int16
|
||||
_C_int int32
|
||||
_C_long int32
|
||||
_C_long_long int64
|
||||
)
|
||||
|
||||
type utmp struct {
|
||||
Type int16
|
||||
Pad_cgo_0 [2]byte
|
||||
Pid int32
|
||||
Line [32]int8
|
||||
Id [4]int8
|
||||
User [32]int8
|
||||
Host [256]int8
|
||||
Exit exit_status
|
||||
Session int32
|
||||
Tv timeval
|
||||
Addr_v6 [4]int32
|
||||
X__unused [20]int8
|
||||
}
|
||||
type exit_status struct {
|
||||
Termination int16
|
||||
Exit int16
|
||||
}
|
||||
type timeval struct {
|
||||
Sec int32
|
||||
Usec int32
|
||||
}
|
||||
43
vendor/github.com/shirou/gopsutil/host/host_linux_mips64le.go
generated
vendored
Normal file
43
vendor/github.com/shirou/gopsutil/host/host_linux_mips64le.go
generated
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// cgo -godefs types_linux.go
|
||||
|
||||
package host
|
||||
|
||||
const (
|
||||
sizeofPtr = 0x4
|
||||
sizeofShort = 0x2
|
||||
sizeofInt = 0x4
|
||||
sizeofLong = 0x4
|
||||
sizeofLongLong = 0x8
|
||||
sizeOfUtmp = 0x180
|
||||
)
|
||||
|
||||
type (
|
||||
_C_short int16
|
||||
_C_int int32
|
||||
_C_long int32
|
||||
_C_long_long int64
|
||||
)
|
||||
|
||||
type utmp struct {
|
||||
Type int16
|
||||
Pad_cgo_0 [2]byte
|
||||
Pid int32
|
||||
Line [32]int8
|
||||
Id [4]int8
|
||||
User [32]int8
|
||||
Host [256]int8
|
||||
Exit exit_status
|
||||
Session int32
|
||||
Tv timeval
|
||||
Addr_v6 [4]int32
|
||||
X__unused [20]int8
|
||||
}
|
||||
type exit_status struct {
|
||||
Termination int16
|
||||
Exit int16
|
||||
}
|
||||
type timeval struct {
|
||||
Sec int32
|
||||
Usec int32
|
||||
}
|
||||
61
vendor/github.com/shirou/gopsutil/host/host_linux_test.go
generated
vendored
61
vendor/github.com/shirou/gopsutil/host/host_linux_test.go
generated
vendored
@@ -1,61 +0,0 @@
|
||||
// +build linux
|
||||
|
||||
package host
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestGetRedhatishVersion(t *testing.T) {
|
||||
var ret string
|
||||
c := []string{"Rawhide"}
|
||||
ret = getRedhatishVersion(c)
|
||||
if ret != "rawhide" {
|
||||
t.Errorf("Could not get version rawhide: %v", ret)
|
||||
}
|
||||
|
||||
c = []string{"Fedora release 15 (Lovelock)"}
|
||||
ret = getRedhatishVersion(c)
|
||||
if ret != "15" {
|
||||
t.Errorf("Could not get version fedora: %v", ret)
|
||||
}
|
||||
|
||||
c = []string{"Enterprise Linux Server release 5.5 (Carthage)"}
|
||||
ret = getRedhatishVersion(c)
|
||||
if ret != "5.5" {
|
||||
t.Errorf("Could not get version redhat enterprise: %v", ret)
|
||||
}
|
||||
|
||||
c = []string{""}
|
||||
ret = getRedhatishVersion(c)
|
||||
if ret != "" {
|
||||
t.Errorf("Could not get version with no value: %v", ret)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetRedhatishPlatform(t *testing.T) {
|
||||
var ret string
|
||||
c := []string{"red hat"}
|
||||
ret = getRedhatishPlatform(c)
|
||||
if ret != "redhat" {
|
||||
t.Errorf("Could not get platform redhat: %v", ret)
|
||||
}
|
||||
|
||||
c = []string{"Fedora release 15 (Lovelock)"}
|
||||
ret = getRedhatishPlatform(c)
|
||||
if ret != "fedora" {
|
||||
t.Errorf("Could not get platform fedora: %v", ret)
|
||||
}
|
||||
|
||||
c = []string{"Enterprise Linux Server release 5.5 (Carthage)"}
|
||||
ret = getRedhatishPlatform(c)
|
||||
if ret != "enterprise" {
|
||||
t.Errorf("Could not get platform redhat enterprise: %v", ret)
|
||||
}
|
||||
|
||||
c = []string{""}
|
||||
ret = getRedhatishPlatform(c)
|
||||
if ret != "" {
|
||||
t.Errorf("Could not get platform with no value: %v", ret)
|
||||
}
|
||||
}
|
||||
40
vendor/github.com/shirou/gopsutil/host/host_openbsd.go
generated
vendored
40
vendor/github.com/shirou/gopsutil/host/host_openbsd.go
generated
vendored
@@ -8,15 +8,15 @@ import (
|
||||
"encoding/binary"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/process"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -40,6 +40,11 @@ func InfoWithContext(ctx context.Context) (*InfoStat, error) {
|
||||
ret.Hostname = hostname
|
||||
}
|
||||
|
||||
kernelArch, err := kernelArch()
|
||||
if err == nil {
|
||||
ret.KernelArch = kernelArch
|
||||
}
|
||||
|
||||
platform, family, version, err := PlatformInformation()
|
||||
if err == nil {
|
||||
ret.Platform = platform
|
||||
@@ -66,20 +71,28 @@ func InfoWithContext(ctx context.Context) (*InfoStat, error) {
|
||||
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) {
|
||||
val, err := common.DoSysctrl("kern.boottime")
|
||||
// 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")
|
||||
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
|
||||
|
||||
boottime, err := strconv.ParseUint(val[0], 10, 64)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
atomic.StoreUint64(&cachedBootTime, boottime)
|
||||
|
||||
return boottime, nil
|
||||
}
|
||||
@@ -108,19 +121,14 @@ func PlatformInformationWithContext(ctx context.Context) (string, string, string
|
||||
platform := ""
|
||||
family := ""
|
||||
version := ""
|
||||
uname, err := exec.LookPath("uname")
|
||||
if err != nil {
|
||||
return "", "", "", err
|
||||
}
|
||||
|
||||
out, err := invoke.Command(uname, "-s")
|
||||
p, err := unix.Sysctl("kern.ostype")
|
||||
if err == nil {
|
||||
platform = strings.ToLower(strings.TrimSpace(string(out)))
|
||||
platform = strings.ToLower(p)
|
||||
}
|
||||
|
||||
out, err = invoke.Command(uname, "-r")
|
||||
v, err := unix.Sysctl("kern.osrelease")
|
||||
if err == nil {
|
||||
version = strings.ToLower(strings.TrimSpace(string(out)))
|
||||
version = strings.ToLower(v)
|
||||
}
|
||||
|
||||
return platform, family, version, nil
|
||||
|
||||
15
vendor/github.com/shirou/gopsutil/host/host_posix.go
generated
vendored
Normal file
15
vendor/github.com/shirou/gopsutil/host/host_posix.go
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
// +build linux freebsd openbsd darwin solaris
|
||||
|
||||
package host
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func kernelArch() (string, error) {
|
||||
var utsname unix.Utsname
|
||||
err := unix.Uname(&utsname)
|
||||
return string(utsname.Machine[:bytes.IndexByte(utsname.Machine[:], 0)]), err
|
||||
}
|
||||
40
vendor/github.com/shirou/gopsutil/host/host_solaris.go
generated
vendored
40
vendor/github.com/shirou/gopsutil/host/host_solaris.go
generated
vendored
@@ -33,12 +33,12 @@ func InfoWithContext(ctx context.Context) (*InfoStat, error) {
|
||||
result.Hostname = hostname
|
||||
|
||||
// Parse versions from output of `uname(1)`
|
||||
uname, err := exec.LookPath("/usr/bin/uname")
|
||||
uname, err := exec.LookPath("uname")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out, err := invoke.Command(uname, "-srv")
|
||||
out, err := invoke.CommandWithContext(ctx, uname, "-srv")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -54,6 +54,11 @@ func InfoWithContext(ctx context.Context) (*InfoStat, error) {
|
||||
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 {
|
||||
@@ -85,9 +90,9 @@ func InfoWithContext(ctx context.Context) (*InfoStat, error) {
|
||||
switch result.Platform {
|
||||
case "SmartOS":
|
||||
// If everything works, use the current zone ID as the HostID if present.
|
||||
zonename, err := exec.LookPath("/usr/bin/zonename")
|
||||
zonename, err := exec.LookPath("zonename")
|
||||
if err == nil {
|
||||
out, err := invoke.Command(zonename)
|
||||
out, err := invoke.CommandWithContext(ctx, zonename)
|
||||
if err == nil {
|
||||
sc := bufio.NewScanner(bytes.NewReader(out))
|
||||
for sc.Scan() {
|
||||
@@ -112,9 +117,9 @@ func InfoWithContext(ctx context.Context) (*InfoStat, error) {
|
||||
// this point there are no hardware facilities available. This behavior
|
||||
// matches that of other supported OSes.
|
||||
if result.HostID == "" {
|
||||
hostID, err := exec.LookPath("/usr/bin/hostid")
|
||||
hostID, err := exec.LookPath("hostid")
|
||||
if err == nil {
|
||||
out, err := invoke.Command(hostID)
|
||||
out, err := invoke.CommandWithContext(ctx, hostID)
|
||||
if err == nil {
|
||||
sc := bufio.NewScanner(bytes.NewReader(out))
|
||||
for sc.Scan() {
|
||||
@@ -151,12 +156,12 @@ func BootTime() (uint64, error) {
|
||||
}
|
||||
|
||||
func BootTimeWithContext(ctx context.Context) (uint64, error) {
|
||||
kstat, err := exec.LookPath("/usr/bin/kstat")
|
||||
kstat, err := exec.LookPath("kstat")
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
out, err := invoke.Command(kstat, "-p", "unix:0:system_misc:boot_time")
|
||||
out, err := invoke.CommandWithContext(ctx, kstat, "-p", "unix:0:system_misc:boot_time")
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@@ -215,12 +220,12 @@ func KernelVersion() (string, error) {
|
||||
|
||||
func KernelVersionWithContext(ctx context.Context) (string, error) {
|
||||
// Parse versions from output of `uname(1)`
|
||||
uname, err := exec.LookPath("/usr/bin/uname")
|
||||
uname, err := exec.LookPath("uname")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
out, err := invoke.Command(uname, "-srv")
|
||||
out, err := invoke.CommandWithContext(ctx, uname, "-srv")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -231,3 +236,18 @@ func KernelVersionWithContext(ctx context.Context) (string, error) {
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
150
vendor/github.com/shirou/gopsutil/host/host_test.go
generated
vendored
150
vendor/github.com/shirou/gopsutil/host/host_test.go
generated
vendored
@@ -1,150 +0,0 @@
|
||||
package host
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestHostInfo(t *testing.T) {
|
||||
v, err := Info()
|
||||
if err != nil {
|
||||
t.Errorf("error %v", err)
|
||||
}
|
||||
empty := &InfoStat{}
|
||||
if v == empty {
|
||||
t.Errorf("Could not get hostinfo %v", v)
|
||||
}
|
||||
if v.Procs == 0 {
|
||||
t.Errorf("Could not determine the number of host processes")
|
||||
}
|
||||
}
|
||||
|
||||
func TestUptime(t *testing.T) {
|
||||
if os.Getenv("CIRCLECI") == "true" {
|
||||
t.Skip("Skip CI")
|
||||
}
|
||||
|
||||
v, err := Uptime()
|
||||
if err != nil {
|
||||
t.Errorf("error %v", err)
|
||||
}
|
||||
if v == 0 {
|
||||
t.Errorf("Could not get up time %v", v)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBoot_time(t *testing.T) {
|
||||
if os.Getenv("CIRCLECI") == "true" {
|
||||
t.Skip("Skip CI")
|
||||
}
|
||||
v, err := BootTime()
|
||||
if err != nil {
|
||||
t.Errorf("error %v", err)
|
||||
}
|
||||
if v == 0 {
|
||||
t.Errorf("Could not get boot time %v", v)
|
||||
}
|
||||
if v < 946652400 {
|
||||
t.Errorf("Invalid Boottime, older than 2000-01-01")
|
||||
}
|
||||
t.Logf("first boot time: %d", v)
|
||||
|
||||
v2, err := BootTime()
|
||||
if v != v2 {
|
||||
t.Errorf("cached boot time is different")
|
||||
}
|
||||
t.Logf("second boot time: %d", v2)
|
||||
}
|
||||
|
||||
func TestUsers(t *testing.T) {
|
||||
v, err := Users()
|
||||
if err != nil {
|
||||
t.Errorf("error %v", err)
|
||||
}
|
||||
empty := UserStat{}
|
||||
if len(v) == 0 {
|
||||
t.Fatal("Users is empty")
|
||||
}
|
||||
for _, u := range v {
|
||||
if u == empty {
|
||||
t.Errorf("Could not Users %v", v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestHostInfoStat_String(t *testing.T) {
|
||||
v := InfoStat{
|
||||
Hostname: "test",
|
||||
Uptime: 3000,
|
||||
Procs: 100,
|
||||
OS: "linux",
|
||||
Platform: "ubuntu",
|
||||
BootTime: 1447040000,
|
||||
HostID: "edfd25ff-3c9c-b1a4-e660-bd826495ad35",
|
||||
}
|
||||
e := `{"hostname":"test","uptime":3000,"bootTime":1447040000,"procs":100,"os":"linux","platform":"ubuntu","platformFamily":"","platformVersion":"","kernelVersion":"","virtualizationSystem":"","virtualizationRole":"","hostid":"edfd25ff-3c9c-b1a4-e660-bd826495ad35"}`
|
||||
if e != fmt.Sprintf("%v", v) {
|
||||
t.Errorf("HostInfoStat string is invalid: %v", v)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUserStat_String(t *testing.T) {
|
||||
v := UserStat{
|
||||
User: "user",
|
||||
Terminal: "term",
|
||||
Host: "host",
|
||||
Started: 100,
|
||||
}
|
||||
e := `{"user":"user","terminal":"term","host":"host","started":100}`
|
||||
if e != fmt.Sprintf("%v", v) {
|
||||
t.Errorf("UserStat string is invalid: %v", v)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHostGuid(t *testing.T) {
|
||||
hi, err := Info()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if hi.HostID == "" {
|
||||
t.Error("Host id is empty")
|
||||
} else {
|
||||
t.Logf("Host id value: %v", hi.HostID)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTemperatureStat_String(t *testing.T) {
|
||||
v := TemperatureStat{
|
||||
SensorKey: "CPU",
|
||||
Temperature: 1.1,
|
||||
}
|
||||
s := `{"sensorKey":"CPU","sensorTemperature":1.1}`
|
||||
if s != fmt.Sprintf("%v", v) {
|
||||
t.Errorf("TemperatureStat string is invalid")
|
||||
}
|
||||
}
|
||||
|
||||
func TestVirtualization(t *testing.T) {
|
||||
system, role, err := Virtualization()
|
||||
if err != nil {
|
||||
t.Errorf("Virtualization() failed, %v", err)
|
||||
}
|
||||
if system == "" || role == "" {
|
||||
t.Errorf("Virtualization() retuns empty system or role: %s, %s", system, role)
|
||||
}
|
||||
|
||||
t.Logf("Virtualization(): %s, %s", system, role)
|
||||
}
|
||||
|
||||
func TestKernelVersion(t *testing.T) {
|
||||
version, err := KernelVersion()
|
||||
if err != nil {
|
||||
t.Errorf("KernelVersion() failed, %v", err)
|
||||
}
|
||||
if version == "" {
|
||||
t.Errorf("KernelVersion() retuns empty: %s", version)
|
||||
}
|
||||
|
||||
t.Logf("KernelVersion(): %s", version)
|
||||
}
|
||||
209
vendor/github.com/shirou/gopsutil/host/host_windows.go
generated
vendored
209
vendor/github.com/shirou/gopsutil/host/host_windows.go
generated
vendored
@@ -5,10 +5,12 @@ package host
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"math"
|
||||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
"syscall"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
@@ -20,15 +22,46 @@ import (
|
||||
|
||||
var (
|
||||
procGetSystemTimeAsFileTime = common.Modkernel32.NewProc("GetSystemTimeAsFileTime")
|
||||
osInfo *Win32_OperatingSystem
|
||||
procGetTickCount32 = common.Modkernel32.NewProc("GetTickCount")
|
||||
procGetTickCount64 = common.Modkernel32.NewProc("GetTickCount64")
|
||||
procGetNativeSystemInfo = common.Modkernel32.NewProc("GetNativeSystemInfo")
|
||||
procRtlGetVersion = common.ModNt.NewProc("RtlGetVersion")
|
||||
)
|
||||
|
||||
type Win32_OperatingSystem struct {
|
||||
Version string
|
||||
Caption string
|
||||
ProductType uint32
|
||||
BuildNumber string
|
||||
LastBootUpTime time.Time
|
||||
// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/wdm/ns-wdm-_osversioninfoexw
|
||||
type osVersionInfoExW struct {
|
||||
dwOSVersionInfoSize uint32
|
||||
dwMajorVersion uint32
|
||||
dwMinorVersion uint32
|
||||
dwBuildNumber uint32
|
||||
dwPlatformId uint32
|
||||
szCSDVersion [128]uint16
|
||||
wServicePackMajor uint16
|
||||
wServicePackMinor uint16
|
||||
wSuiteMask uint16
|
||||
wProductType uint8
|
||||
wReserved uint8
|
||||
}
|
||||
|
||||
type systemInfo struct {
|
||||
wProcessorArchitecture uint16
|
||||
wReserved uint16
|
||||
dwPageSize uint32
|
||||
lpMinimumApplicationAddress uintptr
|
||||
lpMaximumApplicationAddress uintptr
|
||||
dwActiveProcessorMask uintptr
|
||||
dwNumberOfProcessors uint32
|
||||
dwProcessorType uint32
|
||||
dwAllocationGranularity uint32
|
||||
wProcessorLevel uint16
|
||||
wProcessorRevision uint16
|
||||
}
|
||||
|
||||
type msAcpi_ThermalZoneTemperature struct {
|
||||
Active bool
|
||||
CriticalTripPoint uint32
|
||||
CurrentTemperature uint32
|
||||
InstanceName string
|
||||
}
|
||||
|
||||
func Info() (*InfoStat, error) {
|
||||
@@ -59,7 +92,14 @@ func InfoWithContext(ctx context.Context) (*InfoStat, error) {
|
||||
}
|
||||
|
||||
{
|
||||
boot, err := BootTime()
|
||||
kernelArch, err := kernelArch()
|
||||
if err == nil {
|
||||
ret.KernelArch = kernelArch
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
boot, err := BootTimeWithContext(ctx)
|
||||
if err == nil {
|
||||
ret.BootTime = boot
|
||||
ret.Uptime, _ = Uptime()
|
||||
@@ -69,12 +109,12 @@ func InfoWithContext(ctx context.Context) (*InfoStat, error) {
|
||||
{
|
||||
hostID, err := getMachineGuid()
|
||||
if err == nil {
|
||||
ret.HostID = strings.ToLower(hostID)
|
||||
ret.HostID = hostID
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
procs, err := process.Pids()
|
||||
procs, err := process.PidsWithContext(ctx)
|
||||
if err == nil {
|
||||
ret.Procs = uint64(len(procs))
|
||||
}
|
||||
@@ -84,6 +124,8 @@ func InfoWithContext(ctx context.Context) (*InfoStat, error) {
|
||||
}
|
||||
|
||||
func getMachineGuid() (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
|
||||
err := windows.RegOpenKeyEx(windows.HKEY_LOCAL_MACHINE, windows.StringToUTF16Ptr(`SOFTWARE\Microsoft\Cryptography`), 0, windows.KEY_READ|windows.KEY_WOW64_64KEY, &h)
|
||||
if err != nil {
|
||||
@@ -108,24 +150,7 @@ func getMachineGuid() (string, error) {
|
||||
return "", fmt.Errorf("HostID incorrect: %q\n", hostID)
|
||||
}
|
||||
|
||||
return hostID, nil
|
||||
}
|
||||
|
||||
func GetOSInfo() (Win32_OperatingSystem, error) {
|
||||
return GetOSInfoWithContext(context.Background())
|
||||
}
|
||||
|
||||
func GetOSInfoWithContext(ctx context.Context) (Win32_OperatingSystem, error) {
|
||||
var dst []Win32_OperatingSystem
|
||||
q := wmi.CreateQuery(&dst, "")
|
||||
err := common.WMIQueryWithContext(ctx, q, &dst)
|
||||
if err != nil {
|
||||
return Win32_OperatingSystem{}, err
|
||||
}
|
||||
|
||||
osInfo = &dst[0]
|
||||
|
||||
return dst[0], nil
|
||||
return strings.ToLower(hostID), nil
|
||||
}
|
||||
|
||||
func Uptime() (uint64, error) {
|
||||
@@ -133,18 +158,19 @@ func Uptime() (uint64, error) {
|
||||
}
|
||||
|
||||
func UptimeWithContext(ctx context.Context) (uint64, error) {
|
||||
if osInfo == nil {
|
||||
_, err := GetOSInfoWithContext(ctx)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
procGetTickCount := procGetTickCount64
|
||||
err := procGetTickCount64.Find()
|
||||
if err != nil {
|
||||
procGetTickCount = procGetTickCount32 // handle WinXP, but keep in mind that "the time will wrap around to zero if the system is run continuously for 49.7 days." from MSDN
|
||||
}
|
||||
now := time.Now()
|
||||
t := osInfo.LastBootUpTime.Local()
|
||||
return uint64(now.Sub(t).Seconds()), nil
|
||||
r1, _, lastErr := syscall.Syscall(procGetTickCount.Addr(), 0, 0, 0, 0)
|
||||
if lastErr != 0 {
|
||||
return 0, lastErr
|
||||
}
|
||||
return uint64((time.Duration(r1) * time.Millisecond).Seconds()), nil
|
||||
}
|
||||
|
||||
func bootTime(up uint64) uint64 {
|
||||
func bootTimeFromUptime(up uint64) uint64 {
|
||||
return uint64(time.Now().Unix()) - up
|
||||
}
|
||||
|
||||
@@ -164,7 +190,7 @@ func BootTimeWithContext(ctx context.Context) (uint64, error) {
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
t = bootTime(up)
|
||||
t = bootTimeFromUptime(up)
|
||||
atomic.StoreUint64(&cachedBootTime, t)
|
||||
return t, nil
|
||||
}
|
||||
@@ -174,18 +200,50 @@ func PlatformInformation() (platform string, family string, version string, err
|
||||
}
|
||||
|
||||
func PlatformInformationWithContext(ctx context.Context) (platform string, family string, version string, err error) {
|
||||
if osInfo == nil {
|
||||
_, err = GetOSInfoWithContext(ctx)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
// 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
|
||||
// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/wdm/nf-wdm-rtlgetversion
|
||||
// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/wdm/ns-wdm-_osversioninfoexw
|
||||
var osInfo osVersionInfoExW
|
||||
osInfo.dwOSVersionInfoSize = uint32(unsafe.Sizeof(osInfo))
|
||||
ret, _, err := procRtlGetVersion.Call(uintptr(unsafe.Pointer(&osInfo)))
|
||||
if ret != 0 {
|
||||
return
|
||||
}
|
||||
|
||||
// Platform
|
||||
platform = strings.Trim(osInfo.Caption, " ")
|
||||
var h windows.Handle // like getMachineGuid(), 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
|
||||
}
|
||||
defer windows.RegCloseKey(h)
|
||||
var bufLen uint32
|
||||
var valType uint32
|
||||
err = windows.RegQueryValueEx(h, windows.StringToUTF16Ptr(`ProductName`), nil, &valType, nil, &bufLen)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
regBuf := make([]uint16, bufLen/2+1)
|
||||
err = windows.RegQueryValueEx(h, windows.StringToUTF16Ptr(`ProductName`), nil, &valType, (*byte)(unsafe.Pointer(®Buf[0])), &bufLen)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
platform = windows.UTF16ToString(regBuf[:])
|
||||
if !strings.HasPrefix(platform, "Microsoft") {
|
||||
platform = "Microsoft " + platform
|
||||
}
|
||||
err = windows.RegQueryValueEx(h, windows.StringToUTF16Ptr(`CSDVersion`), nil, &valType, nil, &bufLen) // append Service Pack number, only on success
|
||||
if err == nil { // don't return an error if only the Service Pack retrieval fails
|
||||
regBuf = make([]uint16, bufLen/2+1)
|
||||
err = windows.RegQueryValueEx(h, windows.StringToUTF16Ptr(`CSDVersion`), nil, &valType, (*byte)(unsafe.Pointer(®Buf[0])), &bufLen)
|
||||
if err == nil {
|
||||
platform += " " + windows.UTF16ToString(regBuf[:])
|
||||
}
|
||||
}
|
||||
|
||||
// PlatformFamily
|
||||
switch osInfo.ProductType {
|
||||
switch osInfo.wProductType {
|
||||
case 1:
|
||||
family = "Standalone Workstation"
|
||||
case 2:
|
||||
@@ -195,9 +253,9 @@ func PlatformInformationWithContext(ctx context.Context) (platform string, famil
|
||||
}
|
||||
|
||||
// Platform Version
|
||||
version = fmt.Sprintf("%s Build %s", osInfo.Version, osInfo.BuildNumber)
|
||||
version = fmt.Sprintf("%d.%d.%d Build %d", osInfo.dwMajorVersion, osInfo.dwMinorVersion, osInfo.dwBuildNumber, osInfo.dwBuildNumber)
|
||||
|
||||
return
|
||||
return platform, family, version, nil
|
||||
}
|
||||
|
||||
func Users() ([]UserStat, error) {
|
||||
@@ -215,7 +273,30 @@ func SensorsTemperatures() ([]TemperatureStat, error) {
|
||||
}
|
||||
|
||||
func SensorsTemperaturesWithContext(ctx context.Context) ([]TemperatureStat, error) {
|
||||
return []TemperatureStat{}, common.ErrNotImplementedError
|
||||
var ret []TemperatureStat
|
||||
var dst []msAcpi_ThermalZoneTemperature
|
||||
q := wmi.CreateQuery(&dst, "")
|
||||
if err := common.WMIQueryWithContext(ctx, q, &dst, nil, "root/wmi"); err != nil {
|
||||
return ret, err
|
||||
}
|
||||
|
||||
for _, v := range dst {
|
||||
ts := TemperatureStat{
|
||||
SensorKey: v.InstanceName,
|
||||
Temperature: kelvinToCelsius(v.CurrentTemperature, 2),
|
||||
}
|
||||
ret = append(ret, ts)
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func kelvinToCelsius(temp uint32, n int) float64 {
|
||||
// wmi return temperature Kelvin * 10, so need to divide the result by 10,
|
||||
// and then minus 273.15 to get °Celsius.
|
||||
t := float64(temp/10) - 273.15
|
||||
n10 := math.Pow10(n)
|
||||
return math.Trunc((t+0.5/n10)*n10) / n10
|
||||
}
|
||||
|
||||
func Virtualization() (string, string, error) {
|
||||
@@ -234,3 +315,35 @@ func KernelVersionWithContext(ctx context.Context) (string, error) {
|
||||
_, _, version, err := PlatformInformation()
|
||||
return version, err
|
||||
}
|
||||
|
||||
func kernelArch() (string, error) {
|
||||
var systemInfo systemInfo
|
||||
procGetNativeSystemInfo.Call(uintptr(unsafe.Pointer(&systemInfo)))
|
||||
|
||||
const (
|
||||
PROCESSOR_ARCHITECTURE_INTEL = 0
|
||||
PROCESSOR_ARCHITECTURE_ARM = 5
|
||||
PROCESSOR_ARCHITECTURE_ARM64 = 12
|
||||
PROCESSOR_ARCHITECTURE_IA64 = 6
|
||||
PROCESSOR_ARCHITECTURE_AMD64 = 9
|
||||
)
|
||||
switch systemInfo.wProcessorArchitecture {
|
||||
case PROCESSOR_ARCHITECTURE_INTEL:
|
||||
if systemInfo.wProcessorLevel < 3 {
|
||||
return "i386", nil
|
||||
}
|
||||
if systemInfo.wProcessorLevel > 6 {
|
||||
return "i686", nil
|
||||
}
|
||||
return fmt.Sprintf("i%d86", systemInfo.wProcessorLevel), nil
|
||||
case PROCESSOR_ARCHITECTURE_ARM:
|
||||
return "arm", nil
|
||||
case PROCESSOR_ARCHITECTURE_ARM64:
|
||||
return "aarch64", nil
|
||||
case PROCESSOR_ARCHITECTURE_IA64:
|
||||
return "ia64", nil
|
||||
case PROCESSOR_ARCHITECTURE_AMD64:
|
||||
return "x86_64", nil
|
||||
}
|
||||
return "", nil
|
||||
}
|
||||
|
||||
25
vendor/github.com/shirou/gopsutil/host/types.go
generated
vendored
Normal file
25
vendor/github.com/shirou/gopsutil/host/types.go
generated
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
package host
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type Warnings struct {
|
||||
List []error
|
||||
}
|
||||
|
||||
func (w *Warnings) Add(err error) {
|
||||
w.List = append(w.List, err)
|
||||
}
|
||||
|
||||
func (w *Warnings) Reference() error {
|
||||
if len(w.List) > 0 {
|
||||
return w
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (w *Warnings) Error() string {
|
||||
return fmt.Sprintf("Number of warnings: %v", len(w.List))
|
||||
}
|
||||
17
vendor/github.com/shirou/gopsutil/host/types_darwin.go
generated
vendored
17
vendor/github.com/shirou/gopsutil/host/types_darwin.go
generated
vendored
@@ -1,17 +0,0 @@
|
||||
// +build ignore
|
||||
// plus hand editing about timeval
|
||||
|
||||
/*
|
||||
Input to cgo -godefs.
|
||||
*/
|
||||
|
||||
package host
|
||||
|
||||
/*
|
||||
#include <sys/time.h>
|
||||
#include <utmpx.h>
|
||||
*/
|
||||
import "C"
|
||||
|
||||
type Utmpx C.struct_utmpx
|
||||
type Timeval C.struct_timeval
|
||||
44
vendor/github.com/shirou/gopsutil/host/types_freebsd.go
generated
vendored
44
vendor/github.com/shirou/gopsutil/host/types_freebsd.go
generated
vendored
@@ -1,44 +0,0 @@
|
||||
// +build ignore
|
||||
|
||||
/*
|
||||
Input to cgo -godefs.
|
||||
*/
|
||||
|
||||
package host
|
||||
|
||||
/*
|
||||
#define KERNEL
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <utmpx.h>
|
||||
|
||||
enum {
|
||||
sizeofPtr = sizeof(void*),
|
||||
};
|
||||
|
||||
*/
|
||||
import "C"
|
||||
|
||||
// Machine characteristics; for internal use.
|
||||
|
||||
const (
|
||||
sizeofPtr = C.sizeofPtr
|
||||
sizeofShort = C.sizeof_short
|
||||
sizeofInt = C.sizeof_int
|
||||
sizeofLong = C.sizeof_long
|
||||
sizeofLongLong = C.sizeof_longlong
|
||||
sizeOfUtmpx = C.sizeof_struct_utmpx
|
||||
)
|
||||
|
||||
// Basic types
|
||||
|
||||
type (
|
||||
_C_short C.short
|
||||
_C_int C.int
|
||||
_C_long C.long
|
||||
_C_long_long C.longlong
|
||||
)
|
||||
|
||||
type Utmp C.struct_utmp
|
||||
type Utmpx C.struct_utmpx
|
||||
type Timeval C.struct_timeval
|
||||
42
vendor/github.com/shirou/gopsutil/host/types_linux.go
generated
vendored
42
vendor/github.com/shirou/gopsutil/host/types_linux.go
generated
vendored
@@ -1,42 +0,0 @@
|
||||
// +build ignore
|
||||
|
||||
/*
|
||||
Input to cgo -godefs.
|
||||
*/
|
||||
|
||||
package host
|
||||
|
||||
/*
|
||||
#include <sys/types.h>
|
||||
#include <utmp.h>
|
||||
|
||||
enum {
|
||||
sizeofPtr = sizeof(void*),
|
||||
};
|
||||
|
||||
*/
|
||||
import "C"
|
||||
|
||||
// Machine characteristics; for internal use.
|
||||
|
||||
const (
|
||||
sizeofPtr = C.sizeofPtr
|
||||
sizeofShort = C.sizeof_short
|
||||
sizeofInt = C.sizeof_int
|
||||
sizeofLong = C.sizeof_long
|
||||
sizeofLongLong = C.sizeof_longlong
|
||||
sizeOfUtmp = C.sizeof_struct_utmp
|
||||
)
|
||||
|
||||
// Basic types
|
||||
|
||||
type (
|
||||
_C_short C.short
|
||||
_C_int C.int
|
||||
_C_long C.long
|
||||
_C_long_long C.longlong
|
||||
)
|
||||
|
||||
type utmp C.struct_utmp
|
||||
type exit_status C.struct_exit_status
|
||||
type timeval C.struct_timeval
|
||||
43
vendor/github.com/shirou/gopsutil/host/types_openbsd.go
generated
vendored
43
vendor/github.com/shirou/gopsutil/host/types_openbsd.go
generated
vendored
@@ -1,43 +0,0 @@
|
||||
// +build ignore
|
||||
|
||||
/*
|
||||
Input to cgo -godefs.
|
||||
*/
|
||||
|
||||
package host
|
||||
|
||||
/*
|
||||
#define KERNEL
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <utmp.h>
|
||||
|
||||
enum {
|
||||
sizeofPtr = sizeof(void*),
|
||||
};
|
||||
|
||||
*/
|
||||
import "C"
|
||||
|
||||
// Machine characteristics; for internal use.
|
||||
|
||||
const (
|
||||
sizeofPtr = C.sizeofPtr
|
||||
sizeofShort = C.sizeof_short
|
||||
sizeofInt = C.sizeof_int
|
||||
sizeofLong = C.sizeof_long
|
||||
sizeofLongLong = C.sizeof_longlong
|
||||
sizeOfUtmp = C.sizeof_struct_utmp
|
||||
)
|
||||
|
||||
// Basic types
|
||||
|
||||
type (
|
||||
_C_short C.short
|
||||
_C_int C.int
|
||||
_C_long C.long
|
||||
_C_long_long C.longlong
|
||||
)
|
||||
|
||||
type Utmp C.struct_utmp
|
||||
type Timeval C.struct_timeval
|
||||
63
vendor/github.com/shirou/gopsutil/internal/common/common.go
generated
vendored
63
vendor/github.com/shirou/gopsutil/internal/common/common.go
generated
vendored
@@ -32,15 +32,19 @@ var (
|
||||
|
||||
type Invoker interface {
|
||||
Command(string, ...string) ([]byte, error)
|
||||
CommandWithContext(context.Context, string, ...string) ([]byte, error)
|
||||
}
|
||||
|
||||
type Invoke struct{}
|
||||
|
||||
func (i Invoke) Command(name string, arg ...string) ([]byte, error) {
|
||||
ctxt, cancel := context.WithTimeout(context.Background(), Timeout)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), Timeout)
|
||||
defer cancel()
|
||||
return i.CommandWithContext(ctx, name, arg...)
|
||||
}
|
||||
|
||||
cmd := exec.CommandContext(ctxt, name, arg...)
|
||||
func (i Invoke) CommandWithContext(ctx context.Context, name string, arg ...string) ([]byte, error) {
|
||||
cmd := exec.CommandContext(ctx, name, arg...)
|
||||
|
||||
var buf bytes.Buffer
|
||||
cmd.Stdout = &buf
|
||||
@@ -84,6 +88,10 @@ func (i FakeInvoke) Command(name string, arg ...string) ([]byte, error) {
|
||||
return []byte{}, fmt.Errorf("could not find testdata: %s", fpath)
|
||||
}
|
||||
|
||||
func (i FakeInvoke) CommandWithContext(ctx context.Context, name string, arg ...string) ([]byte, error) {
|
||||
return i.Command(name, arg...)
|
||||
}
|
||||
|
||||
var ErrNotImplementedError = errors.New("not implemented yet")
|
||||
|
||||
// ReadLines reads contents from a file and splits them by new lines.
|
||||
@@ -205,6 +213,12 @@ func ReadInts(filename string) ([]int64, error) {
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// Parse Hex to uint32 without error
|
||||
func HexToUint32(hex string) uint32 {
|
||||
vv, _ := strconv.ParseUint(hex, 16, 32)
|
||||
return uint32(vv)
|
||||
}
|
||||
|
||||
// Parse to int32 without error
|
||||
func mustParseInt32(val string) int32 {
|
||||
vv, _ := strconv.ParseInt(val, 10, 32)
|
||||
@@ -320,47 +334,12 @@ func HostVar(combineWith ...string) string {
|
||||
return GetEnv("HOST_VAR", "/var", combineWith...)
|
||||
}
|
||||
|
||||
// https://gist.github.com/kylelemons/1525278
|
||||
func Pipeline(cmds ...*exec.Cmd) ([]byte, []byte, error) {
|
||||
// Require at least one command
|
||||
if len(cmds) < 1 {
|
||||
return nil, nil, nil
|
||||
}
|
||||
func HostRun(combineWith ...string) string {
|
||||
return GetEnv("HOST_RUN", "/run", combineWith...)
|
||||
}
|
||||
|
||||
// Collect the output from the command(s)
|
||||
var output bytes.Buffer
|
||||
var stderr bytes.Buffer
|
||||
|
||||
last := len(cmds) - 1
|
||||
for i, cmd := range cmds[:last] {
|
||||
var err error
|
||||
// Connect each command's stdin to the previous command's stdout
|
||||
if cmds[i+1].Stdin, err = cmd.StdoutPipe(); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
// Connect each command's stderr to a buffer
|
||||
cmd.Stderr = &stderr
|
||||
}
|
||||
|
||||
// Connect the output and error for the last command
|
||||
cmds[last].Stdout, cmds[last].Stderr = &output, &stderr
|
||||
|
||||
// Start each command
|
||||
for _, cmd := range cmds {
|
||||
if err := cmd.Start(); err != nil {
|
||||
return output.Bytes(), stderr.Bytes(), err
|
||||
}
|
||||
}
|
||||
|
||||
// Wait for each command to complete
|
||||
for _, cmd := range cmds {
|
||||
if err := cmd.Wait(); err != nil {
|
||||
return output.Bytes(), stderr.Bytes(), err
|
||||
}
|
||||
}
|
||||
|
||||
// Return the pipeline output and the collected standard error
|
||||
return output.Bytes(), stderr.Bytes(), nil
|
||||
func HostDev(combineWith ...string) string {
|
||||
return GetEnv("HOST_DEV", "/dev", combineWith...)
|
||||
}
|
||||
|
||||
// getSysctrlEnv sets LC_ALL=C in a list of env vars for use when running
|
||||
|
||||
7
vendor/github.com/shirou/gopsutil/internal/common/common_darwin.go
generated
vendored
7
vendor/github.com/shirou/gopsutil/internal/common/common_darwin.go
generated
vendored
@@ -3,6 +3,7 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
@@ -11,12 +12,12 @@ import (
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func DoSysctrl(mib string) ([]string, error) {
|
||||
sysctl, err := exec.LookPath("/usr/sbin/sysctl")
|
||||
func DoSysctrlWithContext(ctx context.Context, mib string) ([]string, error) {
|
||||
sysctl, err := exec.LookPath("sysctl")
|
||||
if err != nil {
|
||||
return []string{}, err
|
||||
}
|
||||
cmd := exec.Command(sysctl, "-n", mib)
|
||||
cmd := exec.CommandContext(ctx, sysctl, "-n", mib)
|
||||
cmd.Env = getSysctrlEnv(os.Environ())
|
||||
out, err := cmd.Output()
|
||||
if err != nil {
|
||||
|
||||
18
vendor/github.com/shirou/gopsutil/internal/common/common_freebsd.go
generated
vendored
18
vendor/github.com/shirou/gopsutil/internal/common/common_freebsd.go
generated
vendored
@@ -3,6 +3,7 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
@@ -11,8 +12,23 @@ import (
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func SysctlUint(mib string) (uint64, error) {
|
||||
buf, err := unix.SysctlRaw(mib)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if len(buf) == 8 { // 64 bit
|
||||
return *(*uint64)(unsafe.Pointer(&buf[0])), nil
|
||||
}
|
||||
if len(buf) == 4 { // 32bit
|
||||
t := *(*uint32)(unsafe.Pointer(&buf[0]))
|
||||
return uint64(t), nil
|
||||
}
|
||||
return 0, fmt.Errorf("unexpected size: %s, %d", mib, len(buf))
|
||||
}
|
||||
|
||||
func DoSysctrl(mib string) ([]string, error) {
|
||||
sysctl, err := exec.LookPath("/sbin/sysctl")
|
||||
sysctl, err := exec.LookPath("sysctl")
|
||||
if err != nil {
|
||||
return []string{}, err
|
||||
}
|
||||
|
||||
227
vendor/github.com/shirou/gopsutil/internal/common/common_linux.go
generated
vendored
227
vendor/github.com/shirou/gopsutil/internal/common/common_linux.go
generated
vendored
@@ -3,13 +3,19 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
)
|
||||
|
||||
func DoSysctrl(mib string) ([]string, error) {
|
||||
sysctl, err := exec.LookPath("/sbin/sysctl")
|
||||
sysctl, err := exec.LookPath("sysctl")
|
||||
if err != nil {
|
||||
return []string{}, err
|
||||
}
|
||||
@@ -37,5 +43,222 @@ func NumProcs() (uint64, error) {
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return uint64(len(list)), err
|
||||
var cnt uint64
|
||||
|
||||
for _, v := range list {
|
||||
if _, err = strconv.ParseUint(v, 10, 64); err == nil {
|
||||
cnt++
|
||||
}
|
||||
}
|
||||
|
||||
return cnt, nil
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
system, role, err := Virtualization()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
statFile := "stat"
|
||||
if system == "lxc" && role == "guest" {
|
||||
// if lxc, /proc/uptime is used.
|
||||
statFile = "uptime"
|
||||
} else if system == "docker" && role == "guest" {
|
||||
// also docker, guest
|
||||
statFile = "uptime"
|
||||
}
|
||||
|
||||
filename := HostProc(statFile)
|
||||
lines, err := ReadLines(filename)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
if statFile == "stat" {
|
||||
for _, line := range lines {
|
||||
if strings.HasPrefix(line, "btime") {
|
||||
f := strings.Fields(line)
|
||||
if len(f) != 2 {
|
||||
return 0, fmt.Errorf("wrong btime format")
|
||||
}
|
||||
b, err := strconv.ParseInt(f[1], 10, 64)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
t = uint64(b)
|
||||
atomic.StoreUint64(&cachedBootTime, t)
|
||||
return t, nil
|
||||
}
|
||||
}
|
||||
} else if statFile == "uptime" {
|
||||
if len(lines) != 1 {
|
||||
return 0, fmt.Errorf("wrong uptime format")
|
||||
}
|
||||
f := strings.Fields(lines[0])
|
||||
b, err := strconv.ParseFloat(f[0], 64)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
t = uint64(time.Now().Unix()) - uint64(b)
|
||||
atomic.StoreUint64(&cachedBootTime, t)
|
||||
return t, nil
|
||||
}
|
||||
|
||||
return 0, fmt.Errorf("could not find btime")
|
||||
}
|
||||
|
||||
func Virtualization() (string, string, error) {
|
||||
return VirtualizationWithContext(context.Background())
|
||||
}
|
||||
|
||||
func VirtualizationWithContext(ctx context.Context) (string, string, error) {
|
||||
var system string
|
||||
var role string
|
||||
|
||||
filename := HostProc("xen")
|
||||
if PathExists(filename) {
|
||||
system = "xen"
|
||||
role = "guest" // assume guest
|
||||
|
||||
if PathExists(filepath.Join(filename, "capabilities")) {
|
||||
contents, err := ReadLines(filepath.Join(filename, "capabilities"))
|
||||
if err == nil {
|
||||
if StringsContains(contents, "control_d") {
|
||||
role = "host"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
filename = HostProc("modules")
|
||||
if PathExists(filename) {
|
||||
contents, err := ReadLines(filename)
|
||||
if err == nil {
|
||||
if StringsContains(contents, "kvm") {
|
||||
system = "kvm"
|
||||
role = "host"
|
||||
} else if StringsContains(contents, "vboxdrv") {
|
||||
system = "vbox"
|
||||
role = "host"
|
||||
} else if StringsContains(contents, "vboxguest") {
|
||||
system = "vbox"
|
||||
role = "guest"
|
||||
} else if StringsContains(contents, "vmware") {
|
||||
system = "vmware"
|
||||
role = "guest"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
filename = HostProc("cpuinfo")
|
||||
if PathExists(filename) {
|
||||
contents, err := ReadLines(filename)
|
||||
if err == nil {
|
||||
if StringsContains(contents, "QEMU Virtual CPU") ||
|
||||
StringsContains(contents, "Common KVM processor") ||
|
||||
StringsContains(contents, "Common 32-bit KVM processor") {
|
||||
system = "kvm"
|
||||
role = "guest"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
filename = HostProc("bus/pci/devices")
|
||||
if PathExists(filename) {
|
||||
contents, err := ReadLines(filename)
|
||||
if err == nil {
|
||||
if StringsContains(contents, "virtio-pci") {
|
||||
role = "guest"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
filename = HostProc()
|
||||
if PathExists(filepath.Join(filename, "bc", "0")) {
|
||||
system = "openvz"
|
||||
role = "host"
|
||||
} else if PathExists(filepath.Join(filename, "vz")) {
|
||||
system = "openvz"
|
||||
role = "guest"
|
||||
}
|
||||
|
||||
// not use dmidecode because it requires root
|
||||
if PathExists(filepath.Join(filename, "self", "status")) {
|
||||
contents, err := ReadLines(filepath.Join(filename, "self", "status"))
|
||||
if err == nil {
|
||||
|
||||
if StringsContains(contents, "s_context:") ||
|
||||
StringsContains(contents, "VxID:") {
|
||||
system = "linux-vserver"
|
||||
}
|
||||
// TODO: guest or host
|
||||
}
|
||||
}
|
||||
|
||||
if PathExists(filepath.Join(filename, "self", "cgroup")) {
|
||||
contents, err := ReadLines(filepath.Join(filename, "self", "cgroup"))
|
||||
if err == nil {
|
||||
if StringsContains(contents, "lxc") {
|
||||
system = "lxc"
|
||||
role = "guest"
|
||||
} else if StringsContains(contents, "docker") {
|
||||
system = "docker"
|
||||
role = "guest"
|
||||
} else if StringsContains(contents, "machine-rkt") {
|
||||
system = "rkt"
|
||||
role = "guest"
|
||||
} else if PathExists("/usr/bin/lxc-version") {
|
||||
system = "lxc"
|
||||
role = "host"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if PathExists(HostEtc("os-release")) {
|
||||
p, _, err := GetOSRelease()
|
||||
if err == nil && p == "coreos" {
|
||||
system = "rkt" // Is it true?
|
||||
role = "host"
|
||||
}
|
||||
}
|
||||
return system, role, nil
|
||||
}
|
||||
|
||||
func GetOSRelease() (platform string, version string, err error) {
|
||||
contents, err := ReadLines(HostEtc("os-release"))
|
||||
if err != nil {
|
||||
return "", "", nil // return empty
|
||||
}
|
||||
for _, line := range contents {
|
||||
field := strings.Split(line, "=")
|
||||
if len(field) < 2 {
|
||||
continue
|
||||
}
|
||||
switch field[0] {
|
||||
case "ID": // use ID for lowercase
|
||||
platform = trimQuotes(field[1])
|
||||
case "VERSION":
|
||||
version = trimQuotes(field[1])
|
||||
}
|
||||
}
|
||||
return platform, version, nil
|
||||
}
|
||||
|
||||
// Remove quotes of the source string
|
||||
func trimQuotes(s string) string {
|
||||
if len(s) >= 2 {
|
||||
if s[0] == '"' && s[len(s)-1] == '"' {
|
||||
return s[1 : len(s)-1]
|
||||
}
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
2
vendor/github.com/shirou/gopsutil/internal/common/common_openbsd.go
generated
vendored
2
vendor/github.com/shirou/gopsutil/internal/common/common_openbsd.go
generated
vendored
@@ -12,7 +12,7 @@ import (
|
||||
)
|
||||
|
||||
func DoSysctrl(mib string) ([]string, error) {
|
||||
sysctl, err := exec.LookPath("/sbin/sysctl")
|
||||
sysctl, err := exec.LookPath("sysctl")
|
||||
if err != nil {
|
||||
return []string{}, err
|
||||
}
|
||||
|
||||
133
vendor/github.com/shirou/gopsutil/internal/common/common_test.go
generated
vendored
133
vendor/github.com/shirou/gopsutil/internal/common/common_test.go
generated
vendored
@@ -1,133 +0,0 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestReadlines(t *testing.T) {
|
||||
ret, err := ReadLines("common_test.go")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if !strings.Contains(ret[0], "package common") {
|
||||
t.Error("could not read correctly")
|
||||
}
|
||||
}
|
||||
|
||||
func TestReadLinesOffsetN(t *testing.T) {
|
||||
ret, err := ReadLinesOffsetN("common_test.go", 2, 1)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
fmt.Println(ret[0])
|
||||
if !strings.Contains(ret[0], `import (`) {
|
||||
t.Error("could not read correctly")
|
||||
}
|
||||
}
|
||||
|
||||
func TestIntToString(t *testing.T) {
|
||||
src := []int8{65, 66, 67}
|
||||
dst := IntToString(src)
|
||||
if dst != "ABC" {
|
||||
t.Error("could not convert")
|
||||
}
|
||||
}
|
||||
func TestByteToString(t *testing.T) {
|
||||
src := []byte{65, 66, 67}
|
||||
dst := ByteToString(src)
|
||||
if dst != "ABC" {
|
||||
t.Error("could not convert")
|
||||
}
|
||||
|
||||
src = []byte{0, 65, 66, 67}
|
||||
dst = ByteToString(src)
|
||||
if dst != "ABC" {
|
||||
t.Error("could not convert")
|
||||
}
|
||||
}
|
||||
|
||||
func TestmustParseInt32(t *testing.T) {
|
||||
ret := mustParseInt32("11111")
|
||||
if ret != int32(11111) {
|
||||
t.Error("could not parse")
|
||||
}
|
||||
}
|
||||
func TestmustParseUint64(t *testing.T) {
|
||||
ret := mustParseUint64("11111")
|
||||
if ret != uint64(11111) {
|
||||
t.Error("could not parse")
|
||||
}
|
||||
}
|
||||
func TestmustParseFloat64(t *testing.T) {
|
||||
ret := mustParseFloat64("11111.11")
|
||||
if ret != float64(11111.11) {
|
||||
t.Error("could not parse")
|
||||
}
|
||||
ret = mustParseFloat64("11111")
|
||||
if ret != float64(11111) {
|
||||
t.Error("could not parse")
|
||||
}
|
||||
}
|
||||
func TestStringsContains(t *testing.T) {
|
||||
target, err := ReadLines("common_test.go")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if !StringsContains(target, "func TestStringsContains(t *testing.T) {") {
|
||||
t.Error("cloud not test correctly")
|
||||
}
|
||||
}
|
||||
|
||||
func TestPathExists(t *testing.T) {
|
||||
if !PathExists("common_test.go") {
|
||||
t.Error("exists but return not exists")
|
||||
}
|
||||
if PathExists("should_not_exists.go") {
|
||||
t.Error("not exists but return exists")
|
||||
}
|
||||
}
|
||||
|
||||
func TestHostEtc(t *testing.T) {
|
||||
if runtime.GOOS == "windows" {
|
||||
t.Skip("windows doesn't have etc")
|
||||
}
|
||||
p := HostEtc("mtab")
|
||||
if p != "/etc/mtab" {
|
||||
t.Errorf("invalid HostEtc, %s", p)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetSysctrlEnv(t *testing.T) {
|
||||
// Append case
|
||||
env := getSysctrlEnv([]string{"FOO=bar"})
|
||||
if !reflect.DeepEqual(env, []string{"FOO=bar", "LC_ALL=C"}) {
|
||||
t.Errorf("unexpected append result from getSysctrlEnv: %q", env)
|
||||
}
|
||||
|
||||
// Replace case
|
||||
env = getSysctrlEnv([]string{"FOO=bar", "LC_ALL=en_US.UTF-8"})
|
||||
if !reflect.DeepEqual(env, []string{"FOO=bar", "LC_ALL=C"}) {
|
||||
t.Errorf("unexpected replace result from getSysctrlEnv: %q", env)
|
||||
}
|
||||
|
||||
// Test against real env
|
||||
env = getSysctrlEnv(os.Environ())
|
||||
found := false
|
||||
for _, v := range env {
|
||||
if v == "LC_ALL=C" {
|
||||
found = true
|
||||
continue
|
||||
}
|
||||
if strings.HasPrefix(v, "LC_ALL") {
|
||||
t.Fatalf("unexpected LC_ALL value: %q", v)
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
t.Errorf("unexpected real result from getSysctrlEnv: %q", env)
|
||||
}
|
||||
}
|
||||
11
vendor/github.com/shirou/gopsutil/internal/common/common_unix.go
generated
vendored
11
vendor/github.com/shirou/gopsutil/internal/common/common_unix.go
generated
vendored
@@ -3,12 +3,13 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func CallLsof(invoke Invoker, pid int32, args ...string) ([]string, error) {
|
||||
func CallLsofWithContext(ctx context.Context, invoke Invoker, pid int32, args ...string) ([]string, error) {
|
||||
var cmd []string
|
||||
if pid == 0 { // will get from all processes.
|
||||
cmd = []string{"-a", "-n", "-P"}
|
||||
@@ -20,9 +21,9 @@ func CallLsof(invoke Invoker, pid int32, args ...string) ([]string, error) {
|
||||
if err != nil {
|
||||
return []string{}, err
|
||||
}
|
||||
out, err := invoke.Command(lsof, cmd...)
|
||||
out, err := invoke.CommandWithContext(ctx, lsof, cmd...)
|
||||
if err != nil {
|
||||
// if no pid found, lsof returnes code 1.
|
||||
// if no pid found, lsof returns code 1.
|
||||
if err.Error() == "exit status 1" && len(out) == 0 {
|
||||
return []string{}, nil
|
||||
}
|
||||
@@ -39,14 +40,14 @@ func CallLsof(invoke Invoker, pid int32, args ...string) ([]string, error) {
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func CallPgrep(invoke Invoker, pid int32) ([]int32, error) {
|
||||
func CallPgrepWithContext(ctx context.Context, invoke Invoker, pid int32) ([]int32, error) {
|
||||
var cmd []string
|
||||
cmd = []string{"-P", strconv.Itoa(int(pid))}
|
||||
pgrep, err := exec.LookPath("pgrep")
|
||||
if err != nil {
|
||||
return []int32{}, err
|
||||
}
|
||||
out, err := invoke.Command(pgrep, cmd...)
|
||||
out, err := invoke.CommandWithContext(ctx, pgrep, cmd...)
|
||||
if err != nil {
|
||||
return []int32{}, err
|
||||
}
|
||||
|
||||
33
vendor/github.com/shirou/gopsutil/internal/common/common_windows.go
generated
vendored
33
vendor/github.com/shirou/gopsutil/internal/common/common_windows.go
generated
vendored
@@ -4,6 +4,9 @@ package common
|
||||
|
||||
import (
|
||||
"context"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"github.com/StackExchange/wmi"
|
||||
@@ -47,10 +50,10 @@ const (
|
||||
)
|
||||
|
||||
var (
|
||||
Modkernel32 = windows.NewLazyDLL("kernel32.dll")
|
||||
ModNt = windows.NewLazyDLL("ntdll.dll")
|
||||
ModPdh = windows.NewLazyDLL("pdh.dll")
|
||||
ModPsapi = windows.NewLazyDLL("psapi.dll")
|
||||
Modkernel32 = windows.NewLazySystemDLL("kernel32.dll")
|
||||
ModNt = windows.NewLazySystemDLL("ntdll.dll")
|
||||
ModPdh = windows.NewLazySystemDLL("pdh.dll")
|
||||
ModPsapi = windows.NewLazySystemDLL("psapi.dll")
|
||||
|
||||
ProcGetSystemTimes = Modkernel32.NewProc("GetSystemTimes")
|
||||
ProcNtQuerySystemInformation = ModNt.NewProc("NtQuerySystemInformation")
|
||||
@@ -59,6 +62,8 @@ var (
|
||||
PdhCollectQueryData = ModPdh.NewProc("PdhCollectQueryData")
|
||||
PdhGetFormattedCounterValue = ModPdh.NewProc("PdhGetFormattedCounterValue")
|
||||
PdhCloseQuery = ModPdh.NewProc("PdhCloseQuery")
|
||||
|
||||
procQueryDosDeviceW = Modkernel32.NewProc("QueryDosDeviceW")
|
||||
)
|
||||
|
||||
type FILETIME struct {
|
||||
@@ -133,3 +138,23 @@ func WMIQueryWithContext(ctx context.Context, query string, dst interface{}, con
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Convert paths using native DOS format like:
|
||||
// "\Device\HarddiskVolume1\Windows\systemew\file.txt"
|
||||
// into:
|
||||
// "C:\Windows\systemew\file.txt"
|
||||
func ConvertDOSPath(p string) string {
|
||||
rawDrive := strings.Join(strings.Split(p, `\`)[:3], `\`)
|
||||
|
||||
for d := 'A'; d <= 'Z'; d++ {
|
||||
szDeviceName := string(d) + ":"
|
||||
szTarget := make([]uint16, 512)
|
||||
ret, _, _ := procQueryDosDeviceW.Call(uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(szDeviceName))),
|
||||
uintptr(unsafe.Pointer(&szTarget[0])),
|
||||
uintptr(len(szTarget)))
|
||||
if ret != 0 && windows.UTF16ToString(szTarget[:]) == rawDrive {
|
||||
return filepath.Join(szDeviceName, p[len(rawDrive):])
|
||||
}
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
49
vendor/github.com/shirou/gopsutil/mem/mem.go
generated
vendored
49
vendor/github.com/shirou/gopsutil/mem/mem.go
generated
vendored
@@ -6,11 +6,7 @@ import (
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
)
|
||||
|
||||
var invoke common.Invoker
|
||||
|
||||
func init() {
|
||||
invoke = common.Invoke{}
|
||||
}
|
||||
var invoke common.Invoker = common.Invoke{}
|
||||
|
||||
// Memory usage statistics. Total, Available and Used contain numbers of bytes
|
||||
// for human consumption.
|
||||
@@ -46,18 +42,40 @@ type VirtualMemoryStat struct {
|
||||
Inactive uint64 `json:"inactive"`
|
||||
Wired uint64 `json:"wired"`
|
||||
|
||||
// FreeBSD specific numbers:
|
||||
// https://reviews.freebsd.org/D8467
|
||||
Laundry uint64 `json:"laundry"`
|
||||
|
||||
// Linux specific numbers
|
||||
// https://www.centos.org/docs/5/html/5.1/Deployment_Guide/s2-proc-meminfo.html
|
||||
// https://www.kernel.org/doc/Documentation/filesystems/proc.txt
|
||||
Buffers uint64 `json:"buffers"`
|
||||
Cached uint64 `json:"cached"`
|
||||
Writeback uint64 `json:"writeback"`
|
||||
Dirty uint64 `json:"dirty"`
|
||||
WritebackTmp uint64 `json:"writebacktmp"`
|
||||
Shared uint64 `json:"shared"`
|
||||
Slab uint64 `json:"slab"`
|
||||
PageTables uint64 `json:"pagetables"`
|
||||
SwapCached uint64 `json:"swapcached"`
|
||||
// https://www.kernel.org/doc/Documentation/vm/overcommit-accounting
|
||||
Buffers uint64 `json:"buffers"`
|
||||
Cached uint64 `json:"cached"`
|
||||
Writeback uint64 `json:"writeback"`
|
||||
Dirty uint64 `json:"dirty"`
|
||||
WritebackTmp uint64 `json:"writebacktmp"`
|
||||
Shared uint64 `json:"shared"`
|
||||
Slab uint64 `json:"slab"`
|
||||
SReclaimable uint64 `json:"sreclaimable"`
|
||||
SUnreclaim uint64 `json:"sunreclaim"`
|
||||
PageTables uint64 `json:"pagetables"`
|
||||
SwapCached uint64 `json:"swapcached"`
|
||||
CommitLimit uint64 `json:"commitlimit"`
|
||||
CommittedAS uint64 `json:"committedas"`
|
||||
HighTotal uint64 `json:"hightotal"`
|
||||
HighFree uint64 `json:"highfree"`
|
||||
LowTotal uint64 `json:"lowtotal"`
|
||||
LowFree uint64 `json:"lowfree"`
|
||||
SwapTotal uint64 `json:"swaptotal"`
|
||||
SwapFree uint64 `json:"swapfree"`
|
||||
Mapped uint64 `json:"mapped"`
|
||||
VMallocTotal uint64 `json:"vmalloctotal"`
|
||||
VMallocUsed uint64 `json:"vmallocused"`
|
||||
VMallocChunk uint64 `json:"vmallocchunk"`
|
||||
HugePagesTotal uint64 `json:"hugepagestotal"`
|
||||
HugePagesFree uint64 `json:"hugepagesfree"`
|
||||
HugePageSize uint64 `json:"hugepagesize"`
|
||||
}
|
||||
|
||||
type SwapMemoryStat struct {
|
||||
@@ -67,6 +85,9 @@ type SwapMemoryStat struct {
|
||||
UsedPercent float64 `json:"usedPercent"`
|
||||
Sin uint64 `json:"sin"`
|
||||
Sout uint64 `json:"sout"`
|
||||
PgIn uint64 `json:"pgin"`
|
||||
PgOut uint64 `json:"pgout"`
|
||||
PgFault uint64 `json:"pgfault"`
|
||||
}
|
||||
|
||||
func (m VirtualMemoryStat) String() string {
|
||||
|
||||
47
vendor/github.com/shirou/gopsutil/mem/mem_darwin.go
generated
vendored
47
vendor/github.com/shirou/gopsutil/mem/mem_darwin.go
generated
vendored
@@ -5,10 +5,9 @@ package mem
|
||||
import (
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"strconv"
|
||||
"strings"
|
||||
"fmt"
|
||||
"unsafe"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
@@ -27,46 +26,42 @@ func getHwMemsize() (uint64, error) {
|
||||
return total, nil
|
||||
}
|
||||
|
||||
// xsw_usage in sys/sysctl.h
|
||||
type swapUsage struct {
|
||||
Total uint64
|
||||
Avail uint64
|
||||
Used uint64
|
||||
Pagesize int32
|
||||
Encrypted bool
|
||||
}
|
||||
|
||||
// SwapMemory returns swapinfo.
|
||||
func SwapMemory() (*SwapMemoryStat, error) {
|
||||
return SwapMemoryWithContext(context.Background())
|
||||
}
|
||||
|
||||
func SwapMemoryWithContext(ctx context.Context) (*SwapMemoryStat, error) {
|
||||
// https://github.com/yanllearnn/go-osstat/blob/ae8a279d26f52ec946a03698c7f50a26cfb427e3/memory/memory_darwin.go
|
||||
var ret *SwapMemoryStat
|
||||
|
||||
swapUsage, err := common.DoSysctrl("vm.swapusage")
|
||||
value, err := unix.SysctlRaw("vm.swapusage")
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
|
||||
total := strings.Replace(swapUsage[2], "M", "", 1)
|
||||
used := strings.Replace(swapUsage[5], "M", "", 1)
|
||||
free := strings.Replace(swapUsage[8], "M", "", 1)
|
||||
|
||||
total_v, err := strconv.ParseFloat(total, 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
used_v, err := strconv.ParseFloat(used, 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
free_v, err := strconv.ParseFloat(free, 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
if len(value) != 32 {
|
||||
return ret, fmt.Errorf("unexpected output of sysctl vm.swapusage: %v (len: %d)", value, len(value))
|
||||
}
|
||||
swap := (*swapUsage)(unsafe.Pointer(&value[0]))
|
||||
|
||||
u := float64(0)
|
||||
if total_v != 0 {
|
||||
u = ((total_v - free_v) / total_v) * 100.0
|
||||
if swap.Total != 0 {
|
||||
u = ((float64(swap.Total) - float64(swap.Avail)) / float64(swap.Total)) * 100.0
|
||||
}
|
||||
|
||||
// vm.swapusage shows "M", multiply 1024 * 1024 to convert bytes.
|
||||
ret = &SwapMemoryStat{
|
||||
Total: uint64(total_v * 1024 * 1024),
|
||||
Used: uint64(used_v * 1024 * 1024),
|
||||
Free: uint64(free_v * 1024 * 1024),
|
||||
Total: swap.Total,
|
||||
Used: swap.Used,
|
||||
Free: swap.Avail,
|
||||
UsedPercent: u,
|
||||
}
|
||||
|
||||
|
||||
46
vendor/github.com/shirou/gopsutil/mem/mem_darwin_test.go
generated
vendored
46
vendor/github.com/shirou/gopsutil/mem/mem_darwin_test.go
generated
vendored
@@ -1,46 +0,0 @@
|
||||
// +build darwin
|
||||
|
||||
package mem
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestVirtualMemoryDarwin(t *testing.T) {
|
||||
v, err := VirtualMemory()
|
||||
assert.Nil(t, err)
|
||||
|
||||
outBytes, err := invoke.Command("/usr/sbin/sysctl", "hw.memsize")
|
||||
assert.Nil(t, err)
|
||||
outString := string(outBytes)
|
||||
outString = strings.TrimSpace(outString)
|
||||
outParts := strings.Split(outString, " ")
|
||||
actualTotal, err := strconv.ParseInt(outParts[1], 10, 64)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, uint64(actualTotal), v.Total)
|
||||
|
||||
assert.True(t, v.Available > 0)
|
||||
assert.Equal(t, v.Available, v.Free+v.Inactive, "%v", v)
|
||||
|
||||
assert.True(t, v.Used > 0)
|
||||
assert.True(t, v.Used < v.Total)
|
||||
|
||||
assert.True(t, v.UsedPercent > 0)
|
||||
assert.True(t, v.UsedPercent < 100)
|
||||
|
||||
assert.True(t, v.Free > 0)
|
||||
assert.True(t, v.Free < v.Available)
|
||||
|
||||
assert.True(t, v.Active > 0)
|
||||
assert.True(t, v.Active < v.Total)
|
||||
|
||||
assert.True(t, v.Inactive > 0)
|
||||
assert.True(t, v.Inactive < v.Total)
|
||||
|
||||
assert.True(t, v.Wired > 0)
|
||||
assert.True(t, v.Wired < v.Total)
|
||||
}
|
||||
210
vendor/github.com/shirou/gopsutil/mem/mem_freebsd.go
generated
vendored
210
vendor/github.com/shirou/gopsutil/mem/mem_freebsd.go
generated
vendored
@@ -5,11 +5,11 @@ package mem
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
)
|
||||
|
||||
func VirtualMemory() (*VirtualMemoryStat, error) {
|
||||
@@ -17,51 +17,62 @@ func VirtualMemory() (*VirtualMemoryStat, error) {
|
||||
}
|
||||
|
||||
func VirtualMemoryWithContext(ctx context.Context) (*VirtualMemoryStat, error) {
|
||||
pageSize, err := unix.SysctlUint32("vm.stats.vm.v_page_size")
|
||||
pageSize, err := common.SysctlUint("vm.stats.vm.v_page_size")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pageCount, err := unix.SysctlUint32("vm.stats.vm.v_page_count")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
free, err := unix.SysctlUint32("vm.stats.vm.v_free_count")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
active, err := unix.SysctlUint32("vm.stats.vm.v_active_count")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
inactive, err := unix.SysctlUint32("vm.stats.vm.v_inactive_count")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cached, err := unix.SysctlUint32("vm.stats.vm.v_cache_count")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
buffers, err := unix.SysctlUint32("vfs.bufspace")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
wired, err := unix.SysctlUint32("vm.stats.vm.v_wire_count")
|
||||
physmem, err := common.SysctlUint("hw.physmem")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
p := uint64(pageSize)
|
||||
free, err := common.SysctlUint("vm.stats.vm.v_free_count")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
active, err := common.SysctlUint("vm.stats.vm.v_active_count")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
inactive, err := common.SysctlUint("vm.stats.vm.v_inactive_count")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
buffers, err := common.SysctlUint("vfs.bufspace")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
wired, err := common.SysctlUint("vm.stats.vm.v_wire_count")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var cached, laundry uint64
|
||||
osreldate, _ := common.SysctlUint("kern.osreldate")
|
||||
if osreldate < 1102000 {
|
||||
cached, err = common.SysctlUint("vm.stats.vm.v_cache_count")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
laundry, err = common.SysctlUint("vm.stats.vm.v_laundry_count")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
p := pageSize
|
||||
ret := &VirtualMemoryStat{
|
||||
Total: uint64(pageCount) * p,
|
||||
Free: uint64(free) * p,
|
||||
Active: uint64(active) * p,
|
||||
Inactive: uint64(inactive) * p,
|
||||
Cached: uint64(cached) * p,
|
||||
Buffers: uint64(buffers),
|
||||
Wired: uint64(wired) * p,
|
||||
Total: physmem,
|
||||
Free: free * p,
|
||||
Active: active * p,
|
||||
Inactive: inactive * p,
|
||||
Cached: cached * p,
|
||||
Buffers: buffers,
|
||||
Wired: wired * p,
|
||||
Laundry: laundry * p,
|
||||
}
|
||||
|
||||
ret.Available = ret.Inactive + ret.Cached + ret.Free
|
||||
ret.Available = ret.Inactive + ret.Cached + ret.Free + ret.Laundry
|
||||
ret.Used = ret.Total - ret.Available
|
||||
ret.UsedPercent = float64(ret.Used) / float64(ret.Total) * 100.0
|
||||
|
||||
@@ -69,53 +80,88 @@ func VirtualMemoryWithContext(ctx context.Context) (*VirtualMemoryStat, error) {
|
||||
}
|
||||
|
||||
// Return swapinfo
|
||||
// FreeBSD can have multiple swap devices. but use only first device
|
||||
func SwapMemory() (*SwapMemoryStat, error) {
|
||||
return SwapMemoryWithContext(context.Background())
|
||||
}
|
||||
|
||||
func SwapMemoryWithContext(ctx context.Context) (*SwapMemoryStat, error) {
|
||||
swapinfo, err := exec.LookPath("swapinfo")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Constants from vm/vm_param.h
|
||||
// nolint: golint
|
||||
const (
|
||||
XSWDEV_VERSION11 = 1
|
||||
XSWDEV_VERSION = 2
|
||||
)
|
||||
|
||||
out, err := invoke.Command(swapinfo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, line := range strings.Split(string(out), "\n") {
|
||||
values := strings.Fields(line)
|
||||
// skip title line
|
||||
if len(values) == 0 || values[0] == "Device" {
|
||||
continue
|
||||
}
|
||||
|
||||
u := strings.Replace(values[4], "%", "", 1)
|
||||
total_v, err := strconv.ParseUint(values[1], 10, 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
used_v, err := strconv.ParseUint(values[2], 10, 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
free_v, err := strconv.ParseUint(values[3], 10, 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
up_v, err := strconv.ParseFloat(u, 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &SwapMemoryStat{
|
||||
Total: total_v,
|
||||
Used: used_v,
|
||||
Free: free_v,
|
||||
UsedPercent: up_v,
|
||||
}, nil
|
||||
}
|
||||
|
||||
return nil, errors.New("no swap devices found")
|
||||
// Types from vm/vm_param.h
|
||||
type xswdev struct {
|
||||
Version uint32 // Version is the version
|
||||
Dev uint64 // Dev is the device identifier
|
||||
Flags int32 // Flags is the swap flags applied to the device
|
||||
NBlks int32 // NBlks is the total number of blocks
|
||||
Used int32 // Used is the number of blocks used
|
||||
}
|
||||
|
||||
// xswdev11 is a compatibility for under FreeBSD 11
|
||||
// sys/vm/swap_pager.c
|
||||
type xswdev11 struct {
|
||||
Version uint32 // Version is the version
|
||||
Dev uint32 // Dev is the device identifier
|
||||
Flags int32 // Flags is the swap flags applied to the device
|
||||
NBlks int32 // NBlks is the total number of blocks
|
||||
Used int32 // Used is the number of blocks used
|
||||
}
|
||||
|
||||
func SwapMemoryWithContext(ctx context.Context) (*SwapMemoryStat, error) {
|
||||
// FreeBSD can have multiple swap devices so we total them up
|
||||
i, err := common.SysctlUint("vm.nswapdev")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if i == 0 {
|
||||
return nil, errors.New("no swap devices found")
|
||||
}
|
||||
|
||||
c := int(i)
|
||||
|
||||
i, err = common.SysctlUint("vm.stats.vm.v_page_size")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pageSize := i
|
||||
|
||||
var buf []byte
|
||||
s := &SwapMemoryStat{}
|
||||
for n := 0; n < c; n++ {
|
||||
buf, err = unix.SysctlRaw("vm.swap_info", n)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// first, try to parse with version 2
|
||||
xsw := (*xswdev)(unsafe.Pointer(&buf[0]))
|
||||
if xsw.Version == XSWDEV_VERSION11 {
|
||||
// this is version 1, so try to parse again
|
||||
xsw := (*xswdev11)(unsafe.Pointer(&buf[0]))
|
||||
if xsw.Version != XSWDEV_VERSION11 {
|
||||
return nil, errors.New("xswdev version mismatch(11)")
|
||||
}
|
||||
s.Total += uint64(xsw.NBlks)
|
||||
s.Used += uint64(xsw.Used)
|
||||
} else if xsw.Version != XSWDEV_VERSION {
|
||||
return nil, errors.New("xswdev version mismatch")
|
||||
} else {
|
||||
s.Total += uint64(xsw.NBlks)
|
||||
s.Used += uint64(xsw.Used)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if s.Total != 0 {
|
||||
s.UsedPercent = float64(s.Used) / float64(s.Total) * 100
|
||||
}
|
||||
s.Total *= pageSize
|
||||
s.Used *= pageSize
|
||||
s.Free = s.Total - s.Used
|
||||
|
||||
return s, nil
|
||||
}
|
||||
|
||||
173
vendor/github.com/shirou/gopsutil/mem/mem_linux.go
generated
vendored
173
vendor/github.com/shirou/gopsutil/mem/mem_linux.go
generated
vendored
@@ -4,6 +4,9 @@ package mem
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"math"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
@@ -11,17 +14,56 @@ import (
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
type VirtualMemoryExStat struct {
|
||||
ActiveFile uint64 `json:"activefile"`
|
||||
InactiveFile uint64 `json:"inactivefile"`
|
||||
ActiveAnon uint64 `json:"activeanon"`
|
||||
InactiveAnon uint64 `json:"inactiveanon"`
|
||||
Unevictable uint64 `json:"unevictable"`
|
||||
}
|
||||
|
||||
func (v VirtualMemoryExStat) String() string {
|
||||
s, _ := json.Marshal(v)
|
||||
return string(s)
|
||||
}
|
||||
|
||||
func VirtualMemory() (*VirtualMemoryStat, error) {
|
||||
return VirtualMemoryWithContext(context.Background())
|
||||
}
|
||||
|
||||
func VirtualMemoryWithContext(ctx context.Context) (*VirtualMemoryStat, error) {
|
||||
vm, _, err := fillFromMeminfoWithContext(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return vm, nil
|
||||
}
|
||||
|
||||
func VirtualMemoryEx() (*VirtualMemoryExStat, error) {
|
||||
return VirtualMemoryExWithContext(context.Background())
|
||||
}
|
||||
|
||||
func VirtualMemoryExWithContext(ctx context.Context) (*VirtualMemoryExStat, error) {
|
||||
_, vmEx, err := fillFromMeminfoWithContext(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return vmEx, nil
|
||||
}
|
||||
|
||||
func fillFromMeminfoWithContext(ctx context.Context) (*VirtualMemoryStat, *VirtualMemoryExStat, error) {
|
||||
filename := common.HostProc("meminfo")
|
||||
lines, _ := common.ReadLines(filename)
|
||||
|
||||
// flag if MemAvailable is in /proc/meminfo (kernel 3.14+)
|
||||
memavail := false
|
||||
activeFile := false // "Active(file)" not available: 2.6.28 / Dec 2008
|
||||
inactiveFile := false // "Inactive(file)" not available: 2.6.28 / Dec 2008
|
||||
sReclaimable := false // "SReclaimable:" not available: 2.6.19 / Nov 2006
|
||||
|
||||
ret := &VirtualMemoryStat{}
|
||||
retEx := &VirtualMemoryExStat{}
|
||||
|
||||
for _, line := range lines {
|
||||
fields := strings.Split(line, ":")
|
||||
if len(fields) != 2 {
|
||||
@@ -33,7 +75,7 @@ func VirtualMemoryWithContext(ctx context.Context) (*VirtualMemoryStat, error) {
|
||||
|
||||
t, err := strconv.ParseUint(value, 10, 64)
|
||||
if err != nil {
|
||||
return ret, err
|
||||
return ret, retEx,err
|
||||
}
|
||||
switch key {
|
||||
case "MemTotal":
|
||||
@@ -51,6 +93,18 @@ func VirtualMemoryWithContext(ctx context.Context) (*VirtualMemoryStat, error) {
|
||||
ret.Active = t * 1024
|
||||
case "Inactive":
|
||||
ret.Inactive = t * 1024
|
||||
case "Active(anon)":
|
||||
retEx.ActiveAnon = t * 1024
|
||||
case "Inactive(anon)":
|
||||
retEx.InactiveAnon = t * 1024
|
||||
case "Active(file)":
|
||||
activeFile = true
|
||||
retEx.ActiveFile = t * 1024
|
||||
case "Inactive(file)":
|
||||
inactiveFile = true
|
||||
retEx.InactiveFile = t * 1024
|
||||
case "Unevictable":
|
||||
retEx.Unevictable = t * 1024
|
||||
case "Writeback":
|
||||
ret.Writeback = t * 1024
|
||||
case "WritebackTmp":
|
||||
@@ -61,19 +115,62 @@ func VirtualMemoryWithContext(ctx context.Context) (*VirtualMemoryStat, error) {
|
||||
ret.Shared = t * 1024
|
||||
case "Slab":
|
||||
ret.Slab = t * 1024
|
||||
case "SReclaimable":
|
||||
sReclaimable = true
|
||||
ret.SReclaimable = t * 1024
|
||||
case "SUnreclaim":
|
||||
ret.SUnreclaim = t * 1024
|
||||
case "PageTables":
|
||||
ret.PageTables = t * 1024
|
||||
case "SwapCached":
|
||||
ret.SwapCached = t * 1024
|
||||
case "CommitLimit":
|
||||
ret.CommitLimit = t * 1024
|
||||
case "Committed_AS":
|
||||
ret.CommittedAS = t * 1024
|
||||
case "HighTotal":
|
||||
ret.HighTotal = t * 1024
|
||||
case "HighFree":
|
||||
ret.HighFree = t * 1024
|
||||
case "LowTotal":
|
||||
ret.LowTotal = t * 1024
|
||||
case "LowFree":
|
||||
ret.LowFree = t * 1024
|
||||
case "SwapTotal":
|
||||
ret.SwapTotal = t * 1024
|
||||
case "SwapFree":
|
||||
ret.SwapFree = t * 1024
|
||||
case "Mapped":
|
||||
ret.Mapped = t * 1024
|
||||
case "VmallocTotal":
|
||||
ret.VMallocTotal = t * 1024
|
||||
case "VmallocUsed":
|
||||
ret.VMallocUsed = t * 1024
|
||||
case "VmallocChunk":
|
||||
ret.VMallocChunk = t * 1024
|
||||
case "HugePages_Total":
|
||||
ret.HugePagesTotal = t
|
||||
case "HugePages_Free":
|
||||
ret.HugePagesFree = t
|
||||
case "Hugepagesize":
|
||||
ret.HugePageSize = t * 1024
|
||||
}
|
||||
}
|
||||
if !memavail {
|
||||
ret.Available = ret.Free + ret.Buffers + ret.Cached
|
||||
}
|
||||
ret.Used = ret.Total - ret.Available
|
||||
ret.UsedPercent = float64(ret.Total-ret.Available) / float64(ret.Total) * 100.0
|
||||
|
||||
return ret, nil
|
||||
ret.Cached += ret.SReclaimable
|
||||
|
||||
if !memavail {
|
||||
if activeFile && inactiveFile && sReclaimable {
|
||||
ret.Available = calcuateAvailVmem(ret, retEx)
|
||||
} else {
|
||||
ret.Available = ret.Cached + ret.Free
|
||||
}
|
||||
}
|
||||
|
||||
ret.Used = ret.Total - ret.Free - ret.Buffers - ret.Cached
|
||||
ret.UsedPercent = float64(ret.Used) / float64(ret.Total) * 100.0
|
||||
|
||||
return ret, retEx, nil
|
||||
}
|
||||
|
||||
func SwapMemory() (*SwapMemoryStat, error) {
|
||||
@@ -117,7 +214,69 @@ func SwapMemoryWithContext(ctx context.Context) (*SwapMemoryStat, error) {
|
||||
continue
|
||||
}
|
||||
ret.Sout = value * 4 * 1024
|
||||
case "pgpgin":
|
||||
value, err := strconv.ParseUint(fields[1], 10, 64)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
ret.PgIn = value * 4 * 1024
|
||||
case "pgpgout":
|
||||
value, err := strconv.ParseUint(fields[1], 10, 64)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
ret.PgOut = value * 4 * 1024
|
||||
case "pgfault":
|
||||
value, err := strconv.ParseUint(fields[1], 10, 64)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
ret.PgFault = value * 4 * 1024
|
||||
}
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// calcuateAvailVmem 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 {
|
||||
var watermarkLow uint64
|
||||
|
||||
fn := common.HostProc("zoneinfo")
|
||||
lines, err := common.ReadLines(fn)
|
||||
|
||||
if err != nil {
|
||||
return ret.Free + ret.Cached // fallback under kernel 2.6.13
|
||||
}
|
||||
|
||||
pagesize := uint64(os.Getpagesize())
|
||||
watermarkLow = 0
|
||||
|
||||
for _, line := range lines {
|
||||
fields := strings.Fields(line)
|
||||
|
||||
if strings.HasPrefix(fields[0], "low") {
|
||||
lowValue, err := strconv.ParseUint(fields[1], 10, 64)
|
||||
|
||||
if err != nil {
|
||||
lowValue = 0
|
||||
}
|
||||
watermarkLow += lowValue
|
||||
}
|
||||
}
|
||||
|
||||
watermarkLow *= pagesize
|
||||
|
||||
availMemory := ret.Free - watermarkLow
|
||||
pageCache := retEx.ActiveFile + retEx.InactiveFile
|
||||
pageCache -= uint64(math.Min(float64(pageCache/2), float64(watermarkLow)))
|
||||
availMemory += pageCache
|
||||
availMemory += ret.SReclaimable - uint64(math.Min(float64(ret.SReclaimable/2.0), float64(watermarkLow)))
|
||||
|
||||
if availMemory < 0 {
|
||||
availMemory = 0
|
||||
}
|
||||
|
||||
return availMemory
|
||||
}
|
||||
|
||||
2
vendor/github.com/shirou/gopsutil/mem/mem_openbsd.go
generated
vendored
2
vendor/github.com/shirou/gopsutil/mem/mem_openbsd.go
generated
vendored
@@ -99,7 +99,7 @@ func SwapMemoryWithContext(ctx context.Context) (*SwapMemoryStat, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out, err := invoke.Command(swapctl, "-sk")
|
||||
out, err := invoke.CommandWithContext(ctx, swapctl, "-sk")
|
||||
if err != nil {
|
||||
return &SwapMemoryStat{}, nil
|
||||
}
|
||||
|
||||
15
vendor/github.com/shirou/gopsutil/mem/mem_solaris.go
generated
vendored
15
vendor/github.com/shirou/gopsutil/mem/mem_solaris.go
generated
vendored
@@ -52,12 +52,13 @@ func SwapMemoryWithContext(ctx context.Context) (*SwapMemoryStat, error) {
|
||||
}
|
||||
|
||||
func zoneName() (string, error) {
|
||||
zonename, err := exec.LookPath("/usr/bin/zonename")
|
||||
zonename, err := exec.LookPath("zonename")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
out, err := invoke.Command(zonename)
|
||||
ctx := context.Background()
|
||||
out, err := invoke.CommandWithContext(ctx, zonename)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -68,12 +69,13 @@ func zoneName() (string, error) {
|
||||
var globalZoneMemoryCapacityMatch = regexp.MustCompile(`memory size: ([\d]+) Megabytes`)
|
||||
|
||||
func globalZoneMemoryCapacity() (uint64, error) {
|
||||
prtconf, err := exec.LookPath("/usr/sbin/prtconf")
|
||||
prtconf, err := exec.LookPath("prtconf")
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
out, err := invoke.Command(prtconf)
|
||||
ctx := context.Background()
|
||||
out, err := invoke.CommandWithContext(ctx, prtconf)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@@ -94,12 +96,13 @@ func globalZoneMemoryCapacity() (uint64, error) {
|
||||
var kstatMatch = regexp.MustCompile(`([^\s]+)[\s]+([^\s]*)`)
|
||||
|
||||
func nonGlobalZoneMemoryCapacity() (uint64, error) {
|
||||
kstat, err := exec.LookPath("/usr/bin/kstat")
|
||||
kstat, err := exec.LookPath("kstat")
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
out, err := invoke.Command(kstat, "-p", "-c", "zone_memory_cap", "memory_cap:*:*:physcap")
|
||||
ctx := context.Background()
|
||||
out, err := invoke.CommandWithContext(ctx, kstat, "-p", "-c", "zone_memory_cap", "memory_cap:*:*:physcap")
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
77
vendor/github.com/shirou/gopsutil/mem/mem_test.go
generated
vendored
77
vendor/github.com/shirou/gopsutil/mem/mem_test.go
generated
vendored
@@ -1,77 +0,0 @@
|
||||
package mem
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestVirtual_memory(t *testing.T) {
|
||||
if runtime.GOOS == "solaris" {
|
||||
t.Skip("Only .Total is supported on Solaris")
|
||||
}
|
||||
|
||||
v, err := VirtualMemory()
|
||||
if err != nil {
|
||||
t.Errorf("error %v", err)
|
||||
}
|
||||
empty := &VirtualMemoryStat{}
|
||||
if v == empty {
|
||||
t.Errorf("error %v", v)
|
||||
}
|
||||
|
||||
assert.True(t, v.Total > 0)
|
||||
assert.True(t, v.Available > 0)
|
||||
assert.True(t, v.Used > 0)
|
||||
|
||||
assert.Equal(t, v.Total, v.Available+v.Used,
|
||||
"Total should be computable from available + used: %v", v)
|
||||
|
||||
assert.True(t, v.Free > 0)
|
||||
assert.True(t, v.Available > v.Free,
|
||||
"Free should be a subset of Available: %v", v)
|
||||
|
||||
assert.InDelta(t, v.UsedPercent,
|
||||
100*float64(v.Used)/float64(v.Total), 0.1,
|
||||
"UsedPercent should be how many percent of Total is Used: %v", v)
|
||||
}
|
||||
|
||||
func TestSwap_memory(t *testing.T) {
|
||||
v, err := SwapMemory()
|
||||
if err != nil {
|
||||
t.Errorf("error %v", err)
|
||||
}
|
||||
empty := &SwapMemoryStat{}
|
||||
if v == empty {
|
||||
t.Errorf("error %v", v)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVirtualMemoryStat_String(t *testing.T) {
|
||||
v := VirtualMemoryStat{
|
||||
Total: 10,
|
||||
Available: 20,
|
||||
Used: 30,
|
||||
UsedPercent: 30.1,
|
||||
Free: 40,
|
||||
}
|
||||
e := `{"total":10,"available":20,"used":30,"usedPercent":30.1,"free":40,"active":0,"inactive":0,"wired":0,"buffers":0,"cached":0,"writeback":0,"dirty":0,"writebacktmp":0,"shared":0,"slab":0,"pagetables":0,"swapcached":0}`
|
||||
if e != fmt.Sprintf("%v", v) {
|
||||
t.Errorf("VirtualMemoryStat string is invalid: %v", v)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSwapMemoryStat_String(t *testing.T) {
|
||||
v := SwapMemoryStat{
|
||||
Total: 10,
|
||||
Used: 30,
|
||||
Free: 40,
|
||||
UsedPercent: 30.1,
|
||||
}
|
||||
e := `{"total":10,"used":30,"free":40,"usedPercent":30.1,"sin":0,"sout":0}`
|
||||
if e != fmt.Sprintf("%v", v) {
|
||||
t.Errorf("SwapMemoryStat string is invalid: %v", v)
|
||||
}
|
||||
}
|
||||
8
vendor/github.com/shirou/gopsutil/mem/mem_windows.go
generated
vendored
8
vendor/github.com/shirou/gopsutil/mem/mem_windows.go
generated
vendored
@@ -80,11 +80,17 @@ func SwapMemoryWithContext(ctx context.Context) (*SwapMemoryStat, error) {
|
||||
tot := perfInfo.commitLimit * perfInfo.pageSize
|
||||
used := perfInfo.commitTotal * perfInfo.pageSize
|
||||
free := tot - used
|
||||
var usedPercent float64
|
||||
if tot == 0 {
|
||||
usedPercent = 0
|
||||
} else {
|
||||
usedPercent = float64(used) / float64(tot)
|
||||
}
|
||||
ret := &SwapMemoryStat{
|
||||
Total: tot,
|
||||
Used: used,
|
||||
Free: free,
|
||||
UsedPercent: float64(used / tot),
|
||||
UsedPercent: usedPercent,
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
|
||||
34
vendor/github.com/shirou/gopsutil/mem/types_openbsd.go
generated
vendored
34
vendor/github.com/shirou/gopsutil/mem/types_openbsd.go
generated
vendored
@@ -1,34 +0,0 @@
|
||||
// +build ignore
|
||||
|
||||
/*
|
||||
Input to cgo -godefs.
|
||||
*/
|
||||
|
||||
package mem
|
||||
|
||||
/*
|
||||
#include <sys/types.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <uvm/uvmexp.h>
|
||||
|
||||
*/
|
||||
import "C"
|
||||
|
||||
// Machine characteristics; for internal use.
|
||||
|
||||
const (
|
||||
CTLVm = 2
|
||||
CTLVfs = 10
|
||||
VmUvmexp = 4 // get uvmexp
|
||||
VfsGeneric = 0
|
||||
VfsBcacheStat = 3
|
||||
)
|
||||
|
||||
const (
|
||||
sizeOfUvmexp = C.sizeof_struct_uvmexp
|
||||
sizeOfBcachestats = C.sizeof_struct_bcachestats
|
||||
)
|
||||
|
||||
type Uvmexp C.struct_uvmexp
|
||||
type Bcachestats C.struct_bcachestats
|
||||
122
vendor/github.com/shirou/gopsutil/net/net.go
generated
vendored
122
vendor/github.com/shirou/gopsutil/net/net.go
generated
vendored
@@ -12,11 +12,7 @@ import (
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
)
|
||||
|
||||
var invoke common.Invoker
|
||||
|
||||
func init() {
|
||||
invoke = common.Invoke{}
|
||||
}
|
||||
var invoke common.Invoker = common.Invoke{}
|
||||
|
||||
type IOCountersStat struct {
|
||||
Name string `json:"name"` // interface name
|
||||
@@ -62,6 +58,7 @@ type InterfaceAddr struct {
|
||||
}
|
||||
|
||||
type InterfaceStat struct {
|
||||
Index int `json:"index"`
|
||||
MTU int `json:"mtu"` // maximum transmission unit
|
||||
Name string `json:"name"` // e.g., "en0", "lo0", "eth0.100"
|
||||
HardwareAddr string `json:"hardwareaddr"` // IEEE MAC-48, EUI-48 and EUI-64 form
|
||||
@@ -74,7 +71,98 @@ type FilterStat struct {
|
||||
ConnTrackMax int64 `json:"conntrackMax"`
|
||||
}
|
||||
|
||||
// ConntrackStat has conntrack summary info
|
||||
type ConntrackStat struct {
|
||||
Entries uint32 `json:"entries"` // Number of entries in the conntrack table
|
||||
Searched uint32 `json:"searched"` // Number of conntrack table lookups performed
|
||||
Found uint32 `json:"found"` // Number of searched entries which were successful
|
||||
New uint32 `json:"new"` // Number of entries added which were not expected before
|
||||
Invalid uint32 `json:"invalid"` // Number of packets seen which can not be tracked
|
||||
Ignore uint32 `json:"ignore"` // Packets seen which are already connected to an entry
|
||||
Delete uint32 `json:"delete"` // Number of entries which were removed
|
||||
DeleteList uint32 `json:"delete_list"` // Number of entries which were put to dying list
|
||||
Insert uint32 `json:"insert"` // Number of entries inserted into the list
|
||||
InsertFailed uint32 `json:"insert_failed"` // # insertion attempted but failed (same entry exists)
|
||||
Drop uint32 `json:"drop"` // Number of packets dropped due to conntrack failure.
|
||||
EarlyDrop uint32 `json:"early_drop"` // Dropped entries to make room for new ones, if maxsize reached
|
||||
IcmpError uint32 `json:"icmp_error"` // Subset of invalid. Packets that can't be tracked d/t error
|
||||
ExpectNew uint32 `json:"expect_new"` // Entries added after an expectation was already present
|
||||
ExpectCreate uint32 `json:"expect_create"` // Expectations added
|
||||
ExpectDelete uint32 `json:"expect_delete"` // Expectations deleted
|
||||
SearchRestart uint32 `json:"search_restart"` // Conntrack table lookups restarted due to hashtable resizes
|
||||
}
|
||||
|
||||
func NewConntrackStat(e uint32, s uint32, f uint32, n uint32, inv uint32, ign uint32, del uint32, dlst uint32, ins uint32, insfail uint32, drop uint32, edrop uint32, ie uint32, en uint32, ec uint32, ed uint32, sr uint32) *ConntrackStat {
|
||||
return &ConntrackStat{
|
||||
Entries: e,
|
||||
Searched: s,
|
||||
Found: f,
|
||||
New: n,
|
||||
Invalid: inv,
|
||||
Ignore: ign,
|
||||
Delete: del,
|
||||
DeleteList: dlst,
|
||||
Insert: ins,
|
||||
InsertFailed: insfail,
|
||||
Drop: drop,
|
||||
EarlyDrop: edrop,
|
||||
IcmpError: ie,
|
||||
ExpectNew: en,
|
||||
ExpectCreate: ec,
|
||||
ExpectDelete: ed,
|
||||
SearchRestart: sr,
|
||||
}
|
||||
}
|
||||
|
||||
type ConntrackStatList struct {
|
||||
items []*ConntrackStat
|
||||
}
|
||||
|
||||
func NewConntrackStatList() *ConntrackStatList {
|
||||
return &ConntrackStatList{
|
||||
items: []*ConntrackStat{},
|
||||
}
|
||||
}
|
||||
|
||||
func (l *ConntrackStatList) Append(c *ConntrackStat) {
|
||||
l.items = append(l.items, c)
|
||||
}
|
||||
|
||||
func (l *ConntrackStatList) Items() []ConntrackStat {
|
||||
items := make([]ConntrackStat, len(l.items), len(l.items))
|
||||
for i, el := range l.items {
|
||||
items[i] = *el
|
||||
}
|
||||
return items
|
||||
}
|
||||
|
||||
// Summary returns a single-element list with totals from all list items.
|
||||
func (l *ConntrackStatList) Summary() []ConntrackStat {
|
||||
summary := NewConntrackStat(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
|
||||
for _, cs := range l.items {
|
||||
summary.Entries += cs.Entries
|
||||
summary.Searched += cs.Searched
|
||||
summary.Found += cs.Found
|
||||
summary.New += cs.New
|
||||
summary.Invalid += cs.Invalid
|
||||
summary.Ignore += cs.Ignore
|
||||
summary.Delete += cs.Delete
|
||||
summary.DeleteList += cs.DeleteList
|
||||
summary.Insert += cs.Insert
|
||||
summary.InsertFailed += cs.InsertFailed
|
||||
summary.Drop += cs.Drop
|
||||
summary.EarlyDrop += cs.EarlyDrop
|
||||
summary.IcmpError += cs.IcmpError
|
||||
summary.ExpectNew += cs.ExpectNew
|
||||
summary.ExpectCreate += cs.ExpectCreate
|
||||
summary.ExpectDelete += cs.ExpectDelete
|
||||
summary.SearchRestart += cs.SearchRestart
|
||||
}
|
||||
return []ConntrackStat{*summary}
|
||||
}
|
||||
|
||||
var constMap = map[string]int{
|
||||
"unix": syscall.AF_UNIX,
|
||||
"TCP": syscall.SOCK_STREAM,
|
||||
"UDP": syscall.SOCK_DGRAM,
|
||||
"IPv4": syscall.AF_INET,
|
||||
@@ -111,6 +199,11 @@ func (n InterfaceAddr) String() string {
|
||||
return string(s)
|
||||
}
|
||||
|
||||
func (n ConntrackStat) String() string {
|
||||
s, _ := json.Marshal(n)
|
||||
return string(s)
|
||||
}
|
||||
|
||||
func Interfaces() ([]InterfaceStat, error) {
|
||||
return InterfacesWithContext(context.Background())
|
||||
}
|
||||
@@ -141,6 +234,7 @@ func InterfacesWithContext(ctx context.Context) ([]InterfaceStat, error) {
|
||||
}
|
||||
|
||||
r := InterfaceStat{
|
||||
Index: ifi.Index,
|
||||
Name: ifi.Name,
|
||||
MTU: ifi.MTU,
|
||||
HardwareAddr: ifi.HardwareAddr.String(),
|
||||
@@ -182,10 +276,15 @@ func getIOCountersAll(n []IOCountersStat) ([]IOCountersStat, error) {
|
||||
|
||||
func parseNetLine(line string) (ConnectionStat, error) {
|
||||
f := strings.Fields(line)
|
||||
if len(f) < 9 {
|
||||
if len(f) < 8 {
|
||||
return ConnectionStat{}, fmt.Errorf("wrong line,%s", line)
|
||||
}
|
||||
|
||||
if len(f) == 8 {
|
||||
f = append(f, f[7])
|
||||
f[7] = "unix"
|
||||
}
|
||||
|
||||
pid, err := strconv.Atoi(f[1])
|
||||
if err != nil {
|
||||
return ConnectionStat{}, err
|
||||
@@ -203,9 +302,14 @@ func parseNetLine(line string) (ConnectionStat, error) {
|
||||
return ConnectionStat{}, fmt.Errorf("unknown type, %s", f[7])
|
||||
}
|
||||
|
||||
laddr, raddr, err := parseNetAddr(f[8])
|
||||
if err != nil {
|
||||
return ConnectionStat{}, fmt.Errorf("failed to parse netaddr, %s", f[8])
|
||||
var laddr, raddr Addr
|
||||
if f[7] == "unix" {
|
||||
laddr.IP = f[8]
|
||||
} else {
|
||||
laddr, raddr, err = parseNetAddr(f[8])
|
||||
if err != nil {
|
||||
return ConnectionStat{}, fmt.Errorf("failed to parse netaddr, %s", f[8])
|
||||
}
|
||||
}
|
||||
|
||||
n := ConnectionStat{
|
||||
|
||||
425
vendor/github.com/shirou/gopsutil/net/net_aix.go
generated
vendored
Normal file
425
vendor/github.com/shirou/gopsutil/net/net_aix.go
generated
vendored
Normal file
@@ -0,0 +1,425 @@
|
||||
// +build aix
|
||||
|
||||
package net
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
)
|
||||
|
||||
func parseNetstatI(output string) ([]IOCountersStat, error) {
|
||||
lines := strings.Split(string(output), "\n")
|
||||
ret := make([]IOCountersStat, 0, len(lines)-1)
|
||||
exists := make([]string, 0, len(ret))
|
||||
|
||||
// Check first line is header
|
||||
if len(lines) > 0 && strings.Fields(lines[0])[0] != "Name" {
|
||||
return nil, fmt.Errorf("not a 'netstat -i' output")
|
||||
}
|
||||
|
||||
for _, line := range lines[1:] {
|
||||
values := strings.Fields(line)
|
||||
if len(values) < 1 || values[0] == "Name" {
|
||||
continue
|
||||
}
|
||||
if common.StringsHas(exists, values[0]) {
|
||||
// skip if already get
|
||||
continue
|
||||
}
|
||||
exists = append(exists, values[0])
|
||||
|
||||
if len(values) < 9 {
|
||||
continue
|
||||
}
|
||||
|
||||
base := 1
|
||||
// sometimes Address is omitted
|
||||
if len(values) < 10 {
|
||||
base = 0
|
||||
}
|
||||
|
||||
parsed := make([]uint64, 0, 5)
|
||||
vv := []string{
|
||||
values[base+3], // Ipkts == PacketsRecv
|
||||
values[base+4], // Ierrs == Errin
|
||||
values[base+5], // Opkts == PacketsSent
|
||||
values[base+6], // Oerrs == Errout
|
||||
values[base+8], // Drops == Dropout
|
||||
}
|
||||
|
||||
for _, target := range vv {
|
||||
if target == "-" {
|
||||
parsed = append(parsed, 0)
|
||||
continue
|
||||
}
|
||||
|
||||
t, err := strconv.ParseUint(target, 10, 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
parsed = append(parsed, t)
|
||||
}
|
||||
|
||||
n := IOCountersStat{
|
||||
Name: values[0],
|
||||
PacketsRecv: parsed[0],
|
||||
Errin: parsed[1],
|
||||
PacketsSent: parsed[2],
|
||||
Errout: parsed[3],
|
||||
Dropout: parsed[4],
|
||||
}
|
||||
ret = append(ret, n)
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func IOCounters(pernic bool) ([]IOCountersStat, error) {
|
||||
return IOCountersWithContext(context.Background(), pernic)
|
||||
}
|
||||
|
||||
func IOCountersWithContext(ctx context.Context, pernic bool) ([]IOCountersStat, error) {
|
||||
netstat, err := exec.LookPath("netstat")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out, err := invoke.CommandWithContext(ctx, netstat, "-idn")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
iocounters, err := parseNetstatI(string(out))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if pernic == false {
|
||||
return getIOCountersAll(iocounters)
|
||||
}
|
||||
return iocounters, nil
|
||||
|
||||
}
|
||||
|
||||
// NetIOCountersByFile is an method which is added just a compatibility for linux.
|
||||
func IOCountersByFile(pernic bool, filename string) ([]IOCountersStat, error) {
|
||||
return IOCountersByFileWithContext(context.Background(), pernic, filename)
|
||||
}
|
||||
|
||||
func IOCountersByFileWithContext(ctx context.Context, pernic bool, filename string) ([]IOCountersStat, error) {
|
||||
return IOCounters(pernic)
|
||||
}
|
||||
|
||||
func FilterCounters() ([]FilterStat, error) {
|
||||
return FilterCountersWithContext(context.Background())
|
||||
}
|
||||
|
||||
func FilterCountersWithContext(ctx context.Context) ([]FilterStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func ConntrackStats(percpu bool) ([]ConntrackStat, error) {
|
||||
return ConntrackStatsWithContext(context.Background(), percpu)
|
||||
}
|
||||
|
||||
func ConntrackStatsWithContext(ctx context.Context, percpu bool) ([]ConntrackStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func ProtoCounters(protocols []string) ([]ProtoCountersStat, error) {
|
||||
return ProtoCountersWithContext(context.Background(), protocols)
|
||||
}
|
||||
|
||||
func ProtoCountersWithContext(ctx context.Context, protocols []string) ([]ProtoCountersStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func parseNetstatNetLine(line string) (ConnectionStat, error) {
|
||||
f := strings.Fields(line)
|
||||
if len(f) < 5 {
|
||||
return ConnectionStat{}, fmt.Errorf("wrong line,%s", line)
|
||||
}
|
||||
|
||||
var netType, netFamily uint32
|
||||
switch f[0] {
|
||||
case "tcp", "tcp4":
|
||||
netType = syscall.SOCK_STREAM
|
||||
netFamily = syscall.AF_INET
|
||||
case "udp", "udp4":
|
||||
netType = syscall.SOCK_DGRAM
|
||||
netFamily = syscall.AF_INET
|
||||
case "tcp6":
|
||||
netType = syscall.SOCK_STREAM
|
||||
netFamily = syscall.AF_INET6
|
||||
case "udp6":
|
||||
netType = syscall.SOCK_DGRAM
|
||||
netFamily = syscall.AF_INET6
|
||||
default:
|
||||
return ConnectionStat{}, fmt.Errorf("unknown type, %s", f[0])
|
||||
}
|
||||
|
||||
laddr, raddr, err := parseNetstatAddr(f[3], f[4], netFamily)
|
||||
if err != nil {
|
||||
return ConnectionStat{}, fmt.Errorf("failed to parse netaddr, %s %s", f[3], f[4])
|
||||
}
|
||||
|
||||
n := ConnectionStat{
|
||||
Fd: uint32(0), // not supported
|
||||
Family: uint32(netFamily),
|
||||
Type: uint32(netType),
|
||||
Laddr: laddr,
|
||||
Raddr: raddr,
|
||||
Pid: int32(0), // not supported
|
||||
}
|
||||
if len(f) == 6 {
|
||||
n.Status = f[5]
|
||||
}
|
||||
|
||||
return n, nil
|
||||
}
|
||||
|
||||
var portMatch = regexp.MustCompile(`(.*)\.(\d+)$`)
|
||||
|
||||
// This function only works for netstat returning addresses with a "."
|
||||
// before the port (0.0.0.0.22 instead of 0.0.0.0:22).
|
||||
func parseNetstatAddr(local string, remote string, family uint32) (laddr Addr, raddr Addr, err error) {
|
||||
parse := func(l string) (Addr, error) {
|
||||
matches := portMatch.FindStringSubmatch(l)
|
||||
if matches == nil {
|
||||
return Addr{}, fmt.Errorf("wrong addr, %s", l)
|
||||
}
|
||||
host := matches[1]
|
||||
port := matches[2]
|
||||
if host == "*" {
|
||||
switch family {
|
||||
case syscall.AF_INET:
|
||||
host = "0.0.0.0"
|
||||
case syscall.AF_INET6:
|
||||
host = "::"
|
||||
default:
|
||||
return Addr{}, fmt.Errorf("unknown family, %d", family)
|
||||
}
|
||||
}
|
||||
lport, err := strconv.Atoi(port)
|
||||
if err != nil {
|
||||
return Addr{}, err
|
||||
}
|
||||
return Addr{IP: host, Port: uint32(lport)}, nil
|
||||
}
|
||||
|
||||
laddr, err = parse(local)
|
||||
if remote != "*.*" { // remote addr exists
|
||||
raddr, err = parse(remote)
|
||||
if err != nil {
|
||||
return laddr, raddr, err
|
||||
}
|
||||
}
|
||||
|
||||
return laddr, raddr, err
|
||||
}
|
||||
|
||||
func parseNetstatUnixLine(f []string) (ConnectionStat, error) {
|
||||
if len(f) < 8 {
|
||||
return ConnectionStat{}, fmt.Errorf("wrong number of fields: expected >=8 got %d", len(f))
|
||||
}
|
||||
|
||||
var netType uint32
|
||||
|
||||
switch f[1] {
|
||||
case "dgram":
|
||||
netType = syscall.SOCK_DGRAM
|
||||
case "stream":
|
||||
netType = syscall.SOCK_STREAM
|
||||
default:
|
||||
return ConnectionStat{}, fmt.Errorf("unknown type: %s", f[1])
|
||||
}
|
||||
|
||||
// Some Unix Socket don't have any address associated
|
||||
addr := ""
|
||||
if len(f) == 9 {
|
||||
addr = f[8]
|
||||
}
|
||||
|
||||
c := ConnectionStat{
|
||||
Fd: uint32(0), // not supported
|
||||
Family: uint32(syscall.AF_UNIX),
|
||||
Type: uint32(netType),
|
||||
Laddr: Addr{
|
||||
IP: addr,
|
||||
},
|
||||
Status: "NONE",
|
||||
Pid: int32(0), // not supported
|
||||
}
|
||||
|
||||
return c, nil
|
||||
}
|
||||
|
||||
// Return true if proto is the corresponding to the kind parameter
|
||||
// Only for Inet lines
|
||||
func hasCorrectInetProto(kind, proto string) bool {
|
||||
switch kind {
|
||||
case "all", "inet":
|
||||
return true
|
||||
case "unix":
|
||||
return false
|
||||
case "inet4":
|
||||
return !strings.HasSuffix(proto, "6")
|
||||
case "inet6":
|
||||
return strings.HasSuffix(proto, "6")
|
||||
case "tcp":
|
||||
return proto == "tcp" || proto == "tcp4" || proto == "tcp6"
|
||||
case "tcp4":
|
||||
return proto == "tcp" || proto == "tcp4"
|
||||
case "tcp6":
|
||||
return proto == "tcp6"
|
||||
case "udp":
|
||||
return proto == "udp" || proto == "udp4" || proto == "udp6"
|
||||
case "udp4":
|
||||
return proto == "udp" || proto == "udp4"
|
||||
case "udp6":
|
||||
return proto == "udp6"
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func parseNetstatA(output string, kind string) ([]ConnectionStat, error) {
|
||||
var ret []ConnectionStat
|
||||
lines := strings.Split(string(output), "\n")
|
||||
|
||||
for _, line := range lines {
|
||||
fields := strings.Fields(line)
|
||||
if len(fields) < 1 {
|
||||
continue
|
||||
}
|
||||
|
||||
if strings.HasPrefix(fields[0], "f1") {
|
||||
// Unix lines
|
||||
if len(fields) < 2 {
|
||||
// every unix connections have two lines
|
||||
continue
|
||||
}
|
||||
|
||||
c, err := parseNetstatUnixLine(fields)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse Unix Address (%s): %s", line, err)
|
||||
}
|
||||
|
||||
ret = append(ret, c)
|
||||
|
||||
} else if strings.HasPrefix(fields[0], "tcp") || strings.HasPrefix(fields[0], "udp") {
|
||||
// Inet lines
|
||||
if !hasCorrectInetProto(kind, fields[0]) {
|
||||
continue
|
||||
}
|
||||
|
||||
// On AIX, netstat display some connections with "*.*" as local addresses
|
||||
// Skip them as they aren't real connections.
|
||||
if fields[3] == "*.*" {
|
||||
continue
|
||||
}
|
||||
|
||||
c, err := parseNetstatNetLine(line)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse Inet Address (%s): %s", line, err)
|
||||
}
|
||||
|
||||
ret = append(ret, c)
|
||||
} else {
|
||||
// Header lines
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
|
||||
}
|
||||
|
||||
func Connections(kind string) ([]ConnectionStat, error) {
|
||||
return ConnectionsWithContext(context.Background(), kind)
|
||||
}
|
||||
|
||||
func ConnectionsWithContext(ctx context.Context, kind string) ([]ConnectionStat, error) {
|
||||
|
||||
args := []string{"-na"}
|
||||
switch strings.ToLower(kind) {
|
||||
default:
|
||||
fallthrough
|
||||
case "":
|
||||
kind = "all"
|
||||
case "all":
|
||||
// nothing to add
|
||||
case "inet", "inet4", "inet6":
|
||||
args = append(args, "-finet")
|
||||
case "tcp", "tcp4", "tcp6":
|
||||
args = append(args, "-finet")
|
||||
case "udp", "udp4", "udp6":
|
||||
args = append(args, "-finet")
|
||||
case "unix":
|
||||
args = append(args, "-funix")
|
||||
}
|
||||
|
||||
netstat, err := exec.LookPath("netstat")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out, err := invoke.CommandWithContext(ctx, netstat, args...)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ret, err := parseNetstatA(string(out), kind)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
|
||||
}
|
||||
|
||||
func ConnectionsMax(kind string, max int) ([]ConnectionStat, error) {
|
||||
return ConnectionsMaxWithContext(context.Background(), kind, max)
|
||||
}
|
||||
|
||||
func ConnectionsMaxWithContext(ctx context.Context, kind string, max int) ([]ConnectionStat, error) {
|
||||
return []ConnectionStat{}, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
// Return a list of network connections opened, omitting `Uids`.
|
||||
// WithoutUids functions are reliant on implementation details. They may be altered to be an alias for Connections or be
|
||||
// removed from the API in the future.
|
||||
func ConnectionsWithoutUids(kind string) ([]ConnectionStat, error) {
|
||||
return ConnectionsWithoutUidsWithContext(context.Background(), kind)
|
||||
}
|
||||
|
||||
func ConnectionsWithoutUidsWithContext(ctx context.Context, kind string) ([]ConnectionStat, error) {
|
||||
return ConnectionsMaxWithoutUidsWithContext(ctx, kind, 0)
|
||||
}
|
||||
|
||||
func ConnectionsMaxWithoutUidsWithContext(ctx context.Context, kind string, max int) ([]ConnectionStat, error) {
|
||||
return ConnectionsPidMaxWithoutUidsWithContext(ctx, kind, 0, max)
|
||||
}
|
||||
|
||||
func ConnectionsPidWithoutUids(kind string, pid int32) ([]ConnectionStat, error) {
|
||||
return ConnectionsPidWithoutUidsWithContext(context.Background(), kind, pid)
|
||||
}
|
||||
|
||||
func ConnectionsPidWithoutUidsWithContext(ctx context.Context, kind string, pid int32) ([]ConnectionStat, error) {
|
||||
return ConnectionsPidMaxWithoutUidsWithContext(ctx, kind, pid, 0)
|
||||
}
|
||||
|
||||
func ConnectionsPidMaxWithoutUids(kind string, pid int32, max int) ([]ConnectionStat, error) {
|
||||
return ConnectionsPidMaxWithoutUidsWithContext(context.Background(), kind, pid, max)
|
||||
}
|
||||
|
||||
func ConnectionsPidMaxWithoutUidsWithContext(ctx context.Context, kind string, pid int32, max int) ([]ConnectionStat, error) {
|
||||
return connectionsPidMaxWithoutUidsWithContext(ctx, kind, pid, max)
|
||||
}
|
||||
|
||||
func connectionsPidMaxWithoutUidsWithContext(ctx context.Context, kind string, pid int32, max int) ([]ConnectionStat, error) {
|
||||
return []ConnectionStat{}, common.ErrNotImplementedError
|
||||
}
|
||||
21
vendor/github.com/shirou/gopsutil/net/net_darwin.go
generated
vendored
21
vendor/github.com/shirou/gopsutil/net/net_darwin.go
generated
vendored
@@ -6,6 +6,7 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
"strconv"
|
||||
@@ -42,7 +43,7 @@ func parseNetstatLine(line string) (stat *IOCountersStat, linkID *uint, err erro
|
||||
|
||||
base := 1
|
||||
numberColumns := len(columns)
|
||||
// sometimes Address is ommitted
|
||||
// sometimes Address is omitted
|
||||
if numberColumns < 12 {
|
||||
base = 0
|
||||
}
|
||||
@@ -174,13 +175,13 @@ func IOCountersWithContext(ctx context.Context, pernic bool) ([]IOCountersStat,
|
||||
retIndex int
|
||||
)
|
||||
|
||||
netstat, err := exec.LookPath("/usr/sbin/netstat")
|
||||
netstat, err := exec.LookPath("netstat")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// try to get all interface metrics, and hope there won't be any truncated
|
||||
out, err := invoke.Command(netstat, "-ibdnW")
|
||||
out, err := invoke.CommandWithContext(ctx, netstat, "-ibdnW")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -204,11 +205,11 @@ func IOCountersWithContext(ctx context.Context, pernic bool) ([]IOCountersStat,
|
||||
}
|
||||
} else {
|
||||
// duplicated interface, list all interfaces
|
||||
ifconfig, err := exec.LookPath("/sbin/ifconfig")
|
||||
ifconfig, err := exec.LookPath("ifconfig")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if out, err = invoke.Command(ifconfig, "-l"); err != nil {
|
||||
if out, err = invoke.CommandWithContext(ctx, ifconfig, "-l"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
interfaceNames := strings.Fields(strings.TrimRight(string(out), endOfLine))
|
||||
@@ -227,7 +228,7 @@ func IOCountersWithContext(ctx context.Context, pernic bool) ([]IOCountersStat,
|
||||
}
|
||||
if truncated {
|
||||
// run netstat with -I$ifacename
|
||||
if out, err = invoke.Command(netstat, "-ibdnWI"+interfaceName); err != nil {
|
||||
if out, err = invoke.CommandWithContext(ctx, netstat, "-ibdnWI"+interfaceName); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
parsedIfaces, err := parseNetstatOutput(string(out))
|
||||
@@ -271,6 +272,14 @@ func FilterCountersWithContext(ctx context.Context) ([]FilterStat, error) {
|
||||
return nil, errors.New("NetFilterCounters not implemented for darwin")
|
||||
}
|
||||
|
||||
func ConntrackStats(percpu bool) ([]ConntrackStat, error) {
|
||||
return ConntrackStatsWithContext(context.Background(), percpu)
|
||||
}
|
||||
|
||||
func ConntrackStatsWithContext(ctx context.Context, percpu bool) ([]ConntrackStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
// NetProtoCounters returns network statistics for the entire system
|
||||
// If protocols is empty then all protocols are returned, otherwise
|
||||
// just the protocols in the list are returned.
|
||||
|
||||
140
vendor/github.com/shirou/gopsutil/net/net_darwin_test.go
generated
vendored
140
vendor/github.com/shirou/gopsutil/net/net_darwin_test.go
generated
vendored
@@ -1,140 +0,0 @@
|
||||
package net
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
assert "github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
const (
|
||||
netstatTruncated = `Name Mtu Network Address Ipkts Ierrs Ibytes Opkts Oerrs Obytes Coll Drop
|
||||
lo0 16384 <Link#1> 31241 0 3769823 31241 0 3769823 0 0
|
||||
lo0 16384 ::1/128 ::1 31241 - 3769823 31241 - 3769823 - -
|
||||
lo0 16384 127 127.0.0.1 31241 - 3769823 31241 - 3769823 - -
|
||||
lo0 16384 fe80::1%lo0 fe80:1::1 31241 - 3769823 31241 - 3769823 - -
|
||||
gif0* 1280 <Link#2> 0 0 0 0 0 0 0 0
|
||||
stf0* 1280 <Link#3> 0 0 0 0 0 0 0 0
|
||||
utun8 1500 <Link#88> 286 0 27175 0 0 0 0 0
|
||||
utun8 1500 <Link#90> 286 0 29554 0 0 0 0 0
|
||||
utun8 1500 <Link#92> 286 0 29244 0 0 0 0 0
|
||||
utun8 1500 <Link#93> 286 0 28267 0 0 0 0 0
|
||||
utun8 1500 <Link#95> 286 0 28593 0 0 0 0 0`
|
||||
netstatNotTruncated = `Name Mtu Network Address Ipkts Ierrs Ibytes Opkts Oerrs Obytes Coll Drop
|
||||
lo0 16384 <Link#1> 27190978 0 12824763793 27190978 0 12824763793 0 0
|
||||
lo0 16384 ::1/128 ::1 27190978 - 12824763793 27190978 - 12824763793 - -
|
||||
lo0 16384 127 127.0.0.1 27190978 - 12824763793 27190978 - 12824763793 - -
|
||||
lo0 16384 fe80::1%lo0 fe80:1::1 27190978 - 12824763793 27190978 - 12824763793 - -
|
||||
gif0* 1280 <Link#2> 0 0 0 0 0 0 0 0
|
||||
stf0* 1280 <Link#3> 0 0 0 0 0 0 0 0
|
||||
en0 1500 <Link#4> a8:66:7f:dd:ee:ff 5708989 0 7295722068 3494252 0 379533492 0 230
|
||||
en0 1500 fe80::aa66: fe80:4::aa66:7fff 5708989 - 7295722068 3494252 - 379533492 - -`
|
||||
)
|
||||
|
||||
func TestparseNetstatLineHeader(t *testing.T) {
|
||||
stat, linkIkd, err := parseNetstatLine(`Name Mtu Network Address Ipkts Ierrs Ibytes Opkts Oerrs Obytes Coll Drop`)
|
||||
assert.Nil(t, linkIkd)
|
||||
assert.Nil(t, stat)
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, errNetstatHeader, err)
|
||||
}
|
||||
|
||||
func assertLoopbackStat(t *testing.T, err error, stat *IOCountersStat) {
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 869107, stat.PacketsRecv)
|
||||
assert.Equal(t, 0, stat.Errin)
|
||||
assert.Equal(t, 169411755, stat.BytesRecv)
|
||||
assert.Equal(t, 869108, stat.PacketsSent)
|
||||
assert.Equal(t, 1, stat.Errout)
|
||||
assert.Equal(t, 169411756, stat.BytesSent)
|
||||
}
|
||||
|
||||
func TestparseNetstatLineLink(t *testing.T) {
|
||||
stat, linkID, err := parseNetstatLine(
|
||||
`lo0 16384 <Link#1> 869107 0 169411755 869108 1 169411756 0 0`,
|
||||
)
|
||||
assertLoopbackStat(t, err, stat)
|
||||
assert.NotNil(t, linkID)
|
||||
assert.Equal(t, uint(1), *linkID)
|
||||
}
|
||||
|
||||
func TestparseNetstatLineIPv6(t *testing.T) {
|
||||
stat, linkID, err := parseNetstatLine(
|
||||
`lo0 16384 ::1/128 ::1 869107 - 169411755 869108 1 169411756 - -`,
|
||||
)
|
||||
assertLoopbackStat(t, err, stat)
|
||||
assert.Nil(t, linkID)
|
||||
}
|
||||
|
||||
func TestparseNetstatLineIPv4(t *testing.T) {
|
||||
stat, linkID, err := parseNetstatLine(
|
||||
`lo0 16384 127 127.0.0.1 869107 - 169411755 869108 1 169411756 - -`,
|
||||
)
|
||||
assertLoopbackStat(t, err, stat)
|
||||
assert.Nil(t, linkID)
|
||||
}
|
||||
|
||||
func TestParseNetstatOutput(t *testing.T) {
|
||||
nsInterfaces, err := parseNetstatOutput(netstatNotTruncated)
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, nsInterfaces, 8)
|
||||
for index := range nsInterfaces {
|
||||
assert.NotNil(t, nsInterfaces[index].stat, "Index %d", index)
|
||||
}
|
||||
|
||||
assert.NotNil(t, nsInterfaces[0].linkID)
|
||||
assert.Equal(t, uint(1), *nsInterfaces[0].linkID)
|
||||
|
||||
assert.Nil(t, nsInterfaces[1].linkID)
|
||||
assert.Nil(t, nsInterfaces[2].linkID)
|
||||
assert.Nil(t, nsInterfaces[3].linkID)
|
||||
|
||||
assert.NotNil(t, nsInterfaces[4].linkID)
|
||||
assert.Equal(t, uint(2), *nsInterfaces[4].linkID)
|
||||
|
||||
assert.NotNil(t, nsInterfaces[5].linkID)
|
||||
assert.Equal(t, uint(3), *nsInterfaces[5].linkID)
|
||||
|
||||
assert.NotNil(t, nsInterfaces[6].linkID)
|
||||
assert.Equal(t, uint(4), *nsInterfaces[6].linkID)
|
||||
|
||||
assert.Nil(t, nsInterfaces[7].linkID)
|
||||
|
||||
mapUsage := newMapInterfaceNameUsage(nsInterfaces)
|
||||
assert.False(t, mapUsage.isTruncated())
|
||||
assert.Len(t, mapUsage.notTruncated(), 4)
|
||||
}
|
||||
|
||||
func TestParseNetstatTruncated(t *testing.T) {
|
||||
nsInterfaces, err := parseNetstatOutput(netstatTruncated)
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, nsInterfaces, 11)
|
||||
for index := range nsInterfaces {
|
||||
assert.NotNil(t, nsInterfaces[index].stat, "Index %d", index)
|
||||
}
|
||||
|
||||
const truncatedIface = "utun8"
|
||||
|
||||
assert.NotNil(t, nsInterfaces[6].linkID)
|
||||
assert.Equal(t, uint(88), *nsInterfaces[6].linkID)
|
||||
assert.Equal(t, truncatedIface, nsInterfaces[6].stat.Name)
|
||||
|
||||
assert.NotNil(t, nsInterfaces[7].linkID)
|
||||
assert.Equal(t, uint(90), *nsInterfaces[7].linkID)
|
||||
assert.Equal(t, truncatedIface, nsInterfaces[7].stat.Name)
|
||||
|
||||
assert.NotNil(t, nsInterfaces[8].linkID)
|
||||
assert.Equal(t, uint(92), *nsInterfaces[8].linkID)
|
||||
assert.Equal(t, truncatedIface, nsInterfaces[8].stat.Name)
|
||||
|
||||
assert.NotNil(t, nsInterfaces[9].linkID)
|
||||
assert.Equal(t, uint(93), *nsInterfaces[9].linkID)
|
||||
assert.Equal(t, truncatedIface, nsInterfaces[9].stat.Name)
|
||||
|
||||
assert.NotNil(t, nsInterfaces[10].linkID)
|
||||
assert.Equal(t, uint(95), *nsInterfaces[10].linkID)
|
||||
assert.Equal(t, truncatedIface, nsInterfaces[10].stat.Name)
|
||||
|
||||
mapUsage := newMapInterfaceNameUsage(nsInterfaces)
|
||||
assert.True(t, mapUsage.isTruncated())
|
||||
assert.Equal(t, 3, len(mapUsage.notTruncated()), "en0, gif0 and stf0")
|
||||
}
|
||||
45
vendor/github.com/shirou/gopsutil/net/net_fallback.go
generated
vendored
45
vendor/github.com/shirou/gopsutil/net/net_fallback.go
generated
vendored
@@ -1,4 +1,4 @@
|
||||
// +build !darwin,!linux,!freebsd,!openbsd,!windows
|
||||
// +build !aix,!darwin,!linux,!freebsd,!openbsd,!windows
|
||||
|
||||
package net
|
||||
|
||||
@@ -24,6 +24,14 @@ func FilterCountersWithContext(ctx context.Context) ([]FilterStat, error) {
|
||||
return []FilterStat{}, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func ConntrackStats(percpu bool) ([]ConntrackStat, error) {
|
||||
return ConntrackStatsWithContext(context.Background(), percpu)
|
||||
}
|
||||
|
||||
func ConntrackStatsWithContext(ctx context.Context, percpu bool) ([]ConntrackStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func ProtoCounters(protocols []string) ([]ProtoCountersStat, error) {
|
||||
return ProtoCountersWithContext(context.Background(), protocols)
|
||||
}
|
||||
@@ -47,3 +55,38 @@ func ConnectionsMax(kind string, max int) ([]ConnectionStat, error) {
|
||||
func ConnectionsMaxWithContext(ctx context.Context, kind string, max int) ([]ConnectionStat, error) {
|
||||
return []ConnectionStat{}, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
// Return a list of network connections opened, omitting `Uids`.
|
||||
// WithoutUids functions are reliant on implementation details. They may be altered to be an alias for Connections or be
|
||||
// removed from the API in the future.
|
||||
func ConnectionsWithoutUids(kind string) ([]ConnectionStat, error) {
|
||||
return ConnectionsWithoutUidsWithContext(context.Background(), kind)
|
||||
}
|
||||
|
||||
func ConnectionsWithoutUidsWithContext(ctx context.Context, kind string) ([]ConnectionStat, error) {
|
||||
return ConnectionsMaxWithoutUidsWithContext(ctx, kind, 0)
|
||||
}
|
||||
|
||||
func ConnectionsMaxWithoutUidsWithContext(ctx context.Context, kind string, max int) ([]ConnectionStat, error) {
|
||||
return ConnectionsPidMaxWithoutUidsWithContext(ctx, kind, 0, max)
|
||||
}
|
||||
|
||||
func ConnectionsPidWithoutUids(kind string, pid int32) ([]ConnectionStat, error) {
|
||||
return ConnectionsPidWithoutUidsWithContext(context.Background(), kind, pid)
|
||||
}
|
||||
|
||||
func ConnectionsPidWithoutUidsWithContext(ctx context.Context, kind string, pid int32) ([]ConnectionStat, error) {
|
||||
return ConnectionsPidMaxWithoutUidsWithContext(ctx, kind, pid, 0)
|
||||
}
|
||||
|
||||
func ConnectionsPidMaxWithoutUids(kind string, pid int32, max int) ([]ConnectionStat, error) {
|
||||
return ConnectionsPidMaxWithoutUidsWithContext(context.Background(), kind, pid, max)
|
||||
}
|
||||
|
||||
func ConnectionsPidMaxWithoutUidsWithContext(ctx context.Context, kind string, pid int32, max int) ([]ConnectionStat, error) {
|
||||
return connectionsPidMaxWithoutUidsWithContext(ctx, kind, pid, max)
|
||||
}
|
||||
|
||||
func connectionsPidMaxWithoutUidsWithContext(ctx context.Context, kind string, pid int32, max int) ([]ConnectionStat, error) {
|
||||
return []ConnectionStat{}, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
14
vendor/github.com/shirou/gopsutil/net/net_freebsd.go
generated
vendored
14
vendor/github.com/shirou/gopsutil/net/net_freebsd.go
generated
vendored
@@ -17,11 +17,11 @@ func IOCounters(pernic bool) ([]IOCountersStat, error) {
|
||||
}
|
||||
|
||||
func IOCountersWithContext(ctx context.Context, pernic bool) ([]IOCountersStat, error) {
|
||||
netstat, err := exec.LookPath("/usr/bin/netstat")
|
||||
netstat, err := exec.LookPath("netstat")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out, err := invoke.Command(netstat, "-ibdnW")
|
||||
out, err := invoke.CommandWithContext(ctx, netstat, "-ibdnW")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -45,7 +45,7 @@ func IOCountersWithContext(ctx context.Context, pernic bool) ([]IOCountersStat,
|
||||
continue
|
||||
}
|
||||
base := 1
|
||||
// sometimes Address is ommitted
|
||||
// sometimes Address is omitted
|
||||
if len(values) < 13 {
|
||||
base = 0
|
||||
}
|
||||
@@ -112,6 +112,14 @@ func FilterCountersWithContext(ctx context.Context) ([]FilterStat, error) {
|
||||
return nil, errors.New("NetFilterCounters not implemented for freebsd")
|
||||
}
|
||||
|
||||
func ConntrackStats(percpu bool) ([]ConntrackStat, error) {
|
||||
return ConntrackStatsWithContext(context.Background(), percpu)
|
||||
}
|
||||
|
||||
func ConntrackStatsWithContext(ctx context.Context, percpu bool) ([]ConntrackStat, error) {
|
||||
return nil, errors.New("ConntrackStats not implemented for freebsd")
|
||||
}
|
||||
|
||||
// NetProtoCounters returns network statistics for the entire system
|
||||
// If protocols is empty then all protocols are returned, otherwise
|
||||
// just the protocols in the list are returned.
|
||||
|
||||
155
vendor/github.com/shirou/gopsutil/net/net_linux.go
generated
vendored
155
vendor/github.com/shirou/gopsutil/net/net_linux.go
generated
vendored
@@ -8,6 +8,7 @@ import (
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
@@ -18,6 +19,26 @@ import (
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
)
|
||||
|
||||
const ( // Conntrack Column numbers
|
||||
CT_ENTRIES = iota
|
||||
CT_SEARCHED
|
||||
CT_FOUND
|
||||
CT_NEW
|
||||
CT_INVALID
|
||||
CT_IGNORE
|
||||
CT_DELETE
|
||||
CT_DELETE_LIST
|
||||
CT_INSERT
|
||||
CT_INSERT_FAILED
|
||||
CT_DROP
|
||||
CT_EARLY_DROP
|
||||
CT_ICMP_ERROR
|
||||
CT_EXPECT_NEW
|
||||
CT_EXPECT_CREATE
|
||||
CT_EXPECT_DELETE
|
||||
CT_SEARCH_RESTART
|
||||
)
|
||||
|
||||
// NetIOCounters returnes 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,
|
||||
@@ -232,6 +253,58 @@ func FilterCountersWithContext(ctx context.Context) ([]FilterStat, error) {
|
||||
return stats, nil
|
||||
}
|
||||
|
||||
// ConntrackStats returns more detailed info about the conntrack table
|
||||
func ConntrackStats(percpu bool) ([]ConntrackStat, error) {
|
||||
return ConntrackStatsWithContext(context.Background(), percpu)
|
||||
}
|
||||
|
||||
// ConntrackStatsWithContext returns more detailed info about the conntrack table
|
||||
func ConntrackStatsWithContext(ctx context.Context, percpu bool) ([]ConntrackStat, error) {
|
||||
return conntrackStatsFromFile(common.HostProc("net/stat/nf_conntrack"), percpu)
|
||||
}
|
||||
|
||||
// conntrackStatsFromFile returns more detailed info about the conntrack table
|
||||
// from `filename`
|
||||
// If 'percpu' is false, the result will contain exactly one item with totals/summary
|
||||
func conntrackStatsFromFile(filename string, percpu bool) ([]ConntrackStat, error) {
|
||||
lines, err := common.ReadLines(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
statlist := NewConntrackStatList()
|
||||
|
||||
for _, line := range lines {
|
||||
fields := strings.Fields(line)
|
||||
if len(fields) == 17 && fields[0] != "entries" {
|
||||
statlist.Append(NewConntrackStat(
|
||||
common.HexToUint32(fields[CT_ENTRIES]),
|
||||
common.HexToUint32(fields[CT_SEARCHED]),
|
||||
common.HexToUint32(fields[CT_FOUND]),
|
||||
common.HexToUint32(fields[CT_NEW]),
|
||||
common.HexToUint32(fields[CT_INVALID]),
|
||||
common.HexToUint32(fields[CT_IGNORE]),
|
||||
common.HexToUint32(fields[CT_DELETE]),
|
||||
common.HexToUint32(fields[CT_DELETE_LIST]),
|
||||
common.HexToUint32(fields[CT_INSERT]),
|
||||
common.HexToUint32(fields[CT_INSERT_FAILED]),
|
||||
common.HexToUint32(fields[CT_DROP]),
|
||||
common.HexToUint32(fields[CT_EARLY_DROP]),
|
||||
common.HexToUint32(fields[CT_ICMP_ERROR]),
|
||||
common.HexToUint32(fields[CT_EXPECT_NEW]),
|
||||
common.HexToUint32(fields[CT_EXPECT_CREATE]),
|
||||
common.HexToUint32(fields[CT_EXPECT_DELETE]),
|
||||
common.HexToUint32(fields[CT_SEARCH_RESTART]),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
if percpu {
|
||||
return statlist.Items(), nil
|
||||
}
|
||||
return statlist.Summary(), nil
|
||||
}
|
||||
|
||||
// http://students.mimuw.edu.pl/lxr/source/include/net/tcp_states.h
|
||||
var TCPStatuses = map[string]string{
|
||||
"01": "ESTABLISHED",
|
||||
@@ -328,32 +401,36 @@ func ConnectionsMaxWithContext(ctx context.Context, kind string, max int) ([]Con
|
||||
return ConnectionsPidMax(kind, 0, max)
|
||||
}
|
||||
|
||||
// Return a list of network connections opened, omitting `Uids`.
|
||||
// WithoutUids functions are reliant on implementation details. They may be altered to be an alias for Connections or be
|
||||
// removed from the API in the future.
|
||||
func ConnectionsWithoutUids(kind string) ([]ConnectionStat, error) {
|
||||
return ConnectionsWithoutUidsWithContext(context.Background(), kind)
|
||||
}
|
||||
|
||||
func ConnectionsWithoutUidsWithContext(ctx context.Context, kind string) ([]ConnectionStat, error) {
|
||||
return ConnectionsMaxWithoutUidsWithContext(ctx, kind, 0)
|
||||
}
|
||||
|
||||
func ConnectionsMaxWithoutUidsWithContext(ctx context.Context, kind string, max int) ([]ConnectionStat, error) {
|
||||
return ConnectionsPidMaxWithoutUidsWithContext(ctx, kind, 0, max)
|
||||
}
|
||||
|
||||
// Return a list of network connections opened by a process.
|
||||
func ConnectionsPid(kind string, pid int32) ([]ConnectionStat, error) {
|
||||
return ConnectionsPidWithContext(context.Background(), kind, pid)
|
||||
}
|
||||
|
||||
func ConnectionsPidWithoutUids(kind string, pid int32) ([]ConnectionStat, error) {
|
||||
return ConnectionsPidWithoutUidsWithContext(context.Background(), kind, pid)
|
||||
}
|
||||
|
||||
func ConnectionsPidWithContext(ctx context.Context, kind string, pid int32) ([]ConnectionStat, error) {
|
||||
tmap, ok := netConnectionKindMap[kind]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid kind, %s", kind)
|
||||
}
|
||||
root := common.HostProc()
|
||||
var err error
|
||||
var inodes map[string][]inodeMap
|
||||
if pid == 0 {
|
||||
inodes, err = getProcInodesAll(root, 0)
|
||||
} else {
|
||||
inodes, err = getProcInodes(root, pid, 0)
|
||||
if len(inodes) == 0 {
|
||||
// no connection for the pid
|
||||
return []ConnectionStat{}, nil
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cound not get pid(s), %d: %s", pid, err)
|
||||
}
|
||||
return statsFromInodes(root, pid, tmap, inodes)
|
||||
return ConnectionsPidMaxWithContext(ctx, kind, pid, 0)
|
||||
}
|
||||
|
||||
func ConnectionsPidWithoutUidsWithContext(ctx context.Context, kind string, pid int32) ([]ConnectionStat, error) {
|
||||
return ConnectionsPidMaxWithoutUidsWithContext(ctx, kind, pid, 0)
|
||||
}
|
||||
|
||||
// Return up to `max` network connections opened by a process.
|
||||
@@ -361,7 +438,19 @@ func ConnectionsPidMax(kind string, pid int32, max int) ([]ConnectionStat, error
|
||||
return ConnectionsPidMaxWithContext(context.Background(), kind, pid, max)
|
||||
}
|
||||
|
||||
func ConnectionsPidMaxWithoutUids(kind string, pid int32, max int) ([]ConnectionStat, error) {
|
||||
return ConnectionsPidMaxWithoutUidsWithContext(context.Background(), kind, pid, max)
|
||||
}
|
||||
|
||||
func ConnectionsPidMaxWithContext(ctx context.Context, kind string, pid int32, max int) ([]ConnectionStat, error) {
|
||||
return connectionsPidMaxWithoutUidsWithContext(ctx, kind, pid, max, false)
|
||||
}
|
||||
|
||||
func ConnectionsPidMaxWithoutUidsWithContext(ctx context.Context, kind string, pid int32, max int) ([]ConnectionStat, error) {
|
||||
return connectionsPidMaxWithoutUidsWithContext(ctx, kind, pid, max, true)
|
||||
}
|
||||
|
||||
func connectionsPidMaxWithoutUidsWithContext(ctx context.Context, kind string, pid int32, max int, skipUids bool) ([]ConnectionStat, error) {
|
||||
tmap, ok := netConnectionKindMap[kind]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid kind, %s", kind)
|
||||
@@ -379,12 +468,12 @@ func ConnectionsPidMaxWithContext(ctx context.Context, kind string, pid int32, m
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cound not get pid(s), %d", pid)
|
||||
return nil, fmt.Errorf("cound not get pid(s), %d: %s", pid, err)
|
||||
}
|
||||
return statsFromInodes(root, pid, tmap, inodes)
|
||||
return statsFromInodes(root, pid, tmap, inodes, skipUids)
|
||||
}
|
||||
|
||||
func statsFromInodes(root string, pid int32, tmap []netConnectionKindType, inodes map[string][]inodeMap) ([]ConnectionStat, error) {
|
||||
func statsFromInodes(root string, pid int32, tmap []netConnectionKindType, inodes map[string][]inodeMap, skipUids bool) ([]ConnectionStat, error) {
|
||||
dupCheckMap := make(map[string]struct{})
|
||||
var ret []ConnectionStat
|
||||
|
||||
@@ -393,11 +482,13 @@ func statsFromInodes(root string, pid int32, tmap []netConnectionKindType, inode
|
||||
var path string
|
||||
var connKey string
|
||||
var ls []connTmp
|
||||
path = fmt.Sprintf("%s/net/%s", root, t.filename)
|
||||
if pid == 0 {
|
||||
path = fmt.Sprintf("%s/net/%s", root, t.filename)
|
||||
} else {
|
||||
path = fmt.Sprintf("%s/%d/net/%s", root, pid, t.filename)
|
||||
}
|
||||
switch t.family {
|
||||
case syscall.AF_INET:
|
||||
fallthrough
|
||||
case syscall.AF_INET6:
|
||||
case syscall.AF_INET, syscall.AF_INET6:
|
||||
ls, err = processInet(path, t, inodes, pid)
|
||||
case syscall.AF_UNIX:
|
||||
ls, err = processUnix(path, t, inodes, pid)
|
||||
@@ -429,9 +520,11 @@ func statsFromInodes(root string, pid int32, tmap []netConnectionKindType, inode
|
||||
conn.Pid = c.pid
|
||||
}
|
||||
|
||||
// fetch process owner Real, effective, saved set, and filesystem UIDs
|
||||
proc := process{Pid: conn.Pid}
|
||||
conn.Uids, _ = proc.getUids()
|
||||
if !skipUids {
|
||||
// fetch process owner Real, effective, saved set, and filesystem UIDs
|
||||
proc := process{Pid: conn.Pid}
|
||||
conn.Uids, _ = proc.getUids()
|
||||
}
|
||||
|
||||
ret = append(ret, conn)
|
||||
dupCheckMap[connKey] = struct{}{}
|
||||
@@ -579,7 +672,7 @@ func getProcInodesAll(root string, max int) (map[string][]inodeMap, error) {
|
||||
t, err := getProcInodes(root, pid, max)
|
||||
if err != nil {
|
||||
// skip if permission error or no longer exists
|
||||
if os.IsPermission(err) || os.IsNotExist(err) {
|
||||
if os.IsPermission(err) || os.IsNotExist(err) || err == io.EOF {
|
||||
continue
|
||||
}
|
||||
return ret, err
|
||||
|
||||
163
vendor/github.com/shirou/gopsutil/net/net_linux_test.go
generated
vendored
163
vendor/github.com/shirou/gopsutil/net/net_linux_test.go
generated
vendored
@@ -1,163 +0,0 @@
|
||||
package net
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
"syscall"
|
||||
"testing"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestIOCountersByFileParsing(t *testing.T) {
|
||||
// Prpare a temporary file, which will be read during the test
|
||||
tmpfile, err := ioutil.TempFile("", "proc_dev_net")
|
||||
defer os.Remove(tmpfile.Name()) // clean up
|
||||
|
||||
assert.Nil(t, err, "Temporary file creation failed: ", err)
|
||||
|
||||
cases := [4][2]string{
|
||||
[2]string{"eth0: ", "eth1: "},
|
||||
[2]string{"eth0:0: ", "eth1:0: "},
|
||||
[2]string{"eth0:", "eth1:"},
|
||||
[2]string{"eth0:0:", "eth1:0:"},
|
||||
}
|
||||
for _, testCase := range cases {
|
||||
err = tmpfile.Truncate(0)
|
||||
assert.Nil(t, err, "Temporary file truncating problem: ", err)
|
||||
|
||||
// Parse interface name for assertion
|
||||
interface0 := strings.TrimSpace(testCase[0])
|
||||
interface0 = interface0[:len(interface0)-1]
|
||||
|
||||
interface1 := strings.TrimSpace(testCase[1])
|
||||
interface1 = interface1[:len(interface1)-1]
|
||||
|
||||
// Replace the interfaces from the test case
|
||||
proc := []byte(fmt.Sprintf("Inter-| Receive | Transmit\n face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed\n %s1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16\n %s100 200 300 400 500 600 700 800 900 1000 1100 1200 1300 1400 1500 1600\n", testCase[0], testCase[1]))
|
||||
|
||||
// Write /proc/net/dev sample output
|
||||
_, err = tmpfile.Write(proc)
|
||||
assert.Nil(t, err, "Temporary file writing failed: ", err)
|
||||
|
||||
counters, err := IOCountersByFile(true, tmpfile.Name())
|
||||
|
||||
assert.Nil(t, err)
|
||||
assert.NotEmpty(t, counters)
|
||||
assert.Equal(t, 2, len(counters))
|
||||
assert.Equal(t, interface0, counters[0].Name)
|
||||
assert.Equal(t, 1, int(counters[0].BytesRecv))
|
||||
assert.Equal(t, 2, int(counters[0].PacketsRecv))
|
||||
assert.Equal(t, 3, int(counters[0].Errin))
|
||||
assert.Equal(t, 4, int(counters[0].Dropin))
|
||||
assert.Equal(t, 5, int(counters[0].Fifoin))
|
||||
assert.Equal(t, 9, int(counters[0].BytesSent))
|
||||
assert.Equal(t, 10, int(counters[0].PacketsSent))
|
||||
assert.Equal(t, 11, int(counters[0].Errout))
|
||||
assert.Equal(t, 12, int(counters[0].Dropout))
|
||||
assert.Equal(t, 13, int(counters[0].Fifoout))
|
||||
assert.Equal(t, interface1, counters[1].Name)
|
||||
assert.Equal(t, 100, int(counters[1].BytesRecv))
|
||||
assert.Equal(t, 200, int(counters[1].PacketsRecv))
|
||||
assert.Equal(t, 300, int(counters[1].Errin))
|
||||
assert.Equal(t, 400, int(counters[1].Dropin))
|
||||
assert.Equal(t, 500, int(counters[1].Fifoin))
|
||||
assert.Equal(t, 900, int(counters[1].BytesSent))
|
||||
assert.Equal(t, 1000, int(counters[1].PacketsSent))
|
||||
assert.Equal(t, 1100, int(counters[1].Errout))
|
||||
assert.Equal(t, 1200, int(counters[1].Dropout))
|
||||
assert.Equal(t, 1300, int(counters[1].Fifoout))
|
||||
}
|
||||
|
||||
err = tmpfile.Close()
|
||||
assert.Nil(t, err, "Temporary file closing failed: ", err)
|
||||
}
|
||||
|
||||
func TestGetProcInodesAll(t *testing.T) {
|
||||
if os.Getenv("CIRCLECI") == "true" {
|
||||
t.Skip("Skip CI")
|
||||
}
|
||||
|
||||
root := common.HostProc("")
|
||||
v, err := getProcInodesAll(root, 0)
|
||||
assert.Nil(t, err)
|
||||
assert.NotEmpty(t, v)
|
||||
}
|
||||
|
||||
func TestConnectionsMax(t *testing.T) {
|
||||
if os.Getenv("CIRCLECI") == "true" {
|
||||
t.Skip("Skip CI")
|
||||
}
|
||||
|
||||
max := 10
|
||||
v, err := ConnectionsMax("tcp", max)
|
||||
assert.Nil(t, err)
|
||||
assert.NotEmpty(t, v)
|
||||
|
||||
cxByPid := map[int32]int{}
|
||||
for _, cx := range v {
|
||||
if cx.Pid > 0 {
|
||||
cxByPid[cx.Pid]++
|
||||
}
|
||||
}
|
||||
for _, c := range cxByPid {
|
||||
assert.True(t, c <= max)
|
||||
}
|
||||
}
|
||||
|
||||
type AddrTest struct {
|
||||
IP string
|
||||
Port int
|
||||
Error bool
|
||||
}
|
||||
|
||||
func TestDecodeAddress(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
addr := map[string]AddrTest{
|
||||
"0500000A:0016": {
|
||||
IP: "10.0.0.5",
|
||||
Port: 22,
|
||||
},
|
||||
"0100007F:D1C2": {
|
||||
IP: "127.0.0.1",
|
||||
Port: 53698,
|
||||
},
|
||||
"11111:0035": {
|
||||
Error: true,
|
||||
},
|
||||
"0100007F:BLAH": {
|
||||
Error: true,
|
||||
},
|
||||
"0085002452100113070057A13F025401:0035": {
|
||||
IP: "2400:8500:1301:1052:a157:7:154:23f",
|
||||
Port: 53,
|
||||
},
|
||||
"00855210011307F025401:0035": {
|
||||
Error: true,
|
||||
},
|
||||
}
|
||||
|
||||
for src, dst := range addr {
|
||||
family := syscall.AF_INET
|
||||
if len(src) > 13 {
|
||||
family = syscall.AF_INET6
|
||||
}
|
||||
addr, err := decodeAddress(uint32(family), src)
|
||||
if dst.Error {
|
||||
assert.NotNil(err, src)
|
||||
} else {
|
||||
assert.Nil(err, src)
|
||||
assert.Equal(dst.IP, addr.IP, src)
|
||||
assert.Equal(dst.Port, int(addr.Port), src)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestReverse(t *testing.T) {
|
||||
src := []byte{0x01, 0x02, 0x03}
|
||||
assert.Equal(t, []byte{0x03, 0x02, 0x01}, Reverse(src))
|
||||
}
|
||||
16
vendor/github.com/shirou/gopsutil/net/net_openbsd.go
generated
vendored
16
vendor/github.com/shirou/gopsutil/net/net_openbsd.go
generated
vendored
@@ -41,7 +41,7 @@ func ParseNetstat(output string, mode string,
|
||||
continue
|
||||
}
|
||||
base := 1
|
||||
// sometimes Address is ommitted
|
||||
// sometimes Address is omitted
|
||||
if len(values) < columns {
|
||||
base = 0
|
||||
}
|
||||
@@ -106,11 +106,11 @@ func IOCountersWithContext(ctx context.Context, pernic bool) ([]IOCountersStat,
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out, err := invoke.Command(netstat, "-inb")
|
||||
out, err := invoke.CommandWithContext(ctx, netstat, "-inb")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out2, err := invoke.Command(netstat, "-ind")
|
||||
out2, err := invoke.CommandWithContext(ctx, netstat, "-ind")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -156,6 +156,14 @@ func FilterCountersWithContext(ctx context.Context) ([]FilterStat, error) {
|
||||
return nil, errors.New("NetFilterCounters not implemented for openbsd")
|
||||
}
|
||||
|
||||
func ConntrackStats(percpu bool) ([]ConntrackStat, error) {
|
||||
return ConntrackStatsWithContext(context.Background(), percpu)
|
||||
}
|
||||
|
||||
func ConntrackStatsWithContext(ctx context.Context, percpu bool) ([]ConntrackStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
// NetProtoCounters returns network statistics for the entire system
|
||||
// If protocols is empty then all protocols are returned, otherwise
|
||||
// just the protocols in the list are returned.
|
||||
@@ -290,7 +298,7 @@ func ConnectionsWithContext(ctx context.Context, kind string) ([]ConnectionStat,
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out, err := invoke.Command(netstat, args...)
|
||||
out, err := invoke.CommandWithContext(ctx, netstat, args...)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
229
vendor/github.com/shirou/gopsutil/net/net_test.go
generated
vendored
229
vendor/github.com/shirou/gopsutil/net/net_test.go
generated
vendored
@@ -1,229 +0,0 @@
|
||||
package net
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
)
|
||||
|
||||
func TestAddrString(t *testing.T) {
|
||||
v := Addr{IP: "192.168.0.1", Port: 8000}
|
||||
|
||||
s := fmt.Sprintf("%v", v)
|
||||
if s != "{\"ip\":\"192.168.0.1\",\"port\":8000}" {
|
||||
t.Errorf("Addr string is invalid: %v", v)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNetIOCountersStatString(t *testing.T) {
|
||||
v := IOCountersStat{
|
||||
Name: "test",
|
||||
BytesSent: 100,
|
||||
}
|
||||
e := `{"name":"test","bytesSent":100,"bytesRecv":0,"packetsSent":0,"packetsRecv":0,"errin":0,"errout":0,"dropin":0,"dropout":0,"fifoin":0,"fifoout":0}`
|
||||
if e != fmt.Sprintf("%v", v) {
|
||||
t.Errorf("NetIOCountersStat string is invalid: %v", v)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNetProtoCountersStatString(t *testing.T) {
|
||||
v := ProtoCountersStat{
|
||||
Protocol: "tcp",
|
||||
Stats: map[string]int64{
|
||||
"MaxConn": -1,
|
||||
"ActiveOpens": 4000,
|
||||
"PassiveOpens": 3000,
|
||||
},
|
||||
}
|
||||
e := `{"protocol":"tcp","stats":{"ActiveOpens":4000,"MaxConn":-1,"PassiveOpens":3000}}`
|
||||
if e != fmt.Sprintf("%v", v) {
|
||||
t.Errorf("NetProtoCountersStat string is invalid: %v", v)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestNetConnectionStatString(t *testing.T) {
|
||||
v := ConnectionStat{
|
||||
Fd: 10,
|
||||
Family: 10,
|
||||
Type: 10,
|
||||
Uids: []int32{10, 10},
|
||||
}
|
||||
e := `{"fd":10,"family":10,"type":10,"localaddr":{"ip":"","port":0},"remoteaddr":{"ip":"","port":0},"status":"","uids":[10,10],"pid":0}`
|
||||
if e != fmt.Sprintf("%v", v) {
|
||||
t.Errorf("NetConnectionStat string is invalid: %v", v)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestNetIOCountersAll(t *testing.T) {
|
||||
v, err := IOCounters(false)
|
||||
per, err := IOCounters(true)
|
||||
if err != nil {
|
||||
t.Errorf("Could not get NetIOCounters: %v", err)
|
||||
}
|
||||
if len(v) != 1 {
|
||||
t.Errorf("Could not get NetIOCounters: %v", v)
|
||||
}
|
||||
if v[0].Name != "all" {
|
||||
t.Errorf("Invalid NetIOCounters: %v", v)
|
||||
}
|
||||
var pr uint64
|
||||
for _, p := range per {
|
||||
pr += p.PacketsRecv
|
||||
}
|
||||
if v[0].PacketsRecv != pr {
|
||||
t.Errorf("invalid sum value: %v, %v", v[0].PacketsRecv, pr)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNetIOCountersPerNic(t *testing.T) {
|
||||
v, err := IOCounters(true)
|
||||
if err != nil {
|
||||
t.Errorf("Could not get NetIOCounters: %v", err)
|
||||
}
|
||||
if len(v) == 0 {
|
||||
t.Errorf("Could not get NetIOCounters: %v", v)
|
||||
}
|
||||
for _, vv := range v {
|
||||
if vv.Name == "" {
|
||||
t.Errorf("Invalid NetIOCounters: %v", vv)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetNetIOCountersAll(t *testing.T) {
|
||||
n := []IOCountersStat{
|
||||
{
|
||||
Name: "a",
|
||||
BytesRecv: 10,
|
||||
PacketsRecv: 10,
|
||||
},
|
||||
{
|
||||
Name: "b",
|
||||
BytesRecv: 10,
|
||||
PacketsRecv: 10,
|
||||
Errin: 10,
|
||||
},
|
||||
}
|
||||
ret, err := getIOCountersAll(n)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if len(ret) != 1 {
|
||||
t.Errorf("invalid return count")
|
||||
}
|
||||
if ret[0].Name != "all" {
|
||||
t.Errorf("invalid return name")
|
||||
}
|
||||
if ret[0].BytesRecv != 20 {
|
||||
t.Errorf("invalid count bytesrecv")
|
||||
}
|
||||
if ret[0].Errin != 10 {
|
||||
t.Errorf("invalid count errin")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNetInterfaces(t *testing.T) {
|
||||
v, err := Interfaces()
|
||||
if err != nil {
|
||||
t.Errorf("Could not get NetInterfaceStat: %v", err)
|
||||
}
|
||||
if len(v) == 0 {
|
||||
t.Errorf("Could not get NetInterfaceStat: %v", err)
|
||||
}
|
||||
for _, vv := range v {
|
||||
if vv.Name == "" {
|
||||
t.Errorf("Invalid NetInterface: %v", vv)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestNetProtoCountersStatsAll(t *testing.T) {
|
||||
v, err := ProtoCounters(nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Could not get NetProtoCounters: %v", err)
|
||||
}
|
||||
if len(v) == 0 {
|
||||
t.Fatalf("Could not get NetProtoCounters: %v", err)
|
||||
}
|
||||
for _, vv := range v {
|
||||
if vv.Protocol == "" {
|
||||
t.Errorf("Invalid NetProtoCountersStat: %v", vv)
|
||||
}
|
||||
if len(vv.Stats) == 0 {
|
||||
t.Errorf("Invalid NetProtoCountersStat: %v", vv)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestNetProtoCountersStats(t *testing.T) {
|
||||
v, err := ProtoCounters([]string{"tcp", "ip"})
|
||||
if err != nil {
|
||||
t.Fatalf("Could not get NetProtoCounters: %v", err)
|
||||
}
|
||||
if len(v) == 0 {
|
||||
t.Fatalf("Could not get NetProtoCounters: %v", err)
|
||||
}
|
||||
if len(v) != 2 {
|
||||
t.Fatalf("Go incorrect number of NetProtoCounters: %v", err)
|
||||
}
|
||||
for _, vv := range v {
|
||||
if vv.Protocol != "tcp" && vv.Protocol != "ip" {
|
||||
t.Errorf("Invalid NetProtoCountersStat: %v", vv)
|
||||
}
|
||||
if len(vv.Stats) == 0 {
|
||||
t.Errorf("Invalid NetProtoCountersStat: %v", vv)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestNetConnections(t *testing.T) {
|
||||
if ci := os.Getenv("CI"); ci != "" { // skip if test on drone.io
|
||||
return
|
||||
}
|
||||
|
||||
v, err := Connections("inet")
|
||||
if err != nil {
|
||||
t.Errorf("could not get NetConnections: %v", err)
|
||||
}
|
||||
if len(v) == 0 {
|
||||
t.Errorf("could not get NetConnections: %v", v)
|
||||
}
|
||||
for _, vv := range v {
|
||||
if vv.Family == 0 {
|
||||
t.Errorf("invalid NetConnections: %v", vv)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestNetFilterCounters(t *testing.T) {
|
||||
if ci := os.Getenv("CI"); ci != "" { // skip if test on drone.io
|
||||
return
|
||||
}
|
||||
|
||||
if runtime.GOOS == "linux" {
|
||||
// some test environment has not the path.
|
||||
if !common.PathExists("/proc/sys/net/netfilter/nf_conntrackCount") {
|
||||
t.SkipNow()
|
||||
}
|
||||
}
|
||||
|
||||
v, err := FilterCounters()
|
||||
if err != nil {
|
||||
t.Errorf("could not get NetConnections: %v", err)
|
||||
}
|
||||
if len(v) == 0 {
|
||||
t.Errorf("could not get NetConnections: %v", v)
|
||||
}
|
||||
for _, vv := range v {
|
||||
if vv.ConnTrackMax == 0 {
|
||||
t.Errorf("nf_conntrackMax needs to be greater than zero: %v", vv)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
39
vendor/github.com/shirou/gopsutil/net/net_unix.go
generated
vendored
39
vendor/github.com/shirou/gopsutil/net/net_unix.go
generated
vendored
@@ -63,10 +63,10 @@ func ConnectionsPidWithContext(ctx context.Context, kind string, pid int32) ([]C
|
||||
case "udp6":
|
||||
args = append(args, "6udp")
|
||||
case "unix":
|
||||
return ret, common.ErrNotImplementedError
|
||||
args = []string{"-U"}
|
||||
}
|
||||
|
||||
r, err := common.CallLsof(invoke, pid, args...)
|
||||
r, err := common.CallLsofWithContext(ctx, invoke, pid, args...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -94,3 +94,38 @@ func ConnectionsPidMax(kind string, pid int32, max int) ([]ConnectionStat, error
|
||||
func ConnectionsPidMaxWithContext(ctx context.Context, kind string, pid int32, max int) ([]ConnectionStat, error) {
|
||||
return []ConnectionStat{}, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
// Return a list of network connections opened, omitting `Uids`.
|
||||
// WithoutUids functions are reliant on implementation details. They may be altered to be an alias for Connections or be
|
||||
// removed from the API in the future.
|
||||
func ConnectionsWithoutUids(kind string) ([]ConnectionStat, error) {
|
||||
return ConnectionsWithoutUidsWithContext(context.Background(), kind)
|
||||
}
|
||||
|
||||
func ConnectionsWithoutUidsWithContext(ctx context.Context, kind string) ([]ConnectionStat, error) {
|
||||
return ConnectionsMaxWithoutUidsWithContext(ctx, kind, 0)
|
||||
}
|
||||
|
||||
func ConnectionsMaxWithoutUidsWithContext(ctx context.Context, kind string, max int) ([]ConnectionStat, error) {
|
||||
return ConnectionsPidMaxWithoutUidsWithContext(ctx, kind, 0, max)
|
||||
}
|
||||
|
||||
func ConnectionsPidWithoutUids(kind string, pid int32) ([]ConnectionStat, error) {
|
||||
return ConnectionsPidWithoutUidsWithContext(context.Background(), kind, pid)
|
||||
}
|
||||
|
||||
func ConnectionsPidWithoutUidsWithContext(ctx context.Context, kind string, pid int32) ([]ConnectionStat, error) {
|
||||
return ConnectionsPidMaxWithoutUidsWithContext(ctx, kind, pid, 0)
|
||||
}
|
||||
|
||||
func ConnectionsPidMaxWithoutUids(kind string, pid int32, max int) ([]ConnectionStat, error) {
|
||||
return ConnectionsPidMaxWithoutUidsWithContext(context.Background(), kind, pid, max)
|
||||
}
|
||||
|
||||
func ConnectionsPidMaxWithoutUidsWithContext(ctx context.Context, kind string, pid int32, max int) ([]ConnectionStat, error) {
|
||||
return connectionsPidMaxWithoutUidsWithContext(ctx, kind, pid, max)
|
||||
}
|
||||
|
||||
func connectionsPidMaxWithoutUidsWithContext(ctx context.Context, kind string, pid int32, max int) ([]ConnectionStat, error) {
|
||||
return []ConnectionStat{}, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
704
vendor/github.com/shirou/gopsutil/net/net_windows.go
generated
vendored
704
vendor/github.com/shirou/gopsutil/net/net_windows.go
generated
vendored
@@ -5,17 +5,21 @@ package net
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
var (
|
||||
modiphlpapi = windows.NewLazyDLL("iphlpapi.dll")
|
||||
modiphlpapi = windows.NewLazySystemDLL("iphlpapi.dll")
|
||||
procGetExtendedTCPTable = modiphlpapi.NewProc("GetExtendedTcpTable")
|
||||
procGetExtendedUDPTable = modiphlpapi.NewProc("GetExtendedUdpTable")
|
||||
procGetIfEntry2 = modiphlpapi.NewProc("GetIfEntry2")
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -30,6 +34,105 @@ const (
|
||||
TCPTableOwnerModuleAll
|
||||
)
|
||||
|
||||
type netConnectionKindType struct {
|
||||
family uint32
|
||||
sockType uint32
|
||||
filename string
|
||||
}
|
||||
|
||||
var kindTCP4 = netConnectionKindType{
|
||||
family: syscall.AF_INET,
|
||||
sockType: syscall.SOCK_STREAM,
|
||||
filename: "tcp",
|
||||
}
|
||||
var kindTCP6 = netConnectionKindType{
|
||||
family: syscall.AF_INET6,
|
||||
sockType: syscall.SOCK_STREAM,
|
||||
filename: "tcp6",
|
||||
}
|
||||
var kindUDP4 = netConnectionKindType{
|
||||
family: syscall.AF_INET,
|
||||
sockType: syscall.SOCK_DGRAM,
|
||||
filename: "udp",
|
||||
}
|
||||
var kindUDP6 = netConnectionKindType{
|
||||
family: syscall.AF_INET6,
|
||||
sockType: syscall.SOCK_DGRAM,
|
||||
filename: "udp6",
|
||||
}
|
||||
|
||||
var netConnectionKindMap = map[string][]netConnectionKindType{
|
||||
"all": {kindTCP4, kindTCP6, kindUDP4, kindUDP6},
|
||||
"tcp": {kindTCP4, kindTCP6},
|
||||
"tcp4": {kindTCP4},
|
||||
"tcp6": {kindTCP6},
|
||||
"udp": {kindUDP4, kindUDP6},
|
||||
"udp4": {kindUDP4},
|
||||
"udp6": {kindUDP6},
|
||||
"inet": {kindTCP4, kindTCP6, kindUDP4, kindUDP6},
|
||||
"inet4": {kindTCP4, kindUDP4},
|
||||
"inet6": {kindTCP6, kindUDP6},
|
||||
}
|
||||
|
||||
// https://github.com/microsoft/ethr/blob/aecdaf923970e5a9b4c461b4e2e3963d781ad2cc/plt_windows.go#L114-L170
|
||||
type guid struct {
|
||||
Data1 uint32
|
||||
Data2 uint16
|
||||
Data3 uint16
|
||||
Data4 [8]byte
|
||||
}
|
||||
|
||||
const (
|
||||
maxStringSize = 256
|
||||
maxPhysAddressLength = 32
|
||||
pad0for64_4for32 = 0
|
||||
)
|
||||
|
||||
type mibIfRow2 struct {
|
||||
InterfaceLuid uint64
|
||||
InterfaceIndex uint32
|
||||
InterfaceGuid guid
|
||||
Alias [maxStringSize + 1]uint16
|
||||
Description [maxStringSize + 1]uint16
|
||||
PhysicalAddressLength uint32
|
||||
PhysicalAddress [maxPhysAddressLength]uint8
|
||||
PermanentPhysicalAddress [maxPhysAddressLength]uint8
|
||||
Mtu uint32
|
||||
Type uint32
|
||||
TunnelType uint32
|
||||
MediaType uint32
|
||||
PhysicalMediumType uint32
|
||||
AccessType uint32
|
||||
DirectionType uint32
|
||||
InterfaceAndOperStatusFlags uint32
|
||||
OperStatus uint32
|
||||
AdminStatus uint32
|
||||
MediaConnectState uint32
|
||||
NetworkGuid guid
|
||||
ConnectionType uint32
|
||||
padding1 [pad0for64_4for32]byte
|
||||
TransmitLinkSpeed uint64
|
||||
ReceiveLinkSpeed uint64
|
||||
InOctets uint64
|
||||
InUcastPkts uint64
|
||||
InNUcastPkts uint64
|
||||
InDiscards uint64
|
||||
InErrors uint64
|
||||
InUnknownProtos uint64
|
||||
InUcastOctets uint64
|
||||
InMulticastOctets uint64
|
||||
InBroadcastOctets uint64
|
||||
OutOctets uint64
|
||||
OutUcastPkts uint64
|
||||
OutNUcastPkts uint64
|
||||
OutDiscards uint64
|
||||
OutErrors uint64
|
||||
OutUcastOctets uint64
|
||||
OutMulticastOctets uint64
|
||||
OutBroadcastOctets uint64
|
||||
OutQLen uint64
|
||||
}
|
||||
|
||||
func IOCounters(pernic bool) ([]IOCountersStat, error) {
|
||||
return IOCountersWithContext(context.Background(), pernic)
|
||||
}
|
||||
@@ -39,34 +142,59 @@ func IOCountersWithContext(ctx context.Context, pernic bool) ([]IOCountersStat,
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var ret []IOCountersStat
|
||||
var counters []IOCountersStat
|
||||
|
||||
for _, ifi := range ifs {
|
||||
c := IOCountersStat{
|
||||
Name: ifi.Name,
|
||||
err = procGetIfEntry2.Find()
|
||||
if err == nil { // Vista+, uint64 values (issue#693)
|
||||
for _, ifi := range ifs {
|
||||
c := IOCountersStat{
|
||||
Name: ifi.Name,
|
||||
}
|
||||
|
||||
row := mibIfRow2{InterfaceIndex: uint32(ifi.Index)}
|
||||
ret, _, err := procGetIfEntry2.Call(uintptr(unsafe.Pointer(&row)))
|
||||
if ret != 0 {
|
||||
return nil, os.NewSyscallError("GetIfEntry2", err)
|
||||
}
|
||||
c.BytesSent = uint64(row.OutOctets)
|
||||
c.BytesRecv = uint64(row.InOctets)
|
||||
c.PacketsSent = uint64(row.OutUcastPkts)
|
||||
c.PacketsRecv = uint64(row.InUcastPkts)
|
||||
c.Errin = uint64(row.InErrors)
|
||||
c.Errout = uint64(row.OutErrors)
|
||||
c.Dropin = uint64(row.InDiscards)
|
||||
c.Dropout = uint64(row.OutDiscards)
|
||||
|
||||
counters = append(counters, c)
|
||||
}
|
||||
} else { // WinXP fallback, uint32 values
|
||||
for _, ifi := range ifs {
|
||||
c := IOCountersStat{
|
||||
Name: ifi.Name,
|
||||
}
|
||||
|
||||
row := windows.MibIfRow{Index: uint32(ifi.Index)}
|
||||
e := windows.GetIfEntry(&row)
|
||||
if e != nil {
|
||||
return nil, os.NewSyscallError("GetIfEntry", e)
|
||||
row := windows.MibIfRow{Index: uint32(ifi.Index)}
|
||||
err = windows.GetIfEntry(&row)
|
||||
if err != nil {
|
||||
return nil, os.NewSyscallError("GetIfEntry", err)
|
||||
}
|
||||
c.BytesSent = uint64(row.OutOctets)
|
||||
c.BytesRecv = uint64(row.InOctets)
|
||||
c.PacketsSent = uint64(row.OutUcastPkts)
|
||||
c.PacketsRecv = uint64(row.InUcastPkts)
|
||||
c.Errin = uint64(row.InErrors)
|
||||
c.Errout = uint64(row.OutErrors)
|
||||
c.Dropin = uint64(row.InDiscards)
|
||||
c.Dropout = uint64(row.OutDiscards)
|
||||
|
||||
counters = append(counters, c)
|
||||
}
|
||||
c.BytesSent = uint64(row.OutOctets)
|
||||
c.BytesRecv = uint64(row.InOctets)
|
||||
c.PacketsSent = uint64(row.OutUcastPkts)
|
||||
c.PacketsRecv = uint64(row.InUcastPkts)
|
||||
c.Errin = uint64(row.InErrors)
|
||||
c.Errout = uint64(row.OutErrors)
|
||||
c.Dropin = uint64(row.InDiscards)
|
||||
c.Dropout = uint64(row.OutDiscards)
|
||||
|
||||
ret = append(ret, c)
|
||||
}
|
||||
|
||||
if pernic == false {
|
||||
return getIOCountersAll(ret)
|
||||
if !pernic {
|
||||
return getIOCountersAll(counters)
|
||||
}
|
||||
return ret, nil
|
||||
return counters, nil
|
||||
}
|
||||
|
||||
// NetIOCountersByFile is an method which is added just a compatibility for linux.
|
||||
@@ -78,15 +206,71 @@ func IOCountersByFileWithContext(ctx context.Context, pernic bool, filename stri
|
||||
return IOCounters(pernic)
|
||||
}
|
||||
|
||||
// Return a list of network connections opened by a process
|
||||
// Return a list of network connections
|
||||
// Available kind:
|
||||
// reference to netConnectionKindMap
|
||||
func Connections(kind string) ([]ConnectionStat, error) {
|
||||
return ConnectionsWithContext(context.Background(), kind)
|
||||
}
|
||||
|
||||
func ConnectionsWithContext(ctx context.Context, kind string) ([]ConnectionStat, error) {
|
||||
var ret []ConnectionStat
|
||||
return ConnectionsPidWithContext(ctx, kind, 0)
|
||||
}
|
||||
|
||||
return ret, common.ErrNotImplementedError
|
||||
// ConnectionsPid Return a list of network connections opened by a process
|
||||
func ConnectionsPid(kind string, pid int32) ([]ConnectionStat, error) {
|
||||
return ConnectionsPidWithContext(context.Background(), kind, pid)
|
||||
}
|
||||
|
||||
func ConnectionsPidWithContext(ctx context.Context, kind string, pid int32) ([]ConnectionStat, error) {
|
||||
tmap, ok := netConnectionKindMap[kind]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid kind, %s", kind)
|
||||
}
|
||||
return getProcInet(tmap, pid)
|
||||
}
|
||||
|
||||
func getProcInet(kinds []netConnectionKindType, pid int32) ([]ConnectionStat, error) {
|
||||
stats := make([]ConnectionStat, 0)
|
||||
|
||||
for _, kind := range kinds {
|
||||
s, err := getNetStatWithKind(kind)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if pid == 0 {
|
||||
stats = append(stats, s...)
|
||||
} else {
|
||||
for _, ns := range s {
|
||||
if ns.Pid != pid {
|
||||
continue
|
||||
}
|
||||
stats = append(stats, ns)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return stats, nil
|
||||
}
|
||||
|
||||
func getNetStatWithKind(kindType netConnectionKindType) ([]ConnectionStat, error) {
|
||||
if kindType.filename == "" {
|
||||
return nil, fmt.Errorf("kind filename must be required")
|
||||
}
|
||||
|
||||
switch kindType.filename {
|
||||
case kindTCP4.filename:
|
||||
return getTCPConnections(kindTCP4.family)
|
||||
case kindTCP6.filename:
|
||||
return getTCPConnections(kindTCP6.family)
|
||||
case kindUDP4.filename:
|
||||
return getUDPConnections(kindUDP4.family)
|
||||
case kindUDP6.filename:
|
||||
return getUDPConnections(kindUDP6.family)
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("invalid kind filename, %s", kindType.filename)
|
||||
}
|
||||
|
||||
// Return a list of network connections opened returning at most `max`
|
||||
@@ -99,6 +283,41 @@ func ConnectionsMaxWithContext(ctx context.Context, kind string, max int) ([]Con
|
||||
return []ConnectionStat{}, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
// Return a list of network connections opened, omitting `Uids`.
|
||||
// WithoutUids functions are reliant on implementation details. They may be altered to be an alias for Connections or be
|
||||
// removed from the API in the future.
|
||||
func ConnectionsWithoutUids(kind string) ([]ConnectionStat, error) {
|
||||
return ConnectionsWithoutUidsWithContext(context.Background(), kind)
|
||||
}
|
||||
|
||||
func ConnectionsWithoutUidsWithContext(ctx context.Context, kind string) ([]ConnectionStat, error) {
|
||||
return ConnectionsMaxWithoutUidsWithContext(ctx, kind, 0)
|
||||
}
|
||||
|
||||
func ConnectionsMaxWithoutUidsWithContext(ctx context.Context, kind string, max int) ([]ConnectionStat, error) {
|
||||
return ConnectionsPidMaxWithoutUidsWithContext(ctx, kind, 0, max)
|
||||
}
|
||||
|
||||
func ConnectionsPidWithoutUids(kind string, pid int32) ([]ConnectionStat, error) {
|
||||
return ConnectionsPidWithoutUidsWithContext(context.Background(), kind, pid)
|
||||
}
|
||||
|
||||
func ConnectionsPidWithoutUidsWithContext(ctx context.Context, kind string, pid int32) ([]ConnectionStat, error) {
|
||||
return ConnectionsPidMaxWithoutUidsWithContext(ctx, kind, pid, 0)
|
||||
}
|
||||
|
||||
func ConnectionsPidMaxWithoutUids(kind string, pid int32, max int) ([]ConnectionStat, error) {
|
||||
return ConnectionsPidMaxWithoutUidsWithContext(context.Background(), kind, pid, max)
|
||||
}
|
||||
|
||||
func ConnectionsPidMaxWithoutUidsWithContext(ctx context.Context, kind string, pid int32, max int) ([]ConnectionStat, error) {
|
||||
return connectionsPidMaxWithoutUidsWithContext(ctx, kind, pid, max)
|
||||
}
|
||||
|
||||
func connectionsPidMaxWithoutUidsWithContext(ctx context.Context, kind string, pid int32, max int) ([]ConnectionStat, error) {
|
||||
return []ConnectionStat{}, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func FilterCounters() ([]FilterStat, error) {
|
||||
return FilterCountersWithContext(context.Background())
|
||||
}
|
||||
@@ -107,6 +326,15 @@ func FilterCountersWithContext(ctx context.Context) ([]FilterStat, error) {
|
||||
return nil, errors.New("NetFilterCounters not implemented for windows")
|
||||
}
|
||||
|
||||
func ConntrackStats(percpu bool) ([]ConntrackStat, error) {
|
||||
return ConntrackStatsWithContext(context.Background(), percpu)
|
||||
}
|
||||
|
||||
func ConntrackStatsWithContext(ctx context.Context, percpu bool) ([]ConntrackStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
|
||||
// NetProtoCounters returns network statistics for the entire system
|
||||
// If protocols is empty then all protocols are returned, otherwise
|
||||
// just the protocols in the list are returned.
|
||||
@@ -118,3 +346,429 @@ func ProtoCounters(protocols []string) ([]ProtoCountersStat, error) {
|
||||
func ProtoCountersWithContext(ctx context.Context, protocols []string) ([]ProtoCountersStat, error) {
|
||||
return nil, errors.New("NetProtoCounters not implemented for windows")
|
||||
}
|
||||
|
||||
func getTableUintptr(family uint32, buf []byte) uintptr {
|
||||
var (
|
||||
pmibTCPTable pmibTCPTableOwnerPidAll
|
||||
pmibTCP6Table pmibTCP6TableOwnerPidAll
|
||||
|
||||
p uintptr
|
||||
)
|
||||
switch family {
|
||||
case kindTCP4.family:
|
||||
if len(buf) > 0 {
|
||||
pmibTCPTable = (*mibTCPTableOwnerPid)(unsafe.Pointer(&buf[0]))
|
||||
p = uintptr(unsafe.Pointer(pmibTCPTable))
|
||||
} else {
|
||||
p = uintptr(unsafe.Pointer(pmibTCPTable))
|
||||
}
|
||||
case kindTCP6.family:
|
||||
if len(buf) > 0 {
|
||||
pmibTCP6Table = (*mibTCP6TableOwnerPid)(unsafe.Pointer(&buf[0]))
|
||||
p = uintptr(unsafe.Pointer(pmibTCP6Table))
|
||||
} else {
|
||||
p = uintptr(unsafe.Pointer(pmibTCP6Table))
|
||||
}
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
func getTableInfo(filename string, table interface{}) (index, step, length int) {
|
||||
switch filename {
|
||||
case kindTCP4.filename:
|
||||
index = int(unsafe.Sizeof(table.(pmibTCPTableOwnerPidAll).DwNumEntries))
|
||||
step = int(unsafe.Sizeof(table.(pmibTCPTableOwnerPidAll).Table))
|
||||
length = int(table.(pmibTCPTableOwnerPidAll).DwNumEntries)
|
||||
case kindTCP6.filename:
|
||||
index = int(unsafe.Sizeof(table.(pmibTCP6TableOwnerPidAll).DwNumEntries))
|
||||
step = int(unsafe.Sizeof(table.(pmibTCP6TableOwnerPidAll).Table))
|
||||
length = int(table.(pmibTCP6TableOwnerPidAll).DwNumEntries)
|
||||
case kindUDP4.filename:
|
||||
index = int(unsafe.Sizeof(table.(pmibUDPTableOwnerPid).DwNumEntries))
|
||||
step = int(unsafe.Sizeof(table.(pmibUDPTableOwnerPid).Table))
|
||||
length = int(table.(pmibUDPTableOwnerPid).DwNumEntries)
|
||||
case kindUDP6.filename:
|
||||
index = int(unsafe.Sizeof(table.(pmibUDP6TableOwnerPid).DwNumEntries))
|
||||
step = int(unsafe.Sizeof(table.(pmibUDP6TableOwnerPid).Table))
|
||||
length = int(table.(pmibUDP6TableOwnerPid).DwNumEntries)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func getTCPConnections(family uint32) ([]ConnectionStat, error) {
|
||||
var (
|
||||
p uintptr
|
||||
buf []byte
|
||||
size uint32
|
||||
|
||||
pmibTCPTable pmibTCPTableOwnerPidAll
|
||||
pmibTCP6Table pmibTCP6TableOwnerPidAll
|
||||
)
|
||||
|
||||
if family == 0 {
|
||||
return nil, fmt.Errorf("faimly must be required")
|
||||
}
|
||||
|
||||
for {
|
||||
switch family {
|
||||
case kindTCP4.family:
|
||||
if len(buf) > 0 {
|
||||
pmibTCPTable = (*mibTCPTableOwnerPid)(unsafe.Pointer(&buf[0]))
|
||||
p = uintptr(unsafe.Pointer(pmibTCPTable))
|
||||
} else {
|
||||
p = uintptr(unsafe.Pointer(pmibTCPTable))
|
||||
}
|
||||
case kindTCP6.family:
|
||||
if len(buf) > 0 {
|
||||
pmibTCP6Table = (*mibTCP6TableOwnerPid)(unsafe.Pointer(&buf[0]))
|
||||
p = uintptr(unsafe.Pointer(pmibTCP6Table))
|
||||
} else {
|
||||
p = uintptr(unsafe.Pointer(pmibTCP6Table))
|
||||
}
|
||||
}
|
||||
|
||||
err := getExtendedTcpTable(p,
|
||||
&size,
|
||||
true,
|
||||
family,
|
||||
tcpTableOwnerPidAll,
|
||||
0)
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
if err != windows.ERROR_INSUFFICIENT_BUFFER {
|
||||
return nil, err
|
||||
}
|
||||
buf = make([]byte, size)
|
||||
}
|
||||
|
||||
var (
|
||||
index, step int
|
||||
length int
|
||||
)
|
||||
|
||||
stats := make([]ConnectionStat, 0)
|
||||
switch family {
|
||||
case kindTCP4.family:
|
||||
index, step, length = getTableInfo(kindTCP4.filename, pmibTCPTable)
|
||||
case kindTCP6.family:
|
||||
index, step, length = getTableInfo(kindTCP6.filename, pmibTCP6Table)
|
||||
}
|
||||
|
||||
if length == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
for i := 0; i < length; i++ {
|
||||
switch family {
|
||||
case kindTCP4.family:
|
||||
mibs := (*mibTCPRowOwnerPid)(unsafe.Pointer(&buf[index]))
|
||||
ns := mibs.convertToConnectionStat()
|
||||
stats = append(stats, ns)
|
||||
case kindTCP6.family:
|
||||
mibs := (*mibTCP6RowOwnerPid)(unsafe.Pointer(&buf[index]))
|
||||
ns := mibs.convertToConnectionStat()
|
||||
stats = append(stats, ns)
|
||||
}
|
||||
|
||||
index += step
|
||||
}
|
||||
return stats, nil
|
||||
}
|
||||
|
||||
func getUDPConnections(family uint32) ([]ConnectionStat, error) {
|
||||
var (
|
||||
p uintptr
|
||||
buf []byte
|
||||
size uint32
|
||||
|
||||
pmibUDPTable pmibUDPTableOwnerPid
|
||||
pmibUDP6Table pmibUDP6TableOwnerPid
|
||||
)
|
||||
|
||||
if family == 0 {
|
||||
return nil, fmt.Errorf("faimly must be required")
|
||||
}
|
||||
|
||||
for {
|
||||
switch family {
|
||||
case kindUDP4.family:
|
||||
if len(buf) > 0 {
|
||||
pmibUDPTable = (*mibUDPTableOwnerPid)(unsafe.Pointer(&buf[0]))
|
||||
p = uintptr(unsafe.Pointer(pmibUDPTable))
|
||||
} else {
|
||||
p = uintptr(unsafe.Pointer(pmibUDPTable))
|
||||
}
|
||||
case kindUDP6.family:
|
||||
if len(buf) > 0 {
|
||||
pmibUDP6Table = (*mibUDP6TableOwnerPid)(unsafe.Pointer(&buf[0]))
|
||||
p = uintptr(unsafe.Pointer(pmibUDP6Table))
|
||||
} else {
|
||||
p = uintptr(unsafe.Pointer(pmibUDP6Table))
|
||||
}
|
||||
}
|
||||
|
||||
err := getExtendedUdpTable(
|
||||
p,
|
||||
&size,
|
||||
true,
|
||||
family,
|
||||
udpTableOwnerPid,
|
||||
0,
|
||||
)
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
if err != windows.ERROR_INSUFFICIENT_BUFFER {
|
||||
return nil, err
|
||||
}
|
||||
buf = make([]byte, size)
|
||||
}
|
||||
|
||||
var (
|
||||
index, step, length int
|
||||
)
|
||||
|
||||
stats := make([]ConnectionStat, 0)
|
||||
switch family {
|
||||
case kindUDP4.family:
|
||||
index, step, length = getTableInfo(kindUDP4.filename, pmibUDPTable)
|
||||
case kindUDP6.family:
|
||||
index, step, length = getTableInfo(kindUDP6.filename, pmibUDP6Table)
|
||||
}
|
||||
|
||||
if length == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
for i := 0; i < length; i++ {
|
||||
switch family {
|
||||
case kindUDP4.family:
|
||||
mibs := (*mibUDPRowOwnerPid)(unsafe.Pointer(&buf[index]))
|
||||
ns := mibs.convertToConnectionStat()
|
||||
stats = append(stats, ns)
|
||||
case kindUDP4.family:
|
||||
mibs := (*mibUDP6RowOwnerPid)(unsafe.Pointer(&buf[index]))
|
||||
ns := mibs.convertToConnectionStat()
|
||||
stats = append(stats, ns)
|
||||
}
|
||||
|
||||
index += step
|
||||
}
|
||||
return stats, nil
|
||||
}
|
||||
|
||||
// tcpStatuses https://msdn.microsoft.com/en-us/library/windows/desktop/bb485761(v=vs.85).aspx
|
||||
var tcpStatuses = map[mibTCPState]string{
|
||||
1: "CLOSED",
|
||||
2: "LISTEN",
|
||||
3: "SYN_SENT",
|
||||
4: "SYN_RECEIVED",
|
||||
5: "ESTABLISHED",
|
||||
6: "FIN_WAIT_1",
|
||||
7: "FIN_WAIT_2",
|
||||
8: "CLOSE_WAIT",
|
||||
9: "CLOSING",
|
||||
10: "LAST_ACK",
|
||||
11: "TIME_WAIT",
|
||||
12: "DELETE",
|
||||
}
|
||||
|
||||
func getExtendedTcpTable(pTcpTable uintptr, pdwSize *uint32, bOrder bool, ulAf uint32, tableClass tcpTableClass, reserved uint32) (errcode error) {
|
||||
r1, _, _ := syscall.Syscall6(procGetExtendedTCPTable.Addr(), 6, pTcpTable, uintptr(unsafe.Pointer(pdwSize)), getUintptrFromBool(bOrder), uintptr(ulAf), uintptr(tableClass), uintptr(reserved))
|
||||
if r1 != 0 {
|
||||
errcode = syscall.Errno(r1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func getExtendedUdpTable(pUdpTable uintptr, pdwSize *uint32, bOrder bool, ulAf uint32, tableClass udpTableClass, reserved uint32) (errcode error) {
|
||||
r1, _, _ := syscall.Syscall6(procGetExtendedUDPTable.Addr(), 6, pUdpTable, uintptr(unsafe.Pointer(pdwSize)), getUintptrFromBool(bOrder), uintptr(ulAf), uintptr(tableClass), uintptr(reserved))
|
||||
if r1 != 0 {
|
||||
errcode = syscall.Errno(r1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func getUintptrFromBool(b bool) uintptr {
|
||||
if b {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
const anySize = 1
|
||||
|
||||
// type MIB_TCP_STATE int32
|
||||
type mibTCPState int32
|
||||
|
||||
type tcpTableClass int32
|
||||
|
||||
const (
|
||||
tcpTableBasicListener tcpTableClass = iota
|
||||
tcpTableBasicConnections
|
||||
tcpTableBasicAll
|
||||
tcpTableOwnerPidListener
|
||||
tcpTableOwnerPidConnections
|
||||
tcpTableOwnerPidAll
|
||||
tcpTableOwnerModuleListener
|
||||
tcpTableOwnerModuleConnections
|
||||
tcpTableOwnerModuleAll
|
||||
)
|
||||
|
||||
type udpTableClass int32
|
||||
|
||||
const (
|
||||
udpTableBasic udpTableClass = iota
|
||||
udpTableOwnerPid
|
||||
udpTableOwnerModule
|
||||
)
|
||||
|
||||
// TCP
|
||||
|
||||
type mibTCPRowOwnerPid struct {
|
||||
DwState uint32
|
||||
DwLocalAddr uint32
|
||||
DwLocalPort uint32
|
||||
DwRemoteAddr uint32
|
||||
DwRemotePort uint32
|
||||
DwOwningPid uint32
|
||||
}
|
||||
|
||||
func (m *mibTCPRowOwnerPid) convertToConnectionStat() ConnectionStat {
|
||||
ns := ConnectionStat{
|
||||
Family: kindTCP4.family,
|
||||
Type: kindTCP4.sockType,
|
||||
Laddr: Addr{
|
||||
IP: parseIPv4HexString(m.DwLocalAddr),
|
||||
Port: uint32(decodePort(m.DwLocalPort)),
|
||||
},
|
||||
Raddr: Addr{
|
||||
IP: parseIPv4HexString(m.DwRemoteAddr),
|
||||
Port: uint32(decodePort(m.DwRemotePort)),
|
||||
},
|
||||
Pid: int32(m.DwOwningPid),
|
||||
Status: tcpStatuses[mibTCPState(m.DwState)],
|
||||
}
|
||||
|
||||
return ns
|
||||
}
|
||||
|
||||
type mibTCPTableOwnerPid struct {
|
||||
DwNumEntries uint32
|
||||
Table [anySize]mibTCPRowOwnerPid
|
||||
}
|
||||
|
||||
type mibTCP6RowOwnerPid struct {
|
||||
UcLocalAddr [16]byte
|
||||
DwLocalScopeId uint32
|
||||
DwLocalPort uint32
|
||||
UcRemoteAddr [16]byte
|
||||
DwRemoteScopeId uint32
|
||||
DwRemotePort uint32
|
||||
DwState uint32
|
||||
DwOwningPid uint32
|
||||
}
|
||||
|
||||
func (m *mibTCP6RowOwnerPid) convertToConnectionStat() ConnectionStat {
|
||||
ns := ConnectionStat{
|
||||
Family: kindTCP6.family,
|
||||
Type: kindTCP6.sockType,
|
||||
Laddr: Addr{
|
||||
IP: parseIPv6HexString(m.UcLocalAddr),
|
||||
Port: uint32(decodePort(m.DwLocalPort)),
|
||||
},
|
||||
Raddr: Addr{
|
||||
IP: parseIPv6HexString(m.UcRemoteAddr),
|
||||
Port: uint32(decodePort(m.DwRemotePort)),
|
||||
},
|
||||
Pid: int32(m.DwOwningPid),
|
||||
Status: tcpStatuses[mibTCPState(m.DwState)],
|
||||
}
|
||||
|
||||
return ns
|
||||
}
|
||||
|
||||
type mibTCP6TableOwnerPid struct {
|
||||
DwNumEntries uint32
|
||||
Table [anySize]mibTCP6RowOwnerPid
|
||||
}
|
||||
|
||||
type pmibTCPTableOwnerPidAll *mibTCPTableOwnerPid
|
||||
type pmibTCP6TableOwnerPidAll *mibTCP6TableOwnerPid
|
||||
|
||||
// UDP
|
||||
|
||||
type mibUDPRowOwnerPid struct {
|
||||
DwLocalAddr uint32
|
||||
DwLocalPort uint32
|
||||
DwOwningPid uint32
|
||||
}
|
||||
|
||||
func (m *mibUDPRowOwnerPid) convertToConnectionStat() ConnectionStat {
|
||||
ns := ConnectionStat{
|
||||
Family: kindUDP4.family,
|
||||
Type: kindUDP4.sockType,
|
||||
Laddr: Addr{
|
||||
IP: parseIPv4HexString(m.DwLocalAddr),
|
||||
Port: uint32(decodePort(m.DwLocalPort)),
|
||||
},
|
||||
Pid: int32(m.DwOwningPid),
|
||||
}
|
||||
|
||||
return ns
|
||||
}
|
||||
|
||||
type mibUDPTableOwnerPid struct {
|
||||
DwNumEntries uint32
|
||||
Table [anySize]mibUDPRowOwnerPid
|
||||
}
|
||||
|
||||
type mibUDP6RowOwnerPid struct {
|
||||
UcLocalAddr [16]byte
|
||||
DwLocalScopeId uint32
|
||||
DwLocalPort uint32
|
||||
DwOwningPid uint32
|
||||
}
|
||||
|
||||
func (m *mibUDP6RowOwnerPid) convertToConnectionStat() ConnectionStat {
|
||||
ns := ConnectionStat{
|
||||
Family: kindUDP6.family,
|
||||
Type: kindUDP6.sockType,
|
||||
Laddr: Addr{
|
||||
IP: parseIPv6HexString(m.UcLocalAddr),
|
||||
Port: uint32(decodePort(m.DwLocalPort)),
|
||||
},
|
||||
Pid: int32(m.DwOwningPid),
|
||||
}
|
||||
|
||||
return ns
|
||||
}
|
||||
|
||||
type mibUDP6TableOwnerPid struct {
|
||||
DwNumEntries uint32
|
||||
Table [anySize]mibUDP6RowOwnerPid
|
||||
}
|
||||
|
||||
type pmibUDPTableOwnerPid *mibUDPTableOwnerPid
|
||||
type pmibUDP6TableOwnerPid *mibUDP6TableOwnerPid
|
||||
|
||||
func decodePort(port uint32) uint16 {
|
||||
return syscall.Ntohs(uint16(port))
|
||||
}
|
||||
|
||||
func parseIPv4HexString(addr uint32) string {
|
||||
return fmt.Sprintf("%d.%d.%d.%d", addr&255, addr>>8&255, addr>>16&255, addr>>24&255)
|
||||
}
|
||||
|
||||
func parseIPv6HexString(addr [16]byte) string {
|
||||
var ret [16]byte
|
||||
for i := 0; i < 16; i++ {
|
||||
ret[i] = uint8(addr[i])
|
||||
}
|
||||
|
||||
// convert []byte to net.IP
|
||||
ip := net.IP(ret[:])
|
||||
return ip.String()
|
||||
}
|
||||
|
||||
103
vendor/github.com/shirou/gopsutil/process/process.go
generated
vendored
103
vendor/github.com/shirou/gopsutil/process/process.go
generated
vendored
@@ -3,7 +3,9 @@ package process
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"runtime"
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"github.com/shirou/gopsutil/cpu"
|
||||
@@ -11,11 +13,11 @@ import (
|
||||
"github.com/shirou/gopsutil/mem"
|
||||
)
|
||||
|
||||
var invoke common.Invoker
|
||||
|
||||
func init() {
|
||||
invoke = common.Invoke{}
|
||||
}
|
||||
var (
|
||||
invoke common.Invoker = common.Invoke{}
|
||||
ErrorNoChildren = errors.New("process does not have children")
|
||||
ErrorProcessNotRunning = errors.New("process does not exist")
|
||||
)
|
||||
|
||||
type Process struct {
|
||||
Pid int32 `json:"pid"`
|
||||
@@ -28,6 +30,7 @@ type Process struct {
|
||||
numThreads int32
|
||||
memInfo *MemoryInfoStat
|
||||
sigInfo *SignalInfoStat
|
||||
createTime int64
|
||||
|
||||
lastCPUTimes *cpu.TimesStat
|
||||
lastCPUTime time.Time
|
||||
@@ -43,6 +46,7 @@ type OpenFilesStat struct {
|
||||
type MemoryInfoStat struct {
|
||||
RSS uint64 `json:"rss"` // bytes
|
||||
VMS uint64 `json:"vms"` // bytes
|
||||
HWM uint64 `json:"hwm"` // bytes
|
||||
Data uint64 `json:"data"` // bytes
|
||||
Stack uint64 `json:"stack"` // bytes
|
||||
Locked uint64 `json:"locked"` // bytes
|
||||
@@ -76,6 +80,13 @@ type NumCtxSwitchesStat struct {
|
||||
Involuntary int64 `json:"involuntary"`
|
||||
}
|
||||
|
||||
type PageFaultsStat struct {
|
||||
MinorFaults uint64 `json:"minorFaults"`
|
||||
MajorFaults uint64 `json:"majorFaults"`
|
||||
ChildMinorFaults uint64 `json:"childMinorFaults"`
|
||||
ChildMajorFaults uint64 `json:"childMajorFaults"`
|
||||
}
|
||||
|
||||
// Resource limit constants are from /usr/include/x86_64-linux-gnu/bits/resource.h
|
||||
// from libc6-dev package in Ubuntu 16.10
|
||||
const (
|
||||
@@ -127,23 +138,50 @@ func (p NumCtxSwitchesStat) String() string {
|
||||
return string(s)
|
||||
}
|
||||
|
||||
// Pids returns a slice of process ID list which are running now.
|
||||
func Pids() ([]int32, error) {
|
||||
return PidsWithContext(context.Background())
|
||||
}
|
||||
|
||||
func PidsWithContext(ctx context.Context) ([]int32, error) {
|
||||
pids, err := pidsWithContext(ctx)
|
||||
sort.Slice(pids, func(i, j int) bool { return pids[i] < pids[j] })
|
||||
return pids, err
|
||||
}
|
||||
|
||||
// NewProcess creates a new Process instance, it only stores the pid and
|
||||
// checks that the process exists. Other method on Process can be used
|
||||
// to get more information about the process. An error will be returned
|
||||
// if the process does not exist.
|
||||
func NewProcess(pid int32) (*Process, error) {
|
||||
p := &Process{Pid: pid}
|
||||
|
||||
exists, err := PidExists(pid)
|
||||
if err != nil {
|
||||
return p, err
|
||||
}
|
||||
if !exists {
|
||||
return p, ErrorProcessNotRunning
|
||||
}
|
||||
p.CreateTime()
|
||||
return p, nil
|
||||
}
|
||||
|
||||
func PidExists(pid int32) (bool, error) {
|
||||
return PidExistsWithContext(context.Background(), pid)
|
||||
}
|
||||
|
||||
func PidExistsWithContext(ctx context.Context, pid int32) (bool, error) {
|
||||
pids, err := Pids()
|
||||
// Background returns true if the process is in background, false otherwise.
|
||||
func (p *Process) Background() (bool, error) {
|
||||
return p.BackgroundWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) BackgroundWithContext(ctx context.Context) (bool, error) {
|
||||
fg, err := p.ForegroundWithContext(ctx)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
for _, i := range pids {
|
||||
if i == pid {
|
||||
return true, err
|
||||
}
|
||||
}
|
||||
|
||||
return false, err
|
||||
return !fg, err
|
||||
}
|
||||
|
||||
// If interval is 0, return difference from last call(non-blocking).
|
||||
@@ -185,6 +223,41 @@ func (p *Process) PercentWithContext(ctx context.Context, interval time.Duration
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// IsRunning returns whether the process is still running or not.
|
||||
func (p *Process) IsRunning() (bool, error) {
|
||||
return p.IsRunningWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) IsRunningWithContext(ctx context.Context) (bool, error) {
|
||||
createTime, err := p.CreateTimeWithContext(ctx)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
p2, err := NewProcess(p.Pid)
|
||||
if err == ErrorProcessNotRunning {
|
||||
return false, nil
|
||||
}
|
||||
createTime2, err := p2.CreateTimeWithContext(ctx)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return createTime == createTime2, nil
|
||||
}
|
||||
|
||||
// CreateTime returns created time of the process in milliseconds since the epoch, in UTC.
|
||||
func (p *Process) CreateTime() (int64, error) {
|
||||
return p.CreateTimeWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) CreateTimeWithContext(ctx context.Context) (int64, error) {
|
||||
if p.createTime != 0 {
|
||||
return p.createTime, nil
|
||||
}
|
||||
createTime, err := p.createTimeWithContext(ctx)
|
||||
p.createTime = createTime
|
||||
return p.createTime, err
|
||||
}
|
||||
|
||||
func calculatePercent(t1, t2 *cpu.TimesStat, delta float64, numcpu int) float64 {
|
||||
if delta == 0 {
|
||||
return 0
|
||||
|
||||
196
vendor/github.com/shirou/gopsutil/process/process_darwin.go
generated
vendored
196
vendor/github.com/shirou/gopsutil/process/process_darwin.go
generated
vendored
@@ -8,6 +8,7 @@ import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -44,14 +45,10 @@ type MemoryInfoExStat struct {
|
||||
type MemoryMapsStat struct {
|
||||
}
|
||||
|
||||
func Pids() ([]int32, error) {
|
||||
return PidsWithContext(context.Background())
|
||||
}
|
||||
|
||||
func PidsWithContext(ctx context.Context) ([]int32, error) {
|
||||
func pidsWithContext(ctx context.Context) ([]int32, error) {
|
||||
var ret []int32
|
||||
|
||||
pids, err := callPs("pid", 0, false)
|
||||
pids, err := callPsWithContext(ctx, "pid", 0, false)
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
@@ -72,7 +69,7 @@ func (p *Process) Ppid() (int32, error) {
|
||||
}
|
||||
|
||||
func (p *Process) PpidWithContext(ctx context.Context) (int32, error) {
|
||||
r, err := callPs("ppid", p.Pid, false)
|
||||
r, err := callPsWithContext(ctx, "ppid", p.Pid, false)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@@ -93,8 +90,24 @@ func (p *Process) NameWithContext(ctx context.Context) (string, error) {
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
name := common.IntToString(k.Proc.P_comm[:])
|
||||
|
||||
return common.IntToString(k.Proc.P_comm[:]), nil
|
||||
if len(name) >= 15 {
|
||||
cmdlineSlice, err := p.CmdlineSliceWithContext(ctx)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if len(cmdlineSlice) > 0 {
|
||||
extendedName := filepath.Base(cmdlineSlice[0])
|
||||
if strings.HasPrefix(extendedName, p.name) {
|
||||
name = extendedName
|
||||
} else {
|
||||
name = cmdlineSlice[0]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return name, nil
|
||||
}
|
||||
func (p *Process) Tgid() (int32, error) {
|
||||
return 0, common.ErrNotImplementedError
|
||||
@@ -103,37 +116,6 @@ func (p *Process) Exe() (string, error) {
|
||||
return p.ExeWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) ExeWithContext(ctx context.Context) (string, error) {
|
||||
lsof_bin, err := exec.LookPath("lsof")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
awk_bin, err := exec.LookPath("awk")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
sed_bin, err := exec.LookPath("sed")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
lsof := exec.Command(lsof_bin, "-p", strconv.Itoa(int(p.Pid)), "-Fpfn")
|
||||
awk := exec.Command(awk_bin, "NR==5{print}")
|
||||
sed := exec.Command(sed_bin, "s/n\\//\\//")
|
||||
|
||||
output, _, err := common.Pipeline(lsof, awk, sed)
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
ret := strings.TrimSpace(string(output))
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// Cmdline returns the command line arguments of the process as a string with
|
||||
// each argument separated by 0x20 ascii character.
|
||||
func (p *Process) Cmdline() (string, error) {
|
||||
@@ -141,7 +123,7 @@ func (p *Process) Cmdline() (string, error) {
|
||||
}
|
||||
|
||||
func (p *Process) CmdlineWithContext(ctx context.Context) (string, error) {
|
||||
r, err := callPs("command", p.Pid, false)
|
||||
r, err := callPsWithContext(ctx, "command", p.Pid, false)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -158,18 +140,15 @@ func (p *Process) CmdlineSlice() ([]string, error) {
|
||||
}
|
||||
|
||||
func (p *Process) CmdlineSliceWithContext(ctx context.Context) ([]string, error) {
|
||||
r, err := callPs("command", p.Pid, false)
|
||||
r, err := callPsWithContext(ctx, "command", p.Pid, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return r[0], err
|
||||
}
|
||||
func (p *Process) CreateTime() (int64, error) {
|
||||
return p.CreateTimeWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) CreateTimeWithContext(ctx context.Context) (int64, error) {
|
||||
r, err := callPs("etime", p.Pid, false)
|
||||
func (p *Process) createTimeWithContext(ctx context.Context) (int64, error) {
|
||||
r, err := callPsWithContext(ctx, "etime", p.Pid, false)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@@ -210,7 +189,7 @@ func (p *Process) Parent() (*Process, error) {
|
||||
}
|
||||
|
||||
func (p *Process) ParentWithContext(ctx context.Context) (*Process, error) {
|
||||
rr, err := common.CallLsof(invoke, p.Pid, "-FR")
|
||||
rr, err := common.CallLsofWithContext(ctx, invoke, p.Pid, "-FR")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -232,13 +211,32 @@ func (p *Process) Status() (string, error) {
|
||||
}
|
||||
|
||||
func (p *Process) StatusWithContext(ctx context.Context) (string, error) {
|
||||
r, err := callPs("state", p.Pid, false)
|
||||
r, err := callPsWithContext(ctx, "state", p.Pid, false)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return r[0][0], err
|
||||
return r[0][0][0:1], err
|
||||
}
|
||||
|
||||
func (p *Process) Foreground() (bool, error) {
|
||||
return p.ForegroundWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) ForegroundWithContext(ctx context.Context) (bool, error) {
|
||||
// see https://github.com/shirou/gopsutil/issues/596#issuecomment-432707831 for implementation details
|
||||
pid := p.Pid
|
||||
ps, err := exec.LookPath("ps")
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
out, err := invoke.CommandWithContext(ctx, ps, "-o", "stat=", "-p", strconv.Itoa(int(pid)))
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return strings.IndexByte(string(out), '+') != -1, nil
|
||||
}
|
||||
|
||||
func (p *Process) Uids() ([]int32, error) {
|
||||
return p.UidsWithContext(context.Background())
|
||||
}
|
||||
@@ -350,7 +348,7 @@ func (p *Process) NumThreads() (int32, error) {
|
||||
}
|
||||
|
||||
func (p *Process) NumThreadsWithContext(ctx context.Context) (int32, error) {
|
||||
r, err := callPs("utime,stime", p.Pid, true)
|
||||
r, err := callPsWithContext(ctx, "utime,stime", p.Pid, true)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@@ -370,12 +368,32 @@ func convertCPUTimes(s string) (ret float64, err error) {
|
||||
var _tmp string
|
||||
if strings.Contains(s, ":") {
|
||||
_t := strings.Split(s, ":")
|
||||
hour, err := strconv.Atoi(_t[0])
|
||||
if err != nil {
|
||||
return ret, err
|
||||
switch len(_t) {
|
||||
case 3:
|
||||
hour, err := strconv.Atoi(_t[0])
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
t += hour * 60 * 60 * ClockTicks
|
||||
|
||||
mins, err := strconv.Atoi(_t[1])
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
t += mins * 60 * ClockTicks
|
||||
_tmp = _t[2]
|
||||
case 2:
|
||||
mins, err := strconv.Atoi(_t[0])
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
t += mins * 60 * ClockTicks
|
||||
_tmp = _t[1]
|
||||
case 1, 0:
|
||||
_tmp = s
|
||||
default:
|
||||
return ret, fmt.Errorf("wrong cpu time string")
|
||||
}
|
||||
t += hour * 60 * 100
|
||||
_tmp = _t[1]
|
||||
} else {
|
||||
_tmp = s
|
||||
}
|
||||
@@ -385,7 +403,7 @@ func convertCPUTimes(s string) (ret float64, err error) {
|
||||
return ret, err
|
||||
}
|
||||
h, err := strconv.Atoi(_t[0])
|
||||
t += h * 100
|
||||
t += h * ClockTicks
|
||||
h, err = strconv.Atoi(_t[1])
|
||||
t += h
|
||||
return float64(t) / ClockTicks, nil
|
||||
@@ -395,7 +413,7 @@ func (p *Process) Times() (*cpu.TimesStat, error) {
|
||||
}
|
||||
|
||||
func (p *Process) TimesWithContext(ctx context.Context) (*cpu.TimesStat, error) {
|
||||
r, err := callPs("utime,stime", p.Pid, false)
|
||||
r, err := callPsWithContext(ctx, "utime,stime", p.Pid, false)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -429,7 +447,7 @@ func (p *Process) MemoryInfo() (*MemoryInfoStat, error) {
|
||||
}
|
||||
|
||||
func (p *Process) MemoryInfoWithContext(ctx context.Context) (*MemoryInfoStat, error) {
|
||||
r, err := callPs("rss,vsize,pagein", p.Pid, false)
|
||||
r, err := callPsWithContext(ctx, "rss,vsize,pagein", p.Pid, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -462,12 +480,20 @@ func (p *Process) MemoryInfoExWithContext(ctx context.Context) (*MemoryInfoExSta
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) PageFaults() (*PageFaultsStat, error) {
|
||||
return p.PageFaultsWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) PageFaultsWithContext(ctx context.Context) (*PageFaultsStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) Children() ([]*Process, error) {
|
||||
return p.ChildrenWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) ChildrenWithContext(ctx context.Context) ([]*Process, error) {
|
||||
pids, err := common.CallPgrep(invoke, p.Pid)
|
||||
pids, err := common.CallPgrepWithContext(ctx, invoke, p.Pid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -498,6 +524,15 @@ func (p *Process) ConnectionsWithContext(ctx context.Context) ([]net.ConnectionS
|
||||
return net.ConnectionsPid("all", p.Pid)
|
||||
}
|
||||
|
||||
// Connections returns a slice of net.ConnectionStat used by the process at most `max`
|
||||
func (p *Process) ConnectionsMax(max int) ([]net.ConnectionStat, error) {
|
||||
return p.ConnectionsMaxWithContext(context.Background(), max)
|
||||
}
|
||||
|
||||
func (p *Process) ConnectionsMaxWithContext(ctx context.Context, max int) ([]net.ConnectionStat, error) {
|
||||
return net.ConnectionsPidMax("all", p.Pid, max)
|
||||
}
|
||||
|
||||
func (p *Process) NetIOCounters(pernic bool) ([]net.IOCountersStat, error) {
|
||||
return p.NetIOCountersWithContext(context.Background(), pernic)
|
||||
}
|
||||
@@ -506,13 +541,6 @@ func (p *Process) NetIOCountersWithContext(ctx context.Context, pernic bool) ([]
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) IsRunning() (bool, error) {
|
||||
return p.IsRunningWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) IsRunningWithContext(ctx context.Context) (bool, error) {
|
||||
return true, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) MemoryMaps(grouped bool) (*[]MemoryMapsStat, error) {
|
||||
return p.MemoryMapsWithContext(context.Background(), grouped)
|
||||
}
|
||||
@@ -527,34 +555,22 @@ func Processes() ([]*Process, error) {
|
||||
}
|
||||
|
||||
func ProcessesWithContext(ctx context.Context) ([]*Process, error) {
|
||||
results := []*Process{}
|
||||
out := []*Process{}
|
||||
|
||||
mib := []int32{CTLKern, KernProc, KernProcAll, 0}
|
||||
buf, length, err := common.CallSyscall(mib)
|
||||
pids, err := PidsWithContext(ctx)
|
||||
if err != nil {
|
||||
return results, err
|
||||
return out, err
|
||||
}
|
||||
|
||||
// get kinfo_proc size
|
||||
k := KinfoProc{}
|
||||
procinfoLen := int(unsafe.Sizeof(k))
|
||||
count := int(length / uint64(procinfoLen))
|
||||
|
||||
// parse buf to procs
|
||||
for i := 0; i < count; i++ {
|
||||
b := buf[i*procinfoLen : i*procinfoLen+procinfoLen]
|
||||
k, err := parseKinfoProc(b)
|
||||
for _, pid := range pids {
|
||||
p, err := NewProcess(pid)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
p, err := NewProcess(int32(k.Proc.P_pid))
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
results = append(results, p)
|
||||
out = append(out, p)
|
||||
}
|
||||
|
||||
return results, nil
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func parseKinfoProc(buf []byte) (KinfoProc, error) {
|
||||
@@ -599,17 +615,11 @@ func (p *Process) getKProcWithContext(ctx context.Context) (*KinfoProc, error) {
|
||||
return &k, nil
|
||||
}
|
||||
|
||||
func NewProcess(pid int32) (*Process, error) {
|
||||
p := &Process{Pid: pid}
|
||||
|
||||
return p, nil
|
||||
}
|
||||
|
||||
// call ps command.
|
||||
// Return value deletes Header line(you must not input wrong arg).
|
||||
// And splited by Space. Caller have responsibility to manage.
|
||||
// If passed arg pid is 0, get information from all process.
|
||||
func callPs(arg string, pid int32, threadOption bool) ([][]string, error) {
|
||||
func callPsWithContext(ctx context.Context, arg string, pid int32, threadOption bool) ([][]string, error) {
|
||||
bin, err := exec.LookPath("ps")
|
||||
if err != nil {
|
||||
return [][]string{}, err
|
||||
@@ -623,7 +633,7 @@ func callPs(arg string, pid int32, threadOption bool) ([][]string, error) {
|
||||
} else {
|
||||
cmd = []string{"-x", "-o", arg, "-p", strconv.Itoa(int(pid))}
|
||||
}
|
||||
out, err := invoke.Command(bin, cmd...)
|
||||
out, err := invoke.CommandWithContext(ctx, bin, cmd...)
|
||||
if err != nil {
|
||||
return [][]string{}, err
|
||||
}
|
||||
|
||||
30
vendor/github.com/shirou/gopsutil/process/process_darwin_cgo.go
generated
vendored
Normal file
30
vendor/github.com/shirou/gopsutil/process/process_darwin_cgo.go
generated
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
// +build darwin
|
||||
// +build cgo
|
||||
|
||||
package process
|
||||
|
||||
// #include <stdlib.h>
|
||||
// #include <libproc.h>
|
||||
import "C"
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
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)
|
||||
buffer := (*C.char)(C.malloc(C.size_t(bufsize)))
|
||||
defer C.free(unsafe.Pointer(buffer))
|
||||
|
||||
ret, err := C.proc_pidpath(C.int(p.Pid), unsafe.Pointer(buffer), C.uint32_t(bufsize))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if ret <= 0 {
|
||||
return "", fmt.Errorf("unknown error: proc_pidpath returned %d", ret)
|
||||
}
|
||||
|
||||
return C.GoString(buffer), nil
|
||||
}
|
||||
34
vendor/github.com/shirou/gopsutil/process/process_darwin_nocgo.go
generated
vendored
Normal file
34
vendor/github.com/shirou/gopsutil/process/process_darwin_nocgo.go
generated
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
// +build darwin
|
||||
// +build !cgo
|
||||
|
||||
package process
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func (p *Process) ExeWithContext(ctx context.Context) (string, error) {
|
||||
lsof_bin, err := exec.LookPath("lsof")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
out, err := invoke.CommandWithContext(ctx, lsof_bin, "-p", strconv.Itoa(int(p.Pid)), "-Fpfn")
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("bad call to lsof: %s", err)
|
||||
}
|
||||
txtFound := 0
|
||||
lines := strings.Split(string(out), "\n")
|
||||
for i := 1; i < len(lines); i += 2 {
|
||||
if lines[i] == "ftxt" {
|
||||
txtFound++
|
||||
if txtFound == 2 {
|
||||
return lines[i-1][1:], nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return "", fmt.Errorf("missing txt data returned by lsof")
|
||||
}
|
||||
60
vendor/github.com/shirou/gopsutil/process/process_fallback.go
generated
vendored
60
vendor/github.com/shirou/gopsutil/process/process_fallback.go
generated
vendored
@@ -28,18 +28,33 @@ type MemoryMapsStat struct {
|
||||
type MemoryInfoExStat struct {
|
||||
}
|
||||
|
||||
func Pids() ([]int32, error) {
|
||||
return PidsWithContext(context.Background())
|
||||
}
|
||||
|
||||
func PidsWithContext(ctx context.Context) ([]int32, error) {
|
||||
func pidsWithContext(ctx context.Context) ([]int32, error) {
|
||||
return []int32{}, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func NewProcess(pid int32) (*Process, error) {
|
||||
func Processes() ([]*Process, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func ProcessesWithContext(ctx context.Context) ([]*Process, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func PidExistsWithContext(ctx context.Context, pid int32) (bool, error) {
|
||||
pids, err := PidsWithContext(ctx)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
for _, i := range pids {
|
||||
if i == pid {
|
||||
return true, err
|
||||
}
|
||||
}
|
||||
|
||||
return false, err
|
||||
}
|
||||
|
||||
func (p *Process) Ppid() (int32, error) {
|
||||
return p.PpidWithContext(context.Background())
|
||||
}
|
||||
@@ -78,11 +93,8 @@ func (p *Process) CmdlineSlice() ([]string, error) {
|
||||
func (p *Process) CmdlineSliceWithContext(ctx context.Context) ([]string, error) {
|
||||
return []string{}, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) CreateTime() (int64, error) {
|
||||
return p.CreateTimeWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) CreateTimeWithContext(ctx context.Context) (int64, error) {
|
||||
func (p *Process) createTimeWithContext(ctx context.Context) (int64, error) {
|
||||
return 0, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) Cwd() (string, error) {
|
||||
@@ -106,6 +118,13 @@ func (p *Process) Status() (string, error) {
|
||||
func (p *Process) StatusWithContext(ctx context.Context) (string, error) {
|
||||
return "", common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) Foreground() (bool, error) {
|
||||
return p.ForegroundWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) ForegroundWithContext(ctx context.Context) (bool, error) {
|
||||
return false, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) Uids() ([]int32, error) {
|
||||
return p.UidsWithContext(context.Background())
|
||||
}
|
||||
@@ -218,6 +237,12 @@ func (p *Process) MemoryInfoEx() (*MemoryInfoExStat, error) {
|
||||
func (p *Process) MemoryInfoExWithContext(ctx context.Context) (*MemoryInfoExStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) PageFaults() (*PageFaultsStat, error) {
|
||||
return p.PageFaultsWithContext(context.Background())
|
||||
}
|
||||
func (p *Process) PageFaultsWithContext(ctx context.Context) (*PageFaultsStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) Children() ([]*Process, error) {
|
||||
return p.ChildrenWithContext(context.Background())
|
||||
}
|
||||
@@ -239,6 +264,15 @@ func (p *Process) Connections() ([]net.ConnectionStat, error) {
|
||||
func (p *Process) ConnectionsWithContext(ctx context.Context) ([]net.ConnectionStat, error) {
|
||||
return []net.ConnectionStat{}, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) ConnectionsMax(max int) ([]net.ConnectionStat, error) {
|
||||
return p.ConnectionsMaxWithContext(context.Background(), max)
|
||||
}
|
||||
|
||||
func (p *Process) ConnectionsMaxWithContext(ctx context.Context, max int) ([]net.ConnectionStat, error) {
|
||||
return []net.ConnectionStat{}, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) NetIOCounters(pernic bool) ([]net.IOCountersStat, error) {
|
||||
return p.NetIOCountersWithContext(context.Background(), pernic)
|
||||
}
|
||||
@@ -246,13 +280,7 @@ func (p *Process) NetIOCounters(pernic bool) ([]net.IOCountersStat, error) {
|
||||
func (p *Process) NetIOCountersWithContext(ctx context.Context, pernic bool) ([]net.IOCountersStat, error) {
|
||||
return []net.IOCountersStat{}, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) IsRunning() (bool, error) {
|
||||
return p.IsRunningWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) IsRunningWithContext(ctx context.Context) (bool, error) {
|
||||
return true, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) MemoryMaps(grouped bool) (*[]MemoryMapsStat, error) {
|
||||
return p.MemoryMapsWithContext(context.Background(), grouped)
|
||||
}
|
||||
|
||||
83
vendor/github.com/shirou/gopsutil/process/process_freebsd.go
generated
vendored
83
vendor/github.com/shirou/gopsutil/process/process_freebsd.go
generated
vendored
@@ -6,6 +6,9 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
cpu "github.com/shirou/gopsutil/cpu"
|
||||
@@ -21,11 +24,7 @@ type MemoryInfoExStat struct {
|
||||
type MemoryMapsStat struct {
|
||||
}
|
||||
|
||||
func Pids() ([]int32, error) {
|
||||
return PidsWithContext(context.Background())
|
||||
}
|
||||
|
||||
func PidsWithContext(ctx context.Context) ([]int32, error) {
|
||||
func pidsWithContext(ctx context.Context) ([]int32, error) {
|
||||
var ret []int32
|
||||
procs, err := Processes()
|
||||
if err != nil {
|
||||
@@ -60,8 +59,24 @@ func (p *Process) NameWithContext(ctx context.Context) (string, error) {
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
name := common.IntToString(k.Comm[:])
|
||||
|
||||
return common.IntToString(k.Comm[:]), nil
|
||||
if len(name) >= 15 {
|
||||
cmdlineSlice, err := p.CmdlineSliceWithContext(ctx)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if len(cmdlineSlice) > 0 {
|
||||
extendedName := filepath.Base(cmdlineSlice[0])
|
||||
if strings.HasPrefix(extendedName, p.name) {
|
||||
name = extendedName
|
||||
} else {
|
||||
name = cmdlineSlice[0]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return name, nil
|
||||
}
|
||||
func (p *Process) Tgid() (int32, error) {
|
||||
return 0, common.ErrNotImplementedError
|
||||
@@ -118,11 +133,8 @@ func (p *Process) CmdlineSliceWithContext(ctx context.Context) ([]string, error)
|
||||
|
||||
return strParts, nil
|
||||
}
|
||||
func (p *Process) CreateTime() (int64, error) {
|
||||
return p.CreateTimeWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) CreateTimeWithContext(ctx context.Context) (int64, error) {
|
||||
func (p *Process) createTimeWithContext(ctx context.Context) (int64, error) {
|
||||
return 0, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) Cwd() (string, error) {
|
||||
@@ -168,6 +180,25 @@ func (p *Process) StatusWithContext(ctx context.Context) (string, error) {
|
||||
|
||||
return s, nil
|
||||
}
|
||||
|
||||
func (p *Process) Foreground() (bool, error) {
|
||||
return p.ForegroundWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) ForegroundWithContext(ctx context.Context) (bool, error) {
|
||||
// see https://github.com/shirou/gopsutil/issues/596#issuecomment-432707831 for implementation details
|
||||
pid := p.Pid
|
||||
ps, err := exec.LookPath("ps")
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
out, err := invoke.CommandWithContext(ctx, ps, "-o", "stat=", "-p", strconv.Itoa(int(pid)))
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return strings.IndexByte(string(out), '+') != -1, nil
|
||||
}
|
||||
|
||||
func (p *Process) Uids() ([]int32, error) {
|
||||
return p.UidsWithContext(context.Background())
|
||||
}
|
||||
@@ -350,12 +381,20 @@ func (p *Process) MemoryInfoExWithContext(ctx context.Context) (*MemoryInfoExSta
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) PageFaults() (*PageFaultsStat, error) {
|
||||
return p.PageFaultsWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) PageFaultsWithContext(ctx context.Context) (*PageFaultsStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) Children() ([]*Process, error) {
|
||||
return p.ChildrenWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) ChildrenWithContext(ctx context.Context) ([]*Process, error) {
|
||||
pids, err := common.CallPgrep(invoke, p.Pid)
|
||||
pids, err := common.CallPgrepWithContext(ctx, invoke, p.Pid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -386,6 +425,15 @@ func (p *Process) ConnectionsWithContext(ctx context.Context) ([]net.ConnectionS
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
// Connections returns a slice of net.ConnectionStat used by the process at most `max`
|
||||
func (p *Process) ConnectionsMax(max int) ([]net.ConnectionStat, error) {
|
||||
return p.ConnectionsMaxWithContext(context.Background(), max)
|
||||
}
|
||||
|
||||
func (p *Process) ConnectionsMaxWithContext(ctx context.Context, max int) ([]net.ConnectionStat, error) {
|
||||
return []net.ConnectionStat{}, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) NetIOCounters(pernic bool) ([]net.IOCountersStat, error) {
|
||||
return p.NetIOCountersWithContext(context.Background(), pernic)
|
||||
}
|
||||
@@ -394,13 +442,6 @@ func (p *Process) NetIOCountersWithContext(ctx context.Context, pernic bool) ([]
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) IsRunning() (bool, error) {
|
||||
return p.IsRunningWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) IsRunningWithContext(ctx context.Context) (bool, error) {
|
||||
return true, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) MemoryMaps(grouped bool) (*[]MemoryMapsStat, error) {
|
||||
return p.MemoryMapsWithContext(context.Background(), grouped)
|
||||
}
|
||||
@@ -472,9 +513,3 @@ func (p *Process) getKProcWithContext(ctx context.Context) (*KinfoProc, error) {
|
||||
}
|
||||
return &k, nil
|
||||
}
|
||||
|
||||
func NewProcess(pid int32) (*Process, error) {
|
||||
p := &Process{Pid: pid}
|
||||
|
||||
return p, nil
|
||||
}
|
||||
|
||||
201
vendor/github.com/shirou/gopsutil/process/process_freebsd_arm64.go
generated
vendored
Normal file
201
vendor/github.com/shirou/gopsutil/process/process_freebsd_arm64.go
generated
vendored
Normal file
@@ -0,0 +1,201 @@
|
||||
// +build freebsd
|
||||
// +build arm64
|
||||
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
|
||||
// cgo -godefs process/types_freebsd.go
|
||||
|
||||
package process
|
||||
|
||||
const (
|
||||
CTLKern = 1
|
||||
KernProc = 14
|
||||
KernProcPID = 1
|
||||
KernProcProc = 8
|
||||
KernProcPathname = 12
|
||||
KernProcArgs = 7
|
||||
)
|
||||
|
||||
const (
|
||||
sizeofPtr = 0x8
|
||||
sizeofShort = 0x2
|
||||
sizeofInt = 0x4
|
||||
sizeofLong = 0x8
|
||||
sizeofLongLong = 0x8
|
||||
)
|
||||
|
||||
const (
|
||||
sizeOfKinfoVmentry = 0x488
|
||||
sizeOfKinfoProc = 0x440
|
||||
)
|
||||
|
||||
const (
|
||||
SIDL = 1
|
||||
SRUN = 2
|
||||
SSLEEP = 3
|
||||
SSTOP = 4
|
||||
SZOMB = 5
|
||||
SWAIT = 6
|
||||
SLOCK = 7
|
||||
)
|
||||
|
||||
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 int64
|
||||
}
|
||||
|
||||
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 int64
|
||||
Max int64
|
||||
}
|
||||
|
||||
type KinfoProc struct {
|
||||
Structsize int32
|
||||
Layout int32
|
||||
Args *int64 /* pargs */
|
||||
Paddr *int64 /* proc */
|
||||
Addr *int64 /* user */
|
||||
Tracep *int64 /* vnode */
|
||||
Textvp *int64 /* vnode */
|
||||
Fd *int64 /* filedesc */
|
||||
Vmspace *int64 /* vmspace */
|
||||
Wchan *byte
|
||||
Pid int32
|
||||
Ppid int32
|
||||
Pgid int32
|
||||
Tpgid int32
|
||||
Sid int32
|
||||
Tsid int32
|
||||
Jobc int16
|
||||
Spare_short1 int16
|
||||
Tdev_freebsd11 uint32
|
||||
Siglist [16]byte /* sigset */
|
||||
Sigmask [16]byte /* sigset */
|
||||
Sigignore [16]byte /* sigset */
|
||||
Sigcatch [16]byte /* sigset */
|
||||
Uid uint32
|
||||
Ruid uint32
|
||||
Svuid uint32
|
||||
Rgid uint32
|
||||
Svgid uint32
|
||||
Ngroups int16
|
||||
Spare_short2 int16
|
||||
Groups [16]uint32
|
||||
Size uint64
|
||||
Rssize int64
|
||||
Swrss int64
|
||||
Tsize int64
|
||||
Dsize int64
|
||||
Ssize int64
|
||||
Xstat uint16
|
||||
Acflag uint16
|
||||
Pctcpu uint32
|
||||
Estcpu uint32
|
||||
Slptime uint32
|
||||
Swtime uint32
|
||||
Cow uint32
|
||||
Runtime uint64
|
||||
Start Timeval
|
||||
Childtime Timeval
|
||||
Flag int64
|
||||
Kiflag int64
|
||||
Traceflag int32
|
||||
Stat uint8
|
||||
Nice int8
|
||||
Lock uint8
|
||||
Rqindex uint8
|
||||
Oncpu_old uint8
|
||||
Lastcpu_old uint8
|
||||
Tdname [17]uint8
|
||||
Wmesg [9]uint8
|
||||
Login [18]uint8
|
||||
Lockname [9]uint8
|
||||
Comm [20]int8
|
||||
Emul [17]uint8
|
||||
Loginclass [18]uint8
|
||||
Moretdname [4]uint8
|
||||
Sparestrings [46]uint8
|
||||
Spareints [2]int32
|
||||
Tdev uint64
|
||||
Oncpu int32
|
||||
Lastcpu int32
|
||||
Tracer int32
|
||||
Flag2 int32
|
||||
Fibnum int32
|
||||
Cr_flags uint32
|
||||
Jid int32
|
||||
Numthreads int32
|
||||
Tid int32
|
||||
Pri Priority
|
||||
Rusage Rusage
|
||||
Rusage_ch Rusage
|
||||
Pcb *int64 /* pcb */
|
||||
Kstack *byte
|
||||
Udata *byte
|
||||
Tdaddr *int64 /* thread */
|
||||
Spareptrs [6]*byte
|
||||
Sparelongs [12]int64
|
||||
Sflag int64
|
||||
Tdflags int64
|
||||
}
|
||||
|
||||
type Priority struct {
|
||||
Class uint8
|
||||
Level uint8
|
||||
Native uint8
|
||||
User uint8
|
||||
}
|
||||
|
||||
type KinfoVmentry struct {
|
||||
Structsize int32
|
||||
Type int32
|
||||
Start uint64
|
||||
End uint64
|
||||
Offset uint64
|
||||
Vn_fileid uint64
|
||||
Vn_fsid_freebsd11 uint32
|
||||
Flags int32
|
||||
Resident int32
|
||||
Private_resident int32
|
||||
Protection int32
|
||||
Ref_count int32
|
||||
Shadow_count int32
|
||||
Vn_type int32
|
||||
Vn_size uint64
|
||||
Vn_rdev_freebsd11 uint32
|
||||
Vn_mode uint16
|
||||
Status uint16
|
||||
Vn_fsid uint64
|
||||
Vn_rdev uint64
|
||||
X_kve_ispare [8]int32
|
||||
Path [1024]uint8
|
||||
}
|
||||
273
vendor/github.com/shirou/gopsutil/process/process_linux.go
generated
vendored
273
vendor/github.com/shirou/gopsutil/process/process_linux.go
generated
vendored
@@ -7,7 +7,6 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"math"
|
||||
@@ -17,16 +16,12 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/shirou/gopsutil/cpu"
|
||||
"github.com/shirou/gopsutil/host"
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/net"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrorNoChildren = errors.New("process does not have children")
|
||||
PageSize = uint64(os.Getpagesize())
|
||||
)
|
||||
var PageSize = uint64(os.Getpagesize())
|
||||
|
||||
const (
|
||||
PrioProcess = 0 // linux/resource.h
|
||||
@@ -69,26 +64,13 @@ func (m MemoryMapsStat) String() string {
|
||||
return string(s)
|
||||
}
|
||||
|
||||
// NewProcess creates a new Process instance, it only stores the pid and
|
||||
// checks that the process exists. Other method on Process can be used
|
||||
// to get more information about the process. An error will be returned
|
||||
// if the process does not exist.
|
||||
func NewProcess(pid int32) (*Process, error) {
|
||||
p := &Process{
|
||||
Pid: int32(pid),
|
||||
}
|
||||
file, err := os.Open(common.HostProc(strconv.Itoa(int(p.Pid))))
|
||||
defer file.Close()
|
||||
return p, err
|
||||
}
|
||||
|
||||
// Ppid returns Parent Process ID of the process.
|
||||
func (p *Process) Ppid() (int32, error) {
|
||||
return p.PpidWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) PpidWithContext(ctx context.Context) (int32, error) {
|
||||
_, ppid, _, _, _, _, err := p.fillFromStat()
|
||||
_, ppid, _, _, _, _, _, err := p.fillFromStatWithContext(ctx)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
@@ -102,7 +84,7 @@ func (p *Process) Name() (string, error) {
|
||||
|
||||
func (p *Process) NameWithContext(ctx context.Context) (string, error) {
|
||||
if p.name == "" {
|
||||
if err := p.fillFromStatus(); err != nil {
|
||||
if err := p.fillFromStatusWithContext(ctx); err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
@@ -112,7 +94,7 @@ func (p *Process) NameWithContext(ctx context.Context) (string, error) {
|
||||
// Tgid returns tgid, a Linux-synonym for user-space Pid
|
||||
func (p *Process) Tgid() (int32, error) {
|
||||
if p.tgid == 0 {
|
||||
if err := p.fillFromStatus(); err != nil {
|
||||
if err := p.fillFromStatusWithContext(context.Background()); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
@@ -125,7 +107,7 @@ func (p *Process) Exe() (string, error) {
|
||||
}
|
||||
|
||||
func (p *Process) ExeWithContext(ctx context.Context) (string, error) {
|
||||
return p.fillFromExe()
|
||||
return p.fillFromExeWithContext(ctx)
|
||||
}
|
||||
|
||||
// Cmdline returns the command line arguments of the process as a string with
|
||||
@@ -135,7 +117,7 @@ func (p *Process) Cmdline() (string, error) {
|
||||
}
|
||||
|
||||
func (p *Process) CmdlineWithContext(ctx context.Context) (string, error) {
|
||||
return p.fillFromCmdline()
|
||||
return p.fillFromCmdlineWithContext(ctx)
|
||||
}
|
||||
|
||||
// CmdlineSlice returns the command line arguments of the process as a slice with each
|
||||
@@ -145,16 +127,11 @@ func (p *Process) CmdlineSlice() ([]string, error) {
|
||||
}
|
||||
|
||||
func (p *Process) CmdlineSliceWithContext(ctx context.Context) ([]string, error) {
|
||||
return p.fillSliceFromCmdline()
|
||||
return p.fillSliceFromCmdlineWithContext(ctx)
|
||||
}
|
||||
|
||||
// CreateTime returns created time of the process in milliseconds since the epoch, in UTC.
|
||||
func (p *Process) CreateTime() (int64, error) {
|
||||
return p.CreateTimeWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) CreateTimeWithContext(ctx context.Context) (int64, error) {
|
||||
_, _, _, createTime, _, _, err := p.fillFromStat()
|
||||
func (p *Process) createTimeWithContext(ctx context.Context) (int64, error) {
|
||||
_, _, _, createTime, _, _, _, err := p.fillFromStatWithContext(ctx)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@@ -167,7 +144,7 @@ func (p *Process) Cwd() (string, error) {
|
||||
}
|
||||
|
||||
func (p *Process) CwdWithContext(ctx context.Context) (string, error) {
|
||||
return p.fillFromCwd()
|
||||
return p.fillFromCwdWithContext(ctx)
|
||||
}
|
||||
|
||||
// Parent returns parent Process of the process.
|
||||
@@ -176,7 +153,7 @@ func (p *Process) Parent() (*Process, error) {
|
||||
}
|
||||
|
||||
func (p *Process) ParentWithContext(ctx context.Context) (*Process, error) {
|
||||
err := p.fillFromStatus()
|
||||
err := p.fillFromStatusWithContext(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -190,26 +167,48 @@ func (p *Process) ParentWithContext(ctx context.Context) (*Process, error) {
|
||||
// Return value could be one of these.
|
||||
// R: Running S: Sleep T: Stop I: Idle
|
||||
// Z: Zombie W: Wait L: Lock
|
||||
// The charactor is same within all supported platforms.
|
||||
// The character is same within all supported platforms.
|
||||
func (p *Process) Status() (string, error) {
|
||||
return p.StatusWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) StatusWithContext(ctx context.Context) (string, error) {
|
||||
err := p.fillFromStatus()
|
||||
err := p.fillFromStatusWithContext(ctx)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return p.status, nil
|
||||
}
|
||||
|
||||
// Foreground returns true if the process is in foreground, false otherwise.
|
||||
func (p *Process) Foreground() (bool, error) {
|
||||
return p.ForegroundWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) ForegroundWithContext(ctx context.Context) (bool, error) {
|
||||
// see https://github.com/shirou/gopsutil/issues/596#issuecomment-432707831 for implementation details
|
||||
pid := p.Pid
|
||||
statPath := common.HostProc(strconv.Itoa(int(pid)), "stat")
|
||||
contents, err := ioutil.ReadFile(statPath)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
fields := strings.Fields(string(contents))
|
||||
if len(fields) < 8 {
|
||||
return false, fmt.Errorf("insufficient data in %s", statPath)
|
||||
}
|
||||
pgid := fields[4]
|
||||
tpgid := fields[7]
|
||||
return pgid == tpgid, nil
|
||||
}
|
||||
|
||||
// Uids returns user ids of the process as a slice of the int
|
||||
func (p *Process) Uids() ([]int32, error) {
|
||||
return p.UidsWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) UidsWithContext(ctx context.Context) ([]int32, error) {
|
||||
err := p.fillFromStatus()
|
||||
err := p.fillFromStatusWithContext(ctx)
|
||||
if err != nil {
|
||||
return []int32{}, err
|
||||
}
|
||||
@@ -222,7 +221,7 @@ func (p *Process) Gids() ([]int32, error) {
|
||||
}
|
||||
|
||||
func (p *Process) GidsWithContext(ctx context.Context) ([]int32, error) {
|
||||
err := p.fillFromStatus()
|
||||
err := p.fillFromStatusWithContext(ctx)
|
||||
if err != nil {
|
||||
return []int32{}, err
|
||||
}
|
||||
@@ -235,7 +234,7 @@ func (p *Process) Terminal() (string, error) {
|
||||
}
|
||||
|
||||
func (p *Process) TerminalWithContext(ctx context.Context) (string, error) {
|
||||
t, _, _, _, _, _, err := p.fillFromStat()
|
||||
t, _, _, _, _, _, _, err := p.fillFromStatWithContext(ctx)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -254,7 +253,7 @@ func (p *Process) Nice() (int32, error) {
|
||||
}
|
||||
|
||||
func (p *Process) NiceWithContext(ctx context.Context) (int32, error) {
|
||||
_, _, _, _, _, nice, err := p.fillFromStat()
|
||||
_, _, _, _, _, nice, _, err := p.fillFromStatWithContext(ctx)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@@ -287,16 +286,16 @@ func (p *Process) RlimitUsage(gatherUsed bool) ([]RlimitStat, error) {
|
||||
}
|
||||
|
||||
func (p *Process) RlimitUsageWithContext(ctx context.Context, gatherUsed bool) ([]RlimitStat, error) {
|
||||
rlimits, err := p.fillFromLimits()
|
||||
rlimits, err := p.fillFromLimitsWithContext(ctx)
|
||||
if !gatherUsed || err != nil {
|
||||
return rlimits, err
|
||||
}
|
||||
|
||||
_, _, _, _, rtprio, nice, err := p.fillFromStat()
|
||||
_, _, _, _, rtprio, nice, _, err := p.fillFromStatWithContext(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := p.fillFromStatus(); err != nil {
|
||||
if err := p.fillFromStatusWithContext(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -347,7 +346,7 @@ func (p *Process) IOCounters() (*IOCountersStat, error) {
|
||||
}
|
||||
|
||||
func (p *Process) IOCountersWithContext(ctx context.Context) (*IOCountersStat, error) {
|
||||
return p.fillFromIO()
|
||||
return p.fillFromIOWithContext(ctx)
|
||||
}
|
||||
|
||||
// NumCtxSwitches returns the number of the context switches of the process.
|
||||
@@ -356,7 +355,7 @@ func (p *Process) NumCtxSwitches() (*NumCtxSwitchesStat, error) {
|
||||
}
|
||||
|
||||
func (p *Process) NumCtxSwitchesWithContext(ctx context.Context) (*NumCtxSwitchesStat, error) {
|
||||
err := p.fillFromStatus()
|
||||
err := p.fillFromStatusWithContext(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -369,7 +368,7 @@ func (p *Process) NumFDs() (int32, error) {
|
||||
}
|
||||
|
||||
func (p *Process) NumFDsWithContext(ctx context.Context) (int32, error) {
|
||||
_, fnames, err := p.fillFromfdList()
|
||||
_, fnames, err := p.fillFromfdListWithContext(ctx)
|
||||
return int32(len(fnames)), err
|
||||
}
|
||||
|
||||
@@ -379,7 +378,7 @@ func (p *Process) NumThreads() (int32, error) {
|
||||
}
|
||||
|
||||
func (p *Process) NumThreadsWithContext(ctx context.Context) (int32, error) {
|
||||
err := p.fillFromStatus()
|
||||
err := p.fillFromStatusWithContext(ctx)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@@ -400,7 +399,7 @@ func (p *Process) ThreadsWithContext(ctx context.Context) (map[int32]*cpu.TimesS
|
||||
}
|
||||
|
||||
for _, tid := range tids {
|
||||
_, _, cpuTimes, _, _, _, err := p.fillFromTIDStat(tid)
|
||||
_, _, cpuTimes, _, _, _, _, err := p.fillFromTIDStatWithContext(ctx, tid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -416,7 +415,7 @@ func (p *Process) Times() (*cpu.TimesStat, error) {
|
||||
}
|
||||
|
||||
func (p *Process) TimesWithContext(ctx context.Context) (*cpu.TimesStat, error) {
|
||||
_, _, cpuTimes, _, _, _, err := p.fillFromStat()
|
||||
_, _, cpuTimes, _, _, _, _, err := p.fillFromStatWithContext(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -440,7 +439,7 @@ func (p *Process) MemoryInfo() (*MemoryInfoStat, error) {
|
||||
}
|
||||
|
||||
func (p *Process) MemoryInfoWithContext(ctx context.Context) (*MemoryInfoStat, error) {
|
||||
meminfo, _, err := p.fillFromStatm()
|
||||
meminfo, _, err := p.fillFromStatmWithContext(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -453,20 +452,34 @@ func (p *Process) MemoryInfoEx() (*MemoryInfoExStat, error) {
|
||||
}
|
||||
|
||||
func (p *Process) MemoryInfoExWithContext(ctx context.Context) (*MemoryInfoExStat, error) {
|
||||
_, memInfoEx, err := p.fillFromStatm()
|
||||
_, memInfoEx, err := p.fillFromStatmWithContext(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return memInfoEx, nil
|
||||
}
|
||||
|
||||
// PageFaultsInfo returns the process's page fault counters
|
||||
func (p *Process) PageFaults() (*PageFaultsStat, error) {
|
||||
return p.PageFaultsWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) PageFaultsWithContext(ctx context.Context) (*PageFaultsStat, error) {
|
||||
_, _, _, _, _, _, pageFaults, err := p.fillFromStatWithContext(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return pageFaults, nil
|
||||
|
||||
}
|
||||
|
||||
// Children returns a slice of Process of the process.
|
||||
func (p *Process) Children() ([]*Process, error) {
|
||||
return p.ChildrenWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) ChildrenWithContext(ctx context.Context) ([]*Process, error) {
|
||||
pids, err := common.CallPgrep(invoke, p.Pid)
|
||||
pids, err := common.CallPgrepWithContext(ctx, invoke, p.Pid)
|
||||
if err != nil {
|
||||
if pids == nil || len(pids) == 0 {
|
||||
return nil, ErrorNoChildren
|
||||
@@ -491,7 +504,7 @@ func (p *Process) OpenFiles() ([]OpenFilesStat, error) {
|
||||
}
|
||||
|
||||
func (p *Process) OpenFilesWithContext(ctx context.Context) ([]OpenFilesStat, error) {
|
||||
_, ofs, err := p.fillFromfd()
|
||||
_, ofs, err := p.fillFromfdWithContext(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -513,6 +526,15 @@ func (p *Process) ConnectionsWithContext(ctx context.Context) ([]net.ConnectionS
|
||||
return net.ConnectionsPid("all", p.Pid)
|
||||
}
|
||||
|
||||
// Connections returns a slice of net.ConnectionStat used by the process at most `max`
|
||||
func (p *Process) ConnectionsMax(max int) ([]net.ConnectionStat, error) {
|
||||
return p.ConnectionsMaxWithContext(context.Background(), max)
|
||||
}
|
||||
|
||||
func (p *Process) ConnectionsMaxWithContext(ctx context.Context, max int) ([]net.ConnectionStat, error) {
|
||||
return net.ConnectionsPidMax("all", p.Pid, max)
|
||||
}
|
||||
|
||||
// NetIOCounters returns NetIOCounters of the process.
|
||||
func (p *Process) NetIOCounters(pernic bool) ([]net.IOCountersStat, error) {
|
||||
return p.NetIOCountersWithContext(context.Background(), pernic)
|
||||
@@ -523,16 +545,6 @@ func (p *Process) NetIOCountersWithContext(ctx context.Context, pernic bool) ([]
|
||||
return net.IOCountersByFile(pernic, filename)
|
||||
}
|
||||
|
||||
// IsRunning returns whether the process is running or not.
|
||||
// Not implemented yet.
|
||||
func (p *Process) IsRunning() (bool, error) {
|
||||
return p.IsRunningWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) IsRunningWithContext(ctx context.Context) (bool, error) {
|
||||
return true, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
// MemoryMaps get memory maps from /proc/(pid)/smaps
|
||||
func (p *Process) MemoryMaps(grouped bool) (*[]MemoryMapsStat, error) {
|
||||
return p.MemoryMapsWithContext(context.Background(), grouped)
|
||||
@@ -541,6 +553,9 @@ func (p *Process) MemoryMaps(grouped bool) (*[]MemoryMapsStat, error) {
|
||||
func (p *Process) MemoryMapsWithContext(ctx context.Context, grouped bool) (*[]MemoryMapsStat, error) {
|
||||
pid := p.Pid
|
||||
var ret []MemoryMapsStat
|
||||
if grouped {
|
||||
ret = make([]MemoryMapsStat, 1)
|
||||
}
|
||||
smapsPath := common.HostProc(strconv.Itoa(int(pid)), "smaps")
|
||||
contents, err := ioutil.ReadFile(smapsPath)
|
||||
if err != nil {
|
||||
@@ -603,7 +618,20 @@ func (p *Process) MemoryMapsWithContext(ctx context.Context, grouped bool) (*[]M
|
||||
if err != nil {
|
||||
return &ret, err
|
||||
}
|
||||
ret = append(ret, g)
|
||||
if grouped {
|
||||
ret[0].Size += g.Size
|
||||
ret[0].Rss += g.Rss
|
||||
ret[0].Pss += g.Pss
|
||||
ret[0].SharedClean += g.SharedClean
|
||||
ret[0].SharedDirty += g.SharedDirty
|
||||
ret[0].PrivateClean += g.PrivateClean
|
||||
ret[0].PrivateDirty += g.PrivateDirty
|
||||
ret[0].Referenced += g.Referenced
|
||||
ret[0].Anonymous += g.Anonymous
|
||||
ret[0].Swap += g.Swap
|
||||
} else {
|
||||
ret = append(ret, g)
|
||||
}
|
||||
}
|
||||
// starts new block
|
||||
blocks = make([]string, 16)
|
||||
@@ -632,10 +660,6 @@ func limitToInt(val string) (int32, error) {
|
||||
}
|
||||
|
||||
// Get num_fds from /proc/(pid)/limits
|
||||
func (p *Process) fillFromLimits() ([]RlimitStat, error) {
|
||||
return p.fillFromLimitsWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) fillFromLimitsWithContext(ctx context.Context) ([]RlimitStat, error) {
|
||||
pid := p.Pid
|
||||
limitsFile := common.HostProc(strconv.Itoa(int(pid)), "limits")
|
||||
@@ -729,10 +753,6 @@ func (p *Process) fillFromLimitsWithContext(ctx context.Context) ([]RlimitStat,
|
||||
}
|
||||
|
||||
// Get list of /proc/(pid)/fd files
|
||||
func (p *Process) fillFromfdList() (string, []string, error) {
|
||||
return p.fillFromfdListWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) fillFromfdListWithContext(ctx context.Context) (string, []string, error) {
|
||||
pid := p.Pid
|
||||
statPath := common.HostProc(strconv.Itoa(int(pid)), "fd")
|
||||
@@ -746,12 +766,8 @@ func (p *Process) fillFromfdListWithContext(ctx context.Context) (string, []stri
|
||||
}
|
||||
|
||||
// Get num_fds from /proc/(pid)/fd
|
||||
func (p *Process) fillFromfd() (int32, []*OpenFilesStat, error) {
|
||||
return p.fillFromfdWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) fillFromfdWithContext(ctx context.Context) (int32, []*OpenFilesStat, error) {
|
||||
statPath, fnames, err := p.fillFromfdList()
|
||||
statPath, fnames, err := p.fillFromfdListWithContext(ctx)
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
@@ -779,10 +795,6 @@ func (p *Process) fillFromfdWithContext(ctx context.Context) (int32, []*OpenFile
|
||||
}
|
||||
|
||||
// Get cwd from /proc/(pid)/cwd
|
||||
func (p *Process) fillFromCwd() (string, error) {
|
||||
return p.fillFromCwdWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) fillFromCwdWithContext(ctx context.Context) (string, error) {
|
||||
pid := p.Pid
|
||||
cwdPath := common.HostProc(strconv.Itoa(int(pid)), "cwd")
|
||||
@@ -794,10 +806,6 @@ func (p *Process) fillFromCwdWithContext(ctx context.Context) (string, error) {
|
||||
}
|
||||
|
||||
// Get exe from /proc/(pid)/exe
|
||||
func (p *Process) fillFromExe() (string, error) {
|
||||
return p.fillFromExeWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) fillFromExeWithContext(ctx context.Context) (string, error) {
|
||||
pid := p.Pid
|
||||
exePath := common.HostProc(strconv.Itoa(int(pid)), "exe")
|
||||
@@ -809,10 +817,6 @@ func (p *Process) fillFromExeWithContext(ctx context.Context) (string, error) {
|
||||
}
|
||||
|
||||
// Get cmdline from /proc/(pid)/cmdline
|
||||
func (p *Process) fillFromCmdline() (string, error) {
|
||||
return p.fillFromCmdlineWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) fillFromCmdlineWithContext(ctx context.Context) (string, error) {
|
||||
pid := p.Pid
|
||||
cmdPath := common.HostProc(strconv.Itoa(int(pid)), "cmdline")
|
||||
@@ -830,10 +834,6 @@ func (p *Process) fillFromCmdlineWithContext(ctx context.Context) (string, error
|
||||
return strings.Join(ret, " "), nil
|
||||
}
|
||||
|
||||
func (p *Process) fillSliceFromCmdline() ([]string, error) {
|
||||
return p.fillSliceFromCmdlineWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) fillSliceFromCmdlineWithContext(ctx context.Context) ([]string, error) {
|
||||
pid := p.Pid
|
||||
cmdPath := common.HostProc(strconv.Itoa(int(pid)), "cmdline")
|
||||
@@ -857,10 +857,6 @@ func (p *Process) fillSliceFromCmdlineWithContext(ctx context.Context) ([]string
|
||||
}
|
||||
|
||||
// Get IO status from /proc/(pid)/io
|
||||
func (p *Process) fillFromIO() (*IOCountersStat, error) {
|
||||
return p.fillFromIOWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) fillFromIOWithContext(ctx context.Context) (*IOCountersStat, error) {
|
||||
pid := p.Pid
|
||||
ioPath := common.HostProc(strconv.Itoa(int(pid)), "io")
|
||||
@@ -900,10 +896,6 @@ func (p *Process) fillFromIOWithContext(ctx context.Context) (*IOCountersStat, e
|
||||
}
|
||||
|
||||
// Get memory info from /proc/(pid)/statm
|
||||
func (p *Process) fillFromStatm() (*MemoryInfoStat, *MemoryInfoExStat, error) {
|
||||
return p.fillFromStatmWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) fillFromStatmWithContext(ctx context.Context) (*MemoryInfoStat, *MemoryInfoExStat, error) {
|
||||
pid := p.Pid
|
||||
memPath := common.HostProc(strconv.Itoa(int(pid)), "statm")
|
||||
@@ -956,10 +948,6 @@ func (p *Process) fillFromStatmWithContext(ctx context.Context) (*MemoryInfoStat
|
||||
}
|
||||
|
||||
// Get various status from /proc/(pid)/status
|
||||
func (p *Process) fillFromStatus() error {
|
||||
return p.fillFromStatusWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) fillFromStatusWithContext(ctx context.Context) error {
|
||||
pid := p.Pid
|
||||
statPath := common.HostProc(strconv.Itoa(int(pid)), "status")
|
||||
@@ -989,6 +977,8 @@ func (p *Process) fillFromStatusWithContext(ctx context.Context) error {
|
||||
extendedName := filepath.Base(cmdlineSlice[0])
|
||||
if strings.HasPrefix(extendedName, p.name) {
|
||||
p.name = extendedName
|
||||
} else {
|
||||
p.name = cmdlineSlice[0]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1063,6 +1053,13 @@ func (p *Process) fillFromStatusWithContext(ctx context.Context) error {
|
||||
return err
|
||||
}
|
||||
p.memInfo.Swap = v * 1024
|
||||
case "VmHWM":
|
||||
value := strings.Trim(value, " kB") // remove last "kB"
|
||||
v, err := strconv.ParseUint(value, 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
p.memInfo.HWM = v * 1024
|
||||
case "VmData":
|
||||
value := strings.Trim(value, " kB") // remove last "kB"
|
||||
v, err := strconv.ParseUint(value, 10, 64)
|
||||
@@ -1120,11 +1117,7 @@ func (p *Process) fillFromStatusWithContext(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Process) fillFromTIDStat(tid int32) (uint64, int32, *cpu.TimesStat, int64, uint32, int32, error) {
|
||||
return p.fillFromTIDStatWithContext(context.Background(), tid)
|
||||
}
|
||||
|
||||
func (p *Process) fillFromTIDStatWithContext(ctx context.Context, tid int32) (uint64, int32, *cpu.TimesStat, int64, uint32, int32, error) {
|
||||
func (p *Process) fillFromTIDStatWithContext(ctx context.Context, tid int32) (uint64, int32, *cpu.TimesStat, int64, uint32, int32, *PageFaultsStat, error) {
|
||||
pid := p.Pid
|
||||
var statPath string
|
||||
|
||||
@@ -1136,7 +1129,7 @@ func (p *Process) fillFromTIDStatWithContext(ctx context.Context, tid int32) (ui
|
||||
|
||||
contents, err := ioutil.ReadFile(statPath)
|
||||
if err != nil {
|
||||
return 0, 0, nil, 0, 0, 0, err
|
||||
return 0, 0, nil, 0, 0, 0, nil, err
|
||||
}
|
||||
fields := strings.Fields(string(contents))
|
||||
|
||||
@@ -1147,21 +1140,21 @@ func (p *Process) fillFromTIDStatWithContext(ctx context.Context, tid int32) (ui
|
||||
|
||||
terminal, err := strconv.ParseUint(fields[i+5], 10, 64)
|
||||
if err != nil {
|
||||
return 0, 0, nil, 0, 0, 0, err
|
||||
return 0, 0, nil, 0, 0, 0, nil, err
|
||||
}
|
||||
|
||||
ppid, err := strconv.ParseInt(fields[i+2], 10, 32)
|
||||
if err != nil {
|
||||
return 0, 0, nil, 0, 0, 0, err
|
||||
return 0, 0, nil, 0, 0, 0, nil, err
|
||||
}
|
||||
utime, err := strconv.ParseFloat(fields[i+12], 64)
|
||||
if err != nil {
|
||||
return 0, 0, nil, 0, 0, 0, err
|
||||
return 0, 0, nil, 0, 0, 0, nil, err
|
||||
}
|
||||
|
||||
stime, err := strconv.ParseFloat(fields[i+13], 64)
|
||||
if err != nil {
|
||||
return 0, 0, nil, 0, 0, 0, err
|
||||
return 0, 0, nil, 0, 0, 0, nil, err
|
||||
}
|
||||
|
||||
cpuTimes := &cpu.TimesStat{
|
||||
@@ -1170,15 +1163,18 @@ func (p *Process) fillFromTIDStatWithContext(ctx context.Context, tid int32) (ui
|
||||
System: float64(stime / ClockTicks),
|
||||
}
|
||||
|
||||
bootTime, _ := host.BootTime()
|
||||
bootTime, _ := common.BootTimeWithContext(ctx)
|
||||
t, err := strconv.ParseUint(fields[i+20], 10, 64)
|
||||
if err != nil {
|
||||
return 0, 0, nil, 0, 0, 0, err
|
||||
return 0, 0, nil, 0, 0, 0, nil, err
|
||||
}
|
||||
ctime := (t / uint64(ClockTicks)) + uint64(bootTime)
|
||||
createTime := int64(ctime * 1000)
|
||||
|
||||
rtpriority, err := strconv.ParseInt(fields[i+16], 10, 32)
|
||||
if err != nil {
|
||||
return 0, 0, nil, 0, 0, 0, nil, err
|
||||
}
|
||||
if rtpriority < 0 {
|
||||
rtpriority = rtpriority*-1 - 1
|
||||
} else {
|
||||
@@ -1190,23 +1186,38 @@ func (p *Process) fillFromTIDStatWithContext(ctx context.Context, tid int32) (ui
|
||||
snice, _ := unix.Getpriority(PrioProcess, int(pid))
|
||||
nice := int32(snice) // FIXME: is this true?
|
||||
|
||||
return terminal, int32(ppid), cpuTimes, createTime, uint32(rtpriority), nice, nil
|
||||
minFault, err := strconv.ParseUint(fields[i+8], 10, 64)
|
||||
if err != nil {
|
||||
return 0, 0, nil, 0, 0, 0, nil, err
|
||||
}
|
||||
cMinFault, err := strconv.ParseUint(fields[i+9], 10, 64)
|
||||
if err != nil {
|
||||
return 0, 0, nil, 0, 0, 0, nil, err
|
||||
}
|
||||
majFault, err := strconv.ParseUint(fields[i+10], 10, 64)
|
||||
if err != nil {
|
||||
return 0, 0, nil, 0, 0, 0, nil, err
|
||||
}
|
||||
cMajFault, err := strconv.ParseUint(fields[i+11], 10, 64)
|
||||
if err != nil {
|
||||
return 0, 0, nil, 0, 0, 0, nil, err
|
||||
}
|
||||
|
||||
faults := &PageFaultsStat{
|
||||
MinorFaults: minFault,
|
||||
MajorFaults: majFault,
|
||||
ChildMinorFaults: cMinFault,
|
||||
ChildMajorFaults: cMajFault,
|
||||
}
|
||||
|
||||
return terminal, int32(ppid), cpuTimes, createTime, uint32(rtpriority), nice, faults, nil
|
||||
}
|
||||
|
||||
func (p *Process) fillFromStat() (uint64, int32, *cpu.TimesStat, int64, uint32, int32, error) {
|
||||
return p.fillFromStatWithContext(context.Background())
|
||||
func (p *Process) fillFromStatWithContext(ctx context.Context) (uint64, int32, *cpu.TimesStat, int64, uint32, int32, *PageFaultsStat, error) {
|
||||
return p.fillFromTIDStatWithContext(ctx, -1)
|
||||
}
|
||||
|
||||
func (p *Process) fillFromStatWithContext(ctx context.Context) (uint64, int32, *cpu.TimesStat, int64, uint32, int32, error) {
|
||||
return p.fillFromTIDStat(-1)
|
||||
}
|
||||
|
||||
// Pids returns a slice of process ID list which are running now.
|
||||
func Pids() ([]int32, error) {
|
||||
return PidsWithContext(context.Background())
|
||||
}
|
||||
|
||||
func PidsWithContext(ctx context.Context) ([]int32, error) {
|
||||
func pidsWithContext(ctx context.Context) ([]int32, error) {
|
||||
return readPidsFromDir(common.HostProc())
|
||||
}
|
||||
|
||||
@@ -1219,7 +1230,7 @@ func Processes() ([]*Process, error) {
|
||||
func ProcessesWithContext(ctx context.Context) ([]*Process, error) {
|
||||
out := []*Process{}
|
||||
|
||||
pids, err := Pids()
|
||||
pids, err := PidsWithContext(ctx)
|
||||
if err != nil {
|
||||
return out, err
|
||||
}
|
||||
|
||||
83
vendor/github.com/shirou/gopsutil/process/process_openbsd.go
generated
vendored
83
vendor/github.com/shirou/gopsutil/process/process_openbsd.go
generated
vendored
@@ -5,7 +5,11 @@ package process
|
||||
import (
|
||||
"C"
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unsafe"
|
||||
|
||||
@@ -15,7 +19,6 @@ import (
|
||||
net "github.com/shirou/gopsutil/net"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
import "context"
|
||||
|
||||
// MemoryInfoExStat is different between OSes
|
||||
type MemoryInfoExStat struct {
|
||||
@@ -24,11 +27,7 @@ type MemoryInfoExStat struct {
|
||||
type MemoryMapsStat struct {
|
||||
}
|
||||
|
||||
func Pids() ([]int32, error) {
|
||||
return PidsWithContext(context.Background())
|
||||
}
|
||||
|
||||
func PidsWithContext(ctx context.Context) ([]int32, error) {
|
||||
func pidsWithContext(ctx context.Context) ([]int32, error) {
|
||||
var ret []int32
|
||||
procs, err := Processes()
|
||||
if err != nil {
|
||||
@@ -63,8 +62,24 @@ func (p *Process) NameWithContext(ctx context.Context) (string, error) {
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
name := common.IntToString(k.Comm[:])
|
||||
|
||||
return common.IntToString(k.Comm[:]), nil
|
||||
if len(name) >= 15 {
|
||||
cmdlineSlice, err := p.CmdlineSliceWithContext(ctx)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if len(cmdlineSlice) > 0 {
|
||||
extendedName := filepath.Base(cmdlineSlice[0])
|
||||
if strings.HasPrefix(extendedName, p.name) {
|
||||
name = extendedName
|
||||
} else {
|
||||
name = cmdlineSlice[0]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return name, nil
|
||||
}
|
||||
func (p *Process) Tgid() (int32, error) {
|
||||
return 0, common.ErrNotImplementedError
|
||||
@@ -116,11 +131,7 @@ func (p *Process) CmdlineWithContext(ctx context.Context) (string, error) {
|
||||
return strings.Join(argv, " "), nil
|
||||
}
|
||||
|
||||
func (p *Process) CreateTime() (int64, error) {
|
||||
return p.CreateTimeWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) CreateTimeWithContext(ctx context.Context) (int64, error) {
|
||||
func (p *Process) createTimeWithContext(ctx context.Context) (int64, error) {
|
||||
return 0, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) Cwd() (string, error) {
|
||||
@@ -162,6 +173,23 @@ func (p *Process) StatusWithContext(ctx context.Context) (string, error) {
|
||||
|
||||
return s, nil
|
||||
}
|
||||
func (p *Process) Foreground() (bool, error) {
|
||||
return p.ForegroundWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) ForegroundWithContext(ctx context.Context) (bool, error) {
|
||||
// see https://github.com/shirou/gopsutil/issues/596#issuecomment-432707831 for implementation details
|
||||
pid := p.Pid
|
||||
ps, err := exec.LookPath("ps")
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
out, err := invoke.CommandWithContext(ctx, ps, "-o", "stat=", "-p", strconv.Itoa(int(pid)))
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return strings.IndexByte(string(out), '+') != -1, nil
|
||||
}
|
||||
func (p *Process) Uids() ([]int32, error) {
|
||||
return p.UidsWithContext(context.Background())
|
||||
}
|
||||
@@ -340,12 +368,20 @@ func (p *Process) MemoryInfoExWithContext(ctx context.Context) (*MemoryInfoExSta
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) PageFaults() (*PageFaultsStat, error) {
|
||||
return p.PageFaultsWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) PageFaultsWithContext(ctx context.Context) (*PageFaultsStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) Children() ([]*Process, error) {
|
||||
return p.ChildrenWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) ChildrenWithContext(ctx context.Context) ([]*Process, error) {
|
||||
pids, err := common.CallPgrep(invoke, p.Pid)
|
||||
pids, err := common.CallPgrepWithContext(ctx, invoke, p.Pid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -376,6 +412,14 @@ func (p *Process) ConnectionsWithContext(ctx context.Context) ([]net.ConnectionS
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) ConnectionsMax(max int) ([]net.ConnectionStat, error) {
|
||||
return p.ConnectionsMaxWithContext(context.Background(), max)
|
||||
}
|
||||
|
||||
func (p *Process) ConnectionsMaxWithContext(ctx context.Context, max int) ([]net.ConnectionStat, error) {
|
||||
return []net.ConnectionStat{}, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) NetIOCounters(pernic bool) ([]net.IOCountersStat, error) {
|
||||
return p.NetIOCountersWithContext(context.Background(), pernic)
|
||||
}
|
||||
@@ -384,13 +428,6 @@ func (p *Process) NetIOCountersWithContext(ctx context.Context, pernic bool) ([]
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) IsRunning() (bool, error) {
|
||||
return p.IsRunningWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) IsRunningWithContext(ctx context.Context) (bool, error) {
|
||||
return true, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) MemoryMaps(grouped bool) (*[]MemoryMapsStat, error) {
|
||||
return p.MemoryMapsWithContext(context.Background(), grouped)
|
||||
}
|
||||
@@ -461,12 +498,6 @@ func (p *Process) getKProcWithContext(ctx context.Context) (*KinfoProc, error) {
|
||||
return &k, nil
|
||||
}
|
||||
|
||||
func NewProcess(pid int32) (*Process, error) {
|
||||
p := &Process{Pid: pid}
|
||||
|
||||
return p, nil
|
||||
}
|
||||
|
||||
func CallKernProcSyscall(op int32, arg int32) ([]byte, uint64, error) {
|
||||
return CallKernProcSyscallWithContext(context.Background(), op, arg)
|
||||
}
|
||||
|
||||
51
vendor/github.com/shirou/gopsutil/process/process_posix.go
generated
vendored
51
vendor/github.com/shirou/gopsutil/process/process_posix.go
generated
vendored
@@ -4,6 +4,7 @@ package process
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/user"
|
||||
"path/filepath"
|
||||
@@ -11,6 +12,7 @@ import (
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
@@ -26,6 +28,9 @@ func getTerminalMap() (map[uint64]string, error) {
|
||||
defer d.Close()
|
||||
|
||||
devnames, err := d.Readdirnames(-1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, devname := range devnames {
|
||||
if strings.HasPrefix(devname, "/dev/tty") {
|
||||
termfiles = append(termfiles, "/dev/tty/"+devname)
|
||||
@@ -45,6 +50,9 @@ func getTerminalMap() (map[uint64]string, error) {
|
||||
if ptsnames == nil {
|
||||
defer ptsd.Close()
|
||||
ptsnames, err = ptsd.Readdirnames(-1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, ptsname := range ptsnames {
|
||||
termfiles = append(termfiles, "/dev/pts/"+ptsname)
|
||||
}
|
||||
@@ -63,6 +71,49 @@ func getTerminalMap() (map[uint64]string, error) {
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func PidExistsWithContext(ctx context.Context, pid int32) (bool, error) {
|
||||
if pid <= 0 {
|
||||
return false, fmt.Errorf("invalid pid %v", pid)
|
||||
}
|
||||
proc, err := os.FindProcess(int(pid))
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if _, err := os.Stat(common.HostProc()); err == nil { //Means that proc filesystem exist
|
||||
// Checking PID existence based on existence of /<HOST_PROC>/proc/<PID> folder
|
||||
// This covers the case when running inside container with a different process namespace (by default)
|
||||
|
||||
_, err := os.Stat(common.HostProc(strconv.Itoa(int(pid))))
|
||||
if os.IsNotExist(err) {
|
||||
return false, nil
|
||||
}
|
||||
return err == nil, err
|
||||
}
|
||||
|
||||
//'/proc' filesystem is not exist, checking of PID existence is done via signalling the process
|
||||
//Make sense only if we run in the same process namespace
|
||||
err = proc.Signal(syscall.Signal(0))
|
||||
if err == nil {
|
||||
return true, nil
|
||||
}
|
||||
if err.Error() == "os: process already finished" {
|
||||
return false, nil
|
||||
}
|
||||
errno, ok := err.(syscall.Errno)
|
||||
if !ok {
|
||||
return false, err
|
||||
}
|
||||
switch errno {
|
||||
case syscall.ESRCH:
|
||||
return false, nil
|
||||
case syscall.EPERM:
|
||||
return true, nil
|
||||
}
|
||||
|
||||
return false, err
|
||||
}
|
||||
|
||||
// SendSignal sends a unix.Signal to the process.
|
||||
// Currently, SIGSTOP, SIGCONT, SIGTERM and SIGKILL are supported.
|
||||
func (p *Process) SendSignal(sig syscall.Signal) error {
|
||||
|
||||
20
vendor/github.com/shirou/gopsutil/process/process_posix_test.go
generated
vendored
20
vendor/github.com/shirou/gopsutil/process/process_posix_test.go
generated
vendored
@@ -1,20 +0,0 @@
|
||||
// +build linux freebsd
|
||||
|
||||
package process
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func Test_SendSignal(t *testing.T) {
|
||||
checkPid := os.Getpid()
|
||||
|
||||
p, _ := NewProcess(int32(checkPid))
|
||||
err := p.SendSignal(unix.SIGCONT)
|
||||
if err != nil {
|
||||
t.Errorf("send signal %v", err)
|
||||
}
|
||||
}
|
||||
446
vendor/github.com/shirou/gopsutil/process/process_test.go
generated
vendored
446
vendor/github.com/shirou/gopsutil/process/process_test.go
generated
vendored
@@ -1,446 +0,0 @@
|
||||
package process
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"os/user"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
var mu sync.Mutex
|
||||
|
||||
func testGetProcess() Process {
|
||||
checkPid := os.Getpid() // process.test
|
||||
ret, _ := NewProcess(int32(checkPid))
|
||||
return *ret
|
||||
}
|
||||
|
||||
func Test_Pids(t *testing.T) {
|
||||
ret, err := Pids()
|
||||
if err != nil {
|
||||
t.Errorf("error %v", err)
|
||||
}
|
||||
if len(ret) == 0 {
|
||||
t.Errorf("could not get pids %v", ret)
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
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()
|
||||
|
||||
ret, err := PidExists(int32(checkPid))
|
||||
if err != nil {
|
||||
t.Errorf("error %v", err)
|
||||
}
|
||||
|
||||
if ret == false {
|
||||
t.Errorf("could not get process exists: %v", ret)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_NewProcess(t *testing.T) {
|
||||
checkPid := os.Getpid()
|
||||
|
||||
ret, err := NewProcess(int32(checkPid))
|
||||
if err != nil {
|
||||
t.Errorf("error %v", err)
|
||||
}
|
||||
empty := &Process{}
|
||||
if runtime.GOOS != "windows" { // Windows pid is 0
|
||||
if empty == ret {
|
||||
t.Errorf("error %v", ret)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func Test_Process_memory_maps(t *testing.T) {
|
||||
checkPid := os.Getpid()
|
||||
|
||||
ret, err := NewProcess(int32(checkPid))
|
||||
|
||||
mmaps, err := ret.MemoryMaps(false)
|
||||
if err != nil {
|
||||
t.Errorf("memory map get error %v", err)
|
||||
}
|
||||
empty := MemoryMapsStat{}
|
||||
for _, m := range *mmaps {
|
||||
if m == empty {
|
||||
t.Errorf("memory map get error %v", m)
|
||||
}
|
||||
}
|
||||
}
|
||||
func Test_Process_MemoryInfo(t *testing.T) {
|
||||
p := testGetProcess()
|
||||
|
||||
v, err := p.MemoryInfo()
|
||||
if err != nil {
|
||||
t.Errorf("geting memory info error %v", err)
|
||||
}
|
||||
empty := MemoryInfoStat{}
|
||||
if v == nil || *v == empty {
|
||||
t.Errorf("could not get memory info %v", v)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_Process_CmdLine(t *testing.T) {
|
||||
p := testGetProcess()
|
||||
|
||||
v, err := p.Cmdline()
|
||||
if err != nil {
|
||||
t.Errorf("geting cmdline error %v", err)
|
||||
}
|
||||
if !strings.Contains(v, "process.test") {
|
||||
t.Errorf("invalid cmd line %v", v)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_Process_CmdLineSlice(t *testing.T) {
|
||||
p := testGetProcess()
|
||||
|
||||
v, err := p.CmdlineSlice()
|
||||
if err != nil {
|
||||
t.Fatalf("geting cmdline slice error %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(v, os.Args) {
|
||||
t.Errorf("returned cmdline slice not as expected:\nexp: %v\ngot: %v", os.Args, v)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_Process_Ppid(t *testing.T) {
|
||||
p := testGetProcess()
|
||||
|
||||
v, err := p.Ppid()
|
||||
if err != nil {
|
||||
t.Errorf("geting ppid error %v", err)
|
||||
}
|
||||
if v == 0 {
|
||||
t.Errorf("return value is 0 %v", v)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_Process_Status(t *testing.T) {
|
||||
p := testGetProcess()
|
||||
|
||||
v, err := p.Status()
|
||||
if err != nil {
|
||||
t.Errorf("geting status error %v", err)
|
||||
}
|
||||
if v != "R" && v != "S" {
|
||||
t.Errorf("could not get state %v", v)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_Process_Terminal(t *testing.T) {
|
||||
p := testGetProcess()
|
||||
|
||||
_, err := p.Terminal()
|
||||
if err != nil {
|
||||
t.Errorf("geting terminal error %v", err)
|
||||
}
|
||||
|
||||
/*
|
||||
if v == "" {
|
||||
t.Errorf("could not get terminal %v", v)
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
func Test_Process_IOCounters(t *testing.T) {
|
||||
p := testGetProcess()
|
||||
|
||||
v, err := p.IOCounters()
|
||||
if err != nil {
|
||||
t.Errorf("geting iocounter error %v", err)
|
||||
return
|
||||
}
|
||||
empty := &IOCountersStat{}
|
||||
if v == empty {
|
||||
t.Errorf("error %v", v)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_Process_NumCtx(t *testing.T) {
|
||||
p := testGetProcess()
|
||||
|
||||
_, err := p.NumCtxSwitches()
|
||||
if err != nil {
|
||||
t.Errorf("geting numctx error %v", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func Test_Process_Nice(t *testing.T) {
|
||||
p := testGetProcess()
|
||||
|
||||
n, err := p.Nice()
|
||||
if err != nil {
|
||||
t.Errorf("geting nice error %v", err)
|
||||
}
|
||||
if n != 0 && n != 20 && n != 8 {
|
||||
t.Errorf("invalid nice: %d", n)
|
||||
}
|
||||
}
|
||||
func Test_Process_NumThread(t *testing.T) {
|
||||
p := testGetProcess()
|
||||
|
||||
n, err := p.NumThreads()
|
||||
if err != nil {
|
||||
t.Errorf("geting NumThread error %v", err)
|
||||
}
|
||||
if n < 0 {
|
||||
t.Errorf("invalid NumThread: %d", n)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_Process_Threads(t *testing.T) {
|
||||
p := testGetProcess()
|
||||
|
||||
n, err := p.NumThreads()
|
||||
if err != nil {
|
||||
t.Errorf("geting NumThread error %v", err)
|
||||
}
|
||||
if n < 0 {
|
||||
t.Errorf("invalid NumThread: %d", n)
|
||||
}
|
||||
|
||||
ts, err := p.Threads()
|
||||
if err != nil {
|
||||
t.Errorf("geting Threads error %v", err)
|
||||
}
|
||||
if len(ts) != int(n) {
|
||||
t.Errorf("unexpected number of threads: %v vs %v", len(ts), n)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_Process_Name(t *testing.T) {
|
||||
p := testGetProcess()
|
||||
|
||||
n, err := p.Name()
|
||||
if err != nil {
|
||||
t.Errorf("geting name error %v", err)
|
||||
}
|
||||
if !strings.Contains(n, "process.test") {
|
||||
t.Errorf("invalid Exe %s", n)
|
||||
}
|
||||
}
|
||||
func Test_Process_Exe(t *testing.T) {
|
||||
p := testGetProcess()
|
||||
|
||||
n, err := p.Exe()
|
||||
if err != nil {
|
||||
t.Errorf("geting Exe error %v", err)
|
||||
}
|
||||
if !strings.Contains(n, "process.test") {
|
||||
t.Errorf("invalid Exe %s", n)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_Process_CpuPercent(t *testing.T) {
|
||||
p := testGetProcess()
|
||||
percent, err := p.Percent(0)
|
||||
if err != nil {
|
||||
t.Errorf("error %v", err)
|
||||
}
|
||||
duration := time.Duration(1000) * time.Microsecond
|
||||
time.Sleep(duration)
|
||||
percent, err = p.Percent(0)
|
||||
if err != nil {
|
||||
t.Errorf("error %v", err)
|
||||
}
|
||||
|
||||
numcpu := runtime.NumCPU()
|
||||
// if percent < 0.0 || percent > 100.0*float64(numcpu) { // TODO
|
||||
if percent < 0.0 {
|
||||
t.Fatalf("CPUPercent value is invalid: %f, %d", percent, numcpu)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_Process_CpuPercentLoop(t *testing.T) {
|
||||
p := testGetProcess()
|
||||
numcpu := runtime.NumCPU()
|
||||
|
||||
for i := 0; i < 2; i++ {
|
||||
duration := time.Duration(100) * time.Microsecond
|
||||
percent, err := p.Percent(duration)
|
||||
if err != nil {
|
||||
t.Errorf("error %v", err)
|
||||
}
|
||||
// if percent < 0.0 || percent > 100.0*float64(numcpu) { // TODO
|
||||
if percent < 0.0 {
|
||||
t.Fatalf("CPUPercent value is invalid: %f, %d", percent, numcpu)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Test_Process_CreateTime(t *testing.T) {
|
||||
if os.Getenv("CIRCLECI") == "true" {
|
||||
t.Skip("Skip CI")
|
||||
}
|
||||
|
||||
p := testGetProcess()
|
||||
|
||||
c, err := p.CreateTime()
|
||||
if err != nil {
|
||||
t.Errorf("error %v", err)
|
||||
}
|
||||
|
||||
if c < 1420000000 {
|
||||
t.Errorf("process created time is wrong.")
|
||||
}
|
||||
|
||||
gotElapsed := time.Since(time.Unix(int64(c/1000), 0))
|
||||
maxElapsed := time.Duration(5 * time.Second)
|
||||
|
||||
if gotElapsed >= maxElapsed {
|
||||
t.Errorf("this process has not been running for %v", gotElapsed)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_Parent(t *testing.T) {
|
||||
p := testGetProcess()
|
||||
|
||||
c, err := p.Parent()
|
||||
if err != nil {
|
||||
t.Fatalf("error %v", err)
|
||||
}
|
||||
if c == nil {
|
||||
t.Fatalf("could not get parent")
|
||||
}
|
||||
if c.Pid == 0 {
|
||||
t.Fatalf("wrong parent pid")
|
||||
}
|
||||
}
|
||||
|
||||
func Test_Connections(t *testing.T) {
|
||||
p := testGetProcess()
|
||||
|
||||
c, err := p.Connections()
|
||||
if err != nil {
|
||||
t.Fatalf("error %v", err)
|
||||
}
|
||||
// TODO:
|
||||
// Since go test open no conneciton, ret is empty.
|
||||
// should invoke child process or other solutions.
|
||||
if len(c) != 0 {
|
||||
t.Fatalf("wrong connections")
|
||||
}
|
||||
}
|
||||
|
||||
func Test_Children(t *testing.T) {
|
||||
p, err := NewProcess(1)
|
||||
if err != nil {
|
||||
t.Fatalf("new process error %v", err)
|
||||
}
|
||||
|
||||
c, err := p.Children()
|
||||
if err != nil {
|
||||
t.Fatalf("error %v", err)
|
||||
}
|
||||
if len(c) == 0 {
|
||||
t.Fatalf("children is empty")
|
||||
}
|
||||
}
|
||||
|
||||
func Test_Username(t *testing.T) {
|
||||
myPid := os.Getpid()
|
||||
currentUser, _ := user.Current()
|
||||
myUsername := currentUser.Username
|
||||
|
||||
process, _ := NewProcess(int32(myPid))
|
||||
pidUsername, _ := process.Username()
|
||||
assert.Equal(t, myUsername, pidUsername)
|
||||
|
||||
t.Log(pidUsername)
|
||||
}
|
||||
|
||||
func Test_CPUTimes(t *testing.T) {
|
||||
pid := os.Getpid()
|
||||
process, err := NewProcess(int32(pid))
|
||||
assert.Nil(t, err)
|
||||
|
||||
spinSeconds := 0.2
|
||||
cpuTimes0, err := process.Times()
|
||||
assert.Nil(t, err)
|
||||
|
||||
// Spin for a duration of spinSeconds
|
||||
t0 := time.Now()
|
||||
tGoal := t0.Add(time.Duration(spinSeconds*1000) * time.Millisecond)
|
||||
assert.Nil(t, err)
|
||||
for time.Now().Before(tGoal) {
|
||||
// This block intentionally left blank
|
||||
}
|
||||
|
||||
cpuTimes1, err := process.Times()
|
||||
assert.Nil(t, err)
|
||||
|
||||
if cpuTimes0 == nil || cpuTimes1 == nil {
|
||||
t.FailNow()
|
||||
}
|
||||
measuredElapsed := cpuTimes1.Total() - cpuTimes0.Total()
|
||||
message := fmt.Sprintf("Measured %fs != spun time of %fs\ncpuTimes0=%v\ncpuTimes1=%v",
|
||||
measuredElapsed, spinSeconds, cpuTimes0, cpuTimes1)
|
||||
assert.True(t, measuredElapsed > float64(spinSeconds)/5, message)
|
||||
assert.True(t, measuredElapsed < float64(spinSeconds)*5, message)
|
||||
}
|
||||
|
||||
func Test_OpenFiles(t *testing.T) {
|
||||
pid := os.Getpid()
|
||||
p, err := NewProcess(int32(pid))
|
||||
assert.Nil(t, err)
|
||||
|
||||
v, err := p.OpenFiles()
|
||||
assert.Nil(t, err)
|
||||
assert.NotEmpty(t, v) // test always open files.
|
||||
|
||||
for _, vv := range v {
|
||||
assert.NotEqual(t, "", vv.Path)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_Kill(t *testing.T) {
|
||||
var cmd *exec.Cmd
|
||||
if runtime.GOOS == "windows" {
|
||||
cmd = exec.Command("choice", "/C", "YN", "/D", "Y", "/t", "3")
|
||||
} else {
|
||||
cmd = exec.Command("sleep", "3")
|
||||
}
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
assert.NotNil(t, cmd.Run())
|
||||
wg.Done()
|
||||
}()
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
p, err := NewProcess(int32(cmd.Process.Pid))
|
||||
assert.Nil(t, err)
|
||||
assert.Nil(t, p.Kill())
|
||||
wg.Wait()
|
||||
}
|
||||
385
vendor/github.com/shirou/gopsutil/process/process_windows.go
generated
vendored
385
vendor/github.com/shirou/gopsutil/process/process_windows.go
generated
vendored
@@ -15,18 +15,21 @@ import (
|
||||
cpu "github.com/shirou/gopsutil/cpu"
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
net "github.com/shirou/gopsutil/net"
|
||||
"github.com/shirou/w32"
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
const (
|
||||
NoMoreFiles = 0x12
|
||||
MaxPathLength = 260
|
||||
)
|
||||
|
||||
var (
|
||||
modpsapi = windows.NewLazyDLL("psapi.dll")
|
||||
procGetProcessMemoryInfo = modpsapi.NewProc("GetProcessMemoryInfo")
|
||||
modpsapi = windows.NewLazySystemDLL("psapi.dll")
|
||||
procGetProcessMemoryInfo = modpsapi.NewProc("GetProcessMemoryInfo")
|
||||
procGetProcessImageFileNameW = modpsapi.NewProc("GetProcessImageFileNameW")
|
||||
|
||||
advapi32 = windows.NewLazySystemDLL("advapi32.dll")
|
||||
procLookupPrivilegeValue = advapi32.NewProc("LookupPrivilegeValueW")
|
||||
procAdjustTokenPrivileges = advapi32.NewProc("AdjustTokenPrivileges")
|
||||
|
||||
procQueryFullProcessImageNameW = common.Modkernel32.NewProc("QueryFullProcessImageNameW")
|
||||
procGetPriorityClass = common.Modkernel32.NewProc("GetPriorityClass")
|
||||
procGetProcessIoCounters = common.Modkernel32.NewProc("GetProcessIoCounters")
|
||||
)
|
||||
|
||||
type SystemProcessInformation struct {
|
||||
@@ -51,6 +54,17 @@ type MemoryInfoExStat struct {
|
||||
type MemoryMapsStat struct {
|
||||
}
|
||||
|
||||
// ioCounters is an equivalent representation of IO_COUNTERS in the Windows API.
|
||||
// https://docs.microsoft.com/windows/win32/api/winnt/ns-winnt-io_counters
|
||||
type ioCounters struct {
|
||||
ReadOperationCount uint64
|
||||
WriteOperationCount uint64
|
||||
OtherOperationCount uint64
|
||||
ReadTransferCount uint64
|
||||
WriteTransferCount uint64
|
||||
OtherTransferCount uint64
|
||||
}
|
||||
|
||||
type Win32_Process struct {
|
||||
Name string
|
||||
ExecutablePath *string
|
||||
@@ -90,15 +104,64 @@ type Win32_Process struct {
|
||||
WorkingSetSize uint64
|
||||
}
|
||||
|
||||
type winLUID struct {
|
||||
LowPart winDWord
|
||||
HighPart winLong
|
||||
}
|
||||
|
||||
// LUID_AND_ATTRIBUTES
|
||||
type winLUIDAndAttributes struct {
|
||||
Luid winLUID
|
||||
Attributes winDWord
|
||||
}
|
||||
|
||||
// TOKEN_PRIVILEGES
|
||||
type winTokenPriviledges struct {
|
||||
PrivilegeCount winDWord
|
||||
Privileges [1]winLUIDAndAttributes
|
||||
}
|
||||
|
||||
type winLong int32
|
||||
type winDWord uint32
|
||||
|
||||
func init() {
|
||||
wmi.DefaultClient.AllowMissingFields = true
|
||||
|
||||
// enable SeDebugPrivilege https://github.com/midstar/proci/blob/6ec79f57b90ba3d9efa2a7b16ef9c9369d4be875/proci_windows.go#L80-L119
|
||||
handle, err := syscall.GetCurrentProcess()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var token syscall.Token
|
||||
err = syscall.OpenProcessToken(handle, 0x0028, &token)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer token.Close()
|
||||
|
||||
tokenPriviledges := winTokenPriviledges{PrivilegeCount: 1}
|
||||
lpName := syscall.StringToUTF16("SeDebugPrivilege")
|
||||
ret, _, _ := procLookupPrivilegeValue.Call(
|
||||
0,
|
||||
uintptr(unsafe.Pointer(&lpName[0])),
|
||||
uintptr(unsafe.Pointer(&tokenPriviledges.Privileges[0].Luid)))
|
||||
if ret == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
tokenPriviledges.Privileges[0].Attributes = 0x00000002 // SE_PRIVILEGE_ENABLED
|
||||
|
||||
procAdjustTokenPrivileges.Call(
|
||||
uintptr(token),
|
||||
0,
|
||||
uintptr(unsafe.Pointer(&tokenPriviledges)),
|
||||
uintptr(unsafe.Sizeof(tokenPriviledges)),
|
||||
0,
|
||||
0)
|
||||
}
|
||||
|
||||
func Pids() ([]int32, error) {
|
||||
return PidsWithContext(context.Background())
|
||||
}
|
||||
|
||||
func PidsWithContext(ctx context.Context) ([]int32, error) {
|
||||
func pidsWithContext(ctx context.Context) ([]int32, error) {
|
||||
// inspired by https://gist.github.com/henkman/3083408
|
||||
// and https://github.com/giampaolo/psutil/blob/1c3a15f637521ba5c0031283da39c733fda53e4c/psutil/arch/windows/process_info.c#L315-L329
|
||||
var ret []int32
|
||||
@@ -108,8 +171,8 @@ func PidsWithContext(ctx context.Context) ([]int32, error) {
|
||||
|
||||
for {
|
||||
ps := make([]uint32, psSize)
|
||||
if !w32.EnumProcesses(ps, uint32(len(ps)), &read) {
|
||||
return nil, fmt.Errorf("could not get w32.EnumProcesses")
|
||||
if err := windows.EnumProcesses(ps, &read); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if uint32(len(ps)) == read { // ps buffer was too small to host every results, retry with a bigger one
|
||||
psSize += 1024
|
||||
@@ -124,6 +187,44 @@ func PidsWithContext(ctx context.Context) ([]int32, error) {
|
||||
|
||||
}
|
||||
|
||||
func PidExistsWithContext(ctx context.Context, pid int32) (bool, error) {
|
||||
if pid == 0 { // special case for pid 0 System Idle Process
|
||||
return true, nil
|
||||
}
|
||||
if pid < 0 {
|
||||
return false, fmt.Errorf("invalid pid %v", pid)
|
||||
}
|
||||
if pid%4 != 0 {
|
||||
// OpenProcess will succeed even on non-existing pid here https://devblogs.microsoft.com/oldnewthing/20080606-00/?p=22043
|
||||
// so we list every pid just to be sure and be future-proof
|
||||
pids, err := PidsWithContext(ctx)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
for _, i := range pids {
|
||||
if i == pid {
|
||||
return true, err
|
||||
}
|
||||
}
|
||||
return false, err
|
||||
}
|
||||
const STILL_ACTIVE = 259 // https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getexitcodeprocess
|
||||
h, err := windows.OpenProcess(windows.PROCESS_QUERY_LIMITED_INFORMATION, false, uint32(pid))
|
||||
if err == windows.ERROR_ACCESS_DENIED {
|
||||
return true, nil
|
||||
}
|
||||
if err == windows.ERROR_INVALID_PARAMETER {
|
||||
return false, nil
|
||||
}
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
defer syscall.CloseHandle(syscall.Handle(h))
|
||||
var exitCode uint32
|
||||
err = windows.GetExitCodeProcess(h, &exitCode)
|
||||
return exitCode == STILL_ACTIVE, err
|
||||
}
|
||||
|
||||
func (p *Process) Ppid() (int32, error) {
|
||||
return p.PpidWithContext(context.Background())
|
||||
}
|
||||
@@ -177,11 +278,30 @@ func (p *Process) Exe() (string, error) {
|
||||
}
|
||||
|
||||
func (p *Process) ExeWithContext(ctx context.Context) (string, error) {
|
||||
dst, err := GetWin32Proc(p.Pid)
|
||||
c, err := windows.OpenProcess(windows.PROCESS_QUERY_LIMITED_INFORMATION, false, uint32(p.Pid))
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("could not get ExecutablePath: %s", err)
|
||||
return "", err
|
||||
}
|
||||
return *dst[0].ExecutablePath, nil
|
||||
defer windows.CloseHandle(c)
|
||||
buf := make([]uint16, syscall.MAX_LONG_PATH)
|
||||
size := uint32(syscall.MAX_LONG_PATH)
|
||||
if err := procQueryFullProcessImageNameW.Find(); err == nil { // Vista+
|
||||
ret, _, err := procQueryFullProcessImageNameW.Call(
|
||||
uintptr(c),
|
||||
uintptr(0),
|
||||
uintptr(unsafe.Pointer(&buf[0])),
|
||||
uintptr(unsafe.Pointer(&size)))
|
||||
if ret == 0 {
|
||||
return "", err
|
||||
}
|
||||
return windows.UTF16ToString(buf[:]), nil
|
||||
}
|
||||
// XP fallback
|
||||
ret, _, err := procGetProcessImageFileNameW.Call(uintptr(c), uintptr(unsafe.Pointer(&buf[0])), uintptr(size))
|
||||
if ret == 0 {
|
||||
return "", err
|
||||
}
|
||||
return common.ConvertDOSPath(windows.UTF16ToString(buf[:])), nil
|
||||
}
|
||||
|
||||
func (p *Process) Cmdline() (string, error) {
|
||||
@@ -189,7 +309,7 @@ func (p *Process) Cmdline() (string, error) {
|
||||
}
|
||||
|
||||
func (p *Process) CmdlineWithContext(ctx context.Context) (string, error) {
|
||||
dst, err := GetWin32Proc(p.Pid)
|
||||
dst, err := GetWin32ProcWithContext(ctx, p.Pid)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("could not get CommandLine: %s", err)
|
||||
}
|
||||
@@ -204,18 +324,14 @@ func (p *Process) CmdlineSlice() ([]string, error) {
|
||||
}
|
||||
|
||||
func (p *Process) CmdlineSliceWithContext(ctx context.Context) ([]string, error) {
|
||||
cmdline, err := p.Cmdline()
|
||||
cmdline, err := p.CmdlineWithContext(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return strings.Split(cmdline, " "), nil
|
||||
}
|
||||
|
||||
func (p *Process) CreateTime() (int64, error) {
|
||||
return p.CreateTimeWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) CreateTimeWithContext(ctx context.Context) (int64, error) {
|
||||
func (p *Process) createTimeWithContext(ctx context.Context) (int64, error) {
|
||||
ru, err := getRusage(p.Pid)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("could not get CreationDate: %s", err)
|
||||
@@ -236,12 +352,12 @@ func (p *Process) Parent() (*Process, error) {
|
||||
}
|
||||
|
||||
func (p *Process) ParentWithContext(ctx context.Context) (*Process, error) {
|
||||
dst, err := GetWin32Proc(p.Pid)
|
||||
ppid, err := p.PpidWithContext(ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not get ParentProcessID: %s", err)
|
||||
}
|
||||
|
||||
return NewProcess(int32(dst[0].ParentProcessID))
|
||||
return NewProcess(ppid)
|
||||
}
|
||||
func (p *Process) Status() (string, error) {
|
||||
return p.StatusWithContext(context.Background())
|
||||
@@ -250,26 +366,37 @@ func (p *Process) Status() (string, error) {
|
||||
func (p *Process) StatusWithContext(ctx context.Context) (string, error) {
|
||||
return "", common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) Foreground() (bool, error) {
|
||||
return p.ForegroundWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) ForegroundWithContext(ctx context.Context) (bool, error) {
|
||||
return false, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) Username() (string, error) {
|
||||
return p.UsernameWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) UsernameWithContext(ctx context.Context) (string, error) {
|
||||
pid := p.Pid
|
||||
// 0x1000 is PROCESS_QUERY_LIMITED_INFORMATION
|
||||
c, err := syscall.OpenProcess(0x1000, false, uint32(pid))
|
||||
c, err := windows.OpenProcess(windows.PROCESS_QUERY_LIMITED_INFORMATION, false, uint32(pid))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer syscall.CloseHandle(c)
|
||||
defer windows.CloseHandle(c)
|
||||
|
||||
var token syscall.Token
|
||||
err = syscall.OpenProcessToken(c, syscall.TOKEN_QUERY, &token)
|
||||
err = syscall.OpenProcessToken(syscall.Handle(c), syscall.TOKEN_QUERY, &token)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer token.Close()
|
||||
tokenUser, err := token.GetTokenUser()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
user, domain, _, err := tokenUser.User.Sid.LookupAccount("")
|
||||
return domain + "\\" + user, err
|
||||
@@ -300,17 +427,38 @@ func (p *Process) TerminalWithContext(ctx context.Context) (string, error) {
|
||||
return "", common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
// Nice returnes priority in Windows
|
||||
// priorityClasses maps a win32 priority class to its WMI equivalent Win32_Process.Priority
|
||||
// https://docs.microsoft.com/en-us/windows/desktop/api/processthreadsapi/nf-processthreadsapi-getpriorityclass
|
||||
// https://docs.microsoft.com/en-us/windows/desktop/cimwin32prov/win32-process
|
||||
var priorityClasses = map[int]int32{
|
||||
0x00008000: 10, // ABOVE_NORMAL_PRIORITY_CLASS
|
||||
0x00004000: 6, // BELOW_NORMAL_PRIORITY_CLASS
|
||||
0x00000080: 13, // HIGH_PRIORITY_CLASS
|
||||
0x00000040: 4, // IDLE_PRIORITY_CLASS
|
||||
0x00000020: 8, // NORMAL_PRIORITY_CLASS
|
||||
0x00000100: 24, // REALTIME_PRIORITY_CLASS
|
||||
}
|
||||
|
||||
// Nice returns priority in Windows
|
||||
func (p *Process) Nice() (int32, error) {
|
||||
return p.NiceWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) NiceWithContext(ctx context.Context) (int32, error) {
|
||||
dst, err := GetWin32Proc(p.Pid)
|
||||
c, err := windows.OpenProcess(windows.PROCESS_QUERY_LIMITED_INFORMATION, false, uint32(p.Pid))
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("could not get Priority: %s", err)
|
||||
return 0, err
|
||||
}
|
||||
return int32(dst[0].Priority), nil
|
||||
defer windows.CloseHandle(c)
|
||||
ret, _, err := procGetPriorityClass.Call(uintptr(c))
|
||||
if ret == 0 {
|
||||
return 0, err
|
||||
}
|
||||
priority, ok := priorityClasses[int(ret)]
|
||||
if !ok {
|
||||
return 0, fmt.Errorf("unknown priority class %v", ret)
|
||||
}
|
||||
return priority, nil
|
||||
}
|
||||
func (p *Process) IOnice() (int32, error) {
|
||||
return p.IOniceWithContext(context.Background())
|
||||
@@ -343,18 +491,24 @@ func (p *Process) IOCounters() (*IOCountersStat, error) {
|
||||
}
|
||||
|
||||
func (p *Process) IOCountersWithContext(ctx context.Context) (*IOCountersStat, error) {
|
||||
dst, err := GetWin32Proc(p.Pid)
|
||||
if err != nil || len(dst) == 0 {
|
||||
return nil, fmt.Errorf("could not get Win32Proc: %s", err)
|
||||
c, err := windows.OpenProcess(windows.PROCESS_QUERY_LIMITED_INFORMATION, false, uint32(p.Pid))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ret := &IOCountersStat{
|
||||
ReadCount: uint64(dst[0].ReadOperationCount),
|
||||
ReadBytes: uint64(dst[0].ReadTransferCount),
|
||||
WriteCount: uint64(dst[0].WriteOperationCount),
|
||||
WriteBytes: uint64(dst[0].WriteTransferCount),
|
||||
defer windows.CloseHandle(c)
|
||||
var ioCounters ioCounters
|
||||
ret, _, err := procGetProcessIoCounters.Call(uintptr(c), uintptr(unsafe.Pointer(&ioCounters)))
|
||||
if ret == 0 {
|
||||
return nil, err
|
||||
}
|
||||
stats := &IOCountersStat{
|
||||
ReadCount: ioCounters.ReadOperationCount,
|
||||
ReadBytes: ioCounters.ReadTransferCount,
|
||||
WriteCount: ioCounters.WriteOperationCount,
|
||||
WriteBytes: ioCounters.WriteTransferCount,
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
return stats, nil
|
||||
}
|
||||
func (p *Process) NumCtxSwitches() (*NumCtxSwitchesStat, error) {
|
||||
return p.NumCtxSwitchesWithContext(context.Background())
|
||||
@@ -375,11 +529,11 @@ func (p *Process) NumThreads() (int32, error) {
|
||||
}
|
||||
|
||||
func (p *Process) NumThreadsWithContext(ctx context.Context) (int32, error) {
|
||||
dst, err := GetWin32Proc(p.Pid)
|
||||
_, ret, _, err := getFromSnapProcess(p.Pid)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("could not get ThreadCount: %s", err)
|
||||
return 0, err
|
||||
}
|
||||
return int32(dst[0].ThreadCount), nil
|
||||
return ret, nil
|
||||
}
|
||||
func (p *Process) Threads() (map[int32]*cpu.TimesStat, error) {
|
||||
return p.ThreadsWithContext(context.Background())
|
||||
@@ -448,27 +602,41 @@ func (p *Process) MemoryInfoExWithContext(ctx context.Context) (*MemoryInfoExSta
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) PageFaults() (*PageFaultsStat, error) {
|
||||
return p.PageFaultsWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) PageFaultsWithContext(ctx context.Context) (*PageFaultsStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) Children() ([]*Process, error) {
|
||||
return p.ChildrenWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) ChildrenWithContext(ctx context.Context) ([]*Process, error) {
|
||||
var dst []Win32_Process
|
||||
query := wmi.CreateQuery(&dst, fmt.Sprintf("Where ParentProcessId = %d", p.Pid))
|
||||
err := common.WMIQueryWithContext(ctx, query, &dst)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out := []*Process{}
|
||||
for _, proc := range dst {
|
||||
p, err := NewProcess(int32(proc.ProcessID))
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
out = append(out, p)
|
||||
snap, err := windows.CreateToolhelp32Snapshot(windows.TH32CS_SNAPPROCESS, uint32(0))
|
||||
if err != nil {
|
||||
return out, err
|
||||
}
|
||||
defer windows.CloseHandle(snap)
|
||||
var pe32 windows.ProcessEntry32
|
||||
pe32.Size = uint32(unsafe.Sizeof(pe32))
|
||||
if err := windows.Process32First(snap, &pe32); err != nil {
|
||||
return out, err
|
||||
}
|
||||
for {
|
||||
if pe32.ParentProcessID == uint32(p.Pid) {
|
||||
p, err := NewProcess(int32(pe32.ProcessID))
|
||||
if err == nil {
|
||||
out = append(out, p)
|
||||
}
|
||||
}
|
||||
if err = windows.Process32Next(snap, &pe32); err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
@@ -485,7 +653,15 @@ func (p *Process) Connections() ([]net.ConnectionStat, error) {
|
||||
}
|
||||
|
||||
func (p *Process) ConnectionsWithContext(ctx context.Context) ([]net.ConnectionStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
return net.ConnectionsPidWithContext(ctx, "all", p.Pid)
|
||||
}
|
||||
|
||||
func (p *Process) ConnectionsMax(max int) ([]net.ConnectionStat, error) {
|
||||
return p.ConnectionsMaxWithContext(context.Background(), max)
|
||||
}
|
||||
|
||||
func (p *Process) ConnectionsMaxWithContext(ctx context.Context, max int) ([]net.ConnectionStat, error) {
|
||||
return []net.ConnectionStat{}, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) NetIOCounters(pernic bool) ([]net.IOCountersStat, error) {
|
||||
@@ -496,14 +672,6 @@ func (p *Process) NetIOCountersWithContext(ctx context.Context, pernic bool) ([]
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) IsRunning() (bool, error) {
|
||||
return p.IsRunningWithContext(context.Background())
|
||||
}
|
||||
|
||||
func (p *Process) IsRunningWithContext(ctx context.Context) (bool, error) {
|
||||
return true, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) MemoryMaps(grouped bool) (*[]MemoryMapsStat, error) {
|
||||
return p.MemoryMapsWithContext(context.Background(), grouped)
|
||||
}
|
||||
@@ -513,12 +681,6 @@ func (p *Process) MemoryMapsWithContext(ctx context.Context, grouped bool) (*[]M
|
||||
return &ret, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func NewProcess(pid int32) (*Process, error) {
|
||||
p := &Process{Pid: pid}
|
||||
|
||||
return p, nil
|
||||
}
|
||||
|
||||
func (p *Process) SendSignal(sig windows.Signal) error {
|
||||
return p.SendSignalWithContext(context.Background(), sig)
|
||||
}
|
||||
@@ -547,16 +709,13 @@ func (p *Process) Terminate() error {
|
||||
}
|
||||
|
||||
func (p *Process) TerminateWithContext(ctx context.Context) error {
|
||||
// PROCESS_TERMINATE = 0x0001
|
||||
proc := w32.OpenProcess(0x0001, false, uint32(p.Pid))
|
||||
ret := w32.TerminateProcess(proc, 0)
|
||||
w32.CloseHandle(proc)
|
||||
|
||||
if ret == false {
|
||||
return windows.GetLastError()
|
||||
} else {
|
||||
return nil
|
||||
proc, err := windows.OpenProcess(windows.PROCESS_TERMINATE, false, uint32(p.Pid))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = windows.TerminateProcess(proc, 0)
|
||||
windows.CloseHandle(proc)
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *Process) Kill() error {
|
||||
@@ -569,29 +728,26 @@ func (p *Process) KillWithContext(ctx context.Context) error {
|
||||
}
|
||||
|
||||
func getFromSnapProcess(pid int32) (int32, int32, string, error) {
|
||||
snap := w32.CreateToolhelp32Snapshot(w32.TH32CS_SNAPPROCESS, uint32(pid))
|
||||
if snap == 0 {
|
||||
return 0, 0, "", windows.GetLastError()
|
||||
snap, err := windows.CreateToolhelp32Snapshot(windows.TH32CS_SNAPPROCESS, uint32(pid))
|
||||
if err != nil {
|
||||
return 0, 0, "", err
|
||||
}
|
||||
defer w32.CloseHandle(snap)
|
||||
var pe32 w32.PROCESSENTRY32
|
||||
pe32.DwSize = uint32(unsafe.Sizeof(pe32))
|
||||
if w32.Process32First(snap, &pe32) == false {
|
||||
return 0, 0, "", windows.GetLastError()
|
||||
defer windows.CloseHandle(snap)
|
||||
var pe32 windows.ProcessEntry32
|
||||
pe32.Size = uint32(unsafe.Sizeof(pe32))
|
||||
if err = windows.Process32First(snap, &pe32); err != nil {
|
||||
return 0, 0, "", err
|
||||
}
|
||||
|
||||
if pe32.Th32ProcessID == uint32(pid) {
|
||||
szexe := windows.UTF16ToString(pe32.SzExeFile[:])
|
||||
return int32(pe32.Th32ParentProcessID), int32(pe32.CntThreads), szexe, nil
|
||||
}
|
||||
|
||||
for w32.Process32Next(snap, &pe32) {
|
||||
if pe32.Th32ProcessID == uint32(pid) {
|
||||
szexe := windows.UTF16ToString(pe32.SzExeFile[:])
|
||||
return int32(pe32.Th32ParentProcessID), int32(pe32.CntThreads), szexe, nil
|
||||
for {
|
||||
if pe32.ProcessID == uint32(pid) {
|
||||
szexe := windows.UTF16ToString(pe32.ExeFile[:])
|
||||
return int32(pe32.ParentProcessID), int32(pe32.Threads), szexe, nil
|
||||
}
|
||||
if err = windows.Process32Next(snap, &pe32); err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
return 0, 0, "", fmt.Errorf("Couldn't find pid: %d", pid)
|
||||
return 0, 0, "", fmt.Errorf("couldn't find pid: %d", pid)
|
||||
}
|
||||
|
||||
// Get processes
|
||||
@@ -600,21 +756,22 @@ func Processes() ([]*Process, error) {
|
||||
}
|
||||
|
||||
func ProcessesWithContext(ctx context.Context) ([]*Process, error) {
|
||||
pids, err := Pids()
|
||||
out := []*Process{}
|
||||
|
||||
pids, err := PidsWithContext(ctx)
|
||||
if err != nil {
|
||||
return []*Process{}, fmt.Errorf("could not get Processes %s", err)
|
||||
return out, fmt.Errorf("could not get Processes %s", err)
|
||||
}
|
||||
|
||||
results := []*Process{}
|
||||
for _, pid := range pids {
|
||||
p, err := NewProcess(int32(pid))
|
||||
p, err := NewProcess(pid)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
results = append(results, p)
|
||||
out = append(out, p)
|
||||
}
|
||||
|
||||
return results, nil
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func getProcInfo(pid int32) (*SystemProcessInformation, error) {
|
||||
@@ -638,7 +795,7 @@ func getProcInfo(pid int32) (*SystemProcessInformation, error) {
|
||||
func getRusage(pid int32) (*windows.Rusage, error) {
|
||||
var CPU windows.Rusage
|
||||
|
||||
c, err := windows.OpenProcess(windows.PROCESS_QUERY_INFORMATION, false, uint32(pid))
|
||||
c, err := windows.OpenProcess(windows.PROCESS_QUERY_LIMITED_INFORMATION, false, uint32(pid))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -653,8 +810,7 @@ func getRusage(pid int32) (*windows.Rusage, error) {
|
||||
|
||||
func getMemoryInfo(pid int32) (PROCESS_MEMORY_COUNTERS, error) {
|
||||
var mem PROCESS_MEMORY_COUNTERS
|
||||
// PROCESS_QUERY_LIMITED_INFORMATION is 0x1000
|
||||
c, err := windows.OpenProcess(0x1000, false, uint32(pid))
|
||||
c, err := windows.OpenProcess(windows.PROCESS_QUERY_LIMITED_INFORMATION, false, uint32(pid))
|
||||
if err != nil {
|
||||
return mem, err
|
||||
}
|
||||
@@ -688,8 +844,7 @@ type SYSTEM_TIMES struct {
|
||||
func getProcessCPUTimes(pid int32) (SYSTEM_TIMES, error) {
|
||||
var times SYSTEM_TIMES
|
||||
|
||||
// PROCESS_QUERY_LIMITED_INFORMATION is 0x1000
|
||||
h, err := windows.OpenProcess(0x1000, false, uint32(pid))
|
||||
h, err := windows.OpenProcess(windows.PROCESS_QUERY_LIMITED_INFORMATION, false, uint32(pid))
|
||||
if err != nil {
|
||||
return times, err
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user