From 0af895258e106d4eacf8232366c1d5760d9e40f4 Mon Sep 17 00:00:00 2001 From: Daniel Theophanes Date: Sun, 18 Oct 2015 20:40:01 -0700 Subject: [PATCH] common: rename package common to internal/common. Add ENV helper funcs. Package common wasn't used for public functions. Place it in an internal directory to prevent other packages from using. Remove the distributed references to "HOST_PROC" and "HOST_SYS" consts and combine into a common function. This also helps so that if a env var is defined with a trailing slash all will continue to work as expected. Fixes #100 --- common/common.go | 218 ---------------------------------- common/common_darwin.go | 60 ---------- common/common_freebsd.go | 61 ---------- common/common_linux.go | 3 - common/common_test.go | 90 -------------- common/common_unix.go | 40 ------- common/common_windows.go | 110 ------------------ cpu/cpu_linux.go | 16 ++- disk/disk_linux.go | 4 +- docker/docker_linux.go | 16 +-- host/host_linux.go | 12 +- host/host_linux_386.go | 50 ++++---- internal/common/common.go | 239 ++++++++++++++++++++++++++++++++++++++ internal/common/common_darwin.go | 60 ++++++++++ internal/common/common_freebsd.go | 60 ++++++++++ internal/common/common_linux.go | 3 + internal/common/common_test.go | 90 ++++++++++++++ internal/common/common_unix.go | 40 +++++++ internal/common/common_windows.go | 110 ++++++++++++++++++ load/load_linux.go | 4 +- mem/mem_linux.go | 6 +- net/net.go | 2 +- net/net_linux.go | 4 +- net/net_unix.go | 2 +- process/process.go | 2 +- process/process_linux.go | 22 ++-- process/process_test.go | 2 +- 27 files changed, 672 insertions(+), 654 deletions(-) delete mode 100644 common/common.go delete mode 100644 common/common_darwin.go delete mode 100644 common/common_freebsd.go delete mode 100644 common/common_linux.go delete mode 100644 common/common_test.go delete mode 100644 common/common_unix.go delete mode 100644 common/common_windows.go create mode 100644 internal/common/common.go create mode 100644 internal/common/common_darwin.go create mode 100644 internal/common/common_freebsd.go create mode 100644 internal/common/common_linux.go create mode 100644 internal/common/common_test.go create mode 100644 internal/common/common_unix.go create mode 100644 internal/common/common_windows.go diff --git a/common/common.go b/common/common.go deleted file mode 100644 index d04cdfd..0000000 --- a/common/common.go +++ /dev/null @@ -1,218 +0,0 @@ -// -// gopsutil is a port of psutil(http://pythonhosted.org/psutil/). -// This covers these architectures. -// - linux (amd64, arm) -// - freebsd (amd64) -// - windows (amd64) -package common - -import ( - "bufio" - "errors" - "io/ioutil" - "net/url" - "os" - "os/exec" - "path" - "reflect" - "runtime" - "strconv" - "strings" -) - -type Invoker interface { - Command(string, ...string) ([]byte, error) -} - -type Invoke struct{} - -func (i Invoke) Command(name string, arg ...string) ([]byte, error) { - return exec.Command(name, arg...).Output() -} - -type FakeInvoke struct { - CommandExpectedDir string // CommandExpectedDir specifies dir which includes expected outputs. - Suffix string // Suffix species expected file name suffix such as "fail" - Error error // If Error specfied, return the error. -} - -// Command in FakeInvoke returns from expected file if exists. -func (i FakeInvoke) Command(name string, arg ...string) ([]byte, error) { - if i.Error != nil { - return []byte{}, i.Error - } - - arch := runtime.GOOS - - fname := strings.Join(append([]string{name}, arg...), "") - fname = url.QueryEscape(fname) - var dir string - if i.CommandExpectedDir == "" { - dir = "expected" - } else { - dir = i.CommandExpectedDir - } - fpath := path.Join(dir, arch, fname) - if i.Suffix != "" { - fpath += "_" + i.Suffix - } - if PathExists(fpath) { - return ioutil.ReadFile(fpath) - } else { - return exec.Command(name, arg...).Output() - } -} - -var NotImplementedError = errors.New("not implemented yet") - -// ReadLines reads contents from a file and splits them by new lines. -// A convenience wrapper to ReadLinesOffsetN(filename, 0, -1). -func ReadLines(filename string) ([]string, error) { - return ReadLinesOffsetN(filename, 0, -1) -} - -// ReadLines reads contents from file and splits them by new line. -// The offset tells at which line number to start. -// The count determines the number of lines to read (starting from offset): -// n >= 0: at most n lines -// n < 0: whole file -func ReadLinesOffsetN(filename string, offset uint, n int) ([]string, error) { - f, err := os.Open(filename) - if err != nil { - return []string{""}, err - } - defer f.Close() - - var ret []string - - r := bufio.NewReader(f) - for i := 0; i < n+int(offset) || n < 0; i++ { - line, err := r.ReadString('\n') - if err != nil { - break - } - if i < int(offset) { - continue - } - ret = append(ret, strings.Trim(line, "\n")) - } - - return ret, nil -} - -func IntToString(orig []int8) string { - ret := make([]byte, len(orig)) - size := -1 - for i, o := range orig { - if o == 0 { - size = i - break - } - ret[i] = byte(o) - } - if size == -1 { - size = len(orig) - } - - return string(ret[0:size]) -} - -func ByteToString(orig []byte) string { - n := -1 - l := -1 - for i, b := range orig { - // skip left side null - if l == -1 && b == 0 { - continue - } - if l == -1 { - l = i - } - - if b == 0 { - break - } - n = i + 1 - } - if n == -1 { - return string(orig) - } - return string(orig[l:n]) -} - -// Parse to int32 without error -func mustParseInt32(val string) int32 { - vv, _ := strconv.ParseInt(val, 10, 32) - return int32(vv) -} - -// Parse to uint64 without error -func mustParseUint64(val string) uint64 { - vv, _ := strconv.ParseInt(val, 10, 64) - return uint64(vv) -} - -// Parse to Float64 without error -func mustParseFloat64(val string) float64 { - vv, _ := strconv.ParseFloat(val, 64) - return vv -} - -// StringsHas checks the target string slice containes src or not -func StringsHas(target []string, src string) bool { - for _, t := range target { - if strings.TrimSpace(t) == src { - return true - } - } - return false -} - -// StringsContains checks the src in any string of the target string slice -func StringsContains(target []string, src string) bool { - for _, t := range target { - if strings.Contains(t, src) { - return true - } - } - return false -} - -// get struct attributes. -// This method is used only for debugging platform dependent code. -func attributes(m interface{}) map[string]reflect.Type { - typ := reflect.TypeOf(m) - if typ.Kind() == reflect.Ptr { - typ = typ.Elem() - } - - attrs := make(map[string]reflect.Type) - if typ.Kind() != reflect.Struct { - return nil - } - - for i := 0; i < typ.NumField(); i++ { - p := typ.Field(i) - if !p.Anonymous { - attrs[p.Name] = p.Type - } - } - - return attrs -} - -func PathExists(filename string) bool { - if _, err := os.Stat(filename); err == nil { - return true - } - return false -} - -//GetEnv retreives the environment variable key. If it does not exist it returns the default. -func GetEnv(key string, dfault string) string { - value := os.Getenv(key) - if value == "" { - value = dfault - } - return value -} diff --git a/common/common_darwin.go b/common/common_darwin.go deleted file mode 100644 index 7d6f3c6..0000000 --- a/common/common_darwin.go +++ /dev/null @@ -1,60 +0,0 @@ -// +build darwin - -package common - -import ( - "os/exec" - "strings" - "syscall" - "unsafe" -) - -func DoSysctrl(mib string) ([]string, error) { - out, err := exec.Command("/usr/sbin/sysctl", "-n", mib).Output() - if err != nil { - return []string{}, err - } - v := strings.Replace(string(out), "{ ", "", 1) - v = strings.Replace(string(v), " }", "", 1) - values := strings.Fields(string(v)) - - return values, nil -} - -func CallSyscall(mib []int32) ([]byte, uint64, error) { - miblen := uint64(len(mib)) - - // get required buffer size - length := uint64(0) - _, _, err := syscall.Syscall6( - syscall.SYS___SYSCTL, - uintptr(unsafe.Pointer(&mib[0])), - uintptr(miblen), - 0, - uintptr(unsafe.Pointer(&length)), - 0, - 0) - if err != 0 { - var b []byte - return b, length, err - } - if length == 0 { - var b []byte - return b, length, err - } - // get proc info itself - buf := make([]byte, length) - _, _, err = syscall.Syscall6( - syscall.SYS___SYSCTL, - uintptr(unsafe.Pointer(&mib[0])), - uintptr(miblen), - uintptr(unsafe.Pointer(&buf[0])), - uintptr(unsafe.Pointer(&length)), - 0, - 0) - if err != 0 { - return buf, length, err - } - - return buf, length, nil -} diff --git a/common/common_freebsd.go b/common/common_freebsd.go deleted file mode 100644 index 3c11246..0000000 --- a/common/common_freebsd.go +++ /dev/null @@ -1,61 +0,0 @@ -// +build freebsd - -package common - -import ( - "syscall" - "os/exec" - "strings" - "unsafe" -) - -func DoSysctrl(mib string) ([]string, error) { - out, err := exec.Command("/sbin/sysctl", "-n", mib).Output() - if err != nil { - return []string{}, err - } - v := strings.Replace(string(out), "{ ", "", 1) - v = strings.Replace(string(v), " }", "", 1) - values := strings.Fields(string(v)) - - return values, nil -} - -func CallSyscall(mib []int32) ([]byte, uint64, error) { - miblen := uint64(len(mib)) - - // get required buffer size - length := uint64(0) - _, _, err := syscall.Syscall6( - syscall.SYS___SYSCTL, - uintptr(unsafe.Pointer(&mib[0])), - uintptr(miblen), - 0, - uintptr(unsafe.Pointer(&length)), - 0, - 0) - if err != 0 { - var b []byte - return b, length, err - } - if length == 0 { - var b []byte - return b, length, err - } - // get proc info itself - buf := make([]byte, length) - _, _, err = syscall.Syscall6( - syscall.SYS___SYSCTL, - uintptr(unsafe.Pointer(&mib[0])), - uintptr(miblen), - uintptr(unsafe.Pointer(&buf[0])), - uintptr(unsafe.Pointer(&length)), - 0, - 0) - if err != 0 { - return buf, length, err - } - - return buf, length, nil -} - diff --git a/common/common_linux.go b/common/common_linux.go deleted file mode 100644 index 0a122e9..0000000 --- a/common/common_linux.go +++ /dev/null @@ -1,3 +0,0 @@ -// +build linux - -package common diff --git a/common/common_test.go b/common/common_test.go deleted file mode 100644 index b2660b2..0000000 --- a/common/common_test.go +++ /dev/null @@ -1,90 +0,0 @@ -package common - -import ( - "fmt" - "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") - } -} diff --git a/common/common_unix.go b/common/common_unix.go deleted file mode 100644 index d0557ad..0000000 --- a/common/common_unix.go +++ /dev/null @@ -1,40 +0,0 @@ -// +build linux freebsd darwin - -package common - -import ( - "os/exec" - "strconv" - "strings" -) - -func CallLsof(invoke Invoker, pid int32, args ...string) ([]string, error) { - var cmd []string - if pid == 0 { // will get from all processes. - cmd = []string{"-a", "-n", "-P"} - } else { - cmd = []string{"-a", "-n", "-P", "-p", strconv.Itoa(int(pid))} - } - cmd = append(cmd, args...) - lsof, err := exec.LookPath("lsof") - if err != nil { - return []string{}, err - } - out, err := invoke.Command(lsof, cmd...) - if err != nil { - // if no pid found, lsof returnes code 1. - if err.Error() == "exit status 1" && len(out) == 0 { - return []string{}, nil - } - } - lines := strings.Split(string(out), "\n") - - var ret []string - for _, l := range lines[1:] { - if len(l) == 0 { - continue - } - ret = append(ret, l) - } - return ret, nil -} diff --git a/common/common_windows.go b/common/common_windows.go deleted file mode 100644 index d727378..0000000 --- a/common/common_windows.go +++ /dev/null @@ -1,110 +0,0 @@ -// +build windows - -package common - -import ( - "syscall" - "unsafe" -) - -// for double values -type PDH_FMT_COUNTERVALUE_DOUBLE struct { - CStatus uint32 - DoubleValue float64 -} - -// for 64 bit integer values -type PDH_FMT_COUNTERVALUE_LARGE struct { - CStatus uint32 - LargeValue int64 -} - -// for long values -type PDH_FMT_COUNTERVALUE_LONG struct { - CStatus uint32 - LongValue int32 - padding [4]byte -} - -// windows system const -const ( - ERROR_SUCCESS = 0 - ERROR_FILE_NOT_FOUND = 2 - DRIVE_REMOVABLE = 2 - DRIVE_FIXED = 3 - HKEY_LOCAL_MACHINE = 0x80000002 - RRF_RT_REG_SZ = 0x00000002 - RRF_RT_REG_DWORD = 0x00000010 - PDH_FMT_LONG = 0x00000100 - PDH_FMT_DOUBLE = 0x00000200 - PDH_FMT_LARGE = 0x00000400 - PDH_INVALID_DATA = 0xc0000bc6 - PDH_INVALID_HANDLE = 0xC0000bbc - PDH_NO_DATA = 0x800007d5 -) - -var ( - Modkernel32 = syscall.NewLazyDLL("kernel32.dll") - ModNt = syscall.NewLazyDLL("ntdll.dll") - ModPdh = syscall.NewLazyDLL("pdh.dll") - - ProcGetSystemTimes = Modkernel32.NewProc("GetSystemTimes") - ProcNtQuerySystemInformation = ModNt.NewProc("NtQuerySystemInformation") - PdhOpenQuery = ModPdh.NewProc("PdhOpenQuery") - PdhAddCounter = ModPdh.NewProc("PdhAddCounterW") - PdhCollectQueryData = ModPdh.NewProc("PdhCollectQueryData") - PdhGetFormattedCounterValue = ModPdh.NewProc("PdhGetFormattedCounterValue") - PdhCloseQuery = ModPdh.NewProc("PdhCloseQuery") -) - -type FILETIME struct { - DwLowDateTime uint32 - DwHighDateTime uint32 -} - -// borrowed from net/interface_windows.go -func BytePtrToString(p *uint8) string { - a := (*[10000]uint8)(unsafe.Pointer(p)) - i := 0 - for a[i] != 0 { - i++ - } - return string(a[:i]) -} - -// CounterInfo -// copied from https://github.com/mackerelio/mackerel-agent/ -type CounterInfo struct { - PostName string - CounterName string - Counter syscall.Handle -} - -// CreateQuery XXX -// copied from https://github.com/mackerelio/mackerel-agent/ -func CreateQuery() (syscall.Handle, error) { - var query syscall.Handle - r, _, err := PdhOpenQuery.Call(0, 0, uintptr(unsafe.Pointer(&query))) - if r != 0 { - return 0, err - } - return query, nil -} - -// CreateCounter XXX -func CreateCounter(query syscall.Handle, pname, cname string) (*CounterInfo, error) { - var counter syscall.Handle - r, _, err := PdhAddCounter.Call( - uintptr(query), - uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(cname))), - 0, - uintptr(unsafe.Pointer(&counter))) - if r != 0 { - return nil, err - } - return &CounterInfo{ - PostName: pname, - CounterName: cname, - Counter: counter, - }, nil -} diff --git a/cpu/cpu_linux.go b/cpu/cpu_linux.go index 6a4e672..b36797f 100644 --- a/cpu/cpu_linux.go +++ b/cpu/cpu_linux.go @@ -3,14 +3,13 @@ package cpu import ( - "path/filepath" - "fmt" "errors" + "fmt" "os/exec" "strconv" "strings" - common "github.com/shirou/gopsutil/common" + "github.com/shirou/gopsutil/internal/common" ) var cpu_tick = float64(100) @@ -27,7 +26,7 @@ func init() { } func CPUTimes(percpu bool) ([]CPUTimesStat, error) { - filename := common.GetEnv("HOST_PROC", "/proc") + "/stat" + filename := common.HostProc("stat") var lines = []string{} if percpu { var startIdx uint = 1 @@ -58,8 +57,7 @@ func CPUTimes(percpu bool) ([]CPUTimesStat, error) { } func sysCpuPath(cpu int32, relPath string) string { - root := common.GetEnv("HOST_SYS", "/sys") - return filepath.Join(root, fmt.Sprintf("devices/system/cpu/cpu%d", cpu), relPath) + return common.HostSys(fmt.Sprintf("devices/system/cpu/cpu%d", cpu), relPath) } func finishCPUInfo(c *CPUInfoStat) error { @@ -75,7 +73,7 @@ func finishCPUInfo(c *CPUInfoStat) error { } if len(c.CoreID) == 0 { lines, err := common.ReadLines(sysCpuPath(c.CPU, "topology/core_id")) - if err == nil { + if err == nil { c.CoreID = lines[0] } } @@ -83,7 +81,7 @@ func finishCPUInfo(c *CPUInfoStat) error { } func CPUInfo() ([]CPUInfoStat, error) { - filename := filepath.Join(common.GetEnv("HOST_PROC", "/proc"), "cpuinfo") + filename := common.HostProc("cpuinfo") lines, _ := common.ReadLines(filename) var ret []CPUInfoStat @@ -148,7 +146,7 @@ func CPUInfo() ([]CPUInfoStat, error) { return ret, err } c.Cores = int32(t) - case "flags","Features": + case "flags", "Features": c.Flags = strings.FieldsFunc(value, func(r rune) bool { return r == ',' || r == ' ' }) diff --git a/disk/disk_linux.go b/disk/disk_linux.go index 93f59b0..caa1e17 100644 --- a/disk/disk_linux.go +++ b/disk/disk_linux.go @@ -9,7 +9,7 @@ import ( "strings" "syscall" - common "github.com/shirou/gopsutil/common" + "github.com/shirou/gopsutil/internal/common" ) const ( @@ -238,7 +238,7 @@ func DiskPartitions(all bool) ([]DiskPartitionStat, error) { } func DiskIOCounters() (map[string]DiskIOCountersStat, error) { - filename := common.GetEnv("HOST_PROC", "/proc") + "/diskstats" + filename := common.HostProc("diskstats") lines, err := common.ReadLines(filename) if err != nil { return nil, err diff --git a/docker/docker_linux.go b/docker/docker_linux.go index fd6df6d..bc2fd6e 100644 --- a/docker/docker_linux.go +++ b/docker/docker_linux.go @@ -4,14 +4,14 @@ package docker import ( "encoding/json" - "os" + "os" "os/exec" "path" "strconv" "strings" - common "github.com/shirou/gopsutil/common" cpu "github.com/shirou/gopsutil/cpu" + "github.com/shirou/gopsutil/internal/common" ) // GetDockerIDList returnes a list of DockerID. @@ -49,9 +49,9 @@ func CgroupCPU(containerid string, base string) (*cpu.CPUTimesStat, error) { } statfile := path.Join(base, containerid, "cpuacct.stat") - if _, err := os.Stat(statfile); os.IsNotExist(err) { - statfile = path.Join("/sys/fs/cgroup/cpuacct/system.slice", "docker-" + containerid + ".scope", "cpuacct.stat") - } + if _, err := os.Stat(statfile); os.IsNotExist(err) { + statfile = path.Join("/sys/fs/cgroup/cpuacct/system.slice", "docker-"+containerid+".scope", "cpuacct.stat") + } lines, err := common.ReadLines(statfile) if err != nil { @@ -91,9 +91,9 @@ func CgroupMem(containerid string, base string) (*CgroupMemStat, error) { } statfile := path.Join(base, containerid, "memory.stat") - if _, err := os.Stat(statfile); os.IsNotExist(err) { - statfile = path.Join("/sys/fs/cgroup/memory/system.slice", "docker-" + containerid + ".scope", "memory.stat") - } + if _, err := os.Stat(statfile); os.IsNotExist(err) { + statfile = path.Join("/sys/fs/cgroup/memory/system.slice", "docker-"+containerid+".scope", "memory.stat") + } // empty containerid means all cgroup if len(containerid) == 0 { diff --git a/host/host_linux.go b/host/host_linux.go index 9131fa8..0ac9ea8 100644 --- a/host/host_linux.go +++ b/host/host_linux.go @@ -15,7 +15,7 @@ import ( "strings" "unsafe" - common "github.com/shirou/gopsutil/common" + "github.com/shirou/gopsutil/internal/common" ) type LSB struct { @@ -56,7 +56,7 @@ func HostInfo() (*HostInfoStat, error) { // BootTime returns the system boot time expressed in seconds since the epoch. func BootTime() (uint64, error) { - filename := common.GetEnv("HOST_PROC", "/proc") + "/stat" + filename := common.HostProc("stat") lines, err := common.ReadLines(filename) if err != nil { return 0, err @@ -321,7 +321,7 @@ func GetVirtualization() (string, string, error) { var system string var role string - filename := common.GetEnv("HOST_PROC", "/proc") + "/xen" + filename := common.HostProc("xen") if common.PathExists(filename) { system = "xen" role = "guest" // assume guest @@ -336,7 +336,7 @@ func GetVirtualization() (string, string, error) { } } - filename = common.GetEnv("HOST_PROC", "/proc") + "/modules" + filename = common.HostProc("modules") if common.PathExists(filename) { contents, err := common.ReadLines(filename) if err == nil { @@ -353,7 +353,7 @@ func GetVirtualization() (string, string, error) { } } - filename = common.GetEnv("HOST_PROC", "/proc") + "/cpuinfo" + filename = common.HostProc("cpuinfo") if common.PathExists(filename) { contents, err := common.ReadLines(filename) if err == nil { @@ -366,7 +366,7 @@ func GetVirtualization() (string, string, error) { } } - filename = common.GetEnv("HOST_PROC", "/proc") + filename = common.HostProc() if common.PathExists(filename + "/bc/0") { system = "openvz" role = "host" diff --git a/host/host_linux_386.go b/host/host_linux_386.go index d8f31c2..fb6d7a0 100644 --- a/host/host_linux_386.go +++ b/host/host_linux_386.go @@ -6,39 +6,39 @@ package host const ( - sizeofPtr = 0x4 - sizeofShort = 0x2 - sizeofInt = 0x4 - sizeofLong = 0x4 - sizeofLongLong = 0x8 + sizeofPtr = 0x4 + sizeofShort = 0x2 + sizeofInt = 0x4 + sizeofLong = 0x4 + sizeofLongLong = 0x8 ) type ( - _C_short int16 - _C_int int32 - _C_long int32 - _C_long_long int64 + _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 UtTv - Addr_v6 [4]int32 - X__unused [20]int8 + 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 UtTv + Addr_v6 [4]int32 + X__unused [20]int8 } type exit_status struct { - Termination int16 - Exit int16 + Termination int16 + Exit int16 } type UtTv struct { - TvSec int32 - TvUsec int32 + TvSec int32 + TvUsec int32 } diff --git a/internal/common/common.go b/internal/common/common.go new file mode 100644 index 0000000..aeadda6 --- /dev/null +++ b/internal/common/common.go @@ -0,0 +1,239 @@ +// +// gopsutil is a port of psutil(http://pythonhosted.org/psutil/). +// This covers these architectures. +// - linux (amd64, arm) +// - freebsd (amd64) +// - windows (amd64) +package common + +import ( + "bufio" + "errors" + "io/ioutil" + "net/url" + "os" + "os/exec" + "path" + "path/filepath" + "reflect" + "runtime" + "strconv" + "strings" +) + +type Invoker interface { + Command(string, ...string) ([]byte, error) +} + +type Invoke struct{} + +func (i Invoke) Command(name string, arg ...string) ([]byte, error) { + return exec.Command(name, arg...).Output() +} + +type FakeInvoke struct { + CommandExpectedDir string // CommandExpectedDir specifies dir which includes expected outputs. + Suffix string // Suffix species expected file name suffix such as "fail" + Error error // If Error specfied, return the error. +} + +// Command in FakeInvoke returns from expected file if exists. +func (i FakeInvoke) Command(name string, arg ...string) ([]byte, error) { + if i.Error != nil { + return []byte{}, i.Error + } + + arch := runtime.GOOS + + fname := strings.Join(append([]string{name}, arg...), "") + fname = url.QueryEscape(fname) + var dir string + if i.CommandExpectedDir == "" { + dir = "expected" + } else { + dir = i.CommandExpectedDir + } + fpath := path.Join(dir, arch, fname) + if i.Suffix != "" { + fpath += "_" + i.Suffix + } + if PathExists(fpath) { + return ioutil.ReadFile(fpath) + } else { + return exec.Command(name, arg...).Output() + } +} + +var NotImplementedError = errors.New("not implemented yet") + +// ReadLines reads contents from a file and splits them by new lines. +// A convenience wrapper to ReadLinesOffsetN(filename, 0, -1). +func ReadLines(filename string) ([]string, error) { + return ReadLinesOffsetN(filename, 0, -1) +} + +// ReadLines reads contents from file and splits them by new line. +// The offset tells at which line number to start. +// The count determines the number of lines to read (starting from offset): +// n >= 0: at most n lines +// n < 0: whole file +func ReadLinesOffsetN(filename string, offset uint, n int) ([]string, error) { + f, err := os.Open(filename) + if err != nil { + return []string{""}, err + } + defer f.Close() + + var ret []string + + r := bufio.NewReader(f) + for i := 0; i < n+int(offset) || n < 0; i++ { + line, err := r.ReadString('\n') + if err != nil { + break + } + if i < int(offset) { + continue + } + ret = append(ret, strings.Trim(line, "\n")) + } + + return ret, nil +} + +func IntToString(orig []int8) string { + ret := make([]byte, len(orig)) + size := -1 + for i, o := range orig { + if o == 0 { + size = i + break + } + ret[i] = byte(o) + } + if size == -1 { + size = len(orig) + } + + return string(ret[0:size]) +} + +func ByteToString(orig []byte) string { + n := -1 + l := -1 + for i, b := range orig { + // skip left side null + if l == -1 && b == 0 { + continue + } + if l == -1 { + l = i + } + + if b == 0 { + break + } + n = i + 1 + } + if n == -1 { + return string(orig) + } + return string(orig[l:n]) +} + +// Parse to int32 without error +func mustParseInt32(val string) int32 { + vv, _ := strconv.ParseInt(val, 10, 32) + return int32(vv) +} + +// Parse to uint64 without error +func mustParseUint64(val string) uint64 { + vv, _ := strconv.ParseInt(val, 10, 64) + return uint64(vv) +} + +// Parse to Float64 without error +func mustParseFloat64(val string) float64 { + vv, _ := strconv.ParseFloat(val, 64) + return vv +} + +// StringsHas checks the target string slice containes src or not +func StringsHas(target []string, src string) bool { + for _, t := range target { + if strings.TrimSpace(t) == src { + return true + } + } + return false +} + +// StringsContains checks the src in any string of the target string slice +func StringsContains(target []string, src string) bool { + for _, t := range target { + if strings.Contains(t, src) { + return true + } + } + return false +} + +// get struct attributes. +// This method is used only for debugging platform dependent code. +func attributes(m interface{}) map[string]reflect.Type { + typ := reflect.TypeOf(m) + if typ.Kind() == reflect.Ptr { + typ = typ.Elem() + } + + attrs := make(map[string]reflect.Type) + if typ.Kind() != reflect.Struct { + return nil + } + + for i := 0; i < typ.NumField(); i++ { + p := typ.Field(i) + if !p.Anonymous { + attrs[p.Name] = p.Type + } + } + + return attrs +} + +func PathExists(filename string) bool { + if _, err := os.Stat(filename); err == nil { + return true + } + return false +} + +//GetEnv retreives the environment variable key. If it does not exist it returns the default. +func GetEnv(key string, dfault string, combineWith ...string) string { + value := os.Getenv(key) + if value == "" { + value = dfault + } + + switch len(combineWith) { + case 0: + return value + case 1: + return filepath.Join(value, combineWith[0]) + default: + all := make([]string, len(combineWith)+1) + all[0] = value + copy(all[1:], combineWith) + return filepath.Join(all...) + } + panic("invalid switch case") +} + +func HostProc(combineWith ...string) string { + return GetEnv("HOST_PROC", "/proc", combineWith...) +} + +func HostSys(combineWith ...string) string { + return GetEnv("HOST_SYS", "/sys", combineWith...) +} diff --git a/internal/common/common_darwin.go b/internal/common/common_darwin.go new file mode 100644 index 0000000..7d6f3c6 --- /dev/null +++ b/internal/common/common_darwin.go @@ -0,0 +1,60 @@ +// +build darwin + +package common + +import ( + "os/exec" + "strings" + "syscall" + "unsafe" +) + +func DoSysctrl(mib string) ([]string, error) { + out, err := exec.Command("/usr/sbin/sysctl", "-n", mib).Output() + if err != nil { + return []string{}, err + } + v := strings.Replace(string(out), "{ ", "", 1) + v = strings.Replace(string(v), " }", "", 1) + values := strings.Fields(string(v)) + + return values, nil +} + +func CallSyscall(mib []int32) ([]byte, uint64, error) { + miblen := uint64(len(mib)) + + // get required buffer size + length := uint64(0) + _, _, err := syscall.Syscall6( + syscall.SYS___SYSCTL, + uintptr(unsafe.Pointer(&mib[0])), + uintptr(miblen), + 0, + uintptr(unsafe.Pointer(&length)), + 0, + 0) + if err != 0 { + var b []byte + return b, length, err + } + if length == 0 { + var b []byte + return b, length, err + } + // get proc info itself + buf := make([]byte, length) + _, _, err = syscall.Syscall6( + syscall.SYS___SYSCTL, + uintptr(unsafe.Pointer(&mib[0])), + uintptr(miblen), + uintptr(unsafe.Pointer(&buf[0])), + uintptr(unsafe.Pointer(&length)), + 0, + 0) + if err != 0 { + return buf, length, err + } + + return buf, length, nil +} diff --git a/internal/common/common_freebsd.go b/internal/common/common_freebsd.go new file mode 100644 index 0000000..8ccd40e --- /dev/null +++ b/internal/common/common_freebsd.go @@ -0,0 +1,60 @@ +// +build freebsd + +package common + +import ( + "os/exec" + "strings" + "syscall" + "unsafe" +) + +func DoSysctrl(mib string) ([]string, error) { + out, err := exec.Command("/sbin/sysctl", "-n", mib).Output() + if err != nil { + return []string{}, err + } + v := strings.Replace(string(out), "{ ", "", 1) + v = strings.Replace(string(v), " }", "", 1) + values := strings.Fields(string(v)) + + return values, nil +} + +func CallSyscall(mib []int32) ([]byte, uint64, error) { + miblen := uint64(len(mib)) + + // get required buffer size + length := uint64(0) + _, _, err := syscall.Syscall6( + syscall.SYS___SYSCTL, + uintptr(unsafe.Pointer(&mib[0])), + uintptr(miblen), + 0, + uintptr(unsafe.Pointer(&length)), + 0, + 0) + if err != 0 { + var b []byte + return b, length, err + } + if length == 0 { + var b []byte + return b, length, err + } + // get proc info itself + buf := make([]byte, length) + _, _, err = syscall.Syscall6( + syscall.SYS___SYSCTL, + uintptr(unsafe.Pointer(&mib[0])), + uintptr(miblen), + uintptr(unsafe.Pointer(&buf[0])), + uintptr(unsafe.Pointer(&length)), + 0, + 0) + if err != 0 { + return buf, length, err + } + + return buf, length, nil +} diff --git a/internal/common/common_linux.go b/internal/common/common_linux.go new file mode 100644 index 0000000..0a122e9 --- /dev/null +++ b/internal/common/common_linux.go @@ -0,0 +1,3 @@ +// +build linux + +package common diff --git a/internal/common/common_test.go b/internal/common/common_test.go new file mode 100644 index 0000000..b2660b2 --- /dev/null +++ b/internal/common/common_test.go @@ -0,0 +1,90 @@ +package common + +import ( + "fmt" + "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") + } +} diff --git a/internal/common/common_unix.go b/internal/common/common_unix.go new file mode 100644 index 0000000..d0557ad --- /dev/null +++ b/internal/common/common_unix.go @@ -0,0 +1,40 @@ +// +build linux freebsd darwin + +package common + +import ( + "os/exec" + "strconv" + "strings" +) + +func CallLsof(invoke Invoker, pid int32, args ...string) ([]string, error) { + var cmd []string + if pid == 0 { // will get from all processes. + cmd = []string{"-a", "-n", "-P"} + } else { + cmd = []string{"-a", "-n", "-P", "-p", strconv.Itoa(int(pid))} + } + cmd = append(cmd, args...) + lsof, err := exec.LookPath("lsof") + if err != nil { + return []string{}, err + } + out, err := invoke.Command(lsof, cmd...) + if err != nil { + // if no pid found, lsof returnes code 1. + if err.Error() == "exit status 1" && len(out) == 0 { + return []string{}, nil + } + } + lines := strings.Split(string(out), "\n") + + var ret []string + for _, l := range lines[1:] { + if len(l) == 0 { + continue + } + ret = append(ret, l) + } + return ret, nil +} diff --git a/internal/common/common_windows.go b/internal/common/common_windows.go new file mode 100644 index 0000000..d727378 --- /dev/null +++ b/internal/common/common_windows.go @@ -0,0 +1,110 @@ +// +build windows + +package common + +import ( + "syscall" + "unsafe" +) + +// for double values +type PDH_FMT_COUNTERVALUE_DOUBLE struct { + CStatus uint32 + DoubleValue float64 +} + +// for 64 bit integer values +type PDH_FMT_COUNTERVALUE_LARGE struct { + CStatus uint32 + LargeValue int64 +} + +// for long values +type PDH_FMT_COUNTERVALUE_LONG struct { + CStatus uint32 + LongValue int32 + padding [4]byte +} + +// windows system const +const ( + ERROR_SUCCESS = 0 + ERROR_FILE_NOT_FOUND = 2 + DRIVE_REMOVABLE = 2 + DRIVE_FIXED = 3 + HKEY_LOCAL_MACHINE = 0x80000002 + RRF_RT_REG_SZ = 0x00000002 + RRF_RT_REG_DWORD = 0x00000010 + PDH_FMT_LONG = 0x00000100 + PDH_FMT_DOUBLE = 0x00000200 + PDH_FMT_LARGE = 0x00000400 + PDH_INVALID_DATA = 0xc0000bc6 + PDH_INVALID_HANDLE = 0xC0000bbc + PDH_NO_DATA = 0x800007d5 +) + +var ( + Modkernel32 = syscall.NewLazyDLL("kernel32.dll") + ModNt = syscall.NewLazyDLL("ntdll.dll") + ModPdh = syscall.NewLazyDLL("pdh.dll") + + ProcGetSystemTimes = Modkernel32.NewProc("GetSystemTimes") + ProcNtQuerySystemInformation = ModNt.NewProc("NtQuerySystemInformation") + PdhOpenQuery = ModPdh.NewProc("PdhOpenQuery") + PdhAddCounter = ModPdh.NewProc("PdhAddCounterW") + PdhCollectQueryData = ModPdh.NewProc("PdhCollectQueryData") + PdhGetFormattedCounterValue = ModPdh.NewProc("PdhGetFormattedCounterValue") + PdhCloseQuery = ModPdh.NewProc("PdhCloseQuery") +) + +type FILETIME struct { + DwLowDateTime uint32 + DwHighDateTime uint32 +} + +// borrowed from net/interface_windows.go +func BytePtrToString(p *uint8) string { + a := (*[10000]uint8)(unsafe.Pointer(p)) + i := 0 + for a[i] != 0 { + i++ + } + return string(a[:i]) +} + +// CounterInfo +// copied from https://github.com/mackerelio/mackerel-agent/ +type CounterInfo struct { + PostName string + CounterName string + Counter syscall.Handle +} + +// CreateQuery XXX +// copied from https://github.com/mackerelio/mackerel-agent/ +func CreateQuery() (syscall.Handle, error) { + var query syscall.Handle + r, _, err := PdhOpenQuery.Call(0, 0, uintptr(unsafe.Pointer(&query))) + if r != 0 { + return 0, err + } + return query, nil +} + +// CreateCounter XXX +func CreateCounter(query syscall.Handle, pname, cname string) (*CounterInfo, error) { + var counter syscall.Handle + r, _, err := PdhAddCounter.Call( + uintptr(query), + uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(cname))), + 0, + uintptr(unsafe.Pointer(&counter))) + if r != 0 { + return nil, err + } + return &CounterInfo{ + PostName: pname, + CounterName: cname, + Counter: counter, + }, nil +} diff --git a/load/load_linux.go b/load/load_linux.go index 4ab5a96..80621c9 100644 --- a/load/load_linux.go +++ b/load/load_linux.go @@ -7,11 +7,11 @@ import ( "strconv" "strings" - common "github.com/shirou/gopsutil/common" + "github.com/shirou/gopsutil/internal/common" ) func LoadAvg() (*LoadAvgStat, error) { - filename := common.GetEnv("HOST_PROC", "/proc") + "/loadavg" + filename := common.HostProc("loadavg") line, err := ioutil.ReadFile(filename) if err != nil { return nil, err diff --git a/mem/mem_linux.go b/mem/mem_linux.go index e45a084..fc92262 100644 --- a/mem/mem_linux.go +++ b/mem/mem_linux.go @@ -7,11 +7,11 @@ import ( "strings" "syscall" - common "github.com/shirou/gopsutil/common" + "github.com/shirou/gopsutil/internal/common" ) func VirtualMemory() (*VirtualMemoryStat, error) { - filename := common.GetEnv("HOST_PROC", "/proc") + "/meminfo" + filename := common.HostProc("meminfo") lines, _ := common.ReadLines(filename) // flag if MemAvailable is in /proc/meminfo (kernel 3.14+) memavail := false @@ -74,7 +74,7 @@ func SwapMemory() (*SwapMemoryStat, error) { } else { ret.UsedPercent = 0 } - filename := common.GetEnv("HOST_PROC", "/proc") + "/vmstat" + filename := common.HostProc("vmstat") lines, _ := common.ReadLines(filename) for _, l := range lines { fields := strings.Fields(l) diff --git a/net/net.go b/net/net.go index 506fe57..e8a1035 100644 --- a/net/net.go +++ b/net/net.go @@ -8,7 +8,7 @@ import ( "strings" "syscall" - "github.com/shirou/gopsutil/common" + "github.com/shirou/gopsutil/internal/common" ) var invoke common.Invoker diff --git a/net/net_linux.go b/net/net_linux.go index 73b2bee..4218373 100644 --- a/net/net_linux.go +++ b/net/net_linux.go @@ -6,7 +6,7 @@ import ( "strconv" "strings" - common "github.com/shirou/gopsutil/common" + "github.com/shirou/gopsutil/internal/common" ) // NetIOCounters returnes network I/O statistics for every network @@ -15,7 +15,7 @@ import ( // every network interface installed on the system is returned // separately. func NetIOCounters(pernic bool) ([]NetIOCountersStat, error) { - filename := common.GetEnv("HOST_PROC", "/proc") + "/net/dev" + filename := common.HostProc("net/dev") lines, err := common.ReadLines(filename) if err != nil { return nil, err diff --git a/net/net_unix.go b/net/net_unix.go index 0b8a844..fe2f1eb 100644 --- a/net/net_unix.go +++ b/net/net_unix.go @@ -5,7 +5,7 @@ package net import ( "strings" - "github.com/shirou/gopsutil/common" + "github.com/shirou/gopsutil/internal/common" ) // Return a list of network connections opened. diff --git a/process/process.go b/process/process.go index abe522c..0526f78 100644 --- a/process/process.go +++ b/process/process.go @@ -5,8 +5,8 @@ import ( "runtime" "time" - "github.com/shirou/gopsutil/common" "github.com/shirou/gopsutil/cpu" + "github.com/shirou/gopsutil/internal/common" ) var invoke common.Invoker diff --git a/process/process_linux.go b/process/process_linux.go index 0d3a397..9855b74 100644 --- a/process/process_linux.go +++ b/process/process_linux.go @@ -12,9 +12,9 @@ import ( "strings" "syscall" - "github.com/shirou/gopsutil/common" "github.com/shirou/gopsutil/cpu" "github.com/shirou/gopsutil/host" + "github.com/shirou/gopsutil/internal/common" "github.com/shirou/gopsutil/net" ) @@ -222,7 +222,7 @@ func (p *Process) IsRunning() (bool, error) { func (p *Process) MemoryMaps(grouped bool) (*[]MemoryMapsStat, error) { pid := p.Pid var ret []MemoryMapsStat - smapsPath := filepath.Join(common.GetEnv("HOST_PROC", "/proc"), strconv.Itoa(int(pid)), "smaps") + smapsPath := common.HostProc(strconv.Itoa(int(pid)), "smaps") contents, err := ioutil.ReadFile(smapsPath) if err != nil { return nil, err @@ -303,7 +303,7 @@ func (p *Process) MemoryMaps(grouped bool) (*[]MemoryMapsStat, error) { // Get num_fds from /proc/(pid)/fd func (p *Process) fillFromfd() (int32, []*OpenFilesStat, error) { pid := p.Pid - statPath := filepath.Join(common.GetEnv("HOST_PROC", "/proc"), strconv.Itoa(int(pid)), "fd") + statPath := common.HostProc(strconv.Itoa(int(pid)), "fd") d, err := os.Open(statPath) if err != nil { return 0, nil, err @@ -336,7 +336,7 @@ func (p *Process) fillFromfd() (int32, []*OpenFilesStat, error) { // Get cwd from /proc/(pid)/cwd func (p *Process) fillFromCwd() (string, error) { pid := p.Pid - cwdPath := filepath.Join(common.GetEnv("HOST_PROC", "/proc"), strconv.Itoa(int(pid)), "cwd") + cwdPath := common.HostProc(strconv.Itoa(int(pid)), "cwd") cwd, err := os.Readlink(cwdPath) if err != nil { return "", err @@ -347,7 +347,7 @@ func (p *Process) fillFromCwd() (string, error) { // Get exe from /proc/(pid)/exe func (p *Process) fillFromExe() (string, error) { pid := p.Pid - exePath := filepath.Join(common.GetEnv("HOST_PROC", "/proc"), strconv.Itoa(int(pid)), "exe") + exePath := common.HostProc(strconv.Itoa(int(pid)), "exe") exe, err := os.Readlink(exePath) if err != nil { return "", err @@ -358,7 +358,7 @@ func (p *Process) fillFromExe() (string, error) { // Get cmdline from /proc/(pid)/cmdline func (p *Process) fillFromCmdline() (string, error) { pid := p.Pid - cmdPath := filepath.Join(common.GetEnv("HOST_PROC", "/proc"), strconv.Itoa(int(pid)), "cmdline") + cmdPath := common.HostProc(strconv.Itoa(int(pid)), "cmdline") cmdline, err := ioutil.ReadFile(cmdPath) if err != nil { return "", err @@ -376,7 +376,7 @@ func (p *Process) fillFromCmdline() (string, error) { // Get IO status from /proc/(pid)/io func (p *Process) fillFromIO() (*IOCountersStat, error) { pid := p.Pid - ioPath := filepath.Join(common.GetEnv("HOST_PROC", "/proc"), strconv.Itoa(int(pid)), "io") + ioPath := common.HostProc(strconv.Itoa(int(pid)), "io") ioline, err := ioutil.ReadFile(ioPath) if err != nil { return nil, err @@ -415,7 +415,7 @@ func (p *Process) fillFromIO() (*IOCountersStat, error) { // Get memory info from /proc/(pid)/statm func (p *Process) fillFromStatm() (*MemoryInfoStat, *MemoryInfoExStat, error) { pid := p.Pid - memPath := filepath.Join(common.GetEnv("HOST_PROC", "/proc"), strconv.Itoa(int(pid)), "statm") + memPath := common.HostProc(strconv.Itoa(int(pid)), "statm") contents, err := ioutil.ReadFile(memPath) if err != nil { return nil, nil, err @@ -467,7 +467,7 @@ func (p *Process) fillFromStatm() (*MemoryInfoStat, *MemoryInfoExStat, error) { // Get various status from /proc/(pid)/status func (p *Process) fillFromStatus() error { pid := p.Pid - statPath := filepath.Join(common.GetEnv("HOST_PROC", "/proc"), strconv.Itoa(int(pid)), "status") + statPath := common.HostProc(strconv.Itoa(int(pid)), "status") contents, err := ioutil.ReadFile(statPath) if err != nil { return err @@ -554,7 +554,7 @@ func (p *Process) fillFromStatus() error { func (p *Process) fillFromStat() (string, int32, *cpu.CPUTimesStat, int64, int32, error) { pid := p.Pid - statPath := filepath.Join(common.GetEnv("HOST_PROC", "/proc"), strconv.Itoa(int(pid)), "stat") + statPath := common.HostProc(strconv.Itoa(int(pid)), "stat") contents, err := ioutil.ReadFile(statPath) if err != nil { return "", 0, nil, 0, 0, err @@ -610,7 +610,7 @@ func (p *Process) fillFromStat() (string, int32, *cpu.CPUTimesStat, int64, int32 func Pids() ([]int32, error) { var ret []int32 - d, err := os.Open(common.GetEnv("HOST_PROC", "/proc")) + d, err := os.Open(common.HostProc()) if err != nil { return nil, err } diff --git a/process/process_test.go b/process/process_test.go index 854d63c..4cb475a 100644 --- a/process/process_test.go +++ b/process/process_test.go @@ -8,7 +8,7 @@ import ( "testing" "time" - "github.com/shirou/gopsutil/common" + "github.com/shirou/gopsutil/internal/common" ) var mu sync.Mutex