Merge pull request #1313 from hashicorp/b-update-gopsutils
Update gopsutils
This commit is contained in:
commit
9aeac0b073
|
@ -133,6 +133,10 @@ func (c *AllocStatusCommand) Run(args []string) int {
|
|||
var statsErr error
|
||||
var stats *api.AllocResourceUsage
|
||||
stats, statsErr = client.Allocations().Stats(alloc, nil)
|
||||
if statsErr != nil {
|
||||
c.Ui.Output("")
|
||||
c.Ui.Error(fmt.Sprintf("couldn't retrieve stats (HINT: ensure Client.Advertise.HTTP is set): %v", statsErr))
|
||||
}
|
||||
|
||||
// Format the allocation data
|
||||
basic := []string{
|
||||
|
@ -166,11 +170,6 @@ func (c *AllocStatusCommand) Run(args []string) int {
|
|||
c.Ui.Output(formatAllocMetrics(alloc.Metrics, true, " "))
|
||||
}
|
||||
|
||||
if statsErr != nil {
|
||||
c.Ui.Output("")
|
||||
c.Ui.Error(fmt.Sprintf("couldn't retreive stats: %v", statsErr))
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
|
|
|
@ -222,6 +222,10 @@ func (c *NodeStatusCommand) Run(args []string) int {
|
|||
func (c *NodeStatusCommand) formatNode(client *api.Client, node *api.Node) int {
|
||||
// Get the host stats
|
||||
hostStats, nodeStatsErr := client.Nodes().Stats(node.ID, nil)
|
||||
if nodeStatsErr != nil {
|
||||
c.Ui.Output("")
|
||||
c.Ui.Error(fmt.Sprintf("error fetching node stats (HINT: ensure Client.Advertise.HTTP is set): %v", nodeStatsErr))
|
||||
}
|
||||
|
||||
// Format the header output
|
||||
basic := []string{
|
||||
|
@ -257,6 +261,10 @@ func (c *NodeStatusCommand) formatNode(client *api.Client, node *api.Node) int {
|
|||
}
|
||||
|
||||
hostResources, err := getHostResources(hostStats, node)
|
||||
if err != nil {
|
||||
c.Ui.Output("")
|
||||
c.Ui.Error(fmt.Sprintf("error fetching node stats (HINT: ensure Client.Advertise.HTTP is set): %v", err))
|
||||
}
|
||||
if err == nil {
|
||||
c.Ui.Output(c.Colorize().Color("\n[bold]Host Resource Utilization[reset]"))
|
||||
c.Ui.Output(formatList(hostResources))
|
||||
|
@ -286,10 +294,6 @@ func (c *NodeStatusCommand) formatNode(client *api.Client, node *api.Node) int {
|
|||
if c.verbose {
|
||||
c.formatAttributes(node)
|
||||
}
|
||||
if nodeStatsErr != nil {
|
||||
c.Ui.Output("")
|
||||
c.Ui.Error(fmt.Sprintf("error fetching node stats: %v", nodeStatsErr))
|
||||
}
|
||||
return 0
|
||||
|
||||
}
|
||||
|
|
|
@ -5,6 +5,9 @@ import (
|
|||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
)
|
||||
|
||||
type TimesStat struct {
|
||||
|
@ -37,8 +40,22 @@ type InfoStat struct {
|
|||
Flags []string `json:"flags"`
|
||||
}
|
||||
|
||||
var lastCPUTimes []TimesStat
|
||||
var lastPerCPUTimes []TimesStat
|
||||
type lastPercent struct {
|
||||
sync.Mutex
|
||||
lastCPUTimes []TimesStat
|
||||
lastPerCPUTimes []TimesStat
|
||||
}
|
||||
|
||||
var lastCPUPercent lastPercent
|
||||
var invoke common.Invoker
|
||||
|
||||
func init() {
|
||||
invoke = common.Invoke{}
|
||||
lastCPUPercent.Lock()
|
||||
lastCPUPercent.lastCPUTimes, _ = Times(false)
|
||||
lastCPUPercent.lastPerCPUTimes, _ = Times(true)
|
||||
lastCPUPercent.Unlock()
|
||||
}
|
||||
|
||||
func Counts(logical bool) (int, error) {
|
||||
return runtime.NumCPU(), nil
|
||||
|
|
|
@ -36,7 +36,7 @@ func Info() ([]InfoStat, error) {
|
|||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
out, err := exec.Command(sysctl, "machdep.cpu").Output()
|
||||
out, err := invoke.Command(sysctl, "machdep.cpu")
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
|
@ -90,7 +90,7 @@ func Info() ([]InfoStat, error) {
|
|||
|
||||
// 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 = exec.Command(sysctl, "hw.cpufrequency").Output()
|
||||
out, err = invoke.Command(sysctl, "hw.cpufrequency")
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
|
|
|
@ -10,7 +10,9 @@ package cpu
|
|||
#include <mach/mach_init.h>
|
||||
#include <mach/mach_host.h>
|
||||
#include <mach/host_info.h>
|
||||
#if TARGET_OS_MAC
|
||||
#include <libproc.h>
|
||||
#endif
|
||||
#include <mach/processor_info.h>
|
||||
#include <mach/vm_map.h>
|
||||
*/
|
||||
|
|
|
@ -27,7 +27,7 @@ func init() {
|
|||
if err != nil {
|
||||
return
|
||||
}
|
||||
out, err := exec.Command(getconf, "CLK_TCK").Output()
|
||||
out, err := invoke.Command(getconf, "CLK_TCK")
|
||||
// ignore errors
|
||||
if err == nil {
|
||||
i, err := strconv.ParseFloat(strings.TrimSpace(string(out)), 64)
|
||||
|
|
|
@ -19,7 +19,7 @@ func init() {
|
|||
if err != nil {
|
||||
return
|
||||
}
|
||||
out, err := exec.Command(getconf, "CLK_TCK").Output()
|
||||
out, err := invoke.Command(getconf, "CLK_TCK")
|
||||
// ignore errors
|
||||
if err == nil {
|
||||
i, err := strconv.ParseFloat(strings.TrimSpace(string(out)), 64)
|
||||
|
|
|
@ -7,24 +7,46 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
func Percent(interval time.Duration, percpu bool) ([]float64, error) {
|
||||
getAllBusy := func(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
|
||||
return busy + t.Idle, busy
|
||||
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
|
||||
return busy + t.Idle, busy
|
||||
}
|
||||
|
||||
func calculateBusy(t1, t2 TimesStat) float64 {
|
||||
t1All, t1Busy := getAllBusy(t1)
|
||||
t2All, t2Busy := getAllBusy(t2)
|
||||
|
||||
if t2Busy <= t1Busy {
|
||||
return 0
|
||||
}
|
||||
if t2All <= t1All {
|
||||
return 1
|
||||
}
|
||||
return (t2Busy - t1Busy) / (t2All - t1All) * 100
|
||||
}
|
||||
|
||||
func calculateAllBusy(t1, t2 []TimesStat) ([]float64, error) {
|
||||
// Make sure the CPU measurements have the same length.
|
||||
if len(t1) != len(t2) {
|
||||
return nil, fmt.Errorf(
|
||||
"received two CPU counts: %d != %d",
|
||||
len(t1), len(t2),
|
||||
)
|
||||
}
|
||||
|
||||
calculate := func(t1, t2 TimesStat) float64 {
|
||||
t1All, t1Busy := getAllBusy(t1)
|
||||
t2All, t2Busy := getAllBusy(t2)
|
||||
ret := make([]float64, len(t1))
|
||||
for i, t := range t2 {
|
||||
ret[i] = calculateBusy(t1[i], t)
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
if t2Busy <= t1Busy {
|
||||
return 0
|
||||
}
|
||||
if t2All <= t1All {
|
||||
return 1
|
||||
}
|
||||
return (t2Busy - t1Busy) / (t2All - t1All) * 100
|
||||
//Percent calculates the percentage of cpu used either per CPU or combined.
|
||||
//If an interval of 0 is given it will compare the current cpu times against the last call.
|
||||
func Percent(interval time.Duration, percpu bool) ([]float64, error) {
|
||||
if interval <= 0 {
|
||||
return percentUsedFromLastCall(percpu)
|
||||
}
|
||||
|
||||
// Get CPU usage at the start of the interval.
|
||||
|
@ -33,9 +55,7 @@ func Percent(interval time.Duration, percpu bool) ([]float64, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
if interval > 0 {
|
||||
time.Sleep(interval)
|
||||
}
|
||||
time.Sleep(interval)
|
||||
|
||||
// And at the end of the interval.
|
||||
cpuTimes2, err := Times(percpu)
|
||||
|
@ -43,17 +63,28 @@ func Percent(interval time.Duration, percpu bool) ([]float64, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
// Make sure the CPU measurements have the same length.
|
||||
if len(cpuTimes1) != len(cpuTimes2) {
|
||||
return nil, fmt.Errorf(
|
||||
"received two CPU counts: %d != %d",
|
||||
len(cpuTimes1), len(cpuTimes2),
|
||||
)
|
||||
return calculateAllBusy(cpuTimes1, cpuTimes2)
|
||||
}
|
||||
|
||||
func percentUsedFromLastCall(percpu bool) ([]float64, error) {
|
||||
cpuTimes, err := Times(percpu)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
lastCPUPercent.Lock()
|
||||
defer lastCPUPercent.Unlock()
|
||||
var lastTimes []TimesStat
|
||||
if percpu {
|
||||
lastTimes = lastCPUPercent.lastPerCPUTimes
|
||||
lastCPUPercent.lastPerCPUTimes = cpuTimes
|
||||
} else {
|
||||
lastTimes = lastCPUPercent.lastCPUTimes
|
||||
lastCPUPercent.lastCPUTimes = cpuTimes
|
||||
}
|
||||
|
||||
ret := make([]float64, len(cpuTimes1))
|
||||
for i, t := range cpuTimes2 {
|
||||
ret[i] = calculate(cpuTimes1[i], t)
|
||||
if lastTimes == nil {
|
||||
return nil, fmt.Errorf("Error getting times for cpu percent. LastTimes was nil")
|
||||
}
|
||||
return ret, nil
|
||||
return calculateAllBusy(lastTimes, cpuTimes)
|
||||
|
||||
}
|
||||
|
|
|
@ -283,6 +283,10 @@ func IOCounters() (map[string]IOCountersStat, error) {
|
|||
|
||||
for _, line := range lines {
|
||||
fields := strings.Fields(line)
|
||||
if len(fields) < 14 {
|
||||
// malformed line in /proc/diskstats, avoid panic by ignoring.
|
||||
continue
|
||||
}
|
||||
name := fields[2]
|
||||
reads, err := strconv.ParseUint((fields[3]), 10, 64)
|
||||
if err != nil {
|
||||
|
@ -332,6 +336,8 @@ func IOCounters() (map[string]IOCountersStat, error) {
|
|||
return ret, nil
|
||||
}
|
||||
|
||||
// GetDiskSerialNumber returns Serial Number of given device or empty string
|
||||
// on error. Name of device is expected, eg. /dev/sda
|
||||
func GetDiskSerialNumber(name string) string {
|
||||
n := fmt.Sprintf("--name=%s", name)
|
||||
udevadm, err := exec.LookPath("/sbin/udevadm")
|
||||
|
|
|
@ -2,17 +2,25 @@ package host
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
)
|
||||
|
||||
var invoke common.Invoker
|
||||
|
||||
func init() {
|
||||
invoke = common.Invoke{}
|
||||
}
|
||||
|
||||
// A HostInfoStat describes the host status.
|
||||
// This is not in the psutil but it useful.
|
||||
type InfoStat struct {
|
||||
Hostname string `json:"hostname"`
|
||||
Uptime uint64 `json:"uptime"`
|
||||
BootTime uint64 `json:"bootTime"`
|
||||
Procs uint64 `json:"procs"` // number of processes
|
||||
OS string `json:"os"` // ex: freebsd, linux
|
||||
Platform string `json:"platform"` // ex: ubuntu, linuxmint
|
||||
Procs uint64 `json:"procs"` // number of processes
|
||||
OS string `json:"os"` // ex: freebsd, linux
|
||||
Platform string `json:"platform"` // ex: ubuntu, linuxmint
|
||||
PlatformFamily string `json:"platformFamily"` // ex: debian, rhel
|
||||
PlatformVersion string `json:"platformVersion"`
|
||||
VirtualizationSystem string `json:"virtualizationSystem"`
|
||||
|
|
|
@ -131,12 +131,12 @@ func PlatformInformation() (string, string, string, error) {
|
|||
if err != nil {
|
||||
return "", "", "", err
|
||||
}
|
||||
out, err := exec.Command(uname, "-s").Output()
|
||||
out, err := invoke.Command(uname, "-s")
|
||||
if err == nil {
|
||||
platform = strings.ToLower(strings.TrimSpace(string(out)))
|
||||
}
|
||||
|
||||
out, err = exec.Command(uname, "-r").Output()
|
||||
out, err = invoke.Command(uname, "-r")
|
||||
if err == nil {
|
||||
version = strings.ToLower(strings.TrimSpace(string(out)))
|
||||
}
|
||||
|
|
|
@ -136,12 +136,12 @@ func PlatformInformation() (string, string, string, error) {
|
|||
return "", "", "", err
|
||||
}
|
||||
|
||||
out, err := exec.Command(uname, "-s").Output()
|
||||
out, err := invoke.Command(uname, "-s")
|
||||
if err == nil {
|
||||
platform = strings.ToLower(strings.TrimSpace(string(out)))
|
||||
}
|
||||
|
||||
out, err = exec.Command(uname, "-r").Output()
|
||||
out, err = invoke.Command(uname, "-r")
|
||||
if err == nil {
|
||||
version = strings.ToLower(strings.TrimSpace(string(out)))
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
common "github.com/shirou/gopsutil/internal/common"
|
||||
)
|
||||
|
||||
type LSB struct {
|
||||
|
@ -136,6 +136,26 @@ func Users() ([]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")) {
|
||||
|
@ -164,7 +184,7 @@ func getLSB() (*LSB, error) {
|
|||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
out, err := exec.Command(lsb_release).Output()
|
||||
out, err := invoke.Command(lsb_release)
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
|
@ -256,6 +276,18 @@ func PlatformInformation() (platform string, family string, version string, err
|
|||
} else if common.PathExists(common.HostEtc("arch-release")) {
|
||||
platform = "arch"
|
||||
version = lsb.Release
|
||||
} else if common.PathExists(common.HostEtc("alpine-release")) {
|
||||
platform = "alpine"
|
||||
contents, err := common.ReadLines(common.HostEtc("alpine-release"))
|
||||
if err == nil && len(contents) > 0 {
|
||||
version = contents[0]
|
||||
}
|
||||
} else if common.PathExists(common.HostEtc("os-release")) {
|
||||
p, v, err := getOSRelease()
|
||||
if err == nil {
|
||||
platform = p
|
||||
version = v
|
||||
}
|
||||
} else if lsb.ID == "RedHat" {
|
||||
platform = "redhat"
|
||||
version = lsb.Release
|
||||
|
@ -290,6 +322,10 @@ func PlatformInformation() (platform string, family string, version string, err
|
|||
family = "arch"
|
||||
case "exherbo":
|
||||
family = "exherbo"
|
||||
case "alpine":
|
||||
family = "alpine"
|
||||
case "coreos":
|
||||
family = "coreos"
|
||||
}
|
||||
|
||||
return platform, family, version, nil
|
||||
|
@ -351,7 +387,7 @@ func Virtualization() (string, string, error) {
|
|||
if common.PathExists(filename + "/capabilities") {
|
||||
contents, err := common.ReadLines(filename + "/capabilities")
|
||||
if err == nil {
|
||||
if common.StringsHas(contents, "control_d") {
|
||||
if common.StringsContains(contents, "control_d") {
|
||||
role = "host"
|
||||
}
|
||||
}
|
||||
|
@ -379,9 +415,9 @@ func Virtualization() (string, string, error) {
|
|||
if common.PathExists(filename) {
|
||||
contents, err := common.ReadLines(filename)
|
||||
if err == nil {
|
||||
if common.StringsHas(contents, "QEMU Virtual CPU") ||
|
||||
common.StringsHas(contents, "Common KVM processor") ||
|
||||
common.StringsHas(contents, "Common 32-bit KVM processor") {
|
||||
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"
|
||||
}
|
||||
|
@ -402,8 +438,8 @@ func Virtualization() (string, string, error) {
|
|||
contents, err := common.ReadLines(filename + "/self/status")
|
||||
if err == nil {
|
||||
|
||||
if common.StringsHas(contents, "s_context:") ||
|
||||
common.StringsHas(contents, "VxID:") {
|
||||
if common.StringsContains(contents, "s_context:") ||
|
||||
common.StringsContains(contents, "VxID:") {
|
||||
system = "linux-vserver"
|
||||
}
|
||||
// TODO: guest or host
|
||||
|
@ -413,16 +449,28 @@ func Virtualization() (string, string, error) {
|
|||
if common.PathExists(filename + "/self/cgroup") {
|
||||
contents, err := common.ReadLines(filename + "/self/cgroup")
|
||||
if err == nil {
|
||||
if common.StringsHas(contents, "lxc") ||
|
||||
common.StringsHas(contents, "docker") {
|
||||
if common.StringsContains(contents, "lxc") {
|
||||
system = "lxc"
|
||||
role = "guest"
|
||||
} else if common.PathExists("/usr/bin/lxc-version") { // TODO: which
|
||||
} 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
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
// +build linux
|
||||
// +build ppc64le
|
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// cgo -godefs types_linux.go
|
||||
|
||||
|
|
|
@ -50,7 +50,7 @@ func Info() (*InfoStat, error) {
|
|||
boot, err := BootTime()
|
||||
if err == nil {
|
||||
ret.BootTime = boot
|
||||
ret.Uptime = uptime(boot)
|
||||
ret.Uptime, _ = Uptime()
|
||||
}
|
||||
|
||||
procs, err := process.Pids()
|
||||
|
@ -76,7 +76,7 @@ func GetOSInfo() (Win32_OperatingSystem, error) {
|
|||
return dst[0], nil
|
||||
}
|
||||
|
||||
func BootTime() (uint64, error) {
|
||||
func Uptime() (uint64, error) {
|
||||
if osInfo == nil {
|
||||
_, err := GetOSInfo()
|
||||
if err != nil {
|
||||
|
@ -88,16 +88,16 @@ func BootTime() (uint64, error) {
|
|||
return uint64(now.Sub(t).Seconds()), nil
|
||||
}
|
||||
|
||||
func uptime(boot uint64) uint64 {
|
||||
return uint64(time.Now().Unix()) - boot
|
||||
func bootTime(up uint64) uint64 {
|
||||
return uint64(time.Now().Unix()) - up
|
||||
}
|
||||
|
||||
func Uptime() (uint64, error) {
|
||||
boot, err := BootTime()
|
||||
func BootTime() (uint64, error) {
|
||||
up, err := Uptime()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return uptime(boot), nil
|
||||
return bootTime(up), nil
|
||||
}
|
||||
|
||||
func PlatformInformation() (platform string, family string, version string, err error) {
|
||||
|
|
|
@ -8,8 +8,10 @@ package common
|
|||
// - windows (amd64)
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/url"
|
||||
"os"
|
||||
"os/exec"
|
||||
|
@ -19,6 +21,12 @@ import (
|
|||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
Timeout = 3 * time.Second
|
||||
TimeoutErr = errors.New("Command timed out.")
|
||||
)
|
||||
|
||||
type Invoker interface {
|
||||
|
@ -28,7 +36,8 @@ type Invoker interface {
|
|||
type Invoke struct{}
|
||||
|
||||
func (i Invoke) Command(name string, arg ...string) ([]byte, error) {
|
||||
return exec.Command(name, arg...).Output()
|
||||
cmd := exec.Command(name, arg...)
|
||||
return CombinedOutputTimeout(cmd, Timeout)
|
||||
}
|
||||
|
||||
type FakeInvoke struct {
|
||||
|
@ -118,20 +127,20 @@ func IntToString(orig []int8) string {
|
|||
}
|
||||
|
||||
func UintToString(orig []uint8) 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)
|
||||
}
|
||||
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])
|
||||
return string(ret[0:size])
|
||||
}
|
||||
|
||||
func ByteToString(orig []byte) string {
|
||||
|
@ -294,3 +303,41 @@ func HostSys(combineWith ...string) string {
|
|||
func HostEtc(combineWith ...string) string {
|
||||
return GetEnv("HOST_ETC", "/etc", combineWith...)
|
||||
}
|
||||
|
||||
// CombinedOutputTimeout runs the given command with the given timeout and
|
||||
// returns the combined output of stdout and stderr.
|
||||
// If the command times out, it attempts to kill the process.
|
||||
// copied from https://github.com/influxdata/telegraf
|
||||
func CombinedOutputTimeout(c *exec.Cmd, timeout time.Duration) ([]byte, error) {
|
||||
var b bytes.Buffer
|
||||
c.Stdout = &b
|
||||
c.Stderr = &b
|
||||
if err := c.Start(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err := WaitTimeout(c, timeout)
|
||||
return b.Bytes(), err
|
||||
}
|
||||
|
||||
// WaitTimeout waits for the given command to finish with a timeout.
|
||||
// It assumes the command has already been started.
|
||||
// If the command times out, it attempts to kill the process.
|
||||
// copied from https://github.com/influxdata/telegraf
|
||||
func WaitTimeout(c *exec.Cmd, timeout time.Duration) error {
|
||||
timer := time.NewTimer(timeout)
|
||||
done := make(chan error)
|
||||
go func() { done <- c.Wait() }()
|
||||
select {
|
||||
case err := <-done:
|
||||
timer.Stop()
|
||||
return err
|
||||
case <-timer.C:
|
||||
if err := c.Process.Kill(); err != nil {
|
||||
log.Printf("FATAL error killing process: %s", err)
|
||||
return err
|
||||
}
|
||||
// wait for the command to return after killing it
|
||||
<-done
|
||||
return TimeoutErr
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,8 +2,16 @@ package mem
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
)
|
||||
|
||||
var invoke common.Invoker
|
||||
|
||||
func init() {
|
||||
invoke = common.Invoke{}
|
||||
}
|
||||
|
||||
// Memory usage statistics. Total, Available and Used contain numbers of bytes
|
||||
// for human consumption.
|
||||
//
|
||||
|
|
|
@ -16,7 +16,7 @@ func getVMStat(vms *VirtualMemoryStat) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
out, err := exec.Command(vm_stat).Output()
|
||||
out, err := invoke.Command(vm_stat)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -93,7 +93,7 @@ func SwapMemory() (*SwapMemoryStat, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
out, err := exec.Command(swapinfo).Output()
|
||||
out, err := invoke.Command(swapinfo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -18,15 +18,18 @@ func init() {
|
|||
}
|
||||
|
||||
type IOCountersStat struct {
|
||||
Name string `json:"name"` // interface name
|
||||
Name string `json:"name"` // interface name
|
||||
BytesSent uint64 `json:"bytesSent"` // number of bytes sent
|
||||
BytesRecv uint64 `json:"bytesRecv"` // number of bytes received
|
||||
PacketsSent uint64 `json:"packetsSent"` // number of packets sent
|
||||
PacketsRecv uint64 `json:"packetsRecv"` // number of packets received
|
||||
Errin uint64 `json:"errin"` // total number of errors while receiving
|
||||
Errout uint64 `json:"errout"` // total number of errors while sending
|
||||
Dropin uint64 `json:"dropin"` // total number of incoming packets which were dropped
|
||||
Dropout uint64 `json:"dropout"` // total number of outgoing packets which were dropped (always 0 on OSX and BSD)
|
||||
Errin uint64 `json:"errin"` // total number of errors while receiving
|
||||
Errout uint64 `json:"errout"` // total number of errors while sending
|
||||
Dropin uint64 `json:"dropin"` // total number of incoming packets which were dropped
|
||||
Dropout uint64 `json:"dropout"` // total number of outgoing packets which were dropped (always 0 on OSX and BSD)
|
||||
Fifoin uint64 `json:"fifoin"` // total number of FIFO buffers errors while receiving
|
||||
Fifoout uint64 `json:"fifoout"` // total number of FIFO buffers errors while sending
|
||||
|
||||
}
|
||||
|
||||
// Addr is implemented compatibility to psutil
|
||||
|
|
|
@ -21,7 +21,7 @@ func IOCounters(pernic bool) ([]IOCountersStat, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out, err := exec.Command(netstat, "-ibdnW").Output()
|
||||
out, err := invoke.Command(netstat, "-ibdnW")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ func IOCounters(pernic bool) ([]IOCountersStat, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out, err := exec.Command(netstat, "-ibdnW").Output()
|
||||
out, err := invoke.Command(netstat, "-ibdnW")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -63,6 +63,10 @@ func IOCountersByFile(pernic bool, filename string) ([]IOCountersStat, error) {
|
|||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
fifoIn, err := strconv.ParseUint(fields[4], 10, 64)
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
bytesSent, err := strconv.ParseUint(fields[8], 10, 64)
|
||||
if err != nil {
|
||||
return ret, err
|
||||
|
@ -79,6 +83,10 @@ func IOCountersByFile(pernic bool, filename string) ([]IOCountersStat, error) {
|
|||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
fifoOut, err := strconv.ParseUint(fields[14], 10, 64)
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
|
||||
nic := IOCountersStat{
|
||||
Name: interfaceName,
|
||||
|
@ -86,10 +94,12 @@ func IOCountersByFile(pernic bool, filename string) ([]IOCountersStat, error) {
|
|||
PacketsRecv: packetsRecv,
|
||||
Errin: errIn,
|
||||
Dropin: dropIn,
|
||||
Fifoin: fifoIn,
|
||||
BytesSent: bytesSent,
|
||||
PacketsSent: packetsSent,
|
||||
Errout: errOut,
|
||||
Dropout: dropOut,
|
||||
Fifoout: fifoOut,
|
||||
}
|
||||
ret = append(ret, nic)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
// +build linux
|
||||
// +build arm64
|
||||
|
||||
package process
|
||||
|
||||
const (
|
||||
ClockTicks = 100 // C.sysconf(C._SC_CLK_TCK)
|
||||
PageSize = 4096 // C.sysconf(C._SC_PAGE_SIZE)
|
||||
)
|
|
@ -9,6 +9,8 @@ import (
|
|||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
)
|
||||
|
||||
// POSIX
|
||||
|
@ -72,7 +74,10 @@ func (p *Process) SendSignal(sig syscall.Signal) error {
|
|||
}
|
||||
cmd := exec.Command(kill, "-s", sigAsStr, strconv.Itoa(int(p.Pid)))
|
||||
cmd.Stderr = os.Stderr
|
||||
err = cmd.Run()
|
||||
if err := cmd.Start(); err != nil {
|
||||
return err
|
||||
}
|
||||
err = common.WaitTimeout(cmd, common.Timeout)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -23,6 +23,11 @@ const (
|
|||
MaxPathLength = 260
|
||||
)
|
||||
|
||||
var (
|
||||
modpsapi = syscall.NewLazyDLL("psapi.dll")
|
||||
procGetProcessMemoryInfo = modpsapi.NewProc("GetProcessMemoryInfo")
|
||||
)
|
||||
|
||||
type SystemProcessInformation struct {
|
||||
NextEntryOffset uint64
|
||||
NumberOfThreads uint64
|
||||
|
@ -46,13 +51,18 @@ type MemoryMapsStat struct {
|
|||
}
|
||||
|
||||
type Win32_Process struct {
|
||||
Name string
|
||||
ExecutablePath *string
|
||||
CommandLine *string
|
||||
Priority uint32
|
||||
CreationDate *time.Time
|
||||
ProcessID uint32
|
||||
ThreadCount uint32
|
||||
Name string
|
||||
ExecutablePath *string
|
||||
CommandLine *string
|
||||
Priority uint32
|
||||
CreationDate *time.Time
|
||||
ProcessID uint32
|
||||
ThreadCount uint32
|
||||
Status *string
|
||||
ReadOperationCount uint64
|
||||
ReadTransferCount uint64
|
||||
WriteOperationCount uint64
|
||||
WriteTransferCount uint64
|
||||
|
||||
/*
|
||||
CSCreationClassName string
|
||||
|
@ -76,14 +86,9 @@ type Win32_Process struct {
|
|||
PeakVirtualSize uint64
|
||||
PeakWorkingSetSize uint32
|
||||
PrivatePageCount uint64
|
||||
ReadOperationCount uint64
|
||||
ReadTransferCount uint64
|
||||
Status *string
|
||||
TerminationDate *time.Time
|
||||
UserModeTime uint64
|
||||
WorkingSetSize uint64
|
||||
WriteOperationCount uint64
|
||||
WriteTransferCount uint64
|
||||
*/
|
||||
}
|
||||
|
||||
|
@ -158,12 +163,12 @@ func (p *Process) CmdlineSlice() ([]string, error) {
|
|||
}
|
||||
|
||||
func (p *Process) CreateTime() (int64, error) {
|
||||
dst, err := GetWin32Proc(p.Pid)
|
||||
ru, err := getRusage(p.Pid)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("could not get CreationDate: %s", err)
|
||||
}
|
||||
date := *dst[0].CreationDate
|
||||
return date.Unix(), nil
|
||||
|
||||
return ru.CreationTime.Nanoseconds() / 1000000, nil
|
||||
}
|
||||
|
||||
func (p *Process) Cwd() (string, error) {
|
||||
|
@ -207,8 +212,20 @@ func (p *Process) Rlimit() ([]RlimitStat, error) {
|
|||
|
||||
return rlimit, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) IOCounters() (*IOCountersStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
dst, err := GetWin32Proc(p.Pid)
|
||||
if err != nil || len(dst) == 0 {
|
||||
return nil, fmt.Errorf("could not get Win32Proc: %s", err)
|
||||
}
|
||||
ret := &IOCountersStat{
|
||||
ReadCount: uint64(dst[0].ReadOperationCount),
|
||||
ReadBytes: uint64(dst[0].ReadTransferCount),
|
||||
WriteCount: uint64(dst[0].WriteOperationCount),
|
||||
WriteBytes: uint64(dst[0].WriteTransferCount),
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
func (p *Process) NumCtxSwitches() (*NumCtxSwitchesStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
|
@ -234,7 +251,17 @@ func (p *Process) CPUAffinity() ([]int32, error) {
|
|||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) MemoryInfo() (*MemoryInfoStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
mem, err := getMemoryInfo(p.Pid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ret := &MemoryInfoStat{
|
||||
RSS: mem.WorkingSetSize,
|
||||
VMS: mem.PagefileUsage,
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
func (p *Process) MemoryInfoEx() (*MemoryInfoExStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
|
@ -355,3 +382,45 @@ func getProcInfo(pid int32) (*SystemProcessInformation, error) {
|
|||
|
||||
return &sysProcInfo, nil
|
||||
}
|
||||
|
||||
func getRusage(pid int32) (*syscall.Rusage, error) {
|
||||
var CPU syscall.Rusage
|
||||
|
||||
c, err := syscall.OpenProcess(syscall.PROCESS_QUERY_INFORMATION, false, uint32(pid))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer syscall.CloseHandle(c)
|
||||
|
||||
if err := syscall.GetProcessTimes(c, &CPU.CreationTime, &CPU.ExitTime, &CPU.KernelTime, &CPU.UserTime); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &CPU, nil
|
||||
}
|
||||
|
||||
func getMemoryInfo(pid int32) (PROCESS_MEMORY_COUNTERS, error) {
|
||||
var mem PROCESS_MEMORY_COUNTERS
|
||||
c, err := syscall.OpenProcess(syscall.PROCESS_QUERY_INFORMATION, false, uint32(pid))
|
||||
if err != nil {
|
||||
return mem, err
|
||||
}
|
||||
defer syscall.CloseHandle(c)
|
||||
if err := getProcessMemoryInfo(c, &mem); err != nil {
|
||||
return mem, err
|
||||
}
|
||||
|
||||
return mem, err
|
||||
}
|
||||
|
||||
func getProcessMemoryInfo(h syscall.Handle, mem *PROCESS_MEMORY_COUNTERS) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procGetProcessMemoryInfo.Addr(), 3, uintptr(h), uintptr(unsafe.Pointer(mem)), uintptr(unsafe.Sizeof(*mem)))
|
||||
if r1 == 0 {
|
||||
if e1 != 0 {
|
||||
err = error(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
// +build windows
|
||||
|
||||
package process
|
||||
|
||||
type PROCESS_MEMORY_COUNTERS struct {
|
||||
CB uint32
|
||||
PageFaultCount uint32
|
||||
PeakWorkingSetSize uint32
|
||||
WorkingSetSize uint32
|
||||
QuotaPeakPagedPoolUsage uint32
|
||||
QuotaPagedPoolUsage uint32
|
||||
QuotaPeakNonPagedPoolUsage uint32
|
||||
QuotaNonPagedPoolUsage uint32
|
||||
PagefileUsage uint32
|
||||
PeakPagefileUsage uint32
|
||||
}
|
16
vendor/github.com/shirou/gopsutil/process/process_windows_amd64.go
generated
vendored
Normal file
16
vendor/github.com/shirou/gopsutil/process/process_windows_amd64.go
generated
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
// +build windows
|
||||
|
||||
package process
|
||||
|
||||
type PROCESS_MEMORY_COUNTERS struct {
|
||||
CB uint32
|
||||
PageFaultCount uint32
|
||||
PeakWorkingSetSize uint64
|
||||
WorkingSetSize uint64
|
||||
QuotaPeakPagedPoolUsage uint64
|
||||
QuotaPagedPoolUsage uint64
|
||||
QuotaPeakNonPagedPoolUsage uint64
|
||||
QuotaNonPagedPoolUsage uint64
|
||||
PagefileUsage uint64
|
||||
PeakPagefileUsage uint64
|
||||
}
|
|
@ -666,52 +666,52 @@
|
|||
"revision": "983d3a5fab1bf04d1b412465d2d9f8430e2e917e"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "dtcffK/n1nDKPtvHg2GnU1C194s=",
|
||||
"checksumSHA1": "G1oy2AGv5pCnNL0hRfg+mlX4Uq4=",
|
||||
"comment": "1.0.0-230-gf58654f",
|
||||
"path": "github.com/shirou/gopsutil/cpu",
|
||||
"revision": "7b991b8135166c7fc81b65665a2f35c7a1966cfc",
|
||||
"revisionTime": "2016-05-04T15:08:50Z"
|
||||
"revision": "5c1bfed85550640833e8bbf50156d114ba99fbf2",
|
||||
"revisionTime": "2016-06-17T08:26:08Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "zs7XTdxVVhxUUwA4kSdSJlNfVZc=",
|
||||
"checksumSHA1": "x4HZyWURx/UwxHVrdaTGbTFd198=",
|
||||
"path": "github.com/shirou/gopsutil/disk",
|
||||
"revision": "83c6e72cbdef6e8ada934549abf700ff0ba96776",
|
||||
"revisionTime": "2016-05-20T22:39:10Z"
|
||||
"revision": "5c1bfed85550640833e8bbf50156d114ba99fbf2",
|
||||
"revisionTime": "2016-06-17T08:26:08Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "lpPewrgMOYaTKZ0wRZpmZJxnEBw=",
|
||||
"checksumSHA1": "tV0skuyoy255WiTlKjd24T+5DeU=",
|
||||
"comment": "1.0.0-230-gf58654f",
|
||||
"path": "github.com/shirou/gopsutil/host",
|
||||
"revision": "7b991b8135166c7fc81b65665a2f35c7a1966cfc",
|
||||
"revisionTime": "2016-05-04T15:08:50Z"
|
||||
"revision": "5c1bfed85550640833e8bbf50156d114ba99fbf2",
|
||||
"revisionTime": "2016-06-17T08:26:08Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "xrMuUxCr8UckY5oI2lwCerYwIhk=",
|
||||
"checksumSHA1": "zJZyxS96XiEnDJSZkWwXtktziRY=",
|
||||
"comment": "1.0.0-230-gf58654f",
|
||||
"path": "github.com/shirou/gopsutil/internal/common",
|
||||
"revision": "7b991b8135166c7fc81b65665a2f35c7a1966cfc",
|
||||
"revisionTime": "2016-05-04T15:08:50Z"
|
||||
"revision": "5c1bfed85550640833e8bbf50156d114ba99fbf2",
|
||||
"revisionTime": "2016-06-17T08:26:08Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "bHTDi2QAN4SmdZpHOtyQ6fQeCnQ=",
|
||||
"checksumSHA1": "LUipApIqOLcKbZfwXknNCifGles=",
|
||||
"comment": "1.0.0-230-gf58654f",
|
||||
"path": "github.com/shirou/gopsutil/mem",
|
||||
"revision": "7b991b8135166c7fc81b65665a2f35c7a1966cfc",
|
||||
"revisionTime": "2016-05-04T15:08:50Z"
|
||||
"revision": "5c1bfed85550640833e8bbf50156d114ba99fbf2",
|
||||
"revisionTime": "2016-06-17T08:26:08Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "LHJDMUXWamoP/yje0R42k96OPG8=",
|
||||
"checksumSHA1": "k57srhFXKSysrFdEh3b6oiO48hw=",
|
||||
"comment": "1.0.0-230-gf58654f",
|
||||
"path": "github.com/shirou/gopsutil/net",
|
||||
"revision": "7b991b8135166c7fc81b65665a2f35c7a1966cfc",
|
||||
"revisionTime": "2016-05-04T15:08:50Z"
|
||||
"revision": "5c1bfed85550640833e8bbf50156d114ba99fbf2",
|
||||
"revisionTime": "2016-06-17T08:26:08Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "o544bXejDPLi6qpjHav8a91W4Ks=",
|
||||
"checksumSHA1": "+m5V0QobB9gklJkz+zk0NvaSeOs=",
|
||||
"comment": "1.0.0-230-gf58654f",
|
||||
"path": "github.com/shirou/gopsutil/process",
|
||||
"revision": "7b991b8135166c7fc81b65665a2f35c7a1966cfc",
|
||||
"revisionTime": "2016-05-04T15:08:50Z"
|
||||
"revision": "5c1bfed85550640833e8bbf50156d114ba99fbf2",
|
||||
"revisionTime": "2016-06-17T08:26:08Z"
|
||||
},
|
||||
{
|
||||
"path": "github.com/shirou/w32",
|
||||
|
|
Loading…
Reference in New Issue