pax_global_header00006660000000000000000000000064131516755020014517gustar00rootroot0000000000000052 comment=a452de7c734a0fa0f16d2e5725b0fa5934d9fbec golang-github-shirou-gopsutil-2.17.08/000077500000000000000000000000001315167550200176005ustar00rootroot00000000000000golang-github-shirou-gopsutil-2.17.08/.gitignore000066400000000000000000000000271315167550200215670ustar00rootroot00000000000000*~ #* _obj *.tmp .idea golang-github-shirou-gopsutil-2.17.08/LICENSE000066400000000000000000000061121315167550200206050ustar00rootroot00000000000000gopsutil is distributed under BSD license reproduced below. Copyright (c) 2014, WAKAYAMA Shirou All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the gopsutil authors nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ------- internal/common/binary.go in the gopsutil is copied and modifid from golang/encoding/binary.go. Copyright (c) 2009 The Go Authors. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Google Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.golang-github-shirou-gopsutil-2.17.08/Makefile000066400000000000000000000023261315167550200212430ustar00rootroot00000000000000.PHONY: help check .DEFAULT_GOAL := help SUBPKGS=cpu disk docker host internal load mem net process help: ## Show help @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' check: ## Check errcheck -ignore="Close|Run|Write" ./... golint ./... | egrep -v 'underscores|HttpOnly|should have comment|comment on exported|CamelCase|VM|UID' && exit 1 || exit 0 BUILD_FAIL_PATTERN=grep -v "exec format error" | grep "build failed" && exit 1 || exit 0 build_test: ## test only buildable # Supported operating systems GOOS=linux go test ./... | $(BUILD_FAIL_PATTERN) GOOS=freebsd go test ./... | $(BUILD_FAIL_PATTERN) # GOOS=openbsd go test ./... | $(BUILD_FAIL_PATTERN) CGO_ENABLED=0 GOOS=darwin go test ./... | $(BUILD_FAIL_PATTERN) CGO_ENABLED=1 GOOS=darwin go test ./... | $(BUILD_FAIL_PATTERN) GOOS=windows go test ./... | $(BUILD_FAIL_PATTERN) # Operating systems supported for building only (not implemented error if used) GOOS=solaris go test ./... | $(BUILD_FAIL_PATTERN) # GOOS=dragonfly go test ./... | $(BUILD_FAIL_PATTERN) GOOS=netbsd go test ./... | $(BUILD_FAIL_PATTERN) @echo 'Successfully built on all known operating systems' golang-github-shirou-gopsutil-2.17.08/README.rst000066400000000000000000000223151315167550200212720ustar00rootroot00000000000000gopsutil: psutil for golang ============================== .. image:: https://circleci.com/gh/shirou/gopsutil.svg?&style=shield :target: https://circleci.com/gh/shirou/gopsutil .. image:: https://coveralls.io/repos/shirou/gopsutil/badge.svg?branch=master :target: https://coveralls.io/r/shirou/gopsutil?branch=master .. image:: https://godoc.org/github.com/shirou/gopsutil?status.svg :target: http://godoc.org/github.com/shirou/gopsutil This is a port of psutil (http://pythonhosted.org/psutil/). The challenge is porting all psutil functions on some architectures. Breaking Changes! golang 1.8 is required ------------------------------------------- After v2.17.04, golang 1.8 is required to build. Tag semantics ------------------------- gopsutil tag policy is almost same as Semantic Versioning, but automatically increase like Ubuntu versioning. for example, `v2.17.04` means - v2: major version - 17: release year, 2017 - 04: release month gopsutil aims to keep backwards-compatiblity until major version change. Taged at every end of month, but there are only a few commits, it can be skipped. Available Architectures ------------------------------------ - FreeBSD i386/amd64/arm - Linux i386/amd64/arm(raspberry pi) - Windows/amd64 - Darwin i386/amd64 - OpenBDS amd64 (Thank you @mpfz0r!) - Solaris amd64 (developed and tested on SmartOS/Illumos, Thank you @jen20!) All works are implemented without cgo by porting c struct to golang struct. Usage --------- Note: gopsutil v2 breaks compatibility. If you want to stay with compatibility, please use v1 branch and vendoring. .. code:: go package main import ( "fmt" "github.com/shirou/gopsutil/mem" ) func main() { v, _ := mem.VirtualMemory() // almost every return value is a struct fmt.Printf("Total: %v, Free:%v, UsedPercent:%f%%\n", v.Total, v.Free, v.UsedPercent) // convert to JSON. String() is also implemented fmt.Println(v) } The output is below. :: Total: 3179569152, Free:284233728, UsedPercent:84.508194% {"total":3179569152,"available":492572672,"used":2895335424,"usedPercent":84.50819439828305, (snip...)} You can set an alternative location to :code:`/proc` by setting the :code:`HOST_PROC` environment variable. You can set an alternative location to :code:`/sys` by setting the :code:`HOST_SYS` environment variable. You can set an alternative location to :code:`/etc` by setting the :code:`HOST_ETC` environment variable. Documentation ------------------------ see http://godoc.org/github.com/shirou/gopsutil Requirements ----------------- - go1.5 or above is required. More Info -------------------- Several methods have been added which are not present in psutil, but will provide useful information. - host/HostInfo() (linux) - Hostname - Uptime - Procs - OS (ex: "linux") - Platform (ex: "ubuntu", "arch") - PlatformFamily (ex: "debian") - PlatformVersion (ex: "Ubuntu 13.10") - VirtualizationSystem (ex: "LXC") - VirtualizationRole (ex: "guest"/"host") - cpu/CPUInfo() (linux, freebsd) - CPU (ex: 0, 1, ...) - VendorID (ex: "GenuineIntel") - Family - Model - Stepping - PhysicalID - CoreID - Cores (ex: 2) - ModelName (ex: "Intel(R) Core(TM) i7-2640M CPU @ 2.80GHz") - Mhz - CacheSize - Flags (ex: "fpu vme de pse tsc msr pae mce cx8 ...") - Microcode - load/LoadAvg() (linux, freebsd) - Load1 - Load5 - Load15 - docker/GetDockerIDList() (linux only) - container id list ([]string) - docker/CgroupCPU() (linux only) - user - system - docker/CgroupMem() (linux only) - various status - net_protocols (linux only) - system wide stats on network protocols (i.e IP, TCP, UDP, etc.) - sourced from /proc/net/snmp - iptables nf_conntrack (linux only) - system wide stats on netfilter conntrack module - sourced from /proc/sys/net/netfilter/nf_conntrack_count Some codes are ported from Ohai. many thanks. Current Status ------------------ - x: work - b: almost works, but something is broken =================== ====== ======= ======= ====== ======= ======= name Linux FreeBSD OpenBSD MacOSX Windows Solaris cpu_times x x x x x cpu_count x x x x x cpu_percent x x x x x cpu_times_percent x x x x x virtual_memory x x x x x b swap_memory x x x x disk_partitions x x x x x disk_io_counters x x x disk_usage x x x x x net_io_counters x x x b x boot_time x x x x x users x x x x x pids x x x x x pid_exists x x x x x net_connections x x net_protocols x net_if_addrs net_if_stats netfilter_conntrack x =================== ====== ======= ======= ====== ======= Process class ^^^^^^^^^^^^^^^ ================ ===== ======= ======= ====== ======= name Linux FreeBSD OpenBSD MacOSX Windows pid x x x x x ppid x x x x x name x x x x x cmdline x x x create_time x x status x x x x cwd x exe x x x x uids x x x x gids x x x x terminal x x x x io_counters x x x x nice x x x x x num_fds x num_ctx_switches x num_threads x x x x x cpu_times x memory_info x x x x x memory_info_ex x memory_maps x open_files x send_signal x x x x suspend x x x x resume x x x x terminate x x x x x kill x x x x username x x x x x ionice rlimit x num_handlers threads cpu_percent x x x cpu_affinity memory_percent parent x x x x children x x x x x connections x x x is_running ================ ===== ======= ======= ====== ======= Original Metrics ^^^^^^^^^^^^^^^^^^^ ================== ===== ======= ======= ====== ======= ======= item Linux FreeBSD OpenBSD MacOSX Windows Solaris **HostInfo** hostname x x x x x x uptime x x x x x proces x x x x os x x x x x x platform x x x x x platformfamily x x x x x virtualization x **CPU** VendorID x x x x x x Family x x x x x x Model x x x x x x Stepping x x x x x x PhysicalID x x CoreID x x Cores x x x ModelName x x x x x x Microcode x x **LoadAvg** Load1 x x x x Load5 x x x x Load15 x x x x **GetDockerID** container id x no no no no **CgroupsCPU** user x no no no no system x no no no no **CgroupsMem** various x no no no no ================== ===== ======= ======= ====== ======= ======= - future work - process_iter - wait_procs - Process class - as_dict - wait License ------------ New BSD License (same as psutil) Related Works ----------------------- I have been influenced by the following great works: - psutil: http://pythonhosted.org/psutil/ - dstat: https://github.com/dagwieers/dstat - gosigar: https://github.com/cloudfoundry/gosigar/ - goprocinfo: https://github.com/c9s/goprocinfo - go-ps: https://github.com/mitchellh/go-ps - ohai: https://github.com/opscode/ohai/ - bosun: https://github.com/bosun-monitor/bosun/tree/master/cmd/scollector/collectors - mackerel: https://github.com/mackerelio/mackerel-agent/tree/master/metrics How to Contribute --------------------------- 1. Fork it 2. Create your feature branch (git checkout -b my-new-feature) 3. Commit your changes (git commit -am 'Add some feature') 4. Push to the branch (git push origin my-new-feature) 5. Create new Pull Request My English is terrible, so documentation or correcting comments are also welcome. golang-github-shirou-gopsutil-2.17.08/circle.yml000066400000000000000000000006201315167550200215620ustar00rootroot00000000000000machine: timezone: Asia/Tokyo pre: - sudo chown -R ubuntu:ubuntu /usr/local/go/pkg/ test: override: - GOOS=linux GOARCH=amd64 go test -v ./... - GOOS=linux GOARCH=386 go get -v ./... - GOOS=linux GOARCH=arm GOARM=7 go get -v ./... - GOOS=freebsd GOARCH=amd64 go get -v ./... - GOOS=windows GOARCH=amd64 go get -v ./... - GOOS=darwin GOARCH=amd64 go get -v ./... golang-github-shirou-gopsutil-2.17.08/coverall.sh000066400000000000000000000010641315167550200217440ustar00rootroot00000000000000#/bin/sh # see http://www.songmu.jp/riji/entry/2015-01-15-goveralls-multi-package.html set -e # cleanup cleanup() { if [ $tmpprof != "" ] && [ -f $tmpprof ]; then rm -f $tmpprof fi exit } trap cleanup INT QUIT TERM EXIT # メインの処理 prof=${1:-".profile.cov"} echo "mode: count" > $prof gopath1=$(echo $GOPATH | cut -d: -f1) for pkg in $(go list ./...); do tmpprof=$gopath1/src/$pkg/profile.tmp go test -covermode=count -coverprofile=$tmpprof $pkg if [ -f $tmpprof ]; then cat $tmpprof | tail -n +2 >> $prof rm $tmpprof fi done golang-github-shirou-gopsutil-2.17.08/cpu/000077500000000000000000000000001315167550200203675ustar00rootroot00000000000000golang-github-shirou-gopsutil-2.17.08/cpu/cpu.go000066400000000000000000000110421315167550200215030ustar00rootroot00000000000000package cpu import ( "encoding/json" "fmt" "runtime" "strconv" "strings" "sync" "time" "github.com/shirou/gopsutil/internal/common" ) type TimesStat struct { CPU string `json:"cpu"` User float64 `json:"user"` System float64 `json:"system"` Idle float64 `json:"idle"` Nice float64 `json:"nice"` Iowait float64 `json:"iowait"` Irq float64 `json:"irq"` Softirq float64 `json:"softirq"` Steal float64 `json:"steal"` Guest float64 `json:"guest"` GuestNice float64 `json:"guestNice"` Stolen float64 `json:"stolen"` } type InfoStat struct { CPU int32 `json:"cpu"` VendorID string `json:"vendorId"` Family string `json:"family"` Model string `json:"model"` Stepping int32 `json:"stepping"` PhysicalID string `json:"physicalId"` CoreID string `json:"coreId"` Cores int32 `json:"cores"` ModelName string `json:"modelName"` Mhz float64 `json:"mhz"` CacheSize int32 `json:"cacheSize"` Flags []string `json:"flags"` Microcode string `json:"microcode"` } 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 } func (c TimesStat) String() string { v := []string{ `"cpu":"` + c.CPU + `"`, `"user":` + strconv.FormatFloat(c.User, 'f', 1, 64), `"system":` + strconv.FormatFloat(c.System, 'f', 1, 64), `"idle":` + strconv.FormatFloat(c.Idle, 'f', 1, 64), `"nice":` + strconv.FormatFloat(c.Nice, 'f', 1, 64), `"iowait":` + strconv.FormatFloat(c.Iowait, 'f', 1, 64), `"irq":` + strconv.FormatFloat(c.Irq, 'f', 1, 64), `"softirq":` + strconv.FormatFloat(c.Softirq, 'f', 1, 64), `"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, ",") + `}` } // 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 return total } func (c InfoStat) String() string { s, _ := json.Marshal(c) return string(s) } 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), ) } ret := make([]float64, len(t1)) for i, t := range t2 { ret[i] = calculateBusy(t1[i], t) } return ret, nil } // 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. // Returns one value per cpu, or a single value if percpu is set to false. func Percent(interval time.Duration, percpu bool) ([]float64, error) { if interval <= 0 { return percentUsedFromLastCall(percpu) } // Get CPU usage at the start of the interval. cpuTimes1, err := Times(percpu) if err != nil { return nil, err } time.Sleep(interval) // And at the end of the interval. cpuTimes2, err := Times(percpu) if err != nil { return nil, err } 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 } if lastTimes == nil { return nil, fmt.Errorf("error getting times for cpu percent. lastTimes was nil") } return calculateAllBusy(lastTimes, cpuTimes) } golang-github-shirou-gopsutil-2.17.08/cpu/cpu_darwin.go000066400000000000000000000047251315167550200230610ustar00rootroot00000000000000// +build darwin package cpu import ( "os/exec" "strconv" "strings" ) // sys/resource.h const ( CPUser = 0 CPNice = 1 CPSys = 2 CPIntr = 3 CPIdle = 4 CPUStates = 5 ) // default value. from time.h var ClocksPerSec = float64(128) func Times(percpu bool) ([]TimesStat, error) { if percpu { return perCPUTimes() } return allCPUTimes() } // Returns only one CPUInfoStat on FreeBSD func Info() ([]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] } } // 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") 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 return append(ret, c), nil } golang-github-shirou-gopsutil-2.17.08/cpu/cpu_darwin_cgo.go000066400000000000000000000053021315167550200237010ustar00rootroot00000000000000// +build darwin // +build cgo package cpu /* #include #include #include #include #include #include #if TARGET_OS_MAC #include #endif #include #include */ import "C" import ( "bytes" "encoding/binary" "fmt" "unsafe" ) // these CPU times for darwin is borrowed from influxdb/telegraf. func perCPUTimes() ([]TimesStat, error) { var ( count C.mach_msg_type_number_t cpuload *C.processor_cpu_load_info_data_t ncpu C.natural_t ) status := C.host_processor_info(C.host_t(C.mach_host_self()), C.PROCESSOR_CPU_LOAD_INFO, &ncpu, (*C.processor_info_array_t)(unsafe.Pointer(&cpuload)), &count) if status != C.KERN_SUCCESS { return nil, fmt.Errorf("host_processor_info error=%d", status) } // jump through some cgo casting hoops and ensure we properly free // the memory that cpuload points to target := C.vm_map_t(C.mach_task_self_) address := C.vm_address_t(uintptr(unsafe.Pointer(cpuload))) defer C.vm_deallocate(target, address, C.vm_size_t(ncpu)) // the body of struct processor_cpu_load_info // aka processor_cpu_load_info_data_t var cpu_ticks [C.CPU_STATE_MAX]uint32 // copy the cpuload array to a []byte buffer // where we can binary.Read the data size := int(ncpu) * binary.Size(cpu_ticks) buf := (*[1 << 30]byte)(unsafe.Pointer(cpuload))[:size:size] bbuf := bytes.NewBuffer(buf) var ret []TimesStat for i := 0; i < int(ncpu); i++ { err := binary.Read(bbuf, binary.LittleEndian, &cpu_ticks) if err != nil { return nil, err } c := TimesStat{ CPU: fmt.Sprintf("cpu%d", i), User: float64(cpu_ticks[C.CPU_STATE_USER]) / ClocksPerSec, System: float64(cpu_ticks[C.CPU_STATE_SYSTEM]) / ClocksPerSec, Nice: float64(cpu_ticks[C.CPU_STATE_NICE]) / ClocksPerSec, Idle: float64(cpu_ticks[C.CPU_STATE_IDLE]) / ClocksPerSec, } ret = append(ret, c) } return ret, nil } func allCPUTimes() ([]TimesStat, error) { var count C.mach_msg_type_number_t var cpuload C.host_cpu_load_info_data_t count = C.HOST_CPU_LOAD_INFO_COUNT status := C.host_statistics(C.host_t(C.mach_host_self()), C.HOST_CPU_LOAD_INFO, C.host_info_t(unsafe.Pointer(&cpuload)), &count) if status != C.KERN_SUCCESS { return nil, fmt.Errorf("host_statistics error=%d", status) } c := TimesStat{ CPU: "cpu-total", User: float64(cpuload.cpu_ticks[C.CPU_STATE_USER]) / ClocksPerSec, System: float64(cpuload.cpu_ticks[C.CPU_STATE_SYSTEM]) / ClocksPerSec, Nice: float64(cpuload.cpu_ticks[C.CPU_STATE_NICE]) / ClocksPerSec, Idle: float64(cpuload.cpu_ticks[C.CPU_STATE_IDLE]) / ClocksPerSec, } return []TimesStat{c}, nil } golang-github-shirou-gopsutil-2.17.08/cpu/cpu_darwin_nocgo.go000066400000000000000000000004461315167550200242420ustar00rootroot00000000000000// +build darwin // +build !cgo package cpu import "github.com/shirou/gopsutil/internal/common" func perCPUTimes() ([]TimesStat, error) { return []TimesStat{}, common.ErrNotImplementedError } func allCPUTimes() ([]TimesStat, error) { return []TimesStat{}, common.ErrNotImplementedError } golang-github-shirou-gopsutil-2.17.08/cpu/cpu_fallback.go000066400000000000000000000005041315167550200233230ustar00rootroot00000000000000// +build !darwin,!linux,!freebsd,!openbsd,!solaris,!windows package cpu import ( "github.com/shirou/gopsutil/internal/common" ) func Times(percpu bool) ([]TimesStat, error) { return []TimesStat{}, common.ErrNotImplementedError } func Info() ([]InfoStat, error) { return []InfoStat{}, common.ErrNotImplementedError } golang-github-shirou-gopsutil-2.17.08/cpu/cpu_freebsd.go000066400000000000000000000112741315167550200232040ustar00rootroot00000000000000package cpu import ( "fmt" "os/exec" "regexp" "strconv" "strings" "github.com/shirou/gopsutil/internal/common" ) // sys/resource.h const ( CPUser = 0 CPNice = 1 CPSys = 2 CPIntr = 3 CPIdle = 4 CPUStates = 5 ) var ClocksPerSec = float64(128) var cpuMatch = regexp.MustCompile(`^CPU:`) var originMatch = regexp.MustCompile(`Origin\s*=\s*"(.+)"\s+Id\s*=\s*(.+)\s+Family\s*=\s*(.+)\s+Model\s*=\s*(.+)\s+Stepping\s*=\s*(.+)`) var featuresMatch = regexp.MustCompile(`Features=.+<(.+)>`) var featuresMatch2 = regexp.MustCompile(`Features2=[a-f\dx]+<(.+)>`) var cpuEnd = regexp.MustCompile(`^Trying to mount root`) var cpuCores = regexp.MustCompile(`FreeBSD/SMP: (\d*) package\(s\) x (\d*) core\(s\)`) 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 Times(percpu bool) ([]TimesStat, error) { var ret []TimesStat var sysctlCall string var ncpu int if percpu { sysctlCall = "kern.cp_times" ncpu, _ = Counts(true) } else { sysctlCall = "kern.cp_time" ncpu = 1 } cpuTimes, err := common.DoSysctrl(sysctlCall) if err != nil { return ret, err } for i := 0; i < ncpu; i++ { offset := CPUStates * i user, err := strconv.ParseFloat(cpuTimes[CPUser+offset], 64) if err != nil { return ret, err } nice, err := strconv.ParseFloat(cpuTimes[CPNice+offset], 64) if err != nil { return ret, err } sys, err := strconv.ParseFloat(cpuTimes[CPSys+offset], 64) if err != nil { return ret, err } idle, err := strconv.ParseFloat(cpuTimes[CPIdle+offset], 64) if err != nil { return ret, err } intr, err := strconv.ParseFloat(cpuTimes[CPIntr+offset], 64) if err != nil { return ret, err } c := TimesStat{ User: float64(user / ClocksPerSec), Nice: float64(nice / ClocksPerSec), System: float64(sys / ClocksPerSec), Idle: float64(idle / ClocksPerSec), Irq: float64(intr / ClocksPerSec), } if !percpu { c.CPU = "cpu-total" } else { c.CPU = fmt.Sprintf("cpu%d", i) } ret = append(ret, c) } return ret, nil } // Returns only one InfoStat on FreeBSD. The information regarding core // count, however is accurate and it is assumed that all InfoStat attributes // are the same across CPUs. func Info() ([]InfoStat, error) { const dmesgBoot = "/var/run/dmesg.boot" c, num, err := parseDmesgBoot(dmesgBoot) if err != nil { return nil, err } var vals []string if vals, err = common.DoSysctrl("hw.clockrate"); err != nil { return nil, err } if c.Mhz, err = strconv.ParseFloat(vals[0], 64); err != nil { return nil, fmt.Errorf("unable to parse FreeBSD CPU clock rate: %v", err) } if vals, err = common.DoSysctrl("hw.ncpu"); err != nil { return nil, err } var i64 int64 if i64, err = strconv.ParseInt(vals[0], 10, 32); err != nil { return nil, fmt.Errorf("unable to parse FreeBSD cores: %v", err) } c.Cores = int32(i64) if vals, err = common.DoSysctrl("hw.model"); err != nil { return nil, err } c.ModelName = strings.Join(vals, " ") ret := make([]InfoStat, num) for i := 0; i < num; i++ { ret[i] = c } return ret, nil } func parseDmesgBoot(fileName string) (InfoStat, int, error) { c := InfoStat{} lines, _ := common.ReadLines(fileName) cpuNum := 1 // default cpu num is 1 for _, line := range lines { if matches := cpuEnd.FindStringSubmatch(line); matches != nil { break } else if matches := originMatch.FindStringSubmatch(line); matches != nil { c.VendorID = matches[1] c.Family = matches[3] c.Model = matches[4] t, err := strconv.ParseInt(matches[5], 10, 32) if err != nil { return c, 0, fmt.Errorf("unable to parse FreeBSD CPU stepping information from %q: %v", line, err) } c.Stepping = int32(t) } else if matches := featuresMatch.FindStringSubmatch(line); matches != nil { for _, v := range strings.Split(matches[1], ",") { c.Flags = append(c.Flags, strings.ToLower(v)) } } else if matches := featuresMatch2.FindStringSubmatch(line); matches != nil { for _, v := range strings.Split(matches[1], ",") { c.Flags = append(c.Flags, strings.ToLower(v)) } } else if matches := cpuCores.FindStringSubmatch(line); matches != nil { t, err := strconv.ParseInt(matches[1], 10, 32) if err != nil { return c, 0, fmt.Errorf("unable to parse FreeBSD CPU Nums from %q: %v", line, err) } cpuNum = int(t) t2, err := strconv.ParseInt(matches[2], 10, 32) if err != nil { return c, 0, fmt.Errorf("unable to parse FreeBSD CPU cores from %q: %v", line, err) } c.Cores = int32(t2) } } return c, cpuNum, nil } golang-github-shirou-gopsutil-2.17.08/cpu/cpu_freebsd_test.go000066400000000000000000000015501315167550200242370ustar00rootroot00000000000000package 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) } } } golang-github-shirou-gopsutil-2.17.08/cpu/cpu_linux.go000066400000000000000000000144161315167550200227320ustar00rootroot00000000000000// +build linux package cpu import ( "errors" "fmt" "os/exec" "strconv" "strings" "github.com/shirou/gopsutil/internal/common" ) var cpu_tick = float64(100) 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 { cpu_tick = float64(i) } } } func Times(percpu bool) ([]TimesStat, error) { filename := common.HostProc("stat") var lines = []string{} if percpu { statlines, err := common.ReadLines(filename) if err != nil || len(statlines) < 2 { return []TimesStat{}, nil } for _, line := range statlines[1:] { if !strings.HasPrefix(line, "cpu") { break } lines = append(lines, line) } } else { lines, _ = common.ReadLinesOffsetN(filename, 0, 1) } ret := make([]TimesStat, 0, len(lines)) for _, line := range lines { ct, err := parseStatLine(line) if err != nil { continue } ret = append(ret, *ct) } return ret, nil } func sysCPUPath(cpu int32, relPath string) string { return common.HostSys(fmt.Sprintf("devices/system/cpu/cpu%d", cpu), relPath) } func finishCPUInfo(c *InfoStat) error { var lines []string var err error var value float64 if len(c.CoreID) == 0 { lines, err = common.ReadLines(sysCPUPath(c.CPU, "topology/core_id")) if err == nil { c.CoreID = lines[0] } } // override the value of c.Mhz with cpufreq/cpuinfo_max_freq regardless // of the value from /proc/cpuinfo because we want to report the maximum // clock-speed of the CPU for c.Mhz, matching the behaviour of Windows 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 { return nil } value, err = strconv.ParseFloat(lines[0], 64) if err != nil { return nil } c.Mhz = value / 1000.0 // value is in kHz if c.Mhz > 9999 { c.Mhz = c.Mhz / 1000.0 // value in Hz } return nil } // CPUInfo on linux will return 1 item per physical thread. // // CPUs have three levels of counting: sockets, cores, threads. // Cores with HyperThreading count as having 2 threads per core. // Sockets often come with many physical CPU cores. // For example a single socket board with two cores each with HT will // return 4 CPUInfoStat structs on Linux and the "Cores" field set to 1. func Info() ([]InfoStat, error) { filename := common.HostProc("cpuinfo") lines, _ := common.ReadLines(filename) var ret []InfoStat var processorName string c := InfoStat{CPU: -1, Cores: 1} for _, line := range lines { fields := strings.Split(line, ":") if len(fields) < 2 { continue } key := strings.TrimSpace(fields[0]) value := strings.TrimSpace(fields[1]) switch key { case "Processor": processorName = value case "processor": if c.CPU >= 0 { err := finishCPUInfo(&c) if err != nil { return ret, err } ret = append(ret, c) } c = InfoStat{Cores: 1, ModelName: processorName} t, err := strconv.ParseInt(value, 10, 64) if err != nil { return ret, err } c.CPU = int32(t) case "vendorId", "vendor_id": c.VendorID = value case "cpu family": c.Family = value case "model": c.Model = value case "model name", "cpu": c.ModelName = value if strings.Contains(value, "POWER8") || strings.Contains(value, "POWER7") { c.Model = strings.Split(value, " ")[0] c.Family = "POWER" c.VendorID = "IBM" } case "stepping", "revision": val := value if key == "revision" { val = strings.Split(value, ".")[0] } t, err := strconv.ParseInt(val, 10, 64) if err != nil { return ret, err } c.Stepping = int32(t) case "cpu MHz", "clock": // treat this as the fallback value, thus we ignore error if t, err := strconv.ParseFloat(strings.Replace(value, "MHz", "", 1), 64); err == nil { c.Mhz = t } case "cache size": t, err := strconv.ParseInt(strings.Replace(value, " KB", "", 1), 10, 64) if err != nil { return ret, err } c.CacheSize = int32(t) case "physical id": c.PhysicalID = value case "core id": c.CoreID = value case "flags", "Features": c.Flags = strings.FieldsFunc(value, func(r rune) bool { return r == ',' || r == ' ' }) case "microcode": c.Microcode = value } } if c.CPU >= 0 { err := finishCPUInfo(&c) if err != nil { return ret, err } ret = append(ret, c) } return ret, nil } func parseStatLine(line string) (*TimesStat, error) { fields := strings.Fields(line) if len(fields) == 0 { return nil, errors.New("stat does not contain cpu info") } if strings.HasPrefix(fields[0], "cpu") == false { // return CPUTimesStat{}, e return nil, errors.New("not contain cpu") } cpu := fields[0] if cpu == "cpu" { cpu = "cpu-total" } user, err := strconv.ParseFloat(fields[1], 64) if err != nil { return nil, err } nice, err := strconv.ParseFloat(fields[2], 64) if err != nil { return nil, err } system, err := strconv.ParseFloat(fields[3], 64) if err != nil { return nil, err } idle, err := strconv.ParseFloat(fields[4], 64) if err != nil { return nil, err } iowait, err := strconv.ParseFloat(fields[5], 64) if err != nil { return nil, err } irq, err := strconv.ParseFloat(fields[6], 64) if err != nil { return nil, err } softirq, err := strconv.ParseFloat(fields[7], 64) if err != nil { return nil, err } 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, } 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 } 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 } 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 } return ct, nil } golang-github-shirou-gopsutil-2.17.08/cpu/cpu_openbsd.go000066400000000000000000000037131315167550200232230ustar00rootroot00000000000000// +build openbsd package cpu import ( "bytes" "encoding/binary" "fmt" "os/exec" "strconv" "strings" "github.com/shirou/gopsutil/internal/common" "golang.org/x/sys/unix" ) // sys/sched.h const ( CPUser = 0 CPNice = 1 CPSys = 2 CPIntr = 3 CPIdle = 4 CPUStates = 5 ) // sys/sysctl.h const ( CTLKern = 1 // "high kernel": proc, limits KernCptime = 40 // KERN_CPTIME KernCptime2 = 71 // KERN_CPTIME2 ) 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 Times(percpu bool) ([]TimesStat, error) { var ret []TimesStat var ncpu int if percpu { ncpu, _ = Counts(true) } else { ncpu = 1 } for i := 0; i < ncpu; i++ { var cpuTimes [CPUStates]int64 var mib []int32 if percpu { mib = []int32{CTLKern, KernCptime} } else { mib = []int32{CTLKern, KernCptime2, int32(i)} } buf, _, err := common.CallSyscall(mib) if err != nil { return ret, err } br := bytes.NewReader(buf) err = binary.Read(br, binary.LittleEndian, &cpuTimes) if err != nil { return ret, err } c := TimesStat{ User: float64(cpuTimes[CPUser]) / ClocksPerSec, Nice: float64(cpuTimes[CPNice]) / ClocksPerSec, System: float64(cpuTimes[CPSys]) / ClocksPerSec, Idle: float64(cpuTimes[CPIdle]) / ClocksPerSec, Irq: float64(cpuTimes[CPIntr]) / ClocksPerSec, } if !percpu { c.CPU = "cpu-total" } else { c.CPU = fmt.Sprintf("cpu%d", i) } ret = append(ret, c) } return ret, nil } // Returns only one (minimal) CPUInfoStat on OpenBSD func Info() ([]InfoStat, error) { var ret []InfoStat c := InfoStat{} v, err := unix.Sysctl("hw.model") if err != nil { return nil, err } c.ModelName = v return append(ret, c), nil } golang-github-shirou-gopsutil-2.17.08/cpu/cpu_solaris.go000066400000000000000000000123461315167550200232470ustar00rootroot00000000000000package cpu import ( "errors" "fmt" "os/exec" "regexp" "sort" "strconv" "strings" "github.com/shirou/gopsutil/internal/common" ) 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 Times(percpu bool) ([]TimesStat, error) { return []TimesStat{}, common.ErrNotImplementedError } func Info() ([]InfoStat, error) { psrInfo, err := exec.LookPath("/usr/sbin/psrinfo") if err != nil { return nil, fmt.Errorf("cannot find psrinfo: %s", err) } psrInfoOut, err := invoke.Command(psrInfo, "-p", "-v") if err != nil { return nil, fmt.Errorf("cannot execute psrinfo: %s", err) } isaInfo, err := exec.LookPath("/usr/bin/isainfo") if err != nil { return nil, fmt.Errorf("cannot find isainfo: %s", err) } isaInfoOut, err := invoke.Command(isaInfo, "-b", "-v") if err != nil { return nil, fmt.Errorf("cannot execute isainfo: %s", err) } procs, err := parseProcessorInfo(string(psrInfoOut)) if err != nil { return nil, fmt.Errorf("error parsing psrinfo output: %s", err) } flags, err := parseISAInfo(string(isaInfoOut)) if err != nil { return nil, fmt.Errorf("error parsing isainfo output: %s", err) } result := make([]InfoStat, 0, len(flags)) for _, proc := range procs { procWithFlags := proc procWithFlags.Flags = flags result = append(result, procWithFlags) } return result, nil } var flagsMatch = regexp.MustCompile(`[\w\.]+`) func parseISAInfo(cmdOutput string) ([]string, error) { words := flagsMatch.FindAllString(cmdOutput, -1) // Sanity check the output if len(words) < 4 || words[1] != "bit" || words[3] != "applications" { return nil, errors.New("attempted to parse invalid isainfo output") } flags := make([]string, len(words)-4) for i, val := range words[4:] { flags[i] = val } sort.Strings(flags) return flags, nil } var psrInfoMatch = regexp.MustCompile(`The physical processor has (?:([\d]+) virtual processor \(([\d]+)\)|([\d]+) cores and ([\d]+) virtual processors[^\n]+)\n(?:\s+ The core has.+\n)*\s+.+ \((\w+) ([\S]+) family (.+) model (.+) step (.+) clock (.+) MHz\)\n[\s]*(.*)`) const ( psrNumCoresOffset = 1 psrNumCoresHTOffset = 3 psrNumHTOffset = 4 psrVendorIDOffset = 5 psrFamilyOffset = 7 psrModelOffset = 8 psrStepOffset = 9 psrClockOffset = 10 psrModelNameOffset = 11 ) func parseProcessorInfo(cmdOutput string) ([]InfoStat, error) { matches := psrInfoMatch.FindAllStringSubmatch(cmdOutput, -1) var infoStatCount int32 result := make([]InfoStat, 0, len(matches)) for physicalIndex, physicalCPU := range matches { var step int32 var clock float64 if physicalCPU[psrStepOffset] != "" { stepParsed, err := strconv.ParseInt(physicalCPU[psrStepOffset], 10, 32) if err != nil { return nil, fmt.Errorf("cannot parse value %q for step as 32-bit integer: %s", physicalCPU[9], err) } step = int32(stepParsed) } if physicalCPU[psrClockOffset] != "" { clockParsed, err := strconv.ParseInt(physicalCPU[psrClockOffset], 10, 64) if err != nil { return nil, fmt.Errorf("cannot parse value %q for clock as 32-bit integer: %s", physicalCPU[10], err) } clock = float64(clockParsed) } var err error var numCores int64 var numHT int64 switch { case physicalCPU[psrNumCoresOffset] != "": numCores, err = strconv.ParseInt(physicalCPU[psrNumCoresOffset], 10, 32) if err != nil { return nil, fmt.Errorf("cannot parse value %q for core count as 32-bit integer: %s", physicalCPU[1], err) } for i := 0; i < int(numCores); i++ { result = append(result, InfoStat{ CPU: infoStatCount, PhysicalID: strconv.Itoa(physicalIndex), CoreID: strconv.Itoa(i), Cores: 1, VendorID: physicalCPU[psrVendorIDOffset], ModelName: physicalCPU[psrModelNameOffset], Family: physicalCPU[psrFamilyOffset], Model: physicalCPU[psrModelOffset], Stepping: step, Mhz: clock, }) infoStatCount++ } case physicalCPU[psrNumCoresHTOffset] != "": numCores, err = strconv.ParseInt(physicalCPU[psrNumCoresHTOffset], 10, 32) if err != nil { return nil, fmt.Errorf("cannot parse value %q for core count as 32-bit integer: %s", physicalCPU[3], err) } numHT, err = strconv.ParseInt(physicalCPU[psrNumHTOffset], 10, 32) if err != nil { return nil, fmt.Errorf("cannot parse value %q for hyperthread count as 32-bit integer: %s", physicalCPU[4], err) } for i := 0; i < int(numCores); i++ { result = append(result, InfoStat{ CPU: infoStatCount, PhysicalID: strconv.Itoa(physicalIndex), CoreID: strconv.Itoa(i), Cores: int32(numHT) / int32(numCores), VendorID: physicalCPU[psrVendorIDOffset], ModelName: physicalCPU[psrModelNameOffset], Family: physicalCPU[psrFamilyOffset], Model: physicalCPU[psrModelOffset], Stepping: step, Mhz: clock, }) infoStatCount++ } default: return nil, errors.New("values for cores with and without hyperthreading are both set") } } return result, nil } golang-github-shirou-gopsutil-2.17.08/cpu/cpu_solaris_test.go000066400000000000000000000130641315167550200243040ustar00rootroot00000000000000package 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) } } } golang-github-shirou-gopsutil-2.17.08/cpu/cpu_test.go000066400000000000000000000062441315167550200225520ustar00rootroot00000000000000package 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) } golang-github-shirou-gopsutil-2.17.08/cpu/cpu_windows.go000066400000000000000000000077611315167550200232720ustar00rootroot00000000000000// +build windows package cpu import ( "fmt" "unsafe" "github.com/StackExchange/wmi" "github.com/shirou/gopsutil/internal/common" "golang.org/x/sys/windows" ) type Win32_Processor struct { LoadPercentage *uint16 Family uint16 Manufacturer string Name string NumberOfLogicalProcessors 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 } // Win32_PerfFormattedData_PerfOS_System struct to have count of processes and processor queue length type Win32_PerfFormattedData_PerfOS_System struct { Processes uint32 ProcessorQueueLength uint32 } // Times returns times stat per cpu and combined for all CPUs func Times(percpu bool) ([]TimesStat, error) { if percpu { return perCPUTimes() } var ret []TimesStat var lpIdleTime common.FILETIME var lpKernelTime common.FILETIME var lpUserTime common.FILETIME r, _, _ := common.ProcGetSystemTimes.Call( uintptr(unsafe.Pointer(&lpIdleTime)), uintptr(unsafe.Pointer(&lpKernelTime)), uintptr(unsafe.Pointer(&lpUserTime))) if r == 0 { return ret, windows.GetLastError() } LOT := float64(0.0000001) HIT := (LOT * 4294967296.0) idle := ((HIT * float64(lpIdleTime.DwHighDateTime)) + (LOT * float64(lpIdleTime.DwLowDateTime))) user := ((HIT * float64(lpUserTime.DwHighDateTime)) + (LOT * float64(lpUserTime.DwLowDateTime))) kernel := ((HIT * float64(lpKernelTime.DwHighDateTime)) + (LOT * float64(lpKernelTime.DwLowDateTime))) system := (kernel - idle) ret = append(ret, TimesStat{ CPU: "cpu-total", Idle: float64(idle), User: float64(user), System: float64(system), }) return ret, nil } func Info() ([]InfoStat, error) { var ret []InfoStat var dst []Win32_Processor q := wmi.CreateQuery(&dst, "") err := wmi.Query(q, &dst) if err != nil { return ret, err } var procID string for i, l := range dst { procID = "" if l.ProcessorID != nil { procID = *l.ProcessorID } cpu := InfoStat{ CPU: int32(i), Family: fmt.Sprintf("%d", l.Family), VendorID: l.Manufacturer, ModelName: l.Name, Cores: int32(l.NumberOfLogicalProcessors), PhysicalID: procID, Mhz: float64(l.MaxClockSpeed), Flags: []string{}, } ret = append(ret, cpu) } 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) { var ret []Win32_PerfFormattedData_Counters_ProcessorInformation q := wmi.CreateQuery(&ret, "") err := wmi.Query(q, &ret) 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) { var ret []Win32_PerfFormattedData_PerfOS_System q := wmi.CreateQuery(&ret, "") err := wmi.Query(q, &ret) return ret, err } // perCPUTimes returns times stat per cpu, per core and overall for all CPUs func perCPUTimes() ([]TimesStat, error) { var ret []TimesStat stats, err := PerfInfo() if err != nil { return nil, err } for _, v := range stats { c := TimesStat{ CPU: v.Name, User: float64(v.PercentUserTime), System: float64(v.PercentPrivilegedTime), Idle: float64(v.PercentIdleTime), Irq: float64(v.PercentInterruptTime), } ret = append(ret, c) } return ret, nil } golang-github-shirou-gopsutil-2.17.08/cpu/testdata/000077500000000000000000000000001315167550200222005ustar00rootroot00000000000000golang-github-shirou-gopsutil-2.17.08/cpu/testdata/freebsd/000077500000000000000000000000001315167550200236125ustar00rootroot00000000000000golang-github-shirou-gopsutil-2.17.08/cpu/testdata/freebsd/1cpu_2core.txt000066400000000000000000000041761315167550200263250ustar00rootroot00000000000000Copyright (c) 1992-2016 The FreeBSD Project. Copyright (c) 1979, 1980, 1983, 1986, 1988, 1989, 1991, 1992, 1993, 1994 The Regents of the University of California. All rights reserved. FreeBSD is a registered trademark of The FreeBSD Foundation. FreeBSD 11.0-RELEASE-p2 #0: Mon Oct 24 06:55:27 UTC 2016 root@amd64-builder.daemonology.net:/usr/obj/usr/src/sys/GENERIC amd64 FreeBSD clang version 3.8.0 (tags/RELEASE_380/final 262564) (based on LLVM 3.8.0) VT(vga): resolution 640x480 CPU: Intel(R) Core(TM) i3 CPU 550 @ 3.20GHz (3192.07-MHz K8-class CPU) Origin="GenuineIntel" Id=0x20655 Family=0x6 Model=0x25 Stepping=5 Features=0xbfebfbff Features2=0x9ae3bd AMD Features=0x28100800 AMD Features2=0x1 VT-x: PAT,HLT,MTF,PAUSE,EPT,UG,VPID TSC: P-state invariant, performance statistics real memory = 8589934592 (8192 MB) avail memory = 8046452736 (7673 MB) Event timer "LAPIC" quality 600 ACPI APIC Table: FreeBSD/SMP: Multiprocessor System Detected: 4 CPUs FreeBSD/SMP: 1 package(s) x 2 core(s) x 2 hardware threads random: unblocking device. ioapic0 irqs 0-23 on motherboard random: entropy device external interface kbd1 at kbdmux0 netmap: loaded module module_register_init: MOD_LOAD (vesa, 0xffffffff8101c970, 0) error 19 vtvga0: on motherboard cryptosoft0: on motherboard aesni0: No AESNI support. acpi0: on motherboard acpi0: Power Button (fixed) cpu0: on acpi0 ACPI BIOS Warning (bug): Incorrect checksum in table [SSDT] - 0x3F, should be 0x1F (20160527/tbprint-229) cpu1: on acpi0 cpu2: on acpi0 cpu3: on acpi0 attimer0: port 0x40-0x43 irq 0 on acpi0 Timecounter "i8254" frequency 1193182 Hz quality 0 Event timer "i8254" frequency 1193182 Hz quality 100 atrtc0: port 0x70-0x71 irq 8 on acpi0 Event timer "RTC" frequency 32768 Hz quality 0golang-github-shirou-gopsutil-2.17.08/cpu/testdata/freebsd/1cpu_4core.txt000066400000000000000000000035471315167550200263300ustar00rootroot00000000000000Copyright (c) 1992-2016 The FreeBSD Project. Copyright (c) 1979, 1980, 1983, 1986, 1988, 1989, 1991, 1992, 1993, 1994 The Regents of the University of California. All rights reserved. FreeBSD is a registered trademark of The FreeBSD Foundation. FreeBSD 10.3-RELEASE-p4 #0: Sat May 28 12:23:44 UTC 2016 root@amd64-builder.daemonology.net:/usr/obj/usr/src/sys/GENERIC amd64 FreeBSD clang version 3.4.1 (tags/RELEASE_34/dot1-final 208032) 20140512 CPU: Intel(R) Xeon(R) CPU E5-1620 v2 @ 3.70GHz (3700.09-MHz K8-class CPU) Origin="GenuineIntel" Id=0x306e4 Family=0x6 Model=0x3e Stepping=4 Features=0xbfebfbff Features2=0x7fbee3ff AMD Features=0x2c100800 AMD Features2=0x1 Structured Extended Features=0x281 XSAVE Features=0x1 VT-x: PAT,HLT,MTF,PAUSE,EPT,UG,VPID,VID,PostIntr TSC: P-state invariant, performance statistics real memory = 34368126976 (32776 MB) avail memory = 33228333056 (31689 MB) Event timer "LAPIC" quality 600 ACPI APIC Table: < > FreeBSD/SMP: Multiprocessor System Detected: 8 CPUs FreeBSD/SMP: 1 package(s) x 4 core(s) x 2 SMT threads cpu0 (BSP): APIC ID: 0 cpu1 (AP): APIC ID: 1 cpu2 (AP): APIC ID: 2 cpu3 (AP): APIC ID: 3 cpu4 (AP): APIC ID: 4 cpu5 (AP): APIC ID: 5 cpu6 (AP): APIC ID: 6 cpu7 (AP): APIC ID: 7 random: initialized ioapic0 irqs 0-23 on motherboard ioapic1 irqs 24-47 on motherboard kbd1 at kbdmux0 cryptosoft0: on motherboard aesni0: on motherboard acpi0: on motherboardgolang-github-shirou-gopsutil-2.17.08/cpu/testdata/freebsd/2cpu_4core.txt000066400000000000000000000035651315167550200263310ustar00rootroot00000000000000Copyright (c) 1992-2011 The FreeBSD Project. Copyright (c) 1979, 1980, 1983, 1986, 1988, 1989, 1991, 1992, 1993, 1994 The Regents of the University of California. All rights reserved. FreeBSD is a registered trademark of The FreeBSD Foundation. FreeBSD 8.2-RELEASE #1: Sat Mar 5 23:03:14 CET 2011 root@host1:/usr/obj/usr/src/sys/MYKERNEL amd64 Timecounter "i8254" frequency 1193182 Hz quality 0 CPU: Intel(R) Xeon(R) CPU E5420 @ 2.50GHz (2500.11-MHz K8-class CPU) Origin = "GenuineIntel" Id = 0x10676 Family = 6 Model = 17 Stepping = 6 Features=0xbfebfbff Features2=0xce3bd AMD Features=0x20100800 AMD Features2=0x1 TSC: P-state invariant real memory = 17179869184 (16384 MB) avail memory = 16531587072 (15765 MB) ACPI APIC Table: FreeBSD/SMP: Multiprocessor System Detected: 8 CPUs FreeBSD/SMP: 2 package(s) x 4 core(s) cpu0 (BSP): APIC ID: 0 cpu1 (AP): APIC ID: 1 cpu2 (AP): APIC ID: 2 cpu3 (AP): APIC ID: 3 cpu4 (AP): APIC ID: 4 cpu5 (AP): APIC ID: 5 cpu6 (AP): APIC ID: 6 cpu7 (AP): APIC ID: 7 ioapic0 irqs 0-23 on motherboard ioapic1 irqs 24-47 on motherboard kbd1 at kbdmux0 acpi0: on motherboard acpi0: [ITHREAD] acpi0: Power Button (fixed) unknown: I/O range not supported Timecounter "ACPI-fast" frequency 3579545 Hz quality 1000 acpi_timer0: <24-bit timer at 3.579545MHz> port 0x1008-0x100b on acpi0 cpu0: on acpi0 cpu1: on acpi0 cpu2: on acpi0 cpu3: on acpi0 cpu4: on acpi0 cpu5: on acpi0 cpu6: on acpi0 cpu7: on acpi0 pcib0: port 0xcf8-0xcff on acpi0golang-github-shirou-gopsutil-2.17.08/cpu/testdata/solaris/000077500000000000000000000000001315167550200236545ustar00rootroot00000000000000golang-github-shirou-gopsutil-2.17.08/cpu/testdata/solaris/1cpu_1core_isainfo.txt000066400000000000000000000003231315167550200300640ustar00rootroot0000000000000064-bit amd64 applications 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 fpugolang-github-shirou-gopsutil-2.17.08/cpu/testdata/solaris/1cpu_1core_psrinfo.txt000066400000000000000000000002461315167550200301200ustar00rootroot00000000000000The physical processor has 1 virtual processor (0) x86 (GenuineIntel 406E3 family 6 model 78 step 3 clock 3312 MHz) Intel(r) Core(tm) i7-6567U CPU @ 3.30GHzgolang-github-shirou-gopsutil-2.17.08/cpu/testdata/solaris/2cpu_1core_isainfo.txt000066400000000000000000000003231315167550200300650ustar00rootroot0000000000000064-bit amd64 applications 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 fpugolang-github-shirou-gopsutil-2.17.08/cpu/testdata/solaris/2cpu_1core_psrinfo.txt000066400000000000000000000005151315167550200301200ustar00rootroot00000000000000The physical processor has 1 virtual processor (0) x86 (GenuineIntel 406E3 family 6 model 78 step 3 clock 3312 MHz) Intel(r) Core(tm) i7-6567U CPU @ 3.30GHz The physical processor has 1 virtual processor (1) x86 (GenuineIntel 406E3 family 6 model 78 step 3 clock 3312 MHz) Intel(r) Core(tm) i7-6567U CPU @ 3.30GHzgolang-github-shirou-gopsutil-2.17.08/cpu/testdata/solaris/2cpu_8core_isainfo.txt000066400000000000000000000002331315167550200300740ustar00rootroot0000000000000064-bit amd64 applications vmx avx xsave pclmulqdq aes sse4.2 sse4.1 ssse3 popcnt tscp cx16 sse3 sse2 sse fxsr mmx cmov amd_sysc cx8 tsc fpugolang-github-shirou-gopsutil-2.17.08/cpu/testdata/solaris/2cpu_8core_psrinfo.txt000066400000000000000000000020601315167550200301240ustar00rootroot00000000000000The physical processor has 8 cores and 16 virtual processors (0-7 16-23) The core has 2 virtual processors (0 16) The core has 2 virtual processors (1 17) The core has 2 virtual processors (2 18) The core has 2 virtual processors (3 19) The core has 2 virtual processors (4 20) The core has 2 virtual processors (5 21) The core has 2 virtual processors (6 22) The core has 2 virtual processors (7 23) x86 (GenuineIntel 206D7 family 6 model 45 step 7 clock 2600 MHz) Intel(r) Xeon(r) CPU E5-2670 0 @ 2.60GHz The physical processor has 8 cores and 16 virtual processors (8-15 24-31) The core has 2 virtual processors (8 24) The core has 2 virtual processors (9 25) The core has 2 virtual processors (10 26) The core has 2 virtual processors (11 27) The core has 2 virtual processors (12 28) The core has 2 virtual processors (13 29) The core has 2 virtual processors (14 30) The core has 2 virtual processors (15 31) x86 (GenuineIntel 206D7 family 6 model 45 step 7 clock 2600 MHz) Intel(r) Xeon(r) CPU E5-2670 0 @ 2.60GHzgolang-github-shirou-gopsutil-2.17.08/disk/000077500000000000000000000000001315167550200205325ustar00rootroot00000000000000golang-github-shirou-gopsutil-2.17.08/disk/disk.go000066400000000000000000000032301315167550200220110ustar00rootroot00000000000000package disk import ( "encoding/json" "github.com/shirou/gopsutil/internal/common" ) var invoke common.Invoker func init() { invoke = common.Invoke{} } type UsageStat struct { Path string `json:"path"` Fstype string `json:"fstype"` Total uint64 `json:"total"` Free uint64 `json:"free"` Used uint64 `json:"used"` UsedPercent float64 `json:"usedPercent"` InodesTotal uint64 `json:"inodesTotal"` InodesUsed uint64 `json:"inodesUsed"` InodesFree uint64 `json:"inodesFree"` InodesUsedPercent float64 `json:"inodesUsedPercent"` } type PartitionStat struct { Device string `json:"device"` Mountpoint string `json:"mountpoint"` Fstype string `json:"fstype"` Opts string `json:"opts"` } type IOCountersStat struct { ReadCount uint64 `json:"readCount"` MergedReadCount uint64 `json:"mergedReadCount"` WriteCount uint64 `json:"writeCount"` MergedWriteCount uint64 `json:"mergedWriteCount"` ReadBytes uint64 `json:"readBytes"` WriteBytes uint64 `json:"writeBytes"` ReadTime uint64 `json:"readTime"` WriteTime uint64 `json:"writeTime"` IopsInProgress uint64 `json:"iopsInProgress"` IoTime uint64 `json:"ioTime"` WeightedIO uint64 `json:"weightedIO"` Name string `json:"name"` SerialNumber string `json:"serialNumber"` } func (d UsageStat) String() string { s, _ := json.Marshal(d) return string(s) } func (d PartitionStat) String() string { s, _ := json.Marshal(d) return string(s) } func (d IOCountersStat) String() string { s, _ := json.Marshal(d) return string(s) } golang-github-shirou-gopsutil-2.17.08/disk/disk_darwin.go000066400000000000000000000042051315167550200233600ustar00rootroot00000000000000// +build darwin package disk import ( "path" "unsafe" "github.com/shirou/gopsutil/internal/common" "golang.org/x/sys/unix" ) func Partitions(all bool) ([]PartitionStat, error) { var ret []PartitionStat count, err := Getfsstat(nil, MntWait) if err != nil { return ret, err } fs := make([]Statfs_t, count) _, err = Getfsstat(fs, MntWait) for _, stat := range fs { opts := "rw" if stat.Flags&MntReadOnly != 0 { opts = "ro" } if stat.Flags&MntSynchronous != 0 { opts += ",sync" } if stat.Flags&MntNoExec != 0 { opts += ",noexec" } if stat.Flags&MntNoSuid != 0 { opts += ",nosuid" } if stat.Flags&MntUnion != 0 { opts += ",union" } if stat.Flags&MntAsync != 0 { opts += ",async" } if stat.Flags&MntSuidDir != 0 { opts += ",suiddir" } if stat.Flags&MntSoftDep != 0 { opts += ",softdep" } if stat.Flags&MntNoSymFollow != 0 { opts += ",nosymfollow" } if stat.Flags&MntGEOMJournal != 0 { opts += ",gjounalc" } if stat.Flags&MntMultilabel != 0 { opts += ",multilabel" } if stat.Flags&MntACLs != 0 { opts += ",acls" } 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" } d := PartitionStat{ Device: common.IntToString(stat.Mntfromname[:]), Mountpoint: common.IntToString(stat.Mntonname[:]), Fstype: common.IntToString(stat.Fstypename[:]), Opts: opts, } if all == false { if !path.IsAbs(d.Device) || !common.PathExists(d.Device) { continue } } ret = append(ret, d) } return ret, nil } func Getfsstat(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[:]) } golang-github-shirou-gopsutil-2.17.08/disk/disk_darwin.h000066400000000000000000000125441315167550200232070ustar00rootroot00000000000000#include #include #include #include #include // The iterator of all things disk. Allocated by StartIOCounterFetch, released // by EndIOCounterFetch. static io_iterator_t diskIter; // 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; } return 1; } // 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; } golang-github-shirou-gopsutil-2.17.08/disk/disk_darwin_amd64.go000066400000000000000000000033671315167550200243630ustar00rootroot00000000000000// +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 } golang-github-shirou-gopsutil-2.17.08/disk/disk_darwin_arm64.go000066400000000000000000000033671315167550200244010ustar00rootroot00000000000000// +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 } golang-github-shirou-gopsutil-2.17.08/disk/disk_darwin_cgo.go000066400000000000000000000040611315167550200242100ustar00rootroot00000000000000// +build darwin // +build cgo package disk /* #cgo LDFLAGS: -lobjc -framework Foundation -framework IOKit #include // ### 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 "disk_darwin.h" */ import "C" import ( "errors" "strings" "unsafe" "github.com/shirou/gopsutil/internal/common" ) func IOCounters(names ...string) (map[string]IOCountersStat, error) { if C.StartIOCounterFetch() == 0 { return nil, errors.New("Unable to fetch disk list") } // 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... 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), } if len(names) > 0 && !common.StringsHas(names, d.Name) { continue } ret[d.Name] = d } return ret, nil } golang-github-shirou-gopsutil-2.17.08/disk/disk_darwin_nocgo.go000066400000000000000000000003271315167550200245460ustar00rootroot00000000000000// +build darwin // +build !cgo package disk import "github.com/shirou/gopsutil/internal/common" func IOCounters(names ...string) (map[string]IOCountersStat, error) { return nil, common.ErrNotImplementedError } golang-github-shirou-gopsutil-2.17.08/disk/disk_fallback.go000066400000000000000000000007011315167550200236300ustar00rootroot00000000000000// +build !darwin,!linux,!freebsd,!openbsd,!windows,!solaris package disk import "github.com/shirou/gopsutil/internal/common" func IOCounters(names ...string) (map[string]IOCountersStat, error) { return nil, common.ErrNotImplementedError } func Partitions(all bool) ([]PartitionStat, error) { return []PartitionStat{}, common.ErrNotImplementedError } func Usage(path string) (*UsageStat, error) { return nil, common.ErrNotImplementedError } golang-github-shirou-gopsutil-2.17.08/disk/disk_freebsd.go000066400000000000000000000077241315167550200235170ustar00rootroot00000000000000// +build freebsd package disk import ( "bytes" "encoding/binary" "path" "strconv" "unsafe" "golang.org/x/sys/unix" "github.com/shirou/gopsutil/internal/common" ) func Partitions(all bool) ([]PartitionStat, error) { var ret []PartitionStat // get length count, err := unix.Getfsstat(nil, MNT_WAIT) if err != nil { return ret, err } fs := make([]Statfs, count) _, err = Getfsstat(fs, MNT_WAIT) for _, stat := range fs { opts := "rw" if stat.Flags&MNT_RDONLY != 0 { opts = "ro" } if stat.Flags&MNT_SYNCHRONOUS != 0 { opts += ",sync" } if stat.Flags&MNT_NOEXEC != 0 { opts += ",noexec" } if stat.Flags&MNT_NOSUID != 0 { opts += ",nosuid" } if stat.Flags&MNT_UNION != 0 { opts += ",union" } if stat.Flags&MNT_ASYNC != 0 { opts += ",async" } if stat.Flags&MNT_SUIDDIR != 0 { opts += ",suiddir" } if stat.Flags&MNT_SOFTDEP != 0 { opts += ",softdep" } if stat.Flags&MNT_NOSYMFOLLOW != 0 { opts += ",nosymfollow" } if stat.Flags&MNT_GJOURNAL != 0 { opts += ",gjounalc" } if stat.Flags&MNT_MULTILABEL != 0 { opts += ",multilabel" } if stat.Flags&MNT_ACLS != 0 { opts += ",acls" } if stat.Flags&MNT_NOATIME != 0 { opts += ",noattime" } if stat.Flags&MNT_NOCLUSTERR != 0 { opts += ",nocluster" } if stat.Flags&MNT_NOCLUSTERW != 0 { opts += ",noclusterw" } if stat.Flags&MNT_NFS4ACLS != 0 { opts += ",nfs4acls" } d := PartitionStat{ Device: common.IntToString(stat.Mntfromname[:]), Mountpoint: common.IntToString(stat.Mntonname[:]), Fstype: common.IntToString(stat.Fstypename[:]), Opts: opts, } if all == false { if !path.IsAbs(d.Device) || !common.PathExists(d.Device) { continue } } ret = append(ret, d) } return ret, nil } func IOCounters(names ...string) (map[string]IOCountersStat, error) { // statinfo->devinfo->devstat // /usr/include/devinfo.h ret := make(map[string]IOCountersStat) r, err := unix.Sysctl("kern.devstat.all") if err != nil { return nil, err } buf := []byte(r) length := len(buf) count := int(uint64(length) / uint64(sizeOfDevstat)) buf = buf[8:] // devstat.all has version in the head. // parse buf to Devstat for i := 0; i < count; i++ { b := buf[i*sizeOfDevstat : i*sizeOfDevstat+sizeOfDevstat] d, err := parseDevstat(b) if err != nil { continue } un := strconv.Itoa(int(d.Unit_number)) name := common.IntToString(d.Device_name[:]) + un if len(names) > 0 && !common.StringsHas(names, name) { continue } ds := IOCountersStat{ ReadCount: d.Operations[DEVSTAT_READ], WriteCount: d.Operations[DEVSTAT_WRITE], ReadBytes: d.Bytes[DEVSTAT_READ], WriteBytes: d.Bytes[DEVSTAT_WRITE], ReadTime: uint64(d.Duration[DEVSTAT_READ].Compute() * 1000), WriteTime: uint64(d.Duration[DEVSTAT_WRITE].Compute() * 1000), IoTime: uint64(d.Busy_time.Compute() * 1000), Name: name, } ret[name] = ds } return ret, nil } func (b Bintime) Compute() float64 { BINTIME_SCALE := 5.42101086242752217003726400434970855712890625e-20 return float64(b.Sec) + float64(b.Frac)*BINTIME_SCALE } // 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) { 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) // err := binary.Read(br, binary.LittleEndian, &ds) err := common.Read(br, binary.LittleEndian, &ds) if err != nil { return ds, err } return ds, nil } func getFsType(stat unix.Statfs_t) string { return common.IntToString(stat.Fstypename[:]) } golang-github-shirou-gopsutil-2.17.08/disk/disk_freebsd_386.go000066400000000000000000000041571315167550200241140ustar00rootroot00000000000000// 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 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 ( sizeOfDevstat = 0xf0 ) type ( _C_short int16 _C_int int32 _C_long int32 _C_long_long int64 _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 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 } golang-github-shirou-gopsutil-2.17.08/disk/disk_freebsd_amd64.go000066400000000000000000000042651315167550200245070ustar00rootroot00000000000000// Created by cgo -godefs - DO NOT EDIT // cgo -godefs 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 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 ( sizeOfDevstat = 0x120 ) type ( _C_short int16 _C_int int32 _C_long int64 _C_long_long int64 _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 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 Pad_cgo_0 [4]byte Tag_types [3]uint64 Flags uint32 Device_type uint32 Priority uint32 Pad_cgo_1 [4]byte ID *byte Sequence1 uint32 Pad_cgo_2 [4]byte } type Bintime struct { Sec int64 Frac uint64 } type _Ctype_struct___0 struct { Empty uint64 } golang-github-shirou-gopsutil-2.17.08/disk/disk_linux.go000066400000000000000000000352301315167550200232350ustar00rootroot00000000000000// +build linux package disk import ( "fmt" "os/exec" "strconv" "strings" "golang.org/x/sys/unix" "github.com/shirou/gopsutil/internal/common" ) const ( SectorSize = 512 ) const ( // man statfs ADFS_SUPER_MAGIC = 0xadf5 AFFS_SUPER_MAGIC = 0xADFF BDEVFS_MAGIC = 0x62646576 BEFS_SUPER_MAGIC = 0x42465331 BFS_MAGIC = 0x1BADFACE BINFMTFS_MAGIC = 0x42494e4d BTRFS_SUPER_MAGIC = 0x9123683E CGROUP_SUPER_MAGIC = 0x27e0eb CIFS_MAGIC_NUMBER = 0xFF534D42 CODA_SUPER_MAGIC = 0x73757245 COH_SUPER_MAGIC = 0x012FF7B7 CRAMFS_MAGIC = 0x28cd3d45 DEBUGFS_MAGIC = 0x64626720 DEVFS_SUPER_MAGIC = 0x1373 DEVPTS_SUPER_MAGIC = 0x1cd1 EFIVARFS_MAGIC = 0xde5e81e4 EFS_SUPER_MAGIC = 0x00414A53 EXT_SUPER_MAGIC = 0x137D EXT2_OLD_SUPER_MAGIC = 0xEF51 EXT2_SUPER_MAGIC = 0xEF53 EXT3_SUPER_MAGIC = 0xEF53 EXT4_SUPER_MAGIC = 0xEF53 FUSE_SUPER_MAGIC = 0x65735546 FUTEXFS_SUPER_MAGIC = 0xBAD1DEA HFS_SUPER_MAGIC = 0x4244 HOSTFS_SUPER_MAGIC = 0x00c0ffee HPFS_SUPER_MAGIC = 0xF995E849 HUGETLBFS_MAGIC = 0x958458f6 ISOFS_SUPER_MAGIC = 0x9660 JFFS2_SUPER_MAGIC = 0x72b6 JFS_SUPER_MAGIC = 0x3153464a MINIX_SUPER_MAGIC = 0x137F /* orig. minix */ MINIX_SUPER_MAGIC2 = 0x138F /* 30 char minix */ MINIX2_SUPER_MAGIC = 0x2468 /* minix V2 */ MINIX2_SUPER_MAGIC2 = 0x2478 /* minix V2, 30 char names */ MINIX3_SUPER_MAGIC = 0x4d5a /* minix V3 fs, 60 char names */ MQUEUE_MAGIC = 0x19800202 MSDOS_SUPER_MAGIC = 0x4d44 NCP_SUPER_MAGIC = 0x564c NFS_SUPER_MAGIC = 0x6969 NILFS_SUPER_MAGIC = 0x3434 NTFS_SB_MAGIC = 0x5346544e OCFS2_SUPER_MAGIC = 0x7461636f OPENPROM_SUPER_MAGIC = 0x9fa1 PIPEFS_MAGIC = 0x50495045 PROC_SUPER_MAGIC = 0x9fa0 PSTOREFS_MAGIC = 0x6165676C QNX4_SUPER_MAGIC = 0x002f QNX6_SUPER_MAGIC = 0x68191122 RAMFS_MAGIC = 0x858458f6 REISERFS_SUPER_MAGIC = 0x52654973 ROMFS_MAGIC = 0x7275 SELINUX_MAGIC = 0xf97cff8c SMACK_MAGIC = 0x43415d53 SMB_SUPER_MAGIC = 0x517B SOCKFS_MAGIC = 0x534F434B SQUASHFS_MAGIC = 0x73717368 SYSFS_MAGIC = 0x62656572 SYSV2_SUPER_MAGIC = 0x012FF7B6 SYSV4_SUPER_MAGIC = 0x012FF7B5 TMPFS_MAGIC = 0x01021994 UDF_SUPER_MAGIC = 0x15013346 UFS_MAGIC = 0x00011954 USBDEVICE_SUPER_MAGIC = 0x9fa2 V9FS_MAGIC = 0x01021997 VXFS_SUPER_MAGIC = 0xa501FCF5 XENFS_SUPER_MAGIC = 0xabba1974 XENIX_SUPER_MAGIC = 0x012FF7B4 XFS_SUPER_MAGIC = 0x58465342 _XIAFS_SUPER_MAGIC = 0x012FD16D AFS_SUPER_MAGIC = 0x5346414F AUFS_SUPER_MAGIC = 0x61756673 ANON_INODE_FS_SUPER_MAGIC = 0x09041934 CEPH_SUPER_MAGIC = 0x00C36400 ECRYPTFS_SUPER_MAGIC = 0xF15F FAT_SUPER_MAGIC = 0x4006 FHGFS_SUPER_MAGIC = 0x19830326 FUSEBLK_SUPER_MAGIC = 0x65735546 FUSECTL_SUPER_MAGIC = 0x65735543 GFS_SUPER_MAGIC = 0x1161970 GPFS_SUPER_MAGIC = 0x47504653 MTD_INODE_FS_SUPER_MAGIC = 0x11307854 INOTIFYFS_SUPER_MAGIC = 0x2BAD1DEA ISOFS_R_WIN_SUPER_MAGIC = 0x4004 ISOFS_WIN_SUPER_MAGIC = 0x4000 JFFS_SUPER_MAGIC = 0x07C0 KAFS_SUPER_MAGIC = 0x6B414653 LUSTRE_SUPER_MAGIC = 0x0BD00BD0 NFSD_SUPER_MAGIC = 0x6E667364 PANFS_SUPER_MAGIC = 0xAAD7AAEA RPC_PIPEFS_SUPER_MAGIC = 0x67596969 SECURITYFS_SUPER_MAGIC = 0x73636673 UFS_BYTESWAPPED_SUPER_MAGIC = 0x54190100 VMHGFS_SUPER_MAGIC = 0xBACBACBC VZFS_SUPER_MAGIC = 0x565A4653 ZFS_SUPER_MAGIC = 0x2FC12FC1 ) // coreutils/src/stat.c var fsTypeMap = map[int64]string{ ADFS_SUPER_MAGIC: "adfs", /* 0xADF5 local */ AFFS_SUPER_MAGIC: "affs", /* 0xADFF local */ AFS_SUPER_MAGIC: "afs", /* 0x5346414F remote */ ANON_INODE_FS_SUPER_MAGIC: "anon-inode FS", /* 0x09041934 local */ AUFS_SUPER_MAGIC: "aufs", /* 0x61756673 remote */ // AUTOFS_SUPER_MAGIC: "autofs", /* 0x0187 local */ BEFS_SUPER_MAGIC: "befs", /* 0x42465331 local */ BDEVFS_MAGIC: "bdevfs", /* 0x62646576 local */ BFS_MAGIC: "bfs", /* 0x1BADFACE local */ BINFMTFS_MAGIC: "binfmt_misc", /* 0x42494E4D local */ BTRFS_SUPER_MAGIC: "btrfs", /* 0x9123683E local */ CEPH_SUPER_MAGIC: "ceph", /* 0x00C36400 remote */ CGROUP_SUPER_MAGIC: "cgroupfs", /* 0x0027E0EB local */ CIFS_MAGIC_NUMBER: "cifs", /* 0xFF534D42 remote */ CODA_SUPER_MAGIC: "coda", /* 0x73757245 remote */ COH_SUPER_MAGIC: "coh", /* 0x012FF7B7 local */ CRAMFS_MAGIC: "cramfs", /* 0x28CD3D45 local */ DEBUGFS_MAGIC: "debugfs", /* 0x64626720 local */ DEVFS_SUPER_MAGIC: "devfs", /* 0x1373 local */ DEVPTS_SUPER_MAGIC: "devpts", /* 0x1CD1 local */ ECRYPTFS_SUPER_MAGIC: "ecryptfs", /* 0xF15F local */ EFS_SUPER_MAGIC: "efs", /* 0x00414A53 local */ EXT_SUPER_MAGIC: "ext", /* 0x137D local */ EXT2_SUPER_MAGIC: "ext2/ext3", /* 0xEF53 local */ EXT2_OLD_SUPER_MAGIC: "ext2", /* 0xEF51 local */ FAT_SUPER_MAGIC: "fat", /* 0x4006 local */ FHGFS_SUPER_MAGIC: "fhgfs", /* 0x19830326 remote */ FUSEBLK_SUPER_MAGIC: "fuseblk", /* 0x65735546 remote */ FUSECTL_SUPER_MAGIC: "fusectl", /* 0x65735543 remote */ FUTEXFS_SUPER_MAGIC: "futexfs", /* 0x0BAD1DEA local */ GFS_SUPER_MAGIC: "gfs/gfs2", /* 0x1161970 remote */ GPFS_SUPER_MAGIC: "gpfs", /* 0x47504653 remote */ HFS_SUPER_MAGIC: "hfs", /* 0x4244 local */ HPFS_SUPER_MAGIC: "hpfs", /* 0xF995E849 local */ HUGETLBFS_MAGIC: "hugetlbfs", /* 0x958458F6 local */ MTD_INODE_FS_SUPER_MAGIC: "inodefs", /* 0x11307854 local */ INOTIFYFS_SUPER_MAGIC: "inotifyfs", /* 0x2BAD1DEA local */ ISOFS_SUPER_MAGIC: "isofs", /* 0x9660 local */ ISOFS_R_WIN_SUPER_MAGIC: "isofs", /* 0x4004 local */ ISOFS_WIN_SUPER_MAGIC: "isofs", /* 0x4000 local */ JFFS_SUPER_MAGIC: "jffs", /* 0x07C0 local */ JFFS2_SUPER_MAGIC: "jffs2", /* 0x72B6 local */ JFS_SUPER_MAGIC: "jfs", /* 0x3153464A local */ KAFS_SUPER_MAGIC: "k-afs", /* 0x6B414653 remote */ LUSTRE_SUPER_MAGIC: "lustre", /* 0x0BD00BD0 remote */ MINIX_SUPER_MAGIC: "minix", /* 0x137F local */ MINIX_SUPER_MAGIC2: "minix (30 char.)", /* 0x138F local */ MINIX2_SUPER_MAGIC: "minix v2", /* 0x2468 local */ MINIX2_SUPER_MAGIC2: "minix v2 (30 char.)", /* 0x2478 local */ MINIX3_SUPER_MAGIC: "minix3", /* 0x4D5A local */ MQUEUE_MAGIC: "mqueue", /* 0x19800202 local */ MSDOS_SUPER_MAGIC: "msdos", /* 0x4D44 local */ NCP_SUPER_MAGIC: "novell", /* 0x564C remote */ NFS_SUPER_MAGIC: "nfs", /* 0x6969 remote */ NFSD_SUPER_MAGIC: "nfsd", /* 0x6E667364 remote */ NILFS_SUPER_MAGIC: "nilfs", /* 0x3434 local */ NTFS_SB_MAGIC: "ntfs", /* 0x5346544E local */ OPENPROM_SUPER_MAGIC: "openprom", /* 0x9FA1 local */ OCFS2_SUPER_MAGIC: "ocfs2", /* 0x7461636f remote */ PANFS_SUPER_MAGIC: "panfs", /* 0xAAD7AAEA remote */ PIPEFS_MAGIC: "pipefs", /* 0x50495045 remote */ PROC_SUPER_MAGIC: "proc", /* 0x9FA0 local */ PSTOREFS_MAGIC: "pstorefs", /* 0x6165676C local */ QNX4_SUPER_MAGIC: "qnx4", /* 0x002F local */ QNX6_SUPER_MAGIC: "qnx6", /* 0x68191122 local */ RAMFS_MAGIC: "ramfs", /* 0x858458F6 local */ REISERFS_SUPER_MAGIC: "reiserfs", /* 0x52654973 local */ ROMFS_MAGIC: "romfs", /* 0x7275 local */ RPC_PIPEFS_SUPER_MAGIC: "rpc_pipefs", /* 0x67596969 local */ SECURITYFS_SUPER_MAGIC: "securityfs", /* 0x73636673 local */ SELINUX_MAGIC: "selinux", /* 0xF97CFF8C local */ SMB_SUPER_MAGIC: "smb", /* 0x517B remote */ SOCKFS_MAGIC: "sockfs", /* 0x534F434B local */ SQUASHFS_MAGIC: "squashfs", /* 0x73717368 local */ SYSFS_MAGIC: "sysfs", /* 0x62656572 local */ SYSV2_SUPER_MAGIC: "sysv2", /* 0x012FF7B6 local */ SYSV4_SUPER_MAGIC: "sysv4", /* 0x012FF7B5 local */ TMPFS_MAGIC: "tmpfs", /* 0x01021994 local */ UDF_SUPER_MAGIC: "udf", /* 0x15013346 local */ UFS_MAGIC: "ufs", /* 0x00011954 local */ UFS_BYTESWAPPED_SUPER_MAGIC: "ufs", /* 0x54190100 local */ USBDEVICE_SUPER_MAGIC: "usbdevfs", /* 0x9FA2 local */ V9FS_MAGIC: "v9fs", /* 0x01021997 local */ VMHGFS_SUPER_MAGIC: "vmhgfs", /* 0xBACBACBC remote */ VXFS_SUPER_MAGIC: "vxfs", /* 0xA501FCF5 local */ VZFS_SUPER_MAGIC: "vzfs", /* 0x565A4653 local */ XENFS_SUPER_MAGIC: "xenfs", /* 0xABBA1974 local */ XENIX_SUPER_MAGIC: "xenix", /* 0x012FF7B4 local */ XFS_SUPER_MAGIC: "xfs", /* 0x58465342 local */ _XIAFS_SUPER_MAGIC: "xia", /* 0x012FD16D local */ ZFS_SUPER_MAGIC: "zfs", /* 0x2FC12FC1 local */ } // Partitions returns disk partitions. If all is false, returns // physical devices only (e.g. hard disks, cd-rom drives, USB keys) // and ignore all others (e.g. memory partitions such as /dev/shm) func Partitions(all bool) ([]PartitionStat, error) { filename := common.HostProc("self/mounts") lines, err := common.ReadLines(filename) if err != nil { return nil, err } fs, err := getFileSystems() if err != nil { 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 } } ret = append(ret, d) } return ret, nil } // getFileSystems returns supported filesystems from /proc/filesystems func getFileSystems() ([]string, error) { filename := common.HostProc("filesystems") lines, err := common.ReadLines(filename) if err != nil { return nil, err } var ret []string for _, line := range lines { if !strings.HasPrefix(line, "nodev") { ret = append(ret, strings.TrimSpace(line)) continue } t := strings.Split(line, "\t") if len(t) != 2 || t[1] != "zfs" { continue } ret = append(ret, strings.TrimSpace(t[1])) } return ret, nil } func IOCounters(names ...string) (map[string]IOCountersStat, error) { filename := common.HostProc("diskstats") lines, err := common.ReadLines(filename) if err != nil { return nil, err } ret := make(map[string]IOCountersStat, 0) empty := IOCountersStat{} 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] if len(names) > 0 && !common.StringsHas(names, name) { continue } reads, err := strconv.ParseUint((fields[3]), 10, 64) if err != nil { return ret, err } mergedReads, err := strconv.ParseUint((fields[4]), 10, 64) if err != nil { return ret, err } rbytes, err := strconv.ParseUint((fields[5]), 10, 64) if err != nil { return ret, err } rtime, err := strconv.ParseUint((fields[6]), 10, 64) if err != nil { return ret, err } writes, err := strconv.ParseUint((fields[7]), 10, 64) if err != nil { return ret, err } mergedWrites, err := strconv.ParseUint((fields[8]), 10, 64) if err != nil { return ret, err } wbytes, err := strconv.ParseUint((fields[9]), 10, 64) if err != nil { return ret, err } wtime, err := strconv.ParseUint((fields[10]), 10, 64) if err != nil { return ret, err } iopsInProgress, err := strconv.ParseUint((fields[11]), 10, 64) if err != nil { return ret, err } iotime, err := strconv.ParseUint((fields[12]), 10, 64) if err != nil { return ret, err } weightedIO, err := strconv.ParseUint((fields[13]), 10, 64) if err != nil { return ret, err } d := IOCountersStat{ ReadBytes: rbytes * SectorSize, WriteBytes: wbytes * SectorSize, ReadCount: reads, WriteCount: writes, MergedReadCount: mergedReads, MergedWriteCount: mergedWrites, ReadTime: rtime, WriteTime: wtime, IopsInProgress: iopsInProgress, IoTime: iotime, WeightedIO: weightedIO, } if d == empty { continue } d.Name = name d.SerialNumber = GetDiskSerialNumber(name) ret[name] = d } 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") if err != nil { return "" } 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 } return values[1] } return "" } func getFsType(stat unix.Statfs_t) string { t := int64(stat.Type) ret, ok := fsTypeMap[t] if !ok { return "" } return ret } golang-github-shirou-gopsutil-2.17.08/disk/disk_openbsd.go000066400000000000000000000070121315167550200235250ustar00rootroot00000000000000// +build openbsd package disk import ( "bytes" "encoding/binary" "path" "unsafe" "github.com/shirou/gopsutil/internal/common" "golang.org/x/sys/unix" ) func Partitions(all bool) ([]PartitionStat, error) { var ret []PartitionStat // get length count, err := unix.Getfsstat(nil, MNT_WAIT) if err != nil { return ret, err } fs := make([]Statfs, count) _, err = Getfsstat(fs, MNT_WAIT) for _, stat := range fs { opts := "rw" if stat.F_flags&MNT_RDONLY != 0 { opts = "ro" } if stat.F_flags&MNT_SYNCHRONOUS != 0 { opts += ",sync" } if stat.F_flags&MNT_NOEXEC != 0 { opts += ",noexec" } if stat.F_flags&MNT_NOSUID != 0 { opts += ",nosuid" } if stat.F_flags&MNT_NODEV != 0 { opts += ",nodev" } if stat.F_flags&MNT_ASYNC != 0 { opts += ",async" } d := PartitionStat{ Device: common.IntToString(stat.F_mntfromname[:]), Mountpoint: common.IntToString(stat.F_mntonname[:]), Fstype: common.IntToString(stat.F_fstypename[:]), Opts: opts, } if all == false { if !path.IsAbs(d.Device) || !common.PathExists(d.Device) { continue } } ret = append(ret, d) } return ret, nil } func IOCounters(names ...string) (map[string]IOCountersStat, error) { ret := make(map[string]IOCountersStat) r, err := unix.Sysctl("hw.diskstats") if err != nil { return nil, err } buf := []byte(r) length := len(buf) count := int(uint64(length) / uint64(sizeOfDiskstats)) // parse buf to Diskstats for i := 0; i < count; i++ { b := buf[i*sizeOfDiskstats : i*sizeOfDiskstats+sizeOfDiskstats] d, err := parseDiskstats(b) if err != nil { continue } name := common.IntToString(d.Name[:]) if len(names) > 0 && !common.StringsHas(names, name) { continue } ds := IOCountersStat{ ReadCount: d.Rxfer, WriteCount: d.Wxfer, ReadBytes: d.Rbytes, WriteBytes: d.Wbytes, Name: name, } ret[name] = ds } return ret, nil } // 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) { 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) // err := binary.Read(br, binary.LittleEndian, &ds) err := common.Read(br, binary.LittleEndian, &ds) if err != nil { return ds, err } return ds, nil } func Usage(path string) (*UsageStat, error) { stat := unix.Statfs_t{} err := unix.Statfs(path, &stat) if err != nil { return nil, err } bsize := stat.F_bsize ret := &UsageStat{ Path: path, Fstype: getFsType(stat), Total: (uint64(stat.F_blocks) * uint64(bsize)), Free: (uint64(stat.F_bavail) * uint64(bsize)), InodesTotal: (uint64(stat.F_files)), InodesFree: (uint64(stat.F_ffree)), } ret.InodesUsed = (ret.InodesTotal - ret.InodesFree) ret.InodesUsedPercent = (float64(ret.InodesUsed) / float64(ret.InodesTotal)) * 100.0 ret.Used = (uint64(stat.F_blocks) - uint64(stat.F_bfree)) * uint64(bsize) ret.UsedPercent = (float64(ret.Used) / float64(ret.Total)) * 100.0 return ret, nil } func getFsType(stat unix.Statfs_t) string { return common.IntToString(stat.F_fstypename[:]) } golang-github-shirou-gopsutil-2.17.08/disk/disk_openbsd_amd64.go000066400000000000000000000031651315167550200245250ustar00rootroot00000000000000// Created by 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 Pad_cgo_0 [4]byte Rxfer uint64 Wxfer uint64 Seek uint64 Rbytes uint64 Wbytes uint64 Attachtime Timeval Timestamp Timeval Time Timeval } type Fsid struct { Val [2]int32 } type Timeval struct { Sec int64 Usec int64 } type Diskstat struct{} type Bintime struct{} golang-github-shirou-gopsutil-2.17.08/disk/disk_test.go000066400000000000000000000044541315167550200230610ustar00rootroot00000000000000package disk import ( "fmt" "runtime" "testing" ) func TestDisk_usage(t *testing.T) { path := "/" if runtime.GOOS == "windows" { path = "C:" } v, err := Usage(path) if err != nil { t.Errorf("error %v", err) } if v.Path != path { t.Errorf("error %v", err) } } func TestDisk_partitions(t *testing.T) { ret, err := Partitions(false) if err != nil || len(ret) == 0 { t.Errorf("error %v", err) } empty := PartitionStat{} if len(ret) == 0 { t.Errorf("ret is empty") } for _, disk := range ret { if disk == empty { t.Errorf("Could not get device info %v", disk) } } } func TestDisk_io_counters(t *testing.T) { ret, err := IOCounters() if err != nil { t.Errorf("error %v", err) } if len(ret) == 0 { t.Errorf("ret is empty") } empty := IOCountersStat{} for part, io := range ret { if io == empty { t.Errorf("io_counter error %v, %v", part, io) } } } func TestDiskUsageStat_String(t *testing.T) { v := UsageStat{ Path: "/", Total: 1000, Free: 2000, Used: 3000, UsedPercent: 50.1, InodesTotal: 4000, InodesUsed: 5000, InodesFree: 6000, InodesUsedPercent: 49.1, Fstype: "ext4", } e := `{"path":"/","fstype":"ext4","total":1000,"free":2000,"used":3000,"usedPercent":50.1,"inodesTotal":4000,"inodesUsed":5000,"inodesFree":6000,"inodesUsedPercent":49.1}` if e != fmt.Sprintf("%v", v) { t.Errorf("DiskUsageStat string is invalid: %v", v) } } func TestDiskPartitionStat_String(t *testing.T) { v := PartitionStat{ Device: "sd01", Mountpoint: "/", Fstype: "ext4", Opts: "ro", } e := `{"device":"sd01","mountpoint":"/","fstype":"ext4","opts":"ro"}` if e != fmt.Sprintf("%v", v) { t.Errorf("DiskUsageStat string is invalid: %v", v) } } func TestDiskIOCountersStat_String(t *testing.T) { v := IOCountersStat{ Name: "sd01", ReadCount: 100, WriteCount: 200, ReadBytes: 300, WriteBytes: 400, SerialNumber: "SERIAL", } e := `{"readCount":100,"mergedReadCount":0,"writeCount":200,"mergedWriteCount":0,"readBytes":300,"writeBytes":400,"readTime":0,"writeTime":0,"iopsInProgress":0,"ioTime":0,"weightedIO":0,"name":"sd01","serialNumber":"SERIAL"}` if e != fmt.Sprintf("%v", v) { t.Errorf("DiskUsageStat string is invalid: %v", v) } } golang-github-shirou-gopsutil-2.17.08/disk/disk_unix.go000066400000000000000000000023331315167550200230570ustar00rootroot00000000000000// +build freebsd linux darwin package disk import "golang.org/x/sys/unix" // Usage returns a file system usage. path is a filessytem 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) { stat := unix.Statfs_t{} err := unix.Statfs(path, &stat) if err != nil { return nil, err } bsize := stat.Bsize ret := &UsageStat{ Path: path, Fstype: getFsType(stat), Total: (uint64(stat.Blocks) * uint64(bsize)), Free: (uint64(stat.Bavail) * uint64(bsize)), InodesTotal: (uint64(stat.Files)), InodesFree: (uint64(stat.Ffree)), } // if could not get InodesTotal, return empty if ret.InodesTotal < ret.InodesFree { return ret, nil } ret.InodesUsed = (ret.InodesTotal - ret.InodesFree) ret.Used = (uint64(stat.Blocks) - uint64(stat.Bfree)) * uint64(bsize) if ret.InodesTotal == 0 { ret.InodesUsedPercent = 0 } else { ret.InodesUsedPercent = (float64(ret.InodesUsed) / float64(ret.InodesTotal)) * 100.0 } if ret.Total == 0 { ret.UsedPercent = 0 } else { ret.UsedPercent = (float64(ret.Used) / float64(ret.Total)) * 100.0 } return ret, nil } golang-github-shirou-gopsutil-2.17.08/disk/disk_windows.go000066400000000000000000000111261315167550200235660ustar00rootroot00000000000000// +build windows package disk import ( "bytes" "unsafe" "github.com/StackExchange/wmi" "github.com/shirou/gopsutil/internal/common" "golang.org/x/sys/windows" ) var ( procGetDiskFreeSpaceExW = common.Modkernel32.NewProc("GetDiskFreeSpaceExW") procGetLogicalDriveStringsW = common.Modkernel32.NewProc("GetLogicalDriveStringsW") procGetDriveType = common.Modkernel32.NewProc("GetDriveTypeW") provGetVolumeInformation = common.Modkernel32.NewProc("GetVolumeInformationW") ) var ( FileFileCompression = int64(16) // 0x00000010 FileReadOnlyVolume = int64(524288) // 0x00080000 ) type Win32_PerfFormattedData struct { Name string AvgDiskBytesPerRead uint64 AvgDiskBytesPerWrite uint64 AvgDiskReadQueueLength uint64 AvgDiskWriteQueueLength uint64 AvgDisksecPerRead uint64 AvgDisksecPerWrite uint64 } const WaitMSec = 500 func Usage(path string) (*UsageStat, error) { ret := &UsageStat{} lpFreeBytesAvailable := int64(0) lpTotalNumberOfBytes := int64(0) lpTotalNumberOfFreeBytes := int64(0) diskret, _, err := procGetDiskFreeSpaceExW.Call( uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(path))), uintptr(unsafe.Pointer(&lpFreeBytesAvailable)), uintptr(unsafe.Pointer(&lpTotalNumberOfBytes)), uintptr(unsafe.Pointer(&lpTotalNumberOfFreeBytes))) if diskret == 0 { return nil, err } ret = &UsageStat{ Path: path, Total: uint64(lpTotalNumberOfBytes), Free: uint64(lpTotalNumberOfFreeBytes), Used: uint64(lpTotalNumberOfBytes) - uint64(lpTotalNumberOfFreeBytes), UsedPercent: (float64(lpTotalNumberOfBytes) - float64(lpTotalNumberOfFreeBytes)) / float64(lpTotalNumberOfBytes) * 100, // InodesTotal: 0, // InodesFree: 0, // InodesUsed: 0, // InodesUsedPercent: 0, } return ret, nil } func Partitions(all bool) ([]PartitionStat, error) { var ret []PartitionStat lpBuffer := make([]byte, 254) diskret, _, err := procGetLogicalDriveStringsW.Call( uintptr(len(lpBuffer)), uintptr(unsafe.Pointer(&lpBuffer[0]))) if diskret == 0 { return ret, err } 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 { return ret, windows.GetLastError() } // 2: DRIVE_REMOVABLE 3: DRIVE_FIXED 4: DRIVE_REMOTE 5: DRIVE_CDROM if typeret == 2 || typeret == 3 || typeret == 4 || typeret == 5 { lpVolumeNameBuffer := make([]byte, 256) lpVolumeSerialNumber := int64(0) lpMaximumComponentLength := int64(0) lpFileSystemFlags := int64(0) lpFileSystemNameBuffer := make([]byte, 256) volpath, _ := windows.UTF16PtrFromString(string(v) + ":/") driveret, _, err := provGetVolumeInformation.Call( uintptr(unsafe.Pointer(volpath)), uintptr(unsafe.Pointer(&lpVolumeNameBuffer[0])), uintptr(len(lpVolumeNameBuffer)), uintptr(unsafe.Pointer(&lpVolumeSerialNumber)), uintptr(unsafe.Pointer(&lpMaximumComponentLength)), uintptr(unsafe.Pointer(&lpFileSystemFlags)), uintptr(unsafe.Pointer(&lpFileSystemNameBuffer[0])), uintptr(len(lpFileSystemNameBuffer))) if driveret == 0 { if typeret == 5 || typeret == 2 { continue //device is not ready will happen if there is no disk in the drive } return ret, err } opts := "rw" if lpFileSystemFlags&FileReadOnlyVolume != 0 { opts = "ro" } if lpFileSystemFlags&FileFileCompression != 0 { opts += ".compress" } d := PartitionStat{ Mountpoint: path, Device: path, Fstype: string(bytes.Replace(lpFileSystemNameBuffer, []byte("\x00"), []byte(""), -1)), Opts: opts, } ret = append(ret, d) } } } return ret, nil } func IOCounters(names ...string) (map[string]IOCountersStat, error) { ret := make(map[string]IOCountersStat, 0) var dst []Win32_PerfFormattedData err := wmi.Query("SELECT * FROM Win32_PerfFormattedData_PerfDisk_LogicalDisk ", &dst) if err != nil { return ret, err } for _, d := range dst { if len(d.Name) > 3 { // not get _Total or Harddrive continue } if len(names) > 0 && !common.StringsHas(names, d.Name) { continue } ret[d.Name] = IOCountersStat{ Name: d.Name, ReadCount: uint64(d.AvgDiskReadQueueLength), WriteCount: d.AvgDiskWriteQueueLength, ReadBytes: uint64(d.AvgDiskBytesPerRead), WriteBytes: uint64(d.AvgDiskBytesPerWrite), ReadTime: d.AvgDisksecPerRead, WriteTime: d.AvgDisksecPerWrite, } } return ret, nil } golang-github-shirou-gopsutil-2.17.08/disk/types_freebsd.go000066400000000000000000000046031315167550200237220ustar00rootroot00000000000000// +build ignore // Hand writing: _Ctype_struct___0 /* Input to cgo -godefs. */ package disk /* #include #include #include enum { sizeofPtr = sizeof(void*), }; // because statinfo has long double snap_time, redefine with changing long long struct statinfo2 { long cp_time[CPUSTATES]; long tk_nin; long tk_nout; struct devinfo *dinfo; long long snap_time; }; */ 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 sizeofLongDouble = C.sizeof_longlong DEVSTAT_NO_DATA = 0x00 DEVSTAT_READ = 0x01 DEVSTAT_WRITE = 0x02 DEVSTAT_FREE = 0x03 // from sys/mount.h MNT_RDONLY = 0x00000001 /* read only filesystem */ MNT_SYNCHRONOUS = 0x00000002 /* filesystem written synchronously */ MNT_NOEXEC = 0x00000004 /* can't exec from filesystem */ MNT_NOSUID = 0x00000008 /* don't honor setuid bits on fs */ MNT_UNION = 0x00000020 /* union with underlying filesystem */ MNT_ASYNC = 0x00000040 /* filesystem written asynchronously */ MNT_SUIDDIR = 0x00100000 /* special handling of SUID on dirs */ MNT_SOFTDEP = 0x00200000 /* soft updates being done */ MNT_NOSYMFOLLOW = 0x00400000 /* do not follow symlinks */ MNT_GJOURNAL = 0x02000000 /* GEOM journal support enabled */ MNT_MULTILABEL = 0x04000000 /* MAC support for individual objects */ MNT_ACLS = 0x08000000 /* ACL support enabled */ MNT_NOATIME = 0x10000000 /* disable update of file access time */ MNT_NOCLUSTERR = 0x40000000 /* disable cluster read */ MNT_NOCLUSTERW = 0x80000000 /* disable cluster write */ MNT_NFS4ACLS = 0x00000010 MNT_WAIT = 1 /* synchronously wait for I/O to complete */ MNT_NOWAIT = 2 /* start all I/O, but do not wait for it */ MNT_LAZY = 3 /* push data not written by filesystem syncer */ MNT_SUSPEND = 4 /* Suspend file system after sync */ ) const ( sizeOfDevstat = C.sizeof_struct_devstat ) // Basic types type ( _C_short C.short _C_int C.int _C_long C.long _C_long_long C.longlong _C_long_double C.longlong ) type Statfs C.struct_statfs type Fsid C.struct_fsid type Devstat C.struct_devstat type Bintime C.struct_bintime golang-github-shirou-gopsutil-2.17.08/disk/types_openbsd.go000066400000000000000000000030361315167550200237410ustar00rootroot00000000000000// +build ignore // Hand writing: _Ctype_struct___0 /* Input to cgo -godefs. */ package disk /* #include #include #include 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 sizeofLongDouble = C.sizeof_longlong DEVSTAT_NO_DATA = 0x00 DEVSTAT_READ = 0x01 DEVSTAT_WRITE = 0x02 DEVSTAT_FREE = 0x03 // from sys/mount.h MNT_RDONLY = 0x00000001 /* read only filesystem */ MNT_SYNCHRONOUS = 0x00000002 /* filesystem written synchronously */ MNT_NOEXEC = 0x00000004 /* can't exec from filesystem */ MNT_NOSUID = 0x00000008 /* don't honor setuid bits on fs */ MNT_NODEV = 0x00000010 /* don't interpret special files */ MNT_ASYNC = 0x00000040 /* filesystem written asynchronously */ MNT_WAIT = 1 /* synchronously wait for I/O to complete */ MNT_NOWAIT = 2 /* start all I/O, but do not wait for it */ MNT_LAZY = 3 /* push data not written by filesystem syncer */ ) const ( sizeOfDiskstats = C.sizeof_struct_diskstats ) // Basic types type ( _C_short C.short _C_int C.int _C_long C.long _C_long_long C.longlong _C_long_double C.longlong ) type Statfs C.struct_statfs type Diskstats C.struct_diskstats type Fsid C.fsid_t type Timeval C.struct_timeval type Diskstat C.struct_diskstat type Bintime C.struct_bintime golang-github-shirou-gopsutil-2.17.08/doc.go000066400000000000000000000000211315167550200206650ustar00rootroot00000000000000package gopsutil golang-github-shirou-gopsutil-2.17.08/docker/000077500000000000000000000000001315167550200210475ustar00rootroot00000000000000golang-github-shirou-gopsutil-2.17.08/docker/docker.go000066400000000000000000000043211315167550200226450ustar00rootroot00000000000000package docker import ( "errors" "github.com/shirou/gopsutil/internal/common" ) var ErrDockerNotAvailable = errors.New("docker not available") var ErrCgroupNotAvailable = errors.New("cgroup not available") var invoke common.Invoker func init() { invoke = common.Invoke{} } type CgroupMemStat struct { ContainerID string `json:"containerID"` Cache uint64 `json:"cache"` RSS uint64 `json:"rss"` RSSHuge uint64 `json:"rssHuge"` MappedFile uint64 `json:"mappedFile"` Pgpgin uint64 `json:"pgpgin"` Pgpgout uint64 `json:"pgpgout"` Pgfault uint64 `json:"pgfault"` Pgmajfault uint64 `json:"pgmajfault"` InactiveAnon uint64 `json:"inactiveAnon"` ActiveAnon uint64 `json:"activeAnon"` InactiveFile uint64 `json:"inactiveFile"` ActiveFile uint64 `json:"activeFile"` Unevictable uint64 `json:"unevictable"` HierarchicalMemoryLimit uint64 `json:"hierarchicalMemoryLimit"` TotalCache uint64 `json:"totalCache"` TotalRSS uint64 `json:"totalRss"` TotalRSSHuge uint64 `json:"totalRssHuge"` TotalMappedFile uint64 `json:"totalMappedFile"` TotalPgpgIn uint64 `json:"totalPgpgin"` TotalPgpgOut uint64 `json:"totalPgpgout"` TotalPgFault uint64 `json:"totalPgfault"` TotalPgMajFault uint64 `json:"totalPgmajfault"` TotalInactiveAnon uint64 `json:"totalInactiveAnon"` TotalActiveAnon uint64 `json:"totalActiveAnon"` TotalInactiveFile uint64 `json:"totalInactiveFile"` TotalActiveFile uint64 `json:"totalActiveFile"` TotalUnevictable uint64 `json:"totalUnevictable"` MemUsageInBytes uint64 `json:"memUsageInBytes"` MemMaxUsageInBytes uint64 `json:"memMaxUsageInBytes"` MemLimitInBytes uint64 `json:"memoryLimitInBbytes"` MemFailCnt uint64 `json:"memoryFailcnt"` } type CgroupDockerStat struct { ContainerID string `json:"containerID"` Name string `json:"name"` Image string `json:"image"` Status string `json:"status"` Running bool `json:"running"` } golang-github-shirou-gopsutil-2.17.08/docker/docker_linux.go000066400000000000000000000141551315167550200240720ustar00rootroot00000000000000// +build linux package docker import ( "encoding/json" "fmt" "os" "os/exec" "path" "strconv" "strings" cpu "github.com/shirou/gopsutil/cpu" "github.com/shirou/gopsutil/internal/common" ) // GetDockerStat returns a list of Docker basic stats. // This requires certain permission. func GetDockerStat() ([]CgroupDockerStat, error) { path, err := exec.LookPath("docker") if err != nil { return nil, ErrDockerNotAvailable } out, err := invoke.Command(path, "ps", "-a", "--no-trunc", "--format", "{{.ID}}|{{.Image}}|{{.Names}}|{{.Status}}") if err != nil { return []CgroupDockerStat{}, err } lines := strings.Split(string(out), "\n") ret := make([]CgroupDockerStat, 0, len(lines)) for _, l := range lines { if l == "" { continue } cols := strings.Split(l, "|") if len(cols) != 4 { continue } names := strings.Split(cols[2], ",") stat := CgroupDockerStat{ ContainerID: cols[0], Name: names[0], Image: cols[1], Status: cols[3], Running: strings.Contains(cols[3], "Up"), } ret = append(ret, stat) } return ret, nil } func (c CgroupDockerStat) String() string { s, _ := json.Marshal(c) return string(s) } // GetDockerIDList returnes a list of DockerID. // This requires certain permission. func GetDockerIDList() ([]string, error) { path, err := exec.LookPath("docker") if err != nil { return nil, ErrDockerNotAvailable } out, err := invoke.Command(path, "ps", "-q", "--no-trunc") if err != nil { return []string{}, err } lines := strings.Split(string(out), "\n") ret := make([]string, 0, len(lines)) for _, l := range lines { if l == "" { continue } ret = append(ret, l) } return ret, nil } // CgroupCPU returnes specified cgroup id CPU status. // containerID is same as docker id if you use docker. // If you use container via systemd.slice, you could use // containerID = docker-.scope and base=/sys/fs/cgroup/cpuacct/system.slice/ func CgroupCPU(containerID string, base string) (*cpu.TimesStat, error) { statfile := getCgroupFilePath(containerID, base, "cpuacct", "cpuacct.stat") lines, err := common.ReadLines(statfile) if err != nil { return nil, err } // empty containerID means all cgroup if len(containerID) == 0 { containerID = "all" } ret := &cpu.TimesStat{CPU: containerID} for _, line := range lines { fields := strings.Split(line, " ") if fields[0] == "user" { user, err := strconv.ParseFloat(fields[1], 64) if err == nil { ret.User = float64(user) } } if fields[0] == "system" { system, err := strconv.ParseFloat(fields[1], 64) if err == nil { ret.System = float64(system) } } } return ret, nil } func CgroupCPUDocker(containerid string) (*cpu.TimesStat, error) { return CgroupCPU(containerid, common.HostSys("fs/cgroup/cpuacct/docker")) } func CgroupMem(containerID string, base string) (*CgroupMemStat, error) { statfile := getCgroupFilePath(containerID, base, "memory", "memory.stat") // empty containerID means all cgroup if len(containerID) == 0 { containerID = "all" } lines, err := common.ReadLines(statfile) if err != nil { return nil, err } ret := &CgroupMemStat{ContainerID: containerID} for _, line := range lines { fields := strings.Split(line, " ") v, err := strconv.ParseUint(fields[1], 10, 64) if err != nil { continue } switch fields[0] { case "cache": ret.Cache = v case "rss": ret.RSS = v case "rssHuge": ret.RSSHuge = v case "mappedFile": ret.MappedFile = v case "pgpgin": ret.Pgpgin = v case "pgpgout": ret.Pgpgout = v case "pgfault": ret.Pgfault = v case "pgmajfault": ret.Pgmajfault = v case "inactiveAnon": ret.InactiveAnon = v case "activeAnon": ret.ActiveAnon = v case "inactiveFile": ret.InactiveFile = v case "activeFile": ret.ActiveFile = v case "unevictable": ret.Unevictable = v case "hierarchicalMemoryLimit": ret.HierarchicalMemoryLimit = v case "totalCache": ret.TotalCache = v case "totalRss": ret.TotalRSS = v case "totalRssHuge": ret.TotalRSSHuge = v case "totalMappedFile": ret.TotalMappedFile = v case "totalPgpgin": ret.TotalPgpgIn = v case "totalPgpgout": ret.TotalPgpgOut = v case "totalPgfault": ret.TotalPgFault = v case "totalPgmajfault": ret.TotalPgMajFault = v case "totalInactiveAnon": ret.TotalInactiveAnon = v case "totalActiveAnon": ret.TotalActiveAnon = v case "totalInactiveFile": ret.TotalInactiveFile = v case "totalActiveFile": ret.TotalActiveFile = v case "totalUnevictable": ret.TotalUnevictable = v } } r, err := getCgroupMemFile(containerID, base, "memory.usage_in_bytes") if err == nil { ret.MemUsageInBytes = r } r, err = getCgroupMemFile(containerID, base, "memory.max_usage_in_bytes") if err == nil { ret.MemMaxUsageInBytes = r } r, err = getCgroupMemFile(containerID, base, "memoryLimitInBbytes") if err == nil { ret.MemLimitInBytes = r } r, err = getCgroupMemFile(containerID, base, "memoryFailcnt") if err == nil { ret.MemFailCnt = r } return ret, nil } func CgroupMemDocker(containerID string) (*CgroupMemStat, error) { return CgroupMem(containerID, common.HostSys("fs/cgroup/memory/docker")) } func (m CgroupMemStat) String() string { s, _ := json.Marshal(m) return string(s) } // getCgroupFilePath constructs file path to get targetted stats file. func getCgroupFilePath(containerID, base, target, file string) string { if len(base) == 0 { base = common.HostSys(fmt.Sprintf("fs/cgroup/%s/docker", target)) } statfile := path.Join(base, containerID, file) if _, err := os.Stat(statfile); os.IsNotExist(err) { statfile = path.Join( common.HostSys(fmt.Sprintf("fs/cgroup/%s/system.slice", target)), "docker-"+containerID+".scope", file) } return statfile } // getCgroupMemFile reads a cgroup file and return the contents as uint64. func getCgroupMemFile(containerID, base, file string) (uint64, error) { statfile := getCgroupFilePath(containerID, base, "memory", file) lines, err := common.ReadLines(statfile) if err != nil { return 0, err } if len(lines) != 1 { return 0, fmt.Errorf("wrong format file: %s", statfile) } return strconv.ParseUint(lines[0], 10, 64) } golang-github-shirou-gopsutil-2.17.08/docker/docker_linux_test.go000066400000000000000000000030171315167550200251240ustar00rootroot00000000000000// +build linux package docker import "testing" func TestGetDockerIDList(t *testing.T) { // If there is not docker environment, this test always fail. // not tested here /* _, err := GetDockerIDList() if err != nil { t.Errorf("error %v", err) } */ } func TestGetDockerStat(t *testing.T) { // If there is not docker environment, this test always fail. // not tested here /* ret, err := GetDockerStat() if err != nil { t.Errorf("error %v", err) } if len(ret) == 0 { t.Errorf("ret is empty") } empty := CgroupDockerStat{} for _, v := range ret { if empty == v { t.Errorf("empty CgroupDockerStat") } if v.ContainerID == "" { t.Errorf("Could not get container id") } } */ } func TestCgroupCPU(t *testing.T) { v, _ := GetDockerIDList() for _, id := range v { v, err := CgroupCPUDocker(id) if err != nil { t.Errorf("error %v", err) } if v.CPU == "" { t.Errorf("could not get CgroupCPU %v", v) } } } func TestCgroupCPUInvalidId(t *testing.T) { _, err := CgroupCPUDocker("bad id") if err == nil { t.Error("Expected path does not exist error") } } func TestCgroupMem(t *testing.T) { v, _ := GetDockerIDList() for _, id := range v { v, err := CgroupMemDocker(id) if err != nil { t.Errorf("error %v", err) } empty := &CgroupMemStat{} if v == empty { t.Errorf("Could not CgroupMemStat %v", v) } } } func TestCgroupMemInvalidId(t *testing.T) { _, err := CgroupMemDocker("bad id") if err == nil { t.Error("Expected path does not exist error") } } golang-github-shirou-gopsutil-2.17.08/docker/docker_notlinux.go000066400000000000000000000025031315167550200246050ustar00rootroot00000000000000// +build !linux package docker import ( "encoding/json" "github.com/shirou/gopsutil/cpu" "github.com/shirou/gopsutil/internal/common" ) // GetDockerStat returns a list of Docker basic stats. // This requires certain permission. func GetDockerStat() ([]CgroupDockerStat, error) { return nil, ErrDockerNotAvailable } // GetDockerIDList returnes a list of DockerID. // This requires certain permission. func GetDockerIDList() ([]string, error) { return nil, ErrDockerNotAvailable } // CgroupCPU returnes specified cgroup id CPU status. // containerid is same as docker id if you use docker. // If you use container via systemd.slice, you could use // containerid = docker-.scope and base=/sys/fs/cgroup/cpuacct/system.slice/ func CgroupCPU(containerid string, base string) (*cpu.TimesStat, error) { return nil, ErrCgroupNotAvailable } func CgroupCPUDocker(containerid string) (*cpu.TimesStat, error) { return CgroupCPU(containerid, common.HostSys("fs/cgroup/cpuacct/docker")) } func CgroupMem(containerid string, base string) (*CgroupMemStat, error) { return nil, ErrCgroupNotAvailable } func CgroupMemDocker(containerid string) (*CgroupMemStat, error) { return CgroupMem(containerid, common.HostSys("fs/cgroup/memory/docker")) } func (m CgroupMemStat) String() string { s, _ := json.Marshal(m) return string(s) } golang-github-shirou-gopsutil-2.17.08/host/000077500000000000000000000000001315167550200205555ustar00rootroot00000000000000golang-github-shirou-gopsutil-2.17.08/host/host.go000066400000000000000000000031411315167550200220600ustar00rootroot00000000000000package 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 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) VirtualizationSystem string `json:"virtualizationSystem"` VirtualizationRole string `json:"virtualizationRole"` // guest or host HostID string `json:"hostid"` // ex: uuid } type UserStat struct { User string `json:"user"` Terminal string `json:"terminal"` Host string `json:"host"` Started int `json:"started"` } type TemperatureStat struct { SensorKey string `json:"sensorKey"` Temperature float64 `json:"sensorTemperature"` } func (h InfoStat) String() string { s, _ := json.Marshal(h) return string(s) } func (u UserStat) String() string { s, _ := json.Marshal(u) return string(s) } func (t TemperatureStat) String() string { s, _ := json.Marshal(t) return string(s) } golang-github-shirou-gopsutil-2.17.08/host/host_darwin.go000066400000000000000000000071251315167550200234320ustar00rootroot00000000000000// +build darwin package host import ( "bytes" "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" ) // from utmpx.h const USER_PROCESS = 7 func Info() (*InfoStat, error) { ret := &InfoStat{ OS: runtime.GOOS, PlatformFamily: "darwin", } hostname, err := os.Hostname() if err == nil { ret.Hostname = hostname } uname, err := exec.LookPath("uname") if err == nil { out, err := invoke.Command(uname, "-r") if err == nil { ret.KernelVersion = strings.ToLower(strings.TrimSpace(string(out))) } } platform, family, pver, err := PlatformInformation() if err == nil { ret.Platform = platform ret.PlatformFamily = family ret.PlatformVersion = pver } system, role, err := Virtualization() if err == nil { ret.VirtualizationSystem = system ret.VirtualizationRole = role } boot, err := BootTime() if err == nil { ret.BootTime = boot ret.Uptime = uptime(boot) } procs, err := process.Pids() if err == nil { ret.Procs = uint64(len(procs)) } values, err := common.DoSysctrl("kern.uuid") if err == nil && len(values) == 1 && values[0] != "" { ret.HostID = strings.ToLower(values[0]) } return ret, nil } // cachedBootTime must be accessed via atomic.Load/StoreUint64 var cachedBootTime uint64 func BootTime() (uint64, error) { t := atomic.LoadUint64(&cachedBootTime) if t != 0 { return t, nil } values, err := common.DoSysctrl("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) return t, nil } func uptime(boot uint64) uint64 { return uint64(time.Now().Unix()) - boot } func Uptime() (uint64, error) { boot, err := BootTime() if err != nil { return 0, err } return uptime(boot), nil } func Users() ([]UserStat, error) { utmpfile := "/var/run/utmpx" var ret []UserStat file, err := os.Open(utmpfile) if err != nil { return ret, err } defer file.Close() buf, err := ioutil.ReadAll(file) if err != nil { return ret, err } u := Utmpx{} entrySize := int(unsafe.Sizeof(u)) count := len(buf) / entrySize for i := 0; i < count; i++ { b := buf[i*entrySize : i*entrySize+entrySize] var u Utmpx br := bytes.NewReader(b) err := binary.Read(br, binary.LittleEndian, &u) if err != nil { continue } if u.Type != USER_PROCESS { continue } user := UserStat{ User: common.IntToString(u.User[:]), Terminal: common.IntToString(u.Line[:]), Host: common.IntToString(u.Host[:]), Started: int(u.Tv.Sec), } ret = append(ret, user) } return ret, nil } func PlatformInformation() (string, string, string, error) { platform := "" family := "" pver := "" sw_vers, err := exec.LookPath("sw_vers") if err != nil { return "", "", "", err } uname, err := exec.LookPath("uname") if err != nil { return "", "", "", err } out, err := invoke.Command(uname, "-s") if err == nil { platform = strings.ToLower(strings.TrimSpace(string(out))) } out, err = invoke.Command(sw_vers, "-productVersion") if err == nil { pver = strings.ToLower(strings.TrimSpace(string(out))) } return platform, family, pver, nil } func Virtualization() (string, string, error) { return "", "", common.ErrNotImplementedError } func KernelVersion() (string, error) { _, _, version, err := PlatformInformation() return version, err } golang-github-shirou-gopsutil-2.17.08/host/host_darwin_386.go000066400000000000000000000004761315167550200240340ustar00rootroot00000000000000// Created by cgo -godefs - DO NOT EDIT // cgo -godefs types_darwin.go package host type Utmpx struct { User [256]int8 ID [4]int8 Line [32]int8 Pid int32 Type int16 Pad_cgo_0 [6]byte Tv Timeval Host [256]int8 Pad [16]uint32 } type Timeval struct { Sec int32 } golang-github-shirou-gopsutil-2.17.08/host/host_darwin_amd64.go000066400000000000000000000004761315167550200244270ustar00rootroot00000000000000// Created by cgo -godefs - DO NOT EDIT // cgo -godefs types_darwin.go package host type Utmpx struct { User [256]int8 ID [4]int8 Line [32]int8 Pid int32 Type int16 Pad_cgo_0 [6]byte Tv Timeval Host [256]int8 Pad [16]uint32 } type Timeval struct { Sec int32 } golang-github-shirou-gopsutil-2.17.08/host/host_darwin_cgo.go000066400000000000000000000016431315167550200242610ustar00rootroot00000000000000// +build darwin // +build cgo package host // #cgo LDFLAGS: -framework IOKit // #include "include/smc.c" import "C" func SensorsTemperatures() ([]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_tmp(C.CString(key), C.CELSIUS)), }) } return temperatures, nil } golang-github-shirou-gopsutil-2.17.08/host/host_darwin_nocgo.go000066400000000000000000000003311315167550200246070ustar00rootroot00000000000000// +build darwin // +build !cgo package host import "github.com/shirou/gopsutil/internal/common" func SensorsTemperatures() ([]TemperatureStat, error) { return []TemperatureStat{}, common.ErrNotImplementedError } golang-github-shirou-gopsutil-2.17.08/host/host_fallback.go000066400000000000000000000011701315167550200236770ustar00rootroot00000000000000// +build !darwin,!linux,!freebsd,!openbsd,!solaris,!windows package host import "github.com/shirou/gopsutil/internal/common" func Info() (*InfoStat, error) { return nil, common.ErrNotImplementedError } func BootTime() (uint64, error) { return 0, common.ErrNotImplementedError } func Uptime() (uint64, error) { return 0, common.ErrNotImplementedError } func Users() ([]UserStat, error) { return []UserStat{}, common.ErrNotImplementedError } func Virtualization() (string, string, error) { return "", "", common.ErrNotImplementedError } func KernelVersion() (string, error) { return "", common.ErrNotImplementedError } golang-github-shirou-gopsutil-2.17.08/host/host_freebsd.go000066400000000000000000000106441315167550200235600ustar00rootroot00000000000000// +build freebsd package host import ( "bytes" "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" ) const ( UTNameSize = 16 /* see MAXLOGNAME in */ UTLineSize = 8 UTHostSize = 16 ) func Info() (*InfoStat, error) { ret := &InfoStat{ OS: runtime.GOOS, PlatformFamily: "freebsd", } hostname, err := os.Hostname() if err == nil { ret.Hostname = hostname } platform, family, version, err := PlatformInformation() if err == nil { ret.Platform = platform ret.PlatformFamily = family ret.PlatformVersion = version ret.KernelVersion = version } system, role, err := Virtualization() if err == nil { ret.VirtualizationSystem = system ret.VirtualizationRole = role } boot, err := BootTime() if err == nil { ret.BootTime = boot ret.Uptime = uptime(boot) } procs, err := process.Pids() if err == nil { ret.Procs = uint64(len(procs)) } values, err := common.DoSysctrl("kern.hostuuid") if err == nil && len(values) == 1 && values[0] != "" { ret.HostID = strings.ToLower(values[0]) } return ret, nil } // cachedBootTime must be accessed via atomic.Load/StoreUint64 var cachedBootTime uint64 func BootTime() (uint64, error) { t := atomic.LoadUint64(&cachedBootTime) if t != 0 { return t, nil } values, err := common.DoSysctrl("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.ParseUint(v, 10, 64) if err != nil { return 0, err } t = uint64(boottime) atomic.StoreUint64(&cachedBootTime, t) return t, nil } func uptime(boot uint64) uint64 { return uint64(time.Now().Unix()) - boot } func Uptime() (uint64, error) { boot, err := BootTime() if err != nil { return 0, err } return uptime(boot), nil } func Users() ([]UserStat, error) { utmpfile := "/var/run/utx.active" if !common.PathExists(utmpfile) { utmpfile = "/var/run/utmp" // before 9.0 return getUsersFromUtmp(utmpfile) } var ret []UserStat file, err := os.Open(utmpfile) if err != nil { return ret, err } defer file.Close() buf, err := ioutil.ReadAll(file) if err != nil { return ret, err } entrySize := sizeOfUtmpx count := len(buf) / entrySize for i := 0; i < count; i++ { b := buf[i*sizeOfUtmpx : (i+1)*sizeOfUtmpx] var u Utmpx br := bytes.NewReader(b) err := binary.Read(br, binary.LittleEndian, &u) if err != nil || u.Type != 4 { continue } sec := (binary.LittleEndian.Uint32(u.Tv.Sec[:])) / 2 // TODO: user := UserStat{ User: common.IntToString(u.User[:]), Terminal: common.IntToString(u.Line[:]), Host: common.IntToString(u.Host[:]), Started: int(sec), } ret = append(ret, user) } return ret, nil } func PlatformInformation() (string, string, string, error) { platform := "" family := "" version := "" uname, err := exec.LookPath("uname") if err != nil { return "", "", "", err } out, err := invoke.Command(uname, "-s") if err == nil { platform = strings.ToLower(strings.TrimSpace(string(out))) } out, err = invoke.Command(uname, "-r") if err == nil { version = strings.ToLower(strings.TrimSpace(string(out))) } return platform, family, version, nil } func Virtualization() (string, string, error) { return "", "", common.ErrNotImplementedError } // before 9.0 func getUsersFromUtmp(utmpfile string) ([]UserStat, error) { var ret []UserStat file, err := os.Open(utmpfile) if err != nil { return ret, err } defer file.Close() buf, err := ioutil.ReadAll(file) if err != nil { return ret, err } u := Utmp{} entrySize := int(unsafe.Sizeof(u)) count := len(buf) / entrySize for i := 0; i < count; i++ { b := buf[i*entrySize : i*entrySize+entrySize] var u Utmp br := bytes.NewReader(b) err := binary.Read(br, binary.LittleEndian, &u) if err != nil || u.Time == 0 { continue } user := UserStat{ User: common.IntToString(u.Name[:]), Terminal: common.IntToString(u.Line[:]), Host: common.IntToString(u.Host[:]), Started: int(u.Time), } ret = append(ret, user) } return ret, nil } func SensorsTemperatures() ([]TemperatureStat, error) { return []TemperatureStat{}, common.ErrNotImplementedError } func KernelVersion() (string, error) { _, _, version, err := PlatformInformation() return version, err } golang-github-shirou-gopsutil-2.17.08/host/host_freebsd_386.go000066400000000000000000000011641315167550200241550ustar00rootroot00000000000000// Created by cgo -godefs - DO NOT EDIT // cgo -godefs types_freebsd.go package host const ( sizeofPtr = 0x4 sizeofShort = 0x2 sizeofInt = 0x4 sizeofLong = 0x4 sizeofLongLong = 0x8 sizeOfUtmpx = 197 // TODO why should 197 ) type ( _C_short int16 _C_int int32 _C_long int32 _C_long_long int64 ) type Utmp struct { Line [8]int8 Name [16]int8 Host [16]int8 Time int32 } type Utmpx struct { Type int16 Tv Timeval Id [8]int8 Pid int32 User [32]int8 Line [16]int8 Host [125]int8 // X__ut_spare [64]int8 } type Timeval struct { Sec [4]byte Usec [3]byte } golang-github-shirou-gopsutil-2.17.08/host/host_freebsd_amd64.go000066400000000000000000000012241315167550200245450ustar00rootroot00000000000000// Created by cgo -godefs - DO NOT EDIT // cgo -godefs types_freebsd.go package host const ( sizeofPtr = 0x8 sizeofShort = 0x2 sizeofInt = 0x4 sizeofLong = 0x8 sizeofLongLong = 0x8 sizeOfUtmpx = 197 // TODO: why should 197, not 0x118 ) 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 int16 Tv Timeval Id [8]int8 Pid int32 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 } golang-github-shirou-gopsutil-2.17.08/host/host_freebsd_arm.go000066400000000000000000000012241315167550200244110ustar00rootroot00000000000000// Created by cgo -godefs - DO NOT EDIT // cgo -godefs types_freebsd.go package host const ( sizeofPtr = 0x4 sizeofShort = 0x2 sizeofInt = 0x4 sizeofLong = 0x8 sizeofLongLong = 0x8 sizeOfUtmpx = 197 // TODO: why should 197, not 0x118 ) type ( _C_short int16 _C_int int32 _C_long int32 _C_long_long int64 ) type Utmp struct { Line [8]int8 Name [16]int8 Host [16]int8 Time int32 } type Utmpx struct { Type int16 Tv Timeval Id [8]int8 Pid int32 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 } golang-github-shirou-gopsutil-2.17.08/host/host_linux.go000066400000000000000000000325671315167550200233150ustar00rootroot00000000000000// +build linux package host import ( "bytes" "encoding/binary" "fmt" "io/ioutil" "os" "os/exec" "path/filepath" "regexp" "runtime" "strconv" "strings" "sync/atomic" "time" "github.com/shirou/gopsutil/internal/common" ) type LSB struct { ID string Release string Codename string Description string } // from utmp.h const USER_PROCESS = 7 func Info() (*InfoStat, error) { ret := &InfoStat{ OS: runtime.GOOS, } hostname, err := os.Hostname() if err == nil { ret.Hostname = hostname } platform, family, version, err := PlatformInformation() if err == nil { ret.Platform = platform ret.PlatformFamily = family ret.PlatformVersion = version } kernelVersion, err := KernelVersion() if err == nil { ret.KernelVersion = kernelVersion } system, role, err := Virtualization() if err == nil { ret.VirtualizationSystem = system ret.VirtualizationRole = role } boot, err := BootTime() if err == nil { ret.BootTime = boot ret.Uptime = uptime(boot) } if numProcs, err := common.NumProcs(); err == nil { ret.Procs = numProcs } sysProductUUID := common.HostSys("class/dmi/id/product_uuid") switch { case common.PathExists(sysProductUUID): lines, err := common.ReadLines(sysProductUUID) if err == nil && len(lines) > 0 && lines[0] != "" { ret.HostID = strings.ToLower(lines[0]) break } fallthrough default: values, err := common.DoSysctrl("kernel.random.boot_id") if err == nil && len(values) == 1 && values[0] != "" { ret.HostID = strings.ToLower(values[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) { t := atomic.LoadUint64(&cachedBootTime) if t != 0 { return t, nil } filename := common.HostProc("stat") 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") } func uptime(boot uint64) uint64 { return uint64(time.Now().Unix()) - boot } func Uptime() (uint64, error) { boot, err := BootTime() if err != nil { return 0, err } return uptime(boot), nil } func Users() ([]UserStat, error) { utmpfile := "/var/run/utmp" file, err := os.Open(utmpfile) if err != nil { return nil, err } defer file.Close() buf, err := ioutil.ReadAll(file) if err != nil { return nil, err } count := len(buf) / sizeOfUtmp ret := make([]UserStat, 0, count) for i := 0; i < count; i++ { b := buf[i*sizeOfUtmp : (i+1)*sizeOfUtmp] var u utmp br := bytes.NewReader(b) err := binary.Read(br, binary.LittleEndian, &u) if err != nil { continue } if u.Type != USER_PROCESS { continue } user := UserStat{ User: common.IntToString(u.User[:]), Terminal: common.IntToString(u.Line[:]), Host: common.IntToString(u.Host[:]), Started: int(u.Tv.Sec), } ret = append(ret, user) } return ret, nil } 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")) { contents, err := common.ReadLines(common.HostEtc("lsb-release")) if err != nil { return ret, err // return empty } for _, line := range contents { field := strings.Split(line, "=") if len(field) < 2 { continue } switch field[0] { case "DISTRIB_ID": ret.ID = field[1] case "DISTRIB_RELEASE": ret.Release = field[1] case "DISTRIB_CODENAME": ret.Codename = field[1] case "DISTRIB_DESCRIPTION": ret.Description = field[1] } } } else if common.PathExists("/usr/bin/lsb_release") { lsb_release, err := exec.LookPath("/usr/bin/lsb_release") if err != nil { return ret, err } out, err := invoke.Command(lsb_release) if err != nil { return ret, err } for _, line := range strings.Split(string(out), "\n") { field := strings.Split(line, ":") if len(field) < 2 { continue } switch field[0] { case "Distributor ID": ret.ID = field[1] case "Release": ret.Release = field[1] case "Codename": ret.Codename = field[1] case "Description": ret.Description = field[1] } } } return ret, nil } func PlatformInformation() (platform string, family string, version string, err error) { lsb, err := getLSB() if err != nil { lsb = &LSB{} } if common.PathExists(common.HostEtc("oracle-release")) { platform = "oracle" contents, err := common.ReadLines(common.HostEtc("oracle-release")) if err == nil { version = getRedhatishVersion(contents) } } else if common.PathExists(common.HostEtc("enterprise-release")) { platform = "oracle" contents, err := common.ReadLines(common.HostEtc("enterprise-release")) if err == nil { version = getRedhatishVersion(contents) } } else if common.PathExists(common.HostEtc("debian_version")) { if lsb.ID == "Ubuntu" { platform = "ubuntu" version = lsb.Release } else if lsb.ID == "LinuxMint" { platform = "linuxmint" version = lsb.Release } else { if common.PathExists("/usr/bin/raspi-config") { platform = "raspbian" } else { platform = "debian" } contents, err := common.ReadLines(common.HostEtc("debian_version")) if err == nil { version = contents[0] } } } else if common.PathExists(common.HostEtc("redhat-release")) { contents, err := common.ReadLines(common.HostEtc("redhat-release")) if err == nil { version = getRedhatishVersion(contents) platform = getRedhatishPlatform(contents) } } else if common.PathExists(common.HostEtc("system-release")) { contents, err := common.ReadLines(common.HostEtc("system-release")) if err == nil { version = getRedhatishVersion(contents) platform = getRedhatishPlatform(contents) } } else if common.PathExists(common.HostEtc("gentoo-release")) { platform = "gentoo" contents, err := common.ReadLines(common.HostEtc("gentoo-release")) if err == nil { version = getRedhatishVersion(contents) } } else if common.PathExists(common.HostEtc("SuSE-release")) { contents, err := common.ReadLines(common.HostEtc("SuSE-release")) if err == nil { version = getSuseVersion(contents) platform = getSusePlatform(contents) } // TODO: slackware detecion } 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 } else if lsb.ID == "Amazon" { platform = "amazon" version = lsb.Release } else if lsb.ID == "ScientificSL" { platform = "scientific" version = lsb.Release } else if lsb.ID == "XenServer" { platform = "xenserver" version = lsb.Release } else if lsb.ID != "" { platform = strings.ToLower(lsb.ID) version = lsb.Release } switch platform { case "debian", "ubuntu", "linuxmint", "raspbian": family = "debian" case "fedora": family = "fedora" case "oracle", "centos", "redhat", "scientific", "enterpriseenterprise", "amazon", "xenserver", "cloudlinux", "ibm_powerkvm": family = "rhel" case "suse", "opensuse": family = "suse" case "gentoo": family = "gentoo" case "slackware": family = "slackware" case "arch": family = "arch" case "exherbo": family = "exherbo" case "alpine": family = "alpine" case "coreos": family = "coreos" } return platform, family, version, nil } func KernelVersion() (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] } } return version, nil } func getRedhatishVersion(contents []string) string { c := strings.ToLower(strings.Join(contents, "")) if strings.Contains(c, "rawhide") { return "rawhide" } if matches := regexp.MustCompile(`release (\d[\d.]*)`).FindStringSubmatch(c); matches != nil { return matches[1] } return "" } func getRedhatishPlatform(contents []string) string { c := strings.ToLower(strings.Join(contents, "")) if strings.Contains(c, "red hat") { return "redhat" } f := strings.Split(c, " ") return f[0] } func getSuseVersion(contents []string) string { version := "" for _, line := range contents { if matches := regexp.MustCompile(`VERSION = ([\d.]+)`).FindStringSubmatch(line); matches != nil { version = matches[1] } else if matches := regexp.MustCompile(`PATCHLEVEL = ([\d]+)`).FindStringSubmatch(line); matches != nil { version = version + "." + matches[1] } } return version } func getSusePlatform(contents []string) string { c := strings.ToLower(strings.Join(contents, "")) if strings.Contains(c, "opensuse") { return "opensuse" } return "suse" } func Virtualization() (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 } func SensorsTemperatures() ([]TemperatureStat, error) { var temperatures []TemperatureStat files, err := filepath.Glob(common.HostSys("/class/hwmon/hwmon*/temp*_*")) if err != nil { return temperatures, err } if len(files) == 0 { // CentOS has an intermediate /device directory: // https://github.com/giampaolo/psutil/issues/971 files, err = filepath.Glob(common.HostSys("/class/hwmon/hwmon*/temp*_*")) if err != nil { return temperatures, err } } for _, match := range files { match = strings.Split(match, "_")[0] name, err := ioutil.ReadFile(filepath.Join(filepath.Dir(match), "name")) if err != nil { return temperatures, err } current, err := ioutil.ReadFile(match + "_input") if err != nil { return temperatures, err } temperature, err := strconv.ParseFloat(string(current), 64) if err != nil { continue } temperatures = append(temperatures, TemperatureStat{ SensorKey: string(name), Temperature: temperature / 1000.0, }) } return temperatures, nil } golang-github-shirou-gopsutil-2.17.08/host/host_linux_386.go000066400000000000000000000014121315167550200236760ustar00rootroot00000000000000// ATTENTION - FILE MANUAL FIXED AFTER CGO. // Fixed line: Tv _Ctype_struct_timeval -> Tv UtTv // Created by cgo -godefs, MANUAL FIXED // 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 UtTv Addr_v6 [4]int32 X__unused [20]int8 } type exit_status struct { Termination int16 Exit int16 } type UtTv struct { Sec int32 Usec int32 } golang-github-shirou-gopsutil-2.17.08/host/host_linux_amd64.go000066400000000000000000000015241315167550200242750ustar00rootroot00000000000000// Created by cgo -godefs - DO NOT EDIT // cgo -godefs types_linux.go package host const ( sizeofPtr = 0x8 sizeofShort = 0x2 sizeofInt = 0x4 sizeofLong = 0x8 sizeofLongLong = 0x8 sizeOfUtmp = 0x180 ) type ( _C_short int16 _C_int int32 _C_long int64 _C_long_long int64 ) type utmp struct { Type int16 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 _Ctype_struct___0 Addr_v6 [4]int32 X__glibc_reserved [20]int8 } type exit_status struct { Termination int16 Exit int16 } type timeval struct { Sec int64 Usec int64 } type _Ctype_struct___0 struct { Sec int32 Usec int32 } golang-github-shirou-gopsutil-2.17.08/host/host_linux_arm.go000066400000000000000000000014461315167550200241440ustar00rootroot00000000000000// Created by cgo -godefs - DO NOT EDIT // cgo -godefs types_linux.go | sed "s/uint8/int8/g" 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__glibc_reserved [20]int8 } type exit_status struct { Termination int16 Exit int16 } type timeval struct { Sec int32 Usec int32 } golang-github-shirou-gopsutil-2.17.08/host/host_linux_arm64.go000066400000000000000000000014171315167550200243140ustar00rootroot00000000000000// Created by cgo -godefs - DO NOT EDIT // cgo -godefs types_linux.go package host const ( sizeofPtr = 0x8 sizeofShort = 0x2 sizeofInt = 0x4 sizeofLong = 0x8 sizeofLongLong = 0x8 sizeOfUtmp = 0x180 ) type ( _C_short int16 _C_int int32 _C_long int64 _C_long_long int64 ) type utmp struct { Type int16 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__glibc_reserved [20]int8 } type exit_status struct { Termination int16 Exit int16 } type timeval struct { Sec int64 Usec int64 } golang-github-shirou-gopsutil-2.17.08/host/host_linux_mips.go000066400000000000000000000012571315167550200243350ustar00rootroot00000000000000// 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 } golang-github-shirou-gopsutil-2.17.08/host/host_linux_mipsle.go000066400000000000000000000012571315167550200246560ustar00rootroot00000000000000// 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 } golang-github-shirou-gopsutil-2.17.08/host/host_linux_ppc64le.go000066400000000000000000000014611315167550200246370ustar00rootroot00000000000000// +build linux // +build ppc64le // Created by cgo -godefs - DO NOT EDIT // cgo -godefs types_linux.go package host const ( sizeofPtr = 0x8 sizeofShort = 0x2 sizeofInt = 0x4 sizeofLong = 0x8 sizeofLongLong = 0x8 sizeOfUtmp = 0x180 ) type ( _C_short int16 _C_int int32 _C_long int64 _C_long_long int64 ) type utmp struct { Type int16 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__glibc_reserved [20]int8 } type exit_status struct { Termination int16 Exit int16 } type timeval struct { Sec int64 Usec int64 } golang-github-shirou-gopsutil-2.17.08/host/host_linux_s390x.go000066400000000000000000000014571315167550200242550ustar00rootroot00000000000000// +build linux // +build s390x // Created by cgo -godefs - DO NOT EDIT // cgo -godefs types_linux.go package host const ( sizeofPtr = 0x8 sizeofShort = 0x2 sizeofInt = 0x4 sizeofLong = 0x8 sizeofLongLong = 0x8 sizeOfUtmp = 0x180 ) type ( _C_short int16 _C_int int32 _C_long int64 _C_long_long int64 ) type utmp struct { Type int16 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__glibc_reserved [20]int8 } type exit_status struct { Termination int16 Exit int16 } type timeval struct { Sec int64 Usec int64 } golang-github-shirou-gopsutil-2.17.08/host/host_linux_test.go000066400000000000000000000025471315167550200243470ustar00rootroot00000000000000// +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) } } golang-github-shirou-gopsutil-2.17.08/host/host_openbsd.go000066400000000000000000000057341315167550200236040ustar00rootroot00000000000000// +build openbsd package host import ( "bytes" "encoding/binary" "io/ioutil" "os" "os/exec" "runtime" "strconv" "strings" "time" "unsafe" "github.com/shirou/gopsutil/internal/common" "github.com/shirou/gopsutil/process" ) const ( UTNameSize = 32 /* see MAXLOGNAME in */ UTLineSize = 8 UTHostSize = 16 ) func Info() (*InfoStat, error) { ret := &InfoStat{ OS: runtime.GOOS, PlatformFamily: "openbsd", } hostname, err := os.Hostname() if err == nil { ret.Hostname = hostname } platform, family, version, err := PlatformInformation() if err == nil { ret.Platform = platform ret.PlatformFamily = family ret.PlatformVersion = version } system, role, err := Virtualization() if err == nil { ret.VirtualizationSystem = system ret.VirtualizationRole = role } procs, err := process.Pids() if err == nil { ret.Procs = uint64(len(procs)) } boot, err := BootTime() if err == nil { ret.BootTime = boot ret.Uptime = uptime(boot) } return ret, nil } func BootTime() (uint64, error) { val, err := common.DoSysctrl("kern.boottime") if err != nil { return 0, err } boottime, err := strconv.ParseUint(val[0], 10, 64) if err != nil { return 0, err } return boottime, nil } func uptime(boot uint64) uint64 { return uint64(time.Now().Unix()) - boot } func Uptime() (uint64, error) { boot, err := BootTime() if err != nil { return 0, err } return uptime(boot), nil } func PlatformInformation() (string, string, string, error) { platform := "" family := "" version := "" uname, err := exec.LookPath("uname") if err != nil { return "", "", "", err } out, err := invoke.Command(uname, "-s") if err == nil { platform = strings.ToLower(strings.TrimSpace(string(out))) } out, err = invoke.Command(uname, "-r") if err == nil { version = strings.ToLower(strings.TrimSpace(string(out))) } return platform, family, version, nil } func Virtualization() (string, string, error) { return "", "", common.ErrNotImplementedError } func Users() ([]UserStat, error) { var ret []UserStat utmpfile := "/var/run/utmp" file, err := os.Open(utmpfile) if err != nil { return ret, err } defer file.Close() buf, err := ioutil.ReadAll(file) if err != nil { return ret, err } u := Utmp{} entrySize := int(unsafe.Sizeof(u)) count := len(buf) / entrySize for i := 0; i < count; i++ { b := buf[i*entrySize : i*entrySize+entrySize] var u Utmp br := bytes.NewReader(b) err := binary.Read(br, binary.LittleEndian, &u) if err != nil || u.Time == 0 { continue } user := UserStat{ User: common.IntToString(u.Name[:]), Terminal: common.IntToString(u.Line[:]), Host: common.IntToString(u.Host[:]), Started: int(u.Time), } ret = append(ret, user) } return ret, nil } func SensorsTemperatures() ([]TemperatureStat, error) { return []TemperatureStat{}, common.ErrNotImplementedError } func KernelVersion() (string, error) { _, _, version, err := PlatformInformation() return version, err } golang-github-shirou-gopsutil-2.17.08/host/host_openbsd_amd64.go000066400000000000000000000007001315167550200245630ustar00rootroot00000000000000// Created by cgo -godefs - DO NOT EDIT // cgo -godefs types_openbsd.go package host const ( sizeofPtr = 0x8 sizeofShort = 0x2 sizeofInt = 0x4 sizeofLong = 0x8 sizeofLongLong = 0x8 sizeOfUtmp = 0x130 ) type ( _C_short int16 _C_int int32 _C_long int64 _C_long_long int64 ) type Utmp struct { Line [8]int8 Name [32]int8 Host [256]int8 Time int64 } type Timeval struct { Sec int64 Usec int64 } golang-github-shirou-gopsutil-2.17.08/host/host_solaris.go000066400000000000000000000106351315167550200236220ustar00rootroot00000000000000package host import ( "bufio" "bytes" "fmt" "io/ioutil" "os" "os/exec" "regexp" "runtime" "strconv" "strings" "time" "github.com/shirou/gopsutil/internal/common" ) func Info() (*InfoStat, error) { result := &InfoStat{ OS: runtime.GOOS, } hostname, err := os.Hostname() if err != nil { return nil, err } result.Hostname = hostname // Parse versions from output of `uname(1)` uname, err := exec.LookPath("/usr/bin/uname") if err != nil { return nil, err } out, err := invoke.Command(uname, "-srv") if err != nil { return nil, err } fields := strings.Fields(string(out)) if len(fields) >= 1 { result.PlatformFamily = fields[0] } if len(fields) >= 2 { result.KernelVersion = fields[1] } if len(fields) == 3 { result.PlatformVersion = fields[2] } // Find distribution name from /etc/release fh, err := os.Open("/etc/release") if err != nil { return nil, err } defer fh.Close() sc := bufio.NewScanner(fh) if sc.Scan() { line := strings.TrimSpace(sc.Text()) switch { case strings.HasPrefix(line, "SmartOS"): result.Platform = "SmartOS" case strings.HasPrefix(line, "OpenIndiana"): result.Platform = "OpenIndiana" case strings.HasPrefix(line, "OmniOS"): result.Platform = "OmniOS" case strings.HasPrefix(line, "Open Storage"): result.Platform = "NexentaStor" case strings.HasPrefix(line, "Solaris"): result.Platform = "Solaris" case strings.HasPrefix(line, "Oracle Solaris"): result.Platform = "Solaris" default: result.Platform = strings.Fields(line)[0] } } switch result.Platform { case "SmartOS": // If everything works, use the current zone ID as the HostID if present. zonename, err := exec.LookPath("/usr/bin/zonename") if err == nil { out, err := invoke.Command(zonename) if err == nil { sc := bufio.NewScanner(bytes.NewReader(out)) for sc.Scan() { line := sc.Text() // If we're in the global zone, rely on the hostname. if line == "global" { hostname, err := os.Hostname() if err == nil { result.HostID = hostname } } else { result.HostID = strings.TrimSpace(line) break } } } } } // If HostID is still empty, use hostid(1), which can lie to callers but at // this point there are no hardware facilities available. This behavior // matches that of other supported OSes. if result.HostID == "" { hostID, err := exec.LookPath("/usr/bin/hostid") if err == nil { out, err := invoke.Command(hostID) if err == nil { sc := bufio.NewScanner(bytes.NewReader(out)) for sc.Scan() { line := sc.Text() result.HostID = strings.TrimSpace(line) break } } } } // Find the boot time and calculate uptime relative to it bootTime, err := BootTime() if err != nil { return nil, err } result.BootTime = bootTime result.Uptime = uptimeSince(bootTime) // Count number of processes based on the number of entries in /proc dirs, err := ioutil.ReadDir("/proc") if err != nil { return nil, err } result.Procs = uint64(len(dirs)) return result, nil } var kstatMatch = regexp.MustCompile(`([^\s]+)[\s]+([^\s]*)`) func BootTime() (uint64, error) { kstat, err := exec.LookPath("/usr/bin/kstat") if err != nil { return 0, err } out, err := invoke.Command(kstat, "-p", "unix:0:system_misc:boot_time") if err != nil { return 0, err } kstats := kstatMatch.FindAllStringSubmatch(string(out), -1) if len(kstats) != 1 { return 0, fmt.Errorf("expected 1 kstat, found %d", len(kstats)) } return strconv.ParseUint(kstats[0][2], 10, 64) } func Uptime() (uint64, error) { bootTime, err := BootTime() if err != nil { return 0, err } return uptimeSince(bootTime), nil } func uptimeSince(since uint64) uint64 { return uint64(time.Now().Unix()) - since } func Users() ([]UserStat, error) { return []UserStat{}, common.ErrNotImplementedError } func SensorsTemperatures() ([]TemperatureStat, error) { return []TemperatureStat{}, common.ErrNotImplementedError } func Virtualization() (string, string, error) { return "", "", common.ErrNotImplementedError } func KernelVersion() (string, error) { // Parse versions from output of `uname(1)` uname, err := exec.LookPath("/usr/bin/uname") if err != nil { return "", err } out, err := invoke.Command(uname, "-srv") if err != nil { return "", err } fields := strings.Fields(string(out)) if len(fields) >= 2 { return fields[1], nil } return "", fmt.Errorf("could not get kernel version") } golang-github-shirou-gopsutil-2.17.08/host/host_test.go000066400000000000000000000056461315167550200231330ustar00rootroot00000000000000package host import ( "fmt" "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) { 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) { 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") } v2, err := BootTime() if v != v2 { t.Errorf("cached boot time is different") } } func TestUsers(t *testing.T) { v, err := Users() if err != nil { t.Errorf("error %v", err) } empty := UserStat{} if len(v) == 0 { t.Errorf("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) } golang-github-shirou-gopsutil-2.17.08/host/host_windows.go000066400000000000000000000075311315167550200236410ustar00rootroot00000000000000// +build windows package host import ( "fmt" "os" "runtime" "strings" "sync/atomic" "time" "unsafe" "github.com/StackExchange/wmi" "github.com/shirou/gopsutil/internal/common" process "github.com/shirou/gopsutil/process" "golang.org/x/sys/windows" ) var ( procGetSystemTimeAsFileTime = common.Modkernel32.NewProc("GetSystemTimeAsFileTime") osInfo *Win32_OperatingSystem ) type Win32_OperatingSystem struct { Version string Caption string ProductType uint32 BuildNumber string LastBootUpTime time.Time } func Info() (*InfoStat, error) { ret := &InfoStat{ OS: runtime.GOOS, } { hostname, err := os.Hostname() if err == nil { ret.Hostname = hostname } } { platform, family, version, err := PlatformInformation() if err == nil { ret.Platform = platform ret.PlatformFamily = family ret.PlatformVersion = version } else { return ret, err } } { boot, err := BootTime() if err == nil { ret.BootTime = boot ret.Uptime, _ = Uptime() } } { hostID, err := getMachineGuid() if err == nil { ret.HostID = strings.ToLower(hostID) } } { procs, err := process.Pids() if err == nil { ret.Procs = uint64(len(procs)) } } return ret, nil } func getMachineGuid() (string, error) { 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 { return "", err } defer windows.RegCloseKey(h) const windowsRegBufLen = 74 // len(`{`) + len(`abcdefgh-1234-456789012-123345456671` * 2) + len(`}`) // 2 == bytes/UTF16 const uuidLen = 36 var regBuf [windowsRegBufLen]uint16 bufLen := uint32(windowsRegBufLen) var valType uint32 err = windows.RegQueryValueEx(h, windows.StringToUTF16Ptr(`MachineGuid`), nil, &valType, (*byte)(unsafe.Pointer(®Buf[0])), &bufLen) if err != nil { return "", err } hostID := windows.UTF16ToString(regBuf[:]) hostIDLen := len(hostID) if hostIDLen != uuidLen { return "", fmt.Errorf("HostID incorrect: %q\n", hostID) } return hostID, nil } func GetOSInfo() (Win32_OperatingSystem, error) { var dst []Win32_OperatingSystem q := wmi.CreateQuery(&dst, "") err := wmi.Query(q, &dst) if err != nil { return Win32_OperatingSystem{}, err } osInfo = &dst[0] return dst[0], nil } func Uptime() (uint64, error) { if osInfo == nil { _, err := GetOSInfo() if err != nil { return 0, err } } now := time.Now() t := osInfo.LastBootUpTime.Local() return uint64(now.Sub(t).Seconds()), nil } func bootTime(up uint64) uint64 { return uint64(time.Now().Unix()) - up } // cachedBootTime must be accessed via atomic.Load/StoreUint64 var cachedBootTime uint64 func BootTime() (uint64, error) { t := atomic.LoadUint64(&cachedBootTime) if t != 0 { return t, nil } up, err := Uptime() if err != nil { return 0, err } t = bootTime(up) atomic.StoreUint64(&cachedBootTime, t) return t, nil } func PlatformInformation() (platform string, family string, version string, err error) { if osInfo == nil { _, err = GetOSInfo() if err != nil { return } } // Platform platform = strings.Trim(osInfo.Caption, " ") // PlatformFamily switch osInfo.ProductType { case 1: family = "Standalone Workstation" case 2: family = "Server (Domain Controller)" case 3: family = "Server" } // Platform Version version = fmt.Sprintf("%s Build %s", osInfo.Version, osInfo.BuildNumber) return } func Users() ([]UserStat, error) { var ret []UserStat return ret, nil } func SensorsTemperatures() ([]TemperatureStat, error) { return []TemperatureStat{}, common.ErrNotImplementedError } func Virtualization() (string, string, error) { return "", "", common.ErrNotImplementedError } func KernelVersion() (string, error) { _, _, version, err := PlatformInformation() return version, err } golang-github-shirou-gopsutil-2.17.08/host/include/000077500000000000000000000000001315167550200222005ustar00rootroot00000000000000golang-github-shirou-gopsutil-2.17.08/host/include/smc.c000066400000000000000000000416711315167550200231370ustar00rootroot00000000000000/* * Apple System Management Controller (SMC) API from user space for Intel based * Macs. Works by talking to the AppleSMC.kext (kernel extension), the driver * for the SMC. * * smc.c * libsmc * * Copyright (C) 2014 beltex * * Based off of fork from: * osx-cpu-temp * * With credits to: * * Copyright (C) 2006 devnull * Apple System Management Control (SMC) Tool * * Copyright (C) 2006 Hendrik Holtmann * smcFanControl * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include "smc.h" //------------------------------------------------------------------------------ // MARK: MACROS //------------------------------------------------------------------------------ /** Name of the SMC IOService as seen in the IORegistry. You can view it either via command line with ioreg or through the IORegistryExplorer app (found on Apple's developer site - Hardware IO Tools for Xcode) */ #define IOSERVICE_SMC "AppleSMC" /** IOService for getting machine model name */ #define IOSERVICE_MODEL "IOPlatformExpertDevice" /** SMC data types - 4 byte multi-character constants Sources: See TMP SMC keys in smc.h http://stackoverflow.com/questions/22160746/fpe2-and-sp78-data-types */ #define DATA_TYPE_UINT8 "ui8 " #define DATA_TYPE_UINT16 "ui16" #define DATA_TYPE_UINT32 "ui32" #define DATA_TYPE_FLAG "flag" #define DATA_TYPE_FPE2 "fpe2" #define DATA_TYPE_SFDS "{fds" #define DATA_TYPE_SP78 "sp78" //------------------------------------------------------------------------------ // MARK: GLOBAL VARS //------------------------------------------------------------------------------ /** Our connection to the SMC */ static io_connect_t conn; /** Number of characters in an SMC key */ static const int SMC_KEY_SIZE = 4; /** Number of characters in a data type "key" returned from the SMC. See data type macros. */ static const int DATA_TYPE_SIZE = 4; //------------------------------------------------------------------------------ // MARK: ENUMS //------------------------------------------------------------------------------ /** Defined by AppleSMC.kext. See SMCParamStruct. These are SMC specific return codes */ typedef enum { kSMCSuccess = 0, kSMCError = 1, kSMCKeyNotFound = 0x84 } kSMC_t; /** Defined by AppleSMC.kext. See SMCParamStruct. Function selectors. Used to tell the SMC which function inside it to call. */ typedef enum { kSMCUserClientOpen = 0, kSMCUserClientClose = 1, kSMCHandleYPCEvent = 2, kSMCReadKey = 5, kSMCWriteKey = 6, kSMCGetKeyCount = 7, kSMCGetKeyFromIndex = 8, kSMCGetKeyInfo = 9 } selector_t; //------------------------------------------------------------------------------ // MARK: STRUCTS //------------------------------------------------------------------------------ /** Defined by AppleSMC.kext. See SMCParamStruct. */ typedef struct { unsigned char major; unsigned char minor; unsigned char build; unsigned char reserved; unsigned short release; } SMCVersion; /** Defined by AppleSMC.kext. See SMCParamStruct. */ typedef struct { uint16_t version; uint16_t length; uint32_t cpuPLimit; uint32_t gpuPLimit; uint32_t memPLimit; } SMCPLimitData; /** Defined by AppleSMC.kext. See SMCParamStruct. - dataSize : How many values written to SMCParamStruct.bytes - dataType : Type of data written to SMCParamStruct.bytes. This lets us know how to interpret it (translate it to human readable) */ typedef struct { IOByteCount dataSize; uint32_t dataType; uint8_t dataAttributes; } SMCKeyInfoData; /** Defined by AppleSMC.kext. This is the predefined struct that must be passed to communicate with the AppleSMC driver. While the driver is closed source, the definition of this struct happened to appear in the Apple PowerManagement project at around version 211, and soon after disappeared. It can be seen in the PrivateLib.c file under pmconfigd. https://www.opensource.apple.com/source/PowerManagement/PowerManagement-211/ */ typedef struct { uint32_t key; SMCVersion vers; SMCPLimitData pLimitData; SMCKeyInfoData keyInfo; uint8_t result; uint8_t status; uint8_t data8; uint32_t data32; uint8_t bytes[32]; } SMCParamStruct; /** Used for returning data from the SMC. */ typedef struct { uint8_t data[32]; uint32_t dataType; uint32_t dataSize; kSMC_t kSMC; } smc_return_t; //------------------------------------------------------------------------------ // MARK: HELPERS - TYPE CONVERSION //------------------------------------------------------------------------------ /** Convert data from SMC of fpe2 type to human readable. :param: data Data from the SMC to be converted. Assumed data size of 2. :returns: Converted data */ static unsigned int from_fpe2(uint8_t data[32]) { unsigned int ans = 0; // Data type for fan calls - fpe2 // This is assumend to mean floating point, with 2 exponent bits // http://stackoverflow.com/questions/22160746/fpe2-and-sp78-data-types ans += data[0] << 6; ans += data[1] << 2; return ans; } /** Convert to fpe2 data type to be passed to SMC. :param: val Value to convert :param: data Pointer to data array to place result */ static void to_fpe2(unsigned int val, uint8_t *data) { data[0] = val >> 6; data[1] = (val << 2) ^ (data[0] << 8); } /** Convert SMC key to uint32_t. This must be done to pass it to the SMC. :param: key The SMC key to convert :returns: uint32_t translation. Returns zero if key is not 4 characters in length. */ static uint32_t to_uint32_t(char *key) { uint32_t ans = 0; uint32_t shift = 24; // SMC key is expected to be 4 bytes - thus 4 chars if (strlen(key) != SMC_KEY_SIZE) { return 0; } for (int i = 0; i < SMC_KEY_SIZE; i++) { ans += key[i] << shift; shift -= 8; } return ans; } /** For converting the dataType return from the SMC to human readable 4 byte multi-character constant. */ static void to_string(uint32_t val, char *dataType) { int shift = 24; for (int i = 0; i < DATA_TYPE_SIZE; i++) { // To get each char, we shift it into the lower 8 bits, and then & by // 255 to insolate it dataType[i] = (val >> shift) & 0xff; shift -= 8; } } //------------------------------------------------------------------------------ // MARK: HELPERS - TMP CONVERSION //------------------------------------------------------------------------------ /** Celsius to Fahrenheit */ static double to_fahrenheit(double tmp) { // http://en.wikipedia.org/wiki/Fahrenheit#Definition_and_conversions return (tmp * 1.8) + 32; } /** Celsius to Kelvin */ static double to_kelvin(double tmp) { // http://en.wikipedia.org/wiki/Kelvin return tmp + 273.15; } //------------------------------------------------------------------------------ // MARK: "PRIVATE" FUNCTIONS //------------------------------------------------------------------------------ /** Make a call to the SMC :param: inputStruct Struct that holds data telling the SMC what you want :param: outputStruct Struct holding the SMC's response :returns: I/O Kit return code */ static kern_return_t call_smc(SMCParamStruct *inputStruct, SMCParamStruct *outputStruct) { kern_return_t result; size_t inputStructCnt = sizeof(SMCParamStruct); size_t outputStructCnt = sizeof(SMCParamStruct); result = IOConnectCallStructMethod(conn, kSMCHandleYPCEvent, inputStruct, inputStructCnt, outputStruct, &outputStructCnt); if (result != kIOReturnSuccess) { // IOReturn error code lookup. See "Accessing Hardware From Applications // -> Handling Errors" Apple doc result = err_get_code(result); } return result; } /** Read data from the SMC :param: key The SMC key */ static kern_return_t read_smc(char *key, smc_return_t *result_smc) { kern_return_t result; SMCParamStruct inputStruct; SMCParamStruct outputStruct; memset(&inputStruct, 0, sizeof(SMCParamStruct)); memset(&outputStruct, 0, sizeof(SMCParamStruct)); memset(result_smc, 0, sizeof(smc_return_t)); // First call to AppleSMC - get key info inputStruct.key = to_uint32_t(key); inputStruct.data8 = kSMCGetKeyInfo; result = call_smc(&inputStruct, &outputStruct); result_smc->kSMC = outputStruct.result; if (result != kIOReturnSuccess || outputStruct.result != kSMCSuccess) { return result; } // Store data for return result_smc->dataSize = outputStruct.keyInfo.dataSize; result_smc->dataType = outputStruct.keyInfo.dataType; // Second call to AppleSMC - now we can get the data inputStruct.keyInfo.dataSize = outputStruct.keyInfo.dataSize; inputStruct.data8 = kSMCReadKey; result = call_smc(&inputStruct, &outputStruct); result_smc->kSMC = outputStruct.result; if (result != kIOReturnSuccess || outputStruct.result != kSMCSuccess) { return result; } memcpy(result_smc->data, outputStruct.bytes, sizeof(outputStruct.bytes)); return result; } /** Write data to the SMC. :returns: IOReturn IOKit return code */ static kern_return_t write_smc(char *key, smc_return_t *result_smc) { kern_return_t result; SMCParamStruct inputStruct; SMCParamStruct outputStruct; memset(&inputStruct, 0, sizeof(SMCParamStruct)); memset(&outputStruct, 0, sizeof(SMCParamStruct)); // First call to AppleSMC - get key info inputStruct.key = to_uint32_t(key); inputStruct.data8 = kSMCGetKeyInfo; result = call_smc(&inputStruct, &outputStruct); result_smc->kSMC = outputStruct.result; if (result != kIOReturnSuccess || outputStruct.result != kSMCSuccess) { return result; } // Check data is correct if (result_smc->dataSize != outputStruct.keyInfo.dataSize || result_smc->dataType != outputStruct.keyInfo.dataType) { return kIOReturnBadArgument; } // Second call to AppleSMC - now we can write the data inputStruct.data8 = kSMCWriteKey; inputStruct.keyInfo.dataSize = outputStruct.keyInfo.dataSize; // Set data to write memcpy(inputStruct.bytes, result_smc->data, sizeof(result_smc->data)); result = call_smc(&inputStruct, &outputStruct); result_smc->kSMC = outputStruct.result; return result; } /** Get the model name of the machine. */ static kern_return_t get_machine_model(io_name_t model) { io_service_t service; kern_return_t result; service = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching(IOSERVICE_MODEL)); if (service == 0) { printf("ERROR: %s NOT FOUND\n", IOSERVICE_MODEL); return kIOReturnError; } // Get the model name result = IORegistryEntryGetName(service, model); IOObjectRelease(service); return result; } //------------------------------------------------------------------------------ // MARK: "PUBLIC" FUNCTIONS //------------------------------------------------------------------------------ kern_return_t open_smc(void) { kern_return_t result; io_service_t service; service = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching(IOSERVICE_SMC)); if (service == 0) { // NOTE: IOServiceMatching documents 0 on failure printf("ERROR: %s NOT FOUND\n", IOSERVICE_SMC); return kIOReturnError; } result = IOServiceOpen(service, mach_task_self(), 0, &conn); IOObjectRelease(service); return result; } kern_return_t close_smc(void) { return IOServiceClose(conn); } bool is_key_valid(char *key) { bool ans = false; kern_return_t result; smc_return_t result_smc; if (strlen(key) != SMC_KEY_SIZE) { printf("ERROR: Invalid key size - must be 4 chars\n"); return ans; } // Try a read and see if it succeeds result = read_smc(key, &result_smc); if (result == kIOReturnSuccess && result_smc.kSMC == kSMCSuccess) { ans = true; } return ans; } double get_tmp(char *key, tmp_unit_t unit) { kern_return_t result; smc_return_t result_smc; result = read_smc(key, &result_smc); if (!(result == kIOReturnSuccess && result_smc.dataSize == 2 && result_smc.dataType == to_uint32_t(DATA_TYPE_SP78))) { // Error return 0.0; } // TODO: Create from_sp78() convert function double tmp = result_smc.data[0]; switch (unit) { case CELSIUS: break; case FAHRENHEIT: tmp = to_fahrenheit(tmp); break; case KELVIN: tmp = to_kelvin(tmp); break; } return tmp; } bool is_battery_powered(void) { kern_return_t result; smc_return_t result_smc; result = read_smc(BATT_PWR, &result_smc); if (!(result == kIOReturnSuccess && result_smc.dataSize == 1 && result_smc.dataType == to_uint32_t(DATA_TYPE_FLAG))) { // Error return false; } return result_smc.data[0]; } bool is_optical_disk_drive_full(void) { kern_return_t result; smc_return_t result_smc; result = read_smc(ODD_FULL, &result_smc); if (!(result == kIOReturnSuccess && result_smc.dataSize == 1 && result_smc.dataType == to_uint32_t(DATA_TYPE_FLAG))) { // Error return false; } return result_smc.data[0]; } //------------------------------------------------------------------------------ // MARK: FAN FUNCTIONS //------------------------------------------------------------------------------ bool get_fan_name(unsigned int fan_num, fan_name_t name) { char key[5]; kern_return_t result; smc_return_t result_smc; sprintf(key, "F%dID", fan_num); result = read_smc(key, &result_smc); if (!(result == kIOReturnSuccess && result_smc.dataSize == 16 && result_smc.dataType == to_uint32_t(DATA_TYPE_SFDS))) { return false; } /* We know the data size is 16 bytes and the type is "{fds", a custom struct defined by the AppleSMC.kext. See TMP enum sources for the struct. The last 12 bytes contain the name of the fan, an array of chars, hence the loop range. */ int index = 0; for (int i = 4; i < 16; i++) { // Check if at the end (name may not be full 12 bytes) // Could check for 0 (null), but instead we check for 32 (space). This // is a hack to remove whitespace. :) if (result_smc.data[i] == 32) { break; } name[index] = result_smc.data[i]; index++; } return true; } int get_num_fans(void) { kern_return_t result; smc_return_t result_smc; result = read_smc(NUM_FANS, &result_smc); if (!(result == kIOReturnSuccess && result_smc.dataSize == 1 && result_smc.dataType == to_uint32_t(DATA_TYPE_UINT8))) { // Error return -1; } return result_smc.data[0]; } unsigned int get_fan_rpm(unsigned int fan_num) { char key[5]; kern_return_t result; smc_return_t result_smc; sprintf(key, "F%dAc", fan_num); result = read_smc(key, &result_smc); if (!(result == kIOReturnSuccess && result_smc.dataSize == 2 && result_smc.dataType == to_uint32_t(DATA_TYPE_FPE2))) { // Error return 0; } return from_fpe2(result_smc.data); } bool set_fan_min_rpm(unsigned int fan_num, unsigned int rpm, bool auth) { // TODO: Add rpm val safety check char key[5]; bool ans = false; kern_return_t result; smc_return_t result_smc; memset(&result_smc, 0, sizeof(smc_return_t)); // TODO: Don't use magic number result_smc.dataSize = 2; result_smc.dataType = to_uint32_t(DATA_TYPE_FPE2); to_fpe2(rpm, result_smc.data); sprintf(key, "F%dMn", fan_num); result = write_smc(key, &result_smc); if (result == kIOReturnSuccess && result_smc.kSMC == kSMCSuccess) { ans = true; } return ans; } golang-github-shirou-gopsutil-2.17.08/host/include/smc.h000066400000000000000000000152701315167550200231400ustar00rootroot00000000000000/* * Apple System Management Controller (SMC) API from user space for Intel based * Macs. Works by talking to the AppleSMC.kext (kernel extension), the driver * for the SMC. * * smc.h * libsmc * * Copyright (C) 2014 beltex * * Based off of fork from: * osx-cpu-temp * * With credits to: * * Copyright (C) 2006 devnull * Apple System Management Control (SMC) Tool * * Copyright (C) 2006 Hendrik Holtmann * smcFanControl * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include //------------------------------------------------------------------------------ // MARK: MACROS //------------------------------------------------------------------------------ /** SMC keys for temperature sensors - 4 byte multi-character constants Not applicable to all Mac's of course. In adition, the definition of the codes may not be 100% accurate necessarily. Finally, list is incomplete. Presumed letter translations: - T = Temperature (if first char) - C = CPU - G = GPU - P = Proximity - D = Diode - H = Heatsink Sources: - https://www.apple.com/downloads/dashboard/status/istatpro.html - https://github.com/hholtmann/smcFanControl - https://github.com/jedda/OSX-Monitoring-Tools - http://www.parhelia.ch/blog/statics/k3_keys.html */ #define AMBIENT_AIR_0 "TA0P" #define AMBIENT_AIR_1 "TA1P" #define CPU_0_DIODE "TC0D" #define CPU_0_HEATSINK "TC0H" #define CPU_0_PROXIMITY "TC0P" #define ENCLOSURE_BASE_0 "TB0T" #define ENCLOSURE_BASE_1 "TB1T" #define ENCLOSURE_BASE_2 "TB2T" #define ENCLOSURE_BASE_3 "TB3T" #define GPU_0_DIODE "TG0D" #define GPU_0_HEATSINK "TG0H" #define GPU_0_PROXIMITY "TG0P" #define HARD_DRIVE_BAY "TH0P" #define MEMORY_SLOT_0 "TM0S" #define MEMORY_SLOTS_PROXIMITY "TM0P" #define NORTHBRIDGE "TN0H" #define NORTHBRIDGE_DIODE "TN0D" #define NORTHBRIDGE_PROXIMITY "TN0P" #define THUNDERBOLT_0 "TI0P" #define THUNDERBOLT_1 "TI1P" #define WIRELESS_MODULE "TW0P" /** SMC keys for fans - 4 byte multi-character constants Number of fans on Macs vary of course, thus not all keys will be applicable. Presumed letter translations: - F = Fan - Ac = Acutal - Mn = Min - Mx = Max - Sf = Safe - Tg = Target Sources: See TMP SMC keys */ #define FAN_0 "F0Ac" #define FAN_0_MIN_RPM "F0Mn" #define FAN_0_MAX_RPM "F0Mx" #define FAN_0_SAFE_RPM "F0Sf" #define FAN_0_TARGET_RPM "F0Tg" #define FAN_1 "F1Ac" #define FAN_1_MIN_RPM "F1Mn" #define FAN_1_MAX_RPM "F1Mx" #define FAN_1_SAFE_RPM "F1Sf" #define FAN_1_TARGET_RPM "F1Tg" #define FAN_2 "F2Ac" #define FAN_2_MIN_RPM "F2Mn" #define FAN_2_MAX_RPM "F2Mx" #define FAN_2_SAFE_RPM "F2Sf" #define FAN_2_TARGET_RPM "F2Tg" #define NUM_FANS "FNum" #define FORCE_BITS "FS! " /** Misc SMC keys - 4 byte multi-character constants Sources: See TMP SMC keys */ #define BATT_PWR "BATP" #define NUM_KEYS "#KEY" #define ODD_FULL "MSDI" //------------------------------------------------------------------------------ // MARK: TYPES //------------------------------------------------------------------------------ typedef char fan_name_t[13]; //------------------------------------------------------------------------------ // MARK: ENUMS //------------------------------------------------------------------------------ typedef enum { CELSIUS, FAHRENHEIT, KELVIN } tmp_unit_t; //------------------------------------------------------------------------------ // MARK: PROTOTYPES //------------------------------------------------------------------------------ /** Open a connection to the SMC :returns: kIOReturnSuccess on successful connection to the SMC. */ kern_return_t open_smc(void); /** Close connection to the SMC :returns: kIOReturnSuccess on successful close of connection to the SMC. */ kern_return_t close_smc(void); /** Check if an SMC key is valid. Useful for determining if a certain machine has particular sensor or fan for example. :param: key The SMC key to check. 4 byte multi-character constant. Must be 4 characters in length. :returns: True if the key is found, false otherwise */ bool is_key_valid(char *key); /** Get the current temperature from a sensor :param: key The temperature sensor to read from :param: unit The unit for the temperature value. :returns: Temperature of sensor. If the sensor is not found, or an error occurs, return will be zero */ double get_tmp(char *key, tmp_unit_t unit); /** Is the machine being powered by the battery? :returns: True if it is, false otherwise */ bool is_battery_powered(void); /** Is there a CD in the optical disk drive (ODD)? :returns: True if there is, false otherwise */ bool is_optical_disk_drive_full(void); /** Get the name of a fan. :param: fanNum The number of the fan to check :param: name The name of the fan. Return will be empty on error. :returns: True if successful, false otherwise. */ bool get_fan_name(unsigned int fan_num, fan_name_t name); /** Get the number of fans on this machine. :returns: The number of fans. If an error occurs, return will be -1. */ int get_num_fans(void); /** Get the current speed (RPM - revolutions per minute) of a fan. :param: fan_num The number of the fan to check :returns: The fan RPM. If the fan is not found, or an error occurs, return will be zero */ UInt get_fan_rpm(UInt fan_num); /** Set the minimum speed (RPM - revolutions per minute) of a fan. This method requires root privileges. By minimum we mean that OS X can interject and raise the fan speed if needed, however it will not go below this. WARNING: You are playing with hardware here, BE CAREFUL. :param: fan_num The number of the fan to set :param: rpm The speed you would like to set the fan to. :param: auth Should the function do authentication? :return: True if successful, false otherwise */ bool set_fan_min_rpm(unsigned int fan_num, unsigned int rpm, bool auth); golang-github-shirou-gopsutil-2.17.08/host/types_darwin.go000066400000000000000000000003231315167550200236120ustar00rootroot00000000000000// +build ignore // plus hand editing about timeval /* Input to cgo -godefs. */ package host /* #include #include */ import "C" type Utmpx C.struct_utmpx type Timeval C.struct_timeval golang-github-shirou-gopsutil-2.17.08/host/types_freebsd.go000066400000000000000000000012141315167550200237400ustar00rootroot00000000000000// +build ignore /* Input to cgo -godefs. */ package host /* #define KERNEL #include #include #include 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 golang-github-shirou-gopsutil-2.17.08/host/types_linux.go000066400000000000000000000011671315167550200234740ustar00rootroot00000000000000// +build ignore /* Input to cgo -godefs. */ package host /* #include #include 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 golang-github-shirou-gopsutil-2.17.08/host/types_openbsd.go000066400000000000000000000011601315167550200237600ustar00rootroot00000000000000// +build ignore /* Input to cgo -godefs. */ package host /* #define KERNEL #include #include #include 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 golang-github-shirou-gopsutil-2.17.08/internal/000077500000000000000000000000001315167550200214145ustar00rootroot00000000000000golang-github-shirou-gopsutil-2.17.08/internal/common/000077500000000000000000000000001315167550200227045ustar00rootroot00000000000000golang-github-shirou-gopsutil-2.17.08/internal/common/binary.go000066400000000000000000000360101315167550200245170ustar00rootroot00000000000000package common // Copyright 2009 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package binary implements simple translation between numbers and byte // sequences and encoding and decoding of varints. // // Numbers are translated by reading and writing fixed-size values. // A fixed-size value is either a fixed-size arithmetic // type (int8, uint8, int16, float32, complex64, ...) // or an array or struct containing only fixed-size values. // // The varint functions encode and decode single integer values using // a variable-length encoding; smaller values require fewer bytes. // For a specification, see // http://code.google.com/apis/protocolbuffers/docs/encoding.html. // // This package favors simplicity over efficiency. Clients that require // high-performance serialization, especially for large data structures, // should look at more advanced solutions such as the encoding/gob // package or protocol buffers. import ( "errors" "io" "math" "reflect" ) // A ByteOrder specifies how to convert byte sequences into // 16-, 32-, or 64-bit unsigned integers. type ByteOrder interface { Uint16([]byte) uint16 Uint32([]byte) uint32 Uint64([]byte) uint64 PutUint16([]byte, uint16) PutUint32([]byte, uint32) PutUint64([]byte, uint64) String() string } // LittleEndian is the little-endian implementation of ByteOrder. var LittleEndian littleEndian // BigEndian is the big-endian implementation of ByteOrder. var BigEndian bigEndian type littleEndian struct{} func (littleEndian) Uint16(b []byte) uint16 { return uint16(b[0]) | uint16(b[1])<<8 } func (littleEndian) PutUint16(b []byte, v uint16) { b[0] = byte(v) b[1] = byte(v >> 8) } func (littleEndian) Uint32(b []byte) uint32 { return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24 } func (littleEndian) PutUint32(b []byte, v uint32) { b[0] = byte(v) b[1] = byte(v >> 8) b[2] = byte(v >> 16) b[3] = byte(v >> 24) } func (littleEndian) Uint64(b []byte) uint64 { return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56 } func (littleEndian) PutUint64(b []byte, v uint64) { b[0] = byte(v) b[1] = byte(v >> 8) b[2] = byte(v >> 16) b[3] = byte(v >> 24) b[4] = byte(v >> 32) b[5] = byte(v >> 40) b[6] = byte(v >> 48) b[7] = byte(v >> 56) } func (littleEndian) String() string { return "LittleEndian" } func (littleEndian) GoString() string { return "binary.LittleEndian" } type bigEndian struct{} func (bigEndian) Uint16(b []byte) uint16 { return uint16(b[1]) | uint16(b[0])<<8 } func (bigEndian) PutUint16(b []byte, v uint16) { b[0] = byte(v >> 8) b[1] = byte(v) } func (bigEndian) Uint32(b []byte) uint32 { return uint32(b[3]) | uint32(b[2])<<8 | uint32(b[1])<<16 | uint32(b[0])<<24 } func (bigEndian) PutUint32(b []byte, v uint32) { b[0] = byte(v >> 24) b[1] = byte(v >> 16) b[2] = byte(v >> 8) b[3] = byte(v) } func (bigEndian) Uint64(b []byte) uint64 { return uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 | uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56 } func (bigEndian) PutUint64(b []byte, v uint64) { b[0] = byte(v >> 56) b[1] = byte(v >> 48) b[2] = byte(v >> 40) b[3] = byte(v >> 32) b[4] = byte(v >> 24) b[5] = byte(v >> 16) b[6] = byte(v >> 8) b[7] = byte(v) } func (bigEndian) String() string { return "BigEndian" } func (bigEndian) GoString() string { return "binary.BigEndian" } // Read reads structured binary data from r into data. // Data must be a pointer to a fixed-size value or a slice // of fixed-size values. // Bytes read from r are decoded using the specified byte order // and written to successive fields of the data. // When reading into structs, the field data for fields with // blank (_) field names is skipped; i.e., blank field names // may be used for padding. // When reading into a struct, all non-blank fields must be exported. func Read(r io.Reader, order ByteOrder, data interface{}) error { // Fast path for basic types and slices. if n := intDataSize(data); n != 0 { var b [8]byte var bs []byte if n > len(b) { bs = make([]byte, n) } else { bs = b[:n] } if _, err := io.ReadFull(r, bs); err != nil { return err } switch data := data.(type) { case *int8: *data = int8(b[0]) case *uint8: *data = b[0] case *int16: *data = int16(order.Uint16(bs)) case *uint16: *data = order.Uint16(bs) case *int32: *data = int32(order.Uint32(bs)) case *uint32: *data = order.Uint32(bs) case *int64: *data = int64(order.Uint64(bs)) case *uint64: *data = order.Uint64(bs) case []int8: for i, x := range bs { // Easier to loop over the input for 8-bit values. data[i] = int8(x) } case []uint8: copy(data, bs) case []int16: for i := range data { data[i] = int16(order.Uint16(bs[2*i:])) } case []uint16: for i := range data { data[i] = order.Uint16(bs[2*i:]) } case []int32: for i := range data { data[i] = int32(order.Uint32(bs[4*i:])) } case []uint32: for i := range data { data[i] = order.Uint32(bs[4*i:]) } case []int64: for i := range data { data[i] = int64(order.Uint64(bs[8*i:])) } case []uint64: for i := range data { data[i] = order.Uint64(bs[8*i:]) } } return nil } // Fallback to reflect-based decoding. v := reflect.ValueOf(data) size := -1 switch v.Kind() { case reflect.Ptr: v = v.Elem() size = dataSize(v) case reflect.Slice: size = dataSize(v) } if size < 0 { return errors.New("binary.Read: invalid type " + reflect.TypeOf(data).String()) } d := &decoder{order: order, buf: make([]byte, size)} if _, err := io.ReadFull(r, d.buf); err != nil { return err } d.value(v) return nil } // Write writes the binary representation of data into w. // Data must be a fixed-size value or a slice of fixed-size // values, or a pointer to such data. // Bytes written to w are encoded using the specified byte order // and read from successive fields of the data. // When writing structs, zero values are written for fields // with blank (_) field names. func Write(w io.Writer, order ByteOrder, data interface{}) error { // Fast path for basic types and slices. if n := intDataSize(data); n != 0 { var b [8]byte var bs []byte if n > len(b) { bs = make([]byte, n) } else { bs = b[:n] } switch v := data.(type) { case *int8: bs = b[:1] b[0] = byte(*v) case int8: bs = b[:1] b[0] = byte(v) case []int8: for i, x := range v { bs[i] = byte(x) } case *uint8: bs = b[:1] b[0] = *v case uint8: bs = b[:1] b[0] = byte(v) case []uint8: bs = v case *int16: bs = b[:2] order.PutUint16(bs, uint16(*v)) case int16: bs = b[:2] order.PutUint16(bs, uint16(v)) case []int16: for i, x := range v { order.PutUint16(bs[2*i:], uint16(x)) } case *uint16: bs = b[:2] order.PutUint16(bs, *v) case uint16: bs = b[:2] order.PutUint16(bs, v) case []uint16: for i, x := range v { order.PutUint16(bs[2*i:], x) } case *int32: bs = b[:4] order.PutUint32(bs, uint32(*v)) case int32: bs = b[:4] order.PutUint32(bs, uint32(v)) case []int32: for i, x := range v { order.PutUint32(bs[4*i:], uint32(x)) } case *uint32: bs = b[:4] order.PutUint32(bs, *v) case uint32: bs = b[:4] order.PutUint32(bs, v) case []uint32: for i, x := range v { order.PutUint32(bs[4*i:], x) } case *int64: bs = b[:8] order.PutUint64(bs, uint64(*v)) case int64: bs = b[:8] order.PutUint64(bs, uint64(v)) case []int64: for i, x := range v { order.PutUint64(bs[8*i:], uint64(x)) } case *uint64: bs = b[:8] order.PutUint64(bs, *v) case uint64: bs = b[:8] order.PutUint64(bs, v) case []uint64: for i, x := range v { order.PutUint64(bs[8*i:], x) } } _, err := w.Write(bs) return err } // Fallback to reflect-based encoding. v := reflect.Indirect(reflect.ValueOf(data)) size := dataSize(v) if size < 0 { return errors.New("binary.Write: invalid type " + reflect.TypeOf(data).String()) } buf := make([]byte, size) e := &encoder{order: order, buf: buf} e.value(v) _, err := w.Write(buf) return err } // Size returns how many bytes Write would generate to encode the value v, which // must be a fixed-size value or a slice of fixed-size values, or a pointer to such data. // If v is neither of these, Size returns -1. func Size(v interface{}) int { return dataSize(reflect.Indirect(reflect.ValueOf(v))) } // dataSize returns the number of bytes the actual data represented by v occupies in memory. // For compound structures, it sums the sizes of the elements. Thus, for instance, for a slice // it returns the length of the slice times the element size and does not count the memory // occupied by the header. If the type of v is not acceptable, dataSize returns -1. func dataSize(v reflect.Value) int { if v.Kind() == reflect.Slice { if s := sizeof(v.Type().Elem()); s >= 0 { return s * v.Len() } return -1 } return sizeof(v.Type()) } // sizeof returns the size >= 0 of variables for the given type or -1 if the type is not acceptable. func sizeof(t reflect.Type) int { switch t.Kind() { case reflect.Array: if s := sizeof(t.Elem()); s >= 0 { return s * t.Len() } case reflect.Struct: sum := 0 for i, n := 0, t.NumField(); i < n; i++ { s := sizeof(t.Field(i).Type) if s < 0 { return -1 } sum += s } return sum case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Float32, reflect.Float64, reflect.Complex64, reflect.Complex128, reflect.Ptr: return int(t.Size()) } return -1 } type coder struct { order ByteOrder buf []byte } type decoder coder type encoder coder func (d *decoder) uint8() uint8 { x := d.buf[0] d.buf = d.buf[1:] return x } func (e *encoder) uint8(x uint8) { e.buf[0] = x e.buf = e.buf[1:] } func (d *decoder) uint16() uint16 { x := d.order.Uint16(d.buf[0:2]) d.buf = d.buf[2:] return x } func (e *encoder) uint16(x uint16) { e.order.PutUint16(e.buf[0:2], x) e.buf = e.buf[2:] } func (d *decoder) uint32() uint32 { x := d.order.Uint32(d.buf[0:4]) d.buf = d.buf[4:] return x } func (e *encoder) uint32(x uint32) { e.order.PutUint32(e.buf[0:4], x) e.buf = e.buf[4:] } func (d *decoder) uint64() uint64 { x := d.order.Uint64(d.buf[0:8]) d.buf = d.buf[8:] return x } func (e *encoder) uint64(x uint64) { e.order.PutUint64(e.buf[0:8], x) e.buf = e.buf[8:] } func (d *decoder) int8() int8 { return int8(d.uint8()) } func (e *encoder) int8(x int8) { e.uint8(uint8(x)) } func (d *decoder) int16() int16 { return int16(d.uint16()) } func (e *encoder) int16(x int16) { e.uint16(uint16(x)) } func (d *decoder) int32() int32 { return int32(d.uint32()) } func (e *encoder) int32(x int32) { e.uint32(uint32(x)) } func (d *decoder) int64() int64 { return int64(d.uint64()) } func (e *encoder) int64(x int64) { e.uint64(uint64(x)) } func (d *decoder) value(v reflect.Value) { switch v.Kind() { case reflect.Array: l := v.Len() for i := 0; i < l; i++ { d.value(v.Index(i)) } case reflect.Struct: t := v.Type() l := v.NumField() for i := 0; i < l; i++ { // Note: Calling v.CanSet() below is an optimization. // It would be sufficient to check the field name, // but creating the StructField info for each field is // costly (run "go test -bench=ReadStruct" and compare // results when making changes to this code). if v := v.Field(i); v.CanSet() || t.Field(i).Name != "_" { d.value(v) } else { d.skip(v) } } case reflect.Slice: l := v.Len() for i := 0; i < l; i++ { d.value(v.Index(i)) } case reflect.Int8: v.SetInt(int64(d.int8())) case reflect.Int16: v.SetInt(int64(d.int16())) case reflect.Int32: v.SetInt(int64(d.int32())) case reflect.Int64: v.SetInt(d.int64()) case reflect.Uint8: v.SetUint(uint64(d.uint8())) case reflect.Uint16: v.SetUint(uint64(d.uint16())) case reflect.Uint32: v.SetUint(uint64(d.uint32())) case reflect.Uint64: v.SetUint(d.uint64()) case reflect.Float32: v.SetFloat(float64(math.Float32frombits(d.uint32()))) case reflect.Float64: v.SetFloat(math.Float64frombits(d.uint64())) case reflect.Complex64: v.SetComplex(complex( float64(math.Float32frombits(d.uint32())), float64(math.Float32frombits(d.uint32())), )) case reflect.Complex128: v.SetComplex(complex( math.Float64frombits(d.uint64()), math.Float64frombits(d.uint64()), )) } } func (e *encoder) value(v reflect.Value) { switch v.Kind() { case reflect.Array: l := v.Len() for i := 0; i < l; i++ { e.value(v.Index(i)) } case reflect.Struct: t := v.Type() l := v.NumField() for i := 0; i < l; i++ { // see comment for corresponding code in decoder.value() if v := v.Field(i); v.CanSet() || t.Field(i).Name != "_" { e.value(v) } else { e.skip(v) } } case reflect.Slice: l := v.Len() for i := 0; i < l; i++ { e.value(v.Index(i)) } case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: switch v.Type().Kind() { case reflect.Int8: e.int8(int8(v.Int())) case reflect.Int16: e.int16(int16(v.Int())) case reflect.Int32: e.int32(int32(v.Int())) case reflect.Int64: e.int64(v.Int()) } case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: switch v.Type().Kind() { case reflect.Uint8: e.uint8(uint8(v.Uint())) case reflect.Uint16: e.uint16(uint16(v.Uint())) case reflect.Uint32: e.uint32(uint32(v.Uint())) case reflect.Uint64: e.uint64(v.Uint()) } case reflect.Float32, reflect.Float64: switch v.Type().Kind() { case reflect.Float32: e.uint32(math.Float32bits(float32(v.Float()))) case reflect.Float64: e.uint64(math.Float64bits(v.Float())) } case reflect.Complex64, reflect.Complex128: switch v.Type().Kind() { case reflect.Complex64: x := v.Complex() e.uint32(math.Float32bits(float32(real(x)))) e.uint32(math.Float32bits(float32(imag(x)))) case reflect.Complex128: x := v.Complex() e.uint64(math.Float64bits(real(x))) e.uint64(math.Float64bits(imag(x))) } } } func (d *decoder) skip(v reflect.Value) { d.buf = d.buf[dataSize(v):] } func (e *encoder) skip(v reflect.Value) { n := dataSize(v) for i := range e.buf[0:n] { e.buf[i] = 0 } e.buf = e.buf[n:] } // intDataSize returns the size of the data required to represent the data when encoded. // It returns zero if the type cannot be implemented by the fast path in Read or Write. func intDataSize(data interface{}) int { switch data := data.(type) { case int8, *int8, *uint8: return 1 case []int8: return len(data) case []uint8: return len(data) case int16, *int16, *uint16: return 2 case []int16: return 2 * len(data) case []uint16: return 2 * len(data) case int32, *int32, *uint32: return 4 case []int32: return 4 * len(data) case []uint32: return 4 * len(data) case int64, *int64, *uint64: return 8 case []int64: return 8 * len(data) case []uint64: return 8 * len(data) } return 0 } golang-github-shirou-gopsutil-2.17.08/internal/common/common.go000066400000000000000000000173231315167550200245310ustar00rootroot00000000000000package common // // gopsutil is a port of psutil(http://pythonhosted.org/psutil/). // This covers these architectures. // - linux (amd64, arm) // - freebsd (amd64) // - windows (amd64) import ( "bufio" "bytes" "context" "errors" "fmt" "io/ioutil" "net/url" "os" "os/exec" "path" "path/filepath" "reflect" "runtime" "strconv" "strings" "time" ) var ( Timeout = 3 * time.Second ErrTimeout = errors.New("command timed out") ) type Invoker interface { Command(string, ...string) ([]byte, error) } type Invoke struct{} func (i Invoke) Command(name string, arg ...string) ([]byte, error) { ctxt, cancel := context.WithTimeout(context.Background(), Timeout) defer cancel() cmd := exec.CommandContext(ctxt, name, arg...) var buf bytes.Buffer cmd.Stdout = &buf cmd.Stderr = &buf if err := cmd.Start(); err != nil { return buf.Bytes(), err } if err := cmd.Wait(); err != nil { return buf.Bytes(), err } return buf.Bytes(), nil } type FakeInvoke struct { 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 commandName := filepath.Base(name) fname := strings.Join(append([]string{commandName}, arg...), "") fname = url.QueryEscape(fname) fpath := path.Join("testdata", arch, fname) if i.Suffix != "" { fpath += "_" + i.Suffix } if PathExists(fpath) { return ioutil.ReadFile(fpath) } return []byte{}, fmt.Errorf("could not find testdata: %s", fpath) } var ErrNotImplementedError = 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 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) } 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]) } // ReadInts reads contents from single line file and returns them as []int32. func ReadInts(filename string) ([]int64, error) { f, err := os.Open(filename) if err != nil { return []int64{}, err } defer f.Close() var ret []int64 r := bufio.NewReader(f) // The int files that this is concerned with should only be one liners. line, err := r.ReadString('\n') if err != nil { return []int64{}, err } i, err := strconv.ParseInt(strings.Trim(line, "\n"), 10, 32) if err != nil { return []int64{}, err } ret = append(ret, i) return ret, nil } // 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 contains 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 } // IntContains checks the src in any int of the target int slice. func IntContains(target []int, src int) bool { for _, t := range target { if src == t { 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 retrieves 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...) } func HostEtc(combineWith ...string) string { return GetEnv("HOST_ETC", "/etc", 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 } // 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 } // getSysctrlEnv sets LC_ALL=C in a list of env vars for use when running // sysctl commands (see DoSysctrl). func getSysctrlEnv(env []string) []string { foundLC := false for i, line := range env { if strings.HasPrefix(line, "LC_ALL") { env[i] = "LC_ALL=C" foundLC = true } } if !foundLC { env = append(env, "LC_ALL=C") } return env } golang-github-shirou-gopsutil-2.17.08/internal/common/common_darwin.go000066400000000000000000000023741315167550200260750ustar00rootroot00000000000000// +build darwin package common import ( "os" "os/exec" "strings" "unsafe" "golang.org/x/sys/unix" ) func DoSysctrl(mib string) ([]string, error) { sysctl, err := exec.LookPath("/usr/sbin/sysctl") if err != nil { return []string{}, err } cmd := exec.Command(sysctl, "-n", mib) cmd.Env = getSysctrlEnv(os.Environ()) out, err := cmd.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 := unix.Syscall6( unix.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 = unix.Syscall6( unix.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 } golang-github-shirou-gopsutil-2.17.08/internal/common/common_freebsd.go000066400000000000000000000024021315167550200262130ustar00rootroot00000000000000// +build freebsd openbsd package common import ( "os" "os/exec" "strings" "unsafe" "golang.org/x/sys/unix" ) func DoSysctrl(mib string) ([]string, error) { sysctl, err := exec.LookPath("/sbin/sysctl") if err != nil { return []string{}, err } cmd := exec.Command(sysctl, "-n", mib) cmd.Env = getSysctrlEnv(os.Environ()) out, err := cmd.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) { mibptr := unsafe.Pointer(&mib[0]) miblen := uint64(len(mib)) // get required buffer size length := uint64(0) _, _, err := unix.Syscall6( unix.SYS___SYSCTL, uintptr(mibptr), 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 = unix.Syscall6( unix.SYS___SYSCTL, uintptr(mibptr), uintptr(miblen), uintptr(unsafe.Pointer(&buf[0])), uintptr(unsafe.Pointer(&length)), 0, 0) if err != 0 { return buf, length, err } return buf, length, nil } golang-github-shirou-gopsutil-2.17.08/internal/common/common_linux.go000066400000000000000000000013401315167550200257400ustar00rootroot00000000000000// +build linux package common import ( "os" "os/exec" "strings" ) func DoSysctrl(mib string) ([]string, error) { sysctl, err := exec.LookPath("/sbin/sysctl") if err != nil { return []string{}, err } cmd := exec.Command(sysctl, "-n", mib) cmd.Env = getSysctrlEnv(os.Environ()) out, err := cmd.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 NumProcs() (uint64, error) { f, err := os.Open(HostProc()) if err != nil { return 0, err } defer f.Close() list, err := f.Readdirnames(-1) if err != nil { return 0, err } return uint64(len(list)), err } golang-github-shirou-gopsutil-2.17.08/internal/common/common_openbsd.go000066400000000000000000000023721315167550200262410ustar00rootroot00000000000000// +build openbsd package common import ( "os" "os/exec" "strings" "unsafe" "golang.org/x/sys/unix" ) func DoSysctrl(mib string) ([]string, error) { sysctl, err := exec.LookPath("/sbin/sysctl") if err != nil { return []string{}, err } cmd := exec.Command(sysctl, "-n", mib) cmd.Env = getSysctrlEnv(os.Environ()) out, err := cmd.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) { mibptr := unsafe.Pointer(&mib[0]) miblen := uint64(len(mib)) // get required buffer size length := uint64(0) _, _, err := unix.Syscall6( unix.SYS___SYSCTL, uintptr(mibptr), 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 = unix.Syscall6( unix.SYS___SYSCTL, uintptr(mibptr), uintptr(miblen), uintptr(unsafe.Pointer(&buf[0])), uintptr(unsafe.Pointer(&length)), 0, 0) if err != 0 { return buf, length, err } return buf, length, nil } golang-github-shirou-gopsutil-2.17.08/internal/common/common_test.go000066400000000000000000000053171315167550200255700ustar00rootroot00000000000000package common import ( "fmt" "os" "reflect" "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) { 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) } } golang-github-shirou-gopsutil-2.17.08/internal/common/common_unix.go000066400000000000000000000025441315167550200255730ustar00rootroot00000000000000// +build linux freebsd darwin openbsd 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 } func CallPgrep(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...) if err != nil { return []int32{}, err } lines := strings.Split(string(out), "\n") ret := make([]int32, 0, len(lines)) for _, l := range lines { if len(l) == 0 { continue } i, err := strconv.Atoi(l) if err != nil { continue } ret = append(ret, int32(i)) } return ret, nil } golang-github-shirou-gopsutil-2.17.08/internal/common/common_windows.go000066400000000000000000000051131315167550200262750ustar00rootroot00000000000000// +build windows package common import ( "unsafe" "golang.org/x/sys/windows" ) // 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 = windows.NewLazyDLL("kernel32.dll") ModNt = windows.NewLazyDLL("ntdll.dll") ModPdh = windows.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 windows.Handle } // CreateQuery XXX // copied from https://github.com/mackerelio/mackerel-agent/ func CreateQuery() (windows.Handle, error) { var query windows.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 windows.Handle, pname, cname string) (*CounterInfo, error) { var counter windows.Handle r, _, err := PdhAddCounter.Call( uintptr(query), uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(cname))), 0, uintptr(unsafe.Pointer(&counter))) if r != 0 { return nil, err } return &CounterInfo{ PostName: pname, CounterName: cname, Counter: counter, }, nil } golang-github-shirou-gopsutil-2.17.08/load/000077500000000000000000000000001315167550200205175ustar00rootroot00000000000000golang-github-shirou-gopsutil-2.17.08/load/load.go000066400000000000000000000011031315167550200217600ustar00rootroot00000000000000package load import ( "encoding/json" "github.com/shirou/gopsutil/internal/common" ) var invoke common.Invoker func init() { invoke = common.Invoke{} } type AvgStat struct { Load1 float64 `json:"load1"` Load5 float64 `json:"load5"` Load15 float64 `json:"load15"` } func (l AvgStat) String() string { s, _ := json.Marshal(l) return string(s) } type MiscStat struct { ProcsRunning int `json:"procsRunning"` ProcsBlocked int `json:"procsBlocked"` Ctxt int `json:"ctxt"` } func (m MiscStat) String() string { s, _ := json.Marshal(m) return string(s) } golang-github-shirou-gopsutil-2.17.08/load/load_darwin.go000066400000000000000000000024321315167550200233320ustar00rootroot00000000000000// +build darwin package load import ( "os/exec" "strconv" "strings" "github.com/shirou/gopsutil/internal/common" ) func Avg() (*AvgStat, error) { values, err := common.DoSysctrl("vm.loadavg") if err != nil { return nil, err } load1, err := strconv.ParseFloat(values[0], 64) if err != nil { return nil, err } load5, err := strconv.ParseFloat(values[1], 64) if err != nil { return nil, err } load15, err := strconv.ParseFloat(values[2], 64) if err != nil { return nil, err } ret := &AvgStat{ Load1: float64(load1), Load5: float64(load5), Load15: float64(load15), } return ret, nil } // Misc returnes miscellaneous host-wide statistics. // darwin use ps command to get process running/blocked count. // Almost same as FreeBSD implementation, but state is different. // U means 'Uninterruptible Sleep'. func Misc() (*MiscStat, error) { bin, err := exec.LookPath("ps") if err != nil { return nil, err } out, err := invoke.Command(bin, "axo", "state") if err != nil { return nil, err } lines := strings.Split(string(out), "\n") ret := MiscStat{} for _, l := range lines { if strings.Contains(l, "R") { ret.ProcsRunning++ } else if strings.Contains(l, "U") { // uninterruptible sleep == blocked ret.ProcsBlocked++ } } return &ret, nil } golang-github-shirou-gopsutil-2.17.08/load/load_fallback.go000066400000000000000000000004231315167550200236030ustar00rootroot00000000000000// +build !darwin,!linux,!freebsd,!openbsd,!windows package load import "github.com/shirou/gopsutil/internal/common" func Avg() (*AvgStat, error) { return nil, common.ErrNotImplementedError } func Misc() (*MiscStat, error) { return nil, common.ErrNotImplementedError } golang-github-shirou-gopsutil-2.17.08/load/load_freebsd.go000066400000000000000000000023171315167550200234620ustar00rootroot00000000000000// +build freebsd package load import ( "os/exec" "strconv" "strings" "github.com/shirou/gopsutil/internal/common" ) func Avg() (*AvgStat, error) { values, err := common.DoSysctrl("vm.loadavg") if err != nil { return nil, err } load1, err := strconv.ParseFloat(values[0], 64) if err != nil { return nil, err } load5, err := strconv.ParseFloat(values[1], 64) if err != nil { return nil, err } load15, err := strconv.ParseFloat(values[2], 64) if err != nil { return nil, err } ret := &AvgStat{ Load1: float64(load1), Load5: float64(load5), Load15: float64(load15), } return ret, nil } // Misc returnes miscellaneous host-wide statistics. // darwin use ps command to get process running/blocked count. // Almost same as Darwin implementation, but state is different. func Misc() (*MiscStat, error) { bin, err := exec.LookPath("ps") if err != nil { return nil, err } out, err := invoke.Command(bin, "axo", "state") if err != nil { return nil, err } lines := strings.Split(string(out), "\n") ret := MiscStat{} for _, l := range lines { if strings.Contains(l, "R") { ret.ProcsRunning++ } else if strings.Contains(l, "D") { ret.ProcsBlocked++ } } return &ret, nil } golang-github-shirou-gopsutil-2.17.08/load/load_linux.go000066400000000000000000000025511315167550200232070ustar00rootroot00000000000000// +build linux package load import ( "io/ioutil" "strconv" "strings" "github.com/shirou/gopsutil/internal/common" ) func Avg() (*AvgStat, error) { filename := common.HostProc("loadavg") line, err := ioutil.ReadFile(filename) if err != nil { return nil, err } values := strings.Fields(string(line)) load1, err := strconv.ParseFloat(values[0], 64) if err != nil { return nil, err } load5, err := strconv.ParseFloat(values[1], 64) if err != nil { return nil, err } load15, err := strconv.ParseFloat(values[2], 64) if err != nil { return nil, err } ret := &AvgStat{ Load1: load1, Load5: load5, Load15: load15, } return ret, nil } // Misc returnes miscellaneous host-wide statistics. // Note: the name should be changed near future. func Misc() (*MiscStat, error) { filename := common.HostProc("stat") out, err := ioutil.ReadFile(filename) if err != nil { return nil, err } ret := &MiscStat{} lines := strings.Split(string(out), "\n") for _, line := range lines { fields := strings.Fields(line) if len(fields) != 2 { continue } v, err := strconv.ParseInt(fields[1], 10, 64) if err != nil { continue } switch fields[0] { case "procs_running": ret.ProcsRunning = int(v) case "procs_blocked": ret.ProcsBlocked = int(v) case "ctxt": ret.Ctxt = int(v) default: continue } } return ret, nil } golang-github-shirou-gopsutil-2.17.08/load/load_openbsd.go000066400000000000000000000023171315167550200235020ustar00rootroot00000000000000// +build openbsd package load import ( "os/exec" "strconv" "strings" "github.com/shirou/gopsutil/internal/common" ) func Avg() (*AvgStat, error) { values, err := common.DoSysctrl("vm.loadavg") if err != nil { return nil, err } load1, err := strconv.ParseFloat(values[0], 64) if err != nil { return nil, err } load5, err := strconv.ParseFloat(values[1], 64) if err != nil { return nil, err } load15, err := strconv.ParseFloat(values[2], 64) if err != nil { return nil, err } ret := &AvgStat{ Load1: float64(load1), Load5: float64(load5), Load15: float64(load15), } return ret, nil } // Misc returnes miscellaneous host-wide statistics. // darwin use ps command to get process running/blocked count. // Almost same as Darwin implementation, but state is different. func Misc() (*MiscStat, error) { bin, err := exec.LookPath("ps") if err != nil { return nil, err } out, err := invoke.Command(bin, "axo", "state") if err != nil { return nil, err } lines := strings.Split(string(out), "\n") ret := MiscStat{} for _, l := range lines { if strings.Contains(l, "R") { ret.ProcsRunning++ } else if strings.Contains(l, "D") { ret.ProcsBlocked++ } } return &ret, nil } golang-github-shirou-gopsutil-2.17.08/load/load_test.go000066400000000000000000000016031315167550200230240ustar00rootroot00000000000000package load import ( "fmt" "testing" ) func TestLoad(t *testing.T) { v, err := Avg() if err != nil { t.Errorf("error %v", err) } empty := &AvgStat{} if v == empty { t.Errorf("error load: %v", v) } } func TestLoadAvgStat_String(t *testing.T) { v := AvgStat{ Load1: 10.1, Load5: 20.1, Load15: 30.1, } e := `{"load1":10.1,"load5":20.1,"load15":30.1}` if e != fmt.Sprintf("%v", v) { t.Errorf("LoadAvgStat string is invalid: %v", v) } } func TestMisc(t *testing.T) { v, err := Misc() if err != nil { t.Errorf("error %v", err) } empty := &MiscStat{} if v == empty { t.Errorf("error load: %v", v) } } func TestMiscStatString(t *testing.T) { v := MiscStat{ ProcsRunning: 1, ProcsBlocked: 2, Ctxt: 3, } e := `{"procsRunning":1,"procsBlocked":2,"ctxt":3}` if e != fmt.Sprintf("%v", v) { t.Errorf("TestMiscString string is invalid: %v", v) } } golang-github-shirou-gopsutil-2.17.08/load/load_windows.go000066400000000000000000000004371315167550200235430ustar00rootroot00000000000000// +build windows package load import ( "github.com/shirou/gopsutil/internal/common" ) func Avg() (*AvgStat, error) { ret := AvgStat{} return &ret, common.ErrNotImplementedError } func Misc() (*MiscStat, error) { ret := MiscStat{} return &ret, common.ErrNotImplementedError } golang-github-shirou-gopsutil-2.17.08/mem/000077500000000000000000000000001315167550200203565ustar00rootroot00000000000000golang-github-shirou-gopsutil-2.17.08/mem/mem.go000066400000000000000000000043031315167550200214630ustar00rootroot00000000000000package 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. // // The other fields in this struct contain kernel specific values. type VirtualMemoryStat struct { // Total amount of RAM on this system Total uint64 `json:"total"` // RAM available for programs to allocate // // This value is computed from the kernel specific values. Available uint64 `json:"available"` // RAM used by programs // // This value is computed from the kernel specific values. Used uint64 `json:"used"` // Percentage of RAM used by programs // // This value is computed from the kernel specific values. UsedPercent float64 `json:"usedPercent"` // This is the kernel's notion of free memory; RAM chips whose bits nobody // cares about the value of right now. For a human consumable number, // Available is what you really want. Free uint64 `json:"free"` // OS X / BSD specific numbers: // http://www.macyourself.com/2010/02/17/what-is-free-wired-active-and-inactive-system-memory-ram/ Active uint64 `json:"active"` Inactive uint64 `json:"inactive"` Wired uint64 `json:"wired"` // 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"` } type SwapMemoryStat struct { Total uint64 `json:"total"` Used uint64 `json:"used"` Free uint64 `json:"free"` UsedPercent float64 `json:"usedPercent"` Sin uint64 `json:"sin"` Sout uint64 `json:"sout"` } func (m VirtualMemoryStat) String() string { s, _ := json.Marshal(m) return string(s) } func (m SwapMemoryStat) String() string { s, _ := json.Marshal(m) return string(s) } golang-github-shirou-gopsutil-2.17.08/mem/mem_darwin.go000066400000000000000000000027051315167550200230330ustar00rootroot00000000000000// +build darwin package mem import ( "encoding/binary" "strconv" "strings" "github.com/shirou/gopsutil/internal/common" "golang.org/x/sys/unix" ) func getHwMemsize() (uint64, error) { totalString, err := unix.Sysctl("hw.memsize") if err != nil { return 0, err } // unix.sysctl() helpfully assumes the result is a null-terminated string and // removes the last byte of the result if it's 0 :/ totalString += "\x00" total := uint64(binary.LittleEndian.Uint64([]byte(totalString))) return total, nil } // SwapMemory returns swapinfo. func SwapMemory() (*SwapMemoryStat, error) { var ret *SwapMemoryStat swapUsage, err := common.DoSysctrl("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 } u := float64(0) if total_v != 0 { u = ((total_v - free_v) / total_v) * 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), UsedPercent: u, } return ret, nil } golang-github-shirou-gopsutil-2.17.08/mem/mem_darwin_cgo.go000066400000000000000000000024231315167550200236600ustar00rootroot00000000000000// +build darwin // +build cgo package mem /* #include */ import "C" import ( "fmt" "unsafe" "golang.org/x/sys/unix" ) // VirtualMemory returns VirtualmemoryStat. func VirtualMemory() (*VirtualMemoryStat, error) { count := C.mach_msg_type_number_t(C.HOST_VM_INFO_COUNT) var vmstat C.vm_statistics_data_t status := C.host_statistics(C.host_t(C.mach_host_self()), C.HOST_VM_INFO, C.host_info_t(unsafe.Pointer(&vmstat)), &count) if status != C.KERN_SUCCESS { return nil, fmt.Errorf("host_statistics error=%d", status) } pageSize := uint64(unix.Getpagesize()) total, err := getHwMemsize() if err != nil { return nil, err } totalCount := C.natural_t(total / pageSize) availableCount := vmstat.inactive_count + vmstat.free_count usedPercent := 100 * float64(totalCount-availableCount) / float64(totalCount) usedCount := totalCount - availableCount return &VirtualMemoryStat{ Total: total, Available: pageSize * uint64(availableCount), Used: pageSize * uint64(usedCount), UsedPercent: usedPercent, Free: pageSize * uint64(vmstat.free_count), Active: pageSize * uint64(vmstat.active_count), Inactive: pageSize * uint64(vmstat.inactive_count), Wired: pageSize * uint64(vmstat.wire_count), }, nil } golang-github-shirou-gopsutil-2.17.08/mem/mem_darwin_nocgo.go000066400000000000000000000033561315167550200242230ustar00rootroot00000000000000// +build darwin // +build !cgo package mem import ( "os/exec" "strconv" "strings" "golang.org/x/sys/unix" ) // Runs vm_stat and returns Free and inactive pages func getVMStat(vms *VirtualMemoryStat) error { vm_stat, err := exec.LookPath("vm_stat") if err != nil { return err } out, err := invoke.Command(vm_stat) if err != nil { return err } return parseVMStat(string(out), vms) } func parseVMStat(out string, vms *VirtualMemoryStat) error { var err error lines := strings.Split(out, "\n") pagesize := uint64(unix.Getpagesize()) for _, line := range lines { fields := strings.Split(line, ":") if len(fields) < 2 { continue } key := strings.TrimSpace(fields[0]) value := strings.Trim(fields[1], " .") switch key { case "Pages free": free, e := strconv.ParseUint(value, 10, 64) if e != nil { err = e } vms.Free = free * pagesize case "Pages inactive": inactive, e := strconv.ParseUint(value, 10, 64) if e != nil { err = e } vms.Inactive = inactive * pagesize case "Pages active": active, e := strconv.ParseUint(value, 10, 64) if e != nil { err = e } vms.Active = active * pagesize case "Pages wired down": wired, e := strconv.ParseUint(value, 10, 64) if e != nil { err = e } vms.Wired = wired * pagesize } } return err } // VirtualMemory returns VirtualmemoryStat. func VirtualMemory() (*VirtualMemoryStat, error) { ret := &VirtualMemoryStat{} total, err := getHwMemsize() if err != nil { return nil, err } err = getVMStat(ret) if err != nil { return nil, err } ret.Available = ret.Free + ret.Inactive ret.Total = total ret.Used = ret.Total - ret.Available ret.UsedPercent = 100 * float64(ret.Used) / float64(ret.Total) return ret, nil } golang-github-shirou-gopsutil-2.17.08/mem/mem_darwin_test.go000066400000000000000000000020151315167550200240640ustar00rootroot00000000000000// +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) } golang-github-shirou-gopsutil-2.17.08/mem/mem_fallback.go000066400000000000000000000004731315167550200233060ustar00rootroot00000000000000// +build !darwin,!linux,!freebsd,!openbsd,!solaris,!windows package mem import "github.com/shirou/gopsutil/internal/common" func VirtualMemory() (*VirtualMemoryStat, error) { return nil, common.ErrNotImplementedError } func SwapMemory() (*SwapMemoryStat, error) { return nil, common.ErrNotImplementedError } golang-github-shirou-gopsutil-2.17.08/mem/mem_freebsd.go000066400000000000000000000054061315167550200231620ustar00rootroot00000000000000// +build freebsd package mem import ( "errors" "os/exec" "strconv" "strings" "github.com/shirou/gopsutil/internal/common" ) func VirtualMemory() (*VirtualMemoryStat, error) { pageSize, err := common.DoSysctrl("vm.stats.vm.v_page_size") if err != nil { return nil, err } p, err := strconv.ParseUint(pageSize[0], 10, 64) if err != nil { return nil, err } pageCount, err := common.DoSysctrl("vm.stats.vm.v_page_count") if err != nil { return nil, err } free, err := common.DoSysctrl("vm.stats.vm.v_free_count") if err != nil { return nil, err } active, err := common.DoSysctrl("vm.stats.vm.v_active_count") if err != nil { return nil, err } inactive, err := common.DoSysctrl("vm.stats.vm.v_inactive_count") if err != nil { return nil, err } cache, err := common.DoSysctrl("vm.stats.vm.v_cache_count") if err != nil { return nil, err } buffer, err := common.DoSysctrl("vfs.bufspace") if err != nil { return nil, err } wired, err := common.DoSysctrl("vm.stats.vm.v_wire_count") if err != nil { return nil, err } parsed := make([]uint64, 0, 7) vv := []string{ pageCount[0], free[0], active[0], inactive[0], cache[0], buffer[0], wired[0], } for _, target := range vv { t, err := strconv.ParseUint(target, 10, 64) if err != nil { return nil, err } parsed = append(parsed, t) } ret := &VirtualMemoryStat{ Total: parsed[0] * p, Free: parsed[1] * p, Active: parsed[2] * p, Inactive: parsed[3] * p, Cached: parsed[4] * p, Buffers: parsed[5], Wired: parsed[6] * p, } ret.Available = ret.Inactive + ret.Cached + ret.Free ret.Used = ret.Total - ret.Available ret.UsedPercent = float64(ret.Used) / float64(ret.Total) * 100.0 return ret, nil } // Return swapinfo // FreeBSD can have multiple swap devices. but use only first device func SwapMemory() (*SwapMemoryStat, error) { swapinfo, err := exec.LookPath("swapinfo") if err != nil { return nil, err } 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") } golang-github-shirou-gopsutil-2.17.08/mem/mem_linux.go000066400000000000000000000047711315167550200227130ustar00rootroot00000000000000// +build linux package mem import ( "strconv" "strings" "github.com/shirou/gopsutil/internal/common" "golang.org/x/sys/unix" ) func VirtualMemory() (*VirtualMemoryStat, error) { filename := common.HostProc("meminfo") lines, _ := common.ReadLines(filename) // flag if MemAvailable is in /proc/meminfo (kernel 3.14+) memavail := false ret := &VirtualMemoryStat{} for _, line := range lines { fields := strings.Split(line, ":") if len(fields) != 2 { continue } key := strings.TrimSpace(fields[0]) value := strings.TrimSpace(fields[1]) value = strings.Replace(value, " kB", "", -1) t, err := strconv.ParseUint(value, 10, 64) if err != nil { return ret, err } switch key { case "MemTotal": ret.Total = t * 1024 case "MemFree": ret.Free = t * 1024 case "MemAvailable": memavail = true ret.Available = t * 1024 case "Buffers": ret.Buffers = t * 1024 case "Cached": ret.Cached = t * 1024 case "Active": ret.Active = t * 1024 case "Inactive": ret.Inactive = t * 1024 case "Writeback": ret.Writeback = t * 1024 case "WritebackTmp": ret.WritebackTmp = t * 1024 case "Dirty": ret.Dirty = t * 1024 case "Shmem": ret.Shared = t * 1024 case "Slab": ret.Slab = t * 1024 case "PageTables": ret.PageTables = t * 1024 case "SwapCached": ret.SwapCached = 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 } func SwapMemory() (*SwapMemoryStat, error) { sysinfo := &unix.Sysinfo_t{} if err := unix.Sysinfo(sysinfo); err != nil { return nil, err } ret := &SwapMemoryStat{ Total: uint64(sysinfo.Totalswap) * uint64(sysinfo.Unit), Free: uint64(sysinfo.Freeswap) * uint64(sysinfo.Unit), } ret.Used = ret.Total - ret.Free //check Infinity if ret.Total != 0 { ret.UsedPercent = float64(ret.Total-ret.Free) / float64(ret.Total) * 100.0 } else { ret.UsedPercent = 0 } filename := common.HostProc("vmstat") lines, _ := common.ReadLines(filename) for _, l := range lines { fields := strings.Fields(l) if len(fields) < 2 { continue } switch fields[0] { case "pswpin": value, err := strconv.ParseUint(fields[1], 10, 64) if err != nil { continue } ret.Sin = value * 4 * 1024 case "pswpout": value, err := strconv.ParseUint(fields[1], 10, 64) if err != nil { continue } ret.Sout = value * 4 * 1024 } } return ret, nil } golang-github-shirou-gopsutil-2.17.08/mem/mem_openbsd.go000066400000000000000000000047431315167550200232050ustar00rootroot00000000000000// +build openbsd package mem import ( "bytes" "encoding/binary" "errors" "fmt" "github.com/shirou/gopsutil/internal/common" "os/exec" ) func GetPageSize() (uint64, error) { mib := []int32{CTLVm, VmUvmexp} buf, length, err := common.CallSyscall(mib) if err != nil { return 0, err } if length < sizeOfUvmexp { return 0, fmt.Errorf("short syscall ret %d bytes", length) } var uvmexp Uvmexp br := bytes.NewReader(buf) err = common.Read(br, binary.LittleEndian, &uvmexp) if err != nil { return 0, err } return uint64(uvmexp.Pagesize), nil } func VirtualMemory() (*VirtualMemoryStat, error) { mib := []int32{CTLVm, VmUvmexp} buf, length, err := common.CallSyscall(mib) if err != nil { return nil, err } if length < sizeOfUvmexp { return nil, fmt.Errorf("short syscall ret %d bytes", length) } var uvmexp Uvmexp br := bytes.NewReader(buf) err = common.Read(br, binary.LittleEndian, &uvmexp) if err != nil { return nil, err } p := uint64(uvmexp.Pagesize) ret := &VirtualMemoryStat{ Total: uint64(uvmexp.Npages) * p, Free: uint64(uvmexp.Free) * p, Active: uint64(uvmexp.Active) * p, Inactive: uint64(uvmexp.Inactive) * p, Cached: 0, // not available Wired: uint64(uvmexp.Wired) * p, } ret.Available = ret.Inactive + ret.Cached + ret.Free ret.Used = ret.Total - ret.Available ret.UsedPercent = float64(ret.Used) / float64(ret.Total) * 100.0 mib = []int32{CTLVfs, VfsGeneric, VfsBcacheStat} buf, length, err = common.CallSyscall(mib) if err != nil { return nil, err } if length < sizeOfBcachestats { return nil, fmt.Errorf("short syscall ret %d bytes", length) } var bcs Bcachestats br = bytes.NewReader(buf) err = common.Read(br, binary.LittleEndian, &bcs) if err != nil { return nil, err } ret.Buffers = uint64(bcs.Numbufpages) * p return ret, nil } // Return swapctl summary info func SwapMemory() (*SwapMemoryStat, error) { swapctl, err := exec.LookPath("swapctl") if err != nil { return nil, err } out, err := invoke.Command(swapctl, "-sk") if err != nil { return &SwapMemoryStat{}, nil } line := string(out) var total, used, free uint64 _, err = fmt.Sscanf(line, "total: %d 1K-blocks allocated, %d used, %d available", &total, &used, &free) if err != nil { return nil, errors.New("failed to parse swapctl output") } percent := float64(used) / float64(total) * 100 return &SwapMemoryStat{ Total: total * 1024, Used: used * 1024, Free: free * 1024, UsedPercent: percent, }, nil } golang-github-shirou-gopsutil-2.17.08/mem/mem_openbsd_amd64.go000066400000000000000000000054211315167550200241720ustar00rootroot00000000000000// Created by cgo -godefs - DO NOT EDIT // cgo -godefs types_openbsd.go package mem const ( CTLVm = 2 CTLVfs = 10 VmUvmexp = 4 VfsGeneric = 0 VfsBcacheStat = 3 ) const ( sizeOfUvmexp = 0x154 sizeOfBcachestats = 0x78 ) type Uvmexp struct { Pagesize int32 Pagemask int32 Pageshift int32 Npages int32 Free int32 Active int32 Inactive int32 Paging int32 Wired int32 Zeropages int32 Reserve_pagedaemon int32 Reserve_kernel int32 Anonpages int32 Vnodepages int32 Vtextpages int32 Freemin int32 Freetarg int32 Inactarg int32 Wiredmax int32 Anonmin int32 Vtextmin int32 Vnodemin int32 Anonminpct int32 Vtextminpct int32 Vnodeminpct int32 Nswapdev int32 Swpages int32 Swpginuse int32 Swpgonly int32 Nswget int32 Nanon int32 Nanonneeded int32 Nfreeanon int32 Faults int32 Traps int32 Intrs int32 Swtch int32 Softs int32 Syscalls int32 Pageins int32 Obsolete_swapins int32 Obsolete_swapouts int32 Pgswapin int32 Pgswapout int32 Forks int32 Forks_ppwait int32 Forks_sharevm int32 Pga_zerohit int32 Pga_zeromiss int32 Zeroaborts int32 Fltnoram int32 Fltnoanon int32 Fltpgwait int32 Fltpgrele int32 Fltrelck int32 Fltrelckok int32 Fltanget int32 Fltanretry int32 Fltamcopy int32 Fltnamap int32 Fltnomap int32 Fltlget int32 Fltget int32 Flt_anon int32 Flt_acow int32 Flt_obj int32 Flt_prcopy int32 Flt_przero int32 Pdwoke int32 Pdrevs int32 Pdswout int32 Pdfreed int32 Pdscans int32 Pdanscan int32 Pdobscan int32 Pdreact int32 Pdbusy int32 Pdpageouts int32 Pdpending int32 Pddeact int32 Pdreanon int32 Pdrevnode int32 Pdrevtext int32 Fpswtch int32 Kmapent int32 } type Bcachestats struct { Numbufs int64 Numbufpages int64 Numdirtypages int64 Numcleanpages int64 Pendingwrites int64 Pendingreads int64 Numwrites int64 Numreads int64 Cachehits int64 Busymapped int64 Dmapages int64 Highpages int64 Delwribufs int64 Kvaslots int64 Avail int64 } golang-github-shirou-gopsutil-2.17.08/mem/mem_solaris.go000066400000000000000000000043431315167550200232230ustar00rootroot00000000000000package mem import ( "errors" "fmt" "os/exec" "regexp" "strconv" "strings" "github.com/shirou/gopsutil/internal/common" ) // VirtualMemory for Solaris is a minimal implementation which only returns // what Nomad needs. It does take into account global vs zone, however. func VirtualMemory() (*VirtualMemoryStat, error) { result := &VirtualMemoryStat{} zoneName, err := zoneName() if err != nil { return nil, err } if zoneName == "global" { cap, err := globalZoneMemoryCapacity() if err != nil { return nil, err } result.Total = cap } else { cap, err := nonGlobalZoneMemoryCapacity() if err != nil { return nil, err } result.Total = cap } return result, nil } func SwapMemory() (*SwapMemoryStat, error) { return nil, common.ErrNotImplementedError } func zoneName() (string, error) { zonename, err := exec.LookPath("/usr/bin/zonename") if err != nil { return "", err } out, err := invoke.Command(zonename) if err != nil { return "", err } return strings.TrimSpace(string(out)), nil } var globalZoneMemoryCapacityMatch = regexp.MustCompile(`memory size: ([\d]+) Megabytes`) func globalZoneMemoryCapacity() (uint64, error) { prtconf, err := exec.LookPath("/usr/sbin/prtconf") if err != nil { return 0, err } out, err := invoke.Command(prtconf) if err != nil { return 0, err } match := globalZoneMemoryCapacityMatch.FindAllStringSubmatch(string(out), -1) if len(match) != 1 { return 0, errors.New("memory size not contained in output of /usr/sbin/prtconf") } totalMB, err := strconv.ParseUint(match[0][1], 10, 64) if err != nil { return 0, err } return totalMB * 1024 * 1024, nil } var kstatMatch = regexp.MustCompile(`([^\s]+)[\s]+([^\s]*)`) func nonGlobalZoneMemoryCapacity() (uint64, error) { kstat, err := exec.LookPath("/usr/bin/kstat") if err != nil { return 0, err } out, err := invoke.Command(kstat, "-p", "-c", "zone_memory_cap", "memory_cap:*:*:physcap") if err != nil { return 0, err } kstats := kstatMatch.FindAllStringSubmatch(string(out), -1) if len(kstats) != 1 { return 0, fmt.Errorf("expected 1 kstat, found %d", len(kstats)) } memSizeBytes, err := strconv.ParseUint(kstats[0][2], 10, 64) if err != nil { return 0, err } return memSizeBytes, nil } golang-github-shirou-gopsutil-2.17.08/mem/mem_test.go000066400000000000000000000034501315167550200225240ustar00rootroot00000000000000package 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) } } golang-github-shirou-gopsutil-2.17.08/mem/mem_windows.go000066400000000000000000000021311315167550200232320ustar00rootroot00000000000000// +build windows package mem import ( "unsafe" "github.com/shirou/gopsutil/internal/common" "golang.org/x/sys/windows" ) var ( procGlobalMemoryStatusEx = common.Modkernel32.NewProc("GlobalMemoryStatusEx") ) type memoryStatusEx struct { cbSize uint32 dwMemoryLoad uint32 ullTotalPhys uint64 // in bytes ullAvailPhys uint64 ullTotalPageFile uint64 ullAvailPageFile uint64 ullTotalVirtual uint64 ullAvailVirtual uint64 ullAvailExtendedVirtual uint64 } func VirtualMemory() (*VirtualMemoryStat, error) { var memInfo memoryStatusEx memInfo.cbSize = uint32(unsafe.Sizeof(memInfo)) mem, _, _ := procGlobalMemoryStatusEx.Call(uintptr(unsafe.Pointer(&memInfo))) if mem == 0 { return nil, windows.GetLastError() } ret := &VirtualMemoryStat{ Total: memInfo.ullTotalPhys, Available: memInfo.ullAvailPhys, UsedPercent: float64(memInfo.dwMemoryLoad), } ret.Used = ret.Total - ret.Available return ret, nil } func SwapMemory() (*SwapMemoryStat, error) { ret := &SwapMemoryStat{} return ret, nil } golang-github-shirou-gopsutil-2.17.08/mem/types_openbsd.go000066400000000000000000000007771315167550200235760ustar00rootroot00000000000000// +build ignore /* Input to cgo -godefs. */ package mem /* #include #include #include #include */ 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 golang-github-shirou-gopsutil-2.17.08/mktypes.sh000066400000000000000000000011241315167550200216260ustar00rootroot00000000000000 DIRS="cpu disk docker host load mem net process" GOOS=`uname | tr '[:upper:]' '[:lower:]'` ARCH=`uname -m` case $ARCH in amd64) GOARCH="amd64" ;; x86_64) GOARCH="amd64" ;; i386) GOARCH="386" ;; i686) GOARCH="386" ;; arm) GOARCH="arm" ;; *) echo "unknown arch: $ARCH" exit 1 esac for DIR in $DIRS do if [ -e ${DIR}/types_${GOOS}.go ]; then echo "// +build $GOOS" > ${DIR}/${DIR}_${GOOS}_${GOARCH}.go echo "// +build $GOARCH" >> ${DIR}/${DIR}_${GOOS}_${GOARCH}.go go tool cgo -godefs ${DIR}/types_${GOOS}.go >> ${DIR}/${DIR}_${GOOS}_${GOARCH}.go fi done golang-github-shirou-gopsutil-2.17.08/net/000077500000000000000000000000001315167550200203665ustar00rootroot00000000000000golang-github-shirou-gopsutil-2.17.08/net/net.go000066400000000000000000000137551315167550200215160ustar00rootroot00000000000000package net import ( "encoding/json" "fmt" "net" "strconv" "strings" "syscall" "github.com/shirou/gopsutil/internal/common" ) var invoke common.Invoker func init() { invoke = common.Invoke{} } type IOCountersStat struct { 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) 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 type Addr struct { IP string `json:"ip"` Port uint32 `json:"port"` } type ConnectionStat struct { Fd uint32 `json:"fd"` Family uint32 `json:"family"` Type uint32 `json:"type"` Laddr Addr `json:"localaddr"` Raddr Addr `json:"remoteaddr"` Status string `json:"status"` Uids []int32 `json:"uids"` Pid int32 `json:"pid"` } // System wide stats about different network protocols type ProtoCountersStat struct { Protocol string `json:"protocol"` Stats map[string]int64 `json:"stats"` } // NetInterfaceAddr is designed for represent interface addresses type InterfaceAddr struct { Addr string `json:"addr"` } type InterfaceStat struct { 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 Flags []string `json:"flags"` // e.g., FlagUp, FlagLoopback, FlagMulticast Addrs []InterfaceAddr `json:"addrs"` } type FilterStat struct { ConnTrackCount int64 `json:"conntrackCount"` ConnTrackMax int64 `json:"conntrackMax"` } var constMap = map[string]int{ "TCP": syscall.SOCK_STREAM, "UDP": syscall.SOCK_DGRAM, "IPv4": syscall.AF_INET, "IPv6": syscall.AF_INET6, } func (n IOCountersStat) String() string { s, _ := json.Marshal(n) return string(s) } func (n ConnectionStat) String() string { s, _ := json.Marshal(n) return string(s) } func (n ProtoCountersStat) String() string { s, _ := json.Marshal(n) return string(s) } func (a Addr) String() string { s, _ := json.Marshal(a) return string(s) } func (n InterfaceStat) String() string { s, _ := json.Marshal(n) return string(s) } func (n InterfaceAddr) String() string { s, _ := json.Marshal(n) return string(s) } func Interfaces() ([]InterfaceStat, error) { is, err := net.Interfaces() if err != nil { return nil, err } ret := make([]InterfaceStat, 0, len(is)) for _, ifi := range is { var flags []string if ifi.Flags&net.FlagUp != 0 { flags = append(flags, "up") } if ifi.Flags&net.FlagBroadcast != 0 { flags = append(flags, "broadcast") } if ifi.Flags&net.FlagLoopback != 0 { flags = append(flags, "loopback") } if ifi.Flags&net.FlagPointToPoint != 0 { flags = append(flags, "pointtopoint") } if ifi.Flags&net.FlagMulticast != 0 { flags = append(flags, "multicast") } r := InterfaceStat{ Name: ifi.Name, MTU: ifi.MTU, HardwareAddr: ifi.HardwareAddr.String(), Flags: flags, } addrs, err := ifi.Addrs() if err == nil { r.Addrs = make([]InterfaceAddr, 0, len(addrs)) for _, addr := range addrs { r.Addrs = append(r.Addrs, InterfaceAddr{ Addr: addr.String(), }) } } ret = append(ret, r) } return ret, nil } func getIOCountersAll(n []IOCountersStat) ([]IOCountersStat, error) { r := IOCountersStat{ Name: "all", } for _, nic := range n { r.BytesRecv += nic.BytesRecv r.PacketsRecv += nic.PacketsRecv r.Errin += nic.Errin r.Dropin += nic.Dropin r.BytesSent += nic.BytesSent r.PacketsSent += nic.PacketsSent r.Errout += nic.Errout r.Dropout += nic.Dropout } return []IOCountersStat{r}, nil } func parseNetLine(line string) (ConnectionStat, error) { f := strings.Fields(line) if len(f) < 9 { return ConnectionStat{}, fmt.Errorf("wrong line,%s", line) } pid, err := strconv.Atoi(f[1]) if err != nil { return ConnectionStat{}, err } fd, err := strconv.Atoi(strings.Trim(f[3], "u")) if err != nil { return ConnectionStat{}, fmt.Errorf("unknown fd, %s", f[3]) } netFamily, ok := constMap[f[4]] if !ok { return ConnectionStat{}, fmt.Errorf("unknown family, %s", f[4]) } netType, ok := constMap[f[7]] if !ok { 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]) } n := ConnectionStat{ Fd: uint32(fd), Family: uint32(netFamily), Type: uint32(netType), Laddr: laddr, Raddr: raddr, Pid: int32(pid), } if len(f) == 10 { n.Status = strings.Trim(f[9], "()") } return n, nil } func parseNetAddr(line string) (laddr Addr, raddr Addr, err error) { parse := func(l string) (Addr, error) { host, port, err := net.SplitHostPort(l) if err != nil { return Addr{}, fmt.Errorf("wrong addr, %s", l) } lport, err := strconv.Atoi(port) if err != nil { return Addr{}, err } return Addr{IP: host, Port: uint32(lport)}, nil } addrs := strings.Split(line, "->") if len(addrs) == 0 { return laddr, raddr, fmt.Errorf("wrong netaddr, %s", line) } laddr, err = parse(addrs[0]) if len(addrs) == 2 { // remote addr exists raddr, err = parse(addrs[1]) if err != nil { return laddr, raddr, err } } return laddr, raddr, err } golang-github-shirou-gopsutil-2.17.08/net/net_darwin.go000066400000000000000000000155171315167550200230600ustar00rootroot00000000000000// +build darwin package net import ( "errors" "fmt" "os/exec" "regexp" "strconv" "strings" ) var ( errNetstatHeader = errors.New("Can't parse header of netstat output") netstatLinkRegexp = regexp.MustCompile(`^$`) ) const endOfLine = "\n" func parseNetstatLine(line string) (stat *IOCountersStat, linkID *uint, err error) { var ( numericValue uint64 columns = strings.Fields(line) ) if columns[0] == "Name" { err = errNetstatHeader return } // try to extract the numeric value from if subMatch := netstatLinkRegexp.FindStringSubmatch(columns[2]); len(subMatch) == 2 { numericValue, err = strconv.ParseUint(subMatch[1], 10, 64) if err != nil { return } linkIDUint := uint(numericValue) linkID = &linkIDUint } base := 1 numberColumns := len(columns) // sometimes Address is ommitted if numberColumns < 12 { base = 0 } if numberColumns < 11 || numberColumns > 13 { err = fmt.Errorf("Line %q do have an invalid number of columns %d", line, numberColumns) return } parsed := make([]uint64, 0, 7) vv := []string{ columns[base+3], // Ipkts == PacketsRecv columns[base+4], // Ierrs == Errin columns[base+5], // Ibytes == BytesRecv columns[base+6], // Opkts == PacketsSent columns[base+7], // Oerrs == Errout columns[base+8], // Obytes == BytesSent } if len(columns) == 12 { vv = append(vv, columns[base+10]) } for _, target := range vv { if target == "-" { parsed = append(parsed, 0) continue } if numericValue, err = strconv.ParseUint(target, 10, 64); err != nil { return } parsed = append(parsed, numericValue) } stat = &IOCountersStat{ Name: strings.Trim(columns[0], "*"), // remove the * that sometimes is on right on interface PacketsRecv: parsed[0], Errin: parsed[1], BytesRecv: parsed[2], PacketsSent: parsed[3], Errout: parsed[4], BytesSent: parsed[5], } if len(parsed) == 7 { stat.Dropout = parsed[6] } return } type netstatInterface struct { linkID *uint stat *IOCountersStat } func parseNetstatOutput(output string) ([]netstatInterface, error) { var ( err error lines = strings.Split(strings.Trim(output, endOfLine), endOfLine) ) // number of interfaces is number of lines less one for the header numberInterfaces := len(lines) - 1 interfaces := make([]netstatInterface, numberInterfaces) // no output beside header if numberInterfaces == 0 { return interfaces, nil } for index := 0; index < numberInterfaces; index++ { nsIface := netstatInterface{} if nsIface.stat, nsIface.linkID, err = parseNetstatLine(lines[index+1]); err != nil { return nil, err } interfaces[index] = nsIface } return interfaces, nil } // map that hold the name of a network interface and the number of usage type mapInterfaceNameUsage map[string]uint func newMapInterfaceNameUsage(ifaces []netstatInterface) mapInterfaceNameUsage { output := make(mapInterfaceNameUsage) for index := range ifaces { if ifaces[index].linkID != nil { ifaceName := ifaces[index].stat.Name usage, ok := output[ifaceName] if ok { output[ifaceName] = usage + 1 } else { output[ifaceName] = 1 } } } return output } func (min mapInterfaceNameUsage) isTruncated() bool { for _, usage := range min { if usage > 1 { return true } } return false } func (min mapInterfaceNameUsage) notTruncated() []string { output := make([]string, 0) for ifaceName, usage := range min { if usage == 1 { output = append(output, ifaceName) } } return output } // example of `netstat -ibdnW` output on yosemite // Name Mtu Network Address Ipkts Ierrs Ibytes Opkts Oerrs Obytes Coll Drop // lo0 16384 869107 0 169411755 869107 0 169411755 0 0 // lo0 16384 ::1/128 ::1 869107 - 169411755 869107 - 169411755 - - // lo0 16384 127 127.0.0.1 869107 - 169411755 869107 - 169411755 - - func IOCounters(pernic bool) ([]IOCountersStat, error) { var ( ret []IOCountersStat retIndex int ) netstat, err := exec.LookPath("/usr/sbin/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") if err != nil { return nil, err } nsInterfaces, err := parseNetstatOutput(string(out)) if err != nil { return nil, err } ifaceUsage := newMapInterfaceNameUsage(nsInterfaces) notTruncated := ifaceUsage.notTruncated() ret = make([]IOCountersStat, len(notTruncated)) if !ifaceUsage.isTruncated() { // no truncated interface name, return stats of all interface with for index := range nsInterfaces { if nsInterfaces[index].linkID != nil { ret[retIndex] = *nsInterfaces[index].stat retIndex++ } } } else { // duplicated interface, list all interfaces ifconfig, err := exec.LookPath("/sbin/ifconfig") if err != nil { return nil, err } if out, err = invoke.Command(ifconfig, "-l"); err != nil { return nil, err } interfaceNames := strings.Fields(strings.TrimRight(string(out), endOfLine)) // for each of the interface name, run netstat if we don't have any stats yet for _, interfaceName := range interfaceNames { truncated := true for index := range nsInterfaces { if nsInterfaces[index].linkID != nil && nsInterfaces[index].stat.Name == interfaceName { // handle the non truncated name to avoid execute netstat for them again ret[retIndex] = *nsInterfaces[index].stat retIndex++ truncated = false break } } if truncated { // run netstat with -I$ifacename if out, err = invoke.Command(netstat, "-ibdnWI"+interfaceName); err != nil { return nil, err } parsedIfaces, err := parseNetstatOutput(string(out)) if err != nil { return nil, err } if len(parsedIfaces) == 0 { // interface had been removed since `ifconfig -l` had been executed continue } for index := range parsedIfaces { if parsedIfaces[index].linkID != nil { ret = append(ret, *parsedIfaces[index].stat) break } } } } } if pernic == false { return getIOCountersAll(ret) } return ret, nil } // NetIOCountersByFile is an method which is added just a compatibility for linux. func IOCountersByFile(pernic bool, filename string) ([]IOCountersStat, error) { return IOCounters(pernic) } func FilterCounters() ([]FilterStat, error) { return nil, errors.New("NetFilterCounters not implemented for darwin") } // 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. // Not Implemented for Darwin func ProtoCounters(protocols []string) ([]ProtoCountersStat, error) { return nil, errors.New("NetProtoCounters not implemented for darwin") } golang-github-shirou-gopsutil-2.17.08/net/net_darwin_test.go000066400000000000000000000135251315167550200241140ustar00rootroot00000000000000package 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 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 0 0 0 0 0 0 0 0 stf0* 1280 0 0 0 0 0 0 0 0 utun8 1500 286 0 27175 0 0 0 0 0 utun8 1500 286 0 29554 0 0 0 0 0 utun8 1500 286 0 29244 0 0 0 0 0 utun8 1500 286 0 28267 0 0 0 0 0 utun8 1500 286 0 28593 0 0 0 0 0` netstatNotTruncated = `Name Mtu Network Address Ipkts Ierrs Ibytes Opkts Oerrs Obytes Coll Drop lo0 16384 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 0 0 0 0 0 0 0 0 stf0* 1280 0 0 0 0 0 0 0 0 en0 1500 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 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") } golang-github-shirou-gopsutil-2.17.08/net/net_fallback.go000066400000000000000000000013231315167550200233210ustar00rootroot00000000000000// +build !darwin,!linux,!freebsd,!openbsd,!windows package net import "github.com/shirou/gopsutil/internal/common" func IOCounters(pernic bool) ([]IOCountersStat, error) { return []IOCountersStat{}, common.ErrNotImplementedError } func FilterCounters() ([]FilterStat, error) { return []FilterStat{}, common.ErrNotImplementedError } func ProtoCounters(protocols []string) ([]ProtoCountersStat, error) { return []ProtoCountersStat{}, common.ErrNotImplementedError } func Connections(kind string) ([]ConnectionStat, error) { return []ConnectionStat{}, common.ErrNotImplementedError } func ConnectionsMax(kind string, max int) ([]ConnectionStat, error) { return []ConnectionStat{}, common.ErrNotImplementedError } golang-github-shirou-gopsutil-2.17.08/net/net_freebsd.go000066400000000000000000000046361315167550200232060ustar00rootroot00000000000000// +build freebsd package net import ( "errors" "os/exec" "strconv" "strings" "github.com/shirou/gopsutil/internal/common" ) func IOCounters(pernic bool) ([]IOCountersStat, error) { netstat, err := exec.LookPath("/usr/bin/netstat") if err != nil { return nil, err } out, err := invoke.Command(netstat, "-ibdnW") if err != nil { return nil, err } lines := strings.Split(string(out), "\n") ret := make([]IOCountersStat, 0, len(lines)-1) exists := make([]string, 0, len(ret)) for _, line := range lines { 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) < 12 { continue } base := 1 // sometimes Address is ommitted if len(values) < 13 { base = 0 } parsed := make([]uint64, 0, 8) vv := []string{ values[base+3], // PacketsRecv values[base+4], // Errin values[base+5], // Dropin values[base+6], // BytesRecvn values[base+7], // PacketSent values[base+8], // Errout values[base+9], // BytesSent values[base+11], // 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], Dropin: parsed[2], BytesRecv: parsed[3], PacketsSent: parsed[4], Errout: parsed[5], BytesSent: parsed[6], Dropout: parsed[7], } ret = append(ret, n) } if pernic == false { return getIOCountersAll(ret) } return ret, nil } // NetIOCountersByFile is an method which is added just a compatibility for linux. func IOCountersByFile(pernic bool, filename string) ([]IOCountersStat, error) { return IOCounters(pernic) } func FilterCounters() ([]FilterStat, error) { return nil, errors.New("NetFilterCounters 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. // Not Implemented for FreeBSD func ProtoCounters(protocols []string) ([]ProtoCountersStat, error) { return nil, errors.New("NetProtoCounters not implemented for freebsd") } golang-github-shirou-gopsutil-2.17.08/net/net_linux.go000066400000000000000000000414111315167550200227230ustar00rootroot00000000000000// +build linux package net import ( "bytes" "encoding/hex" "errors" "fmt" "io/ioutil" "net" "os" "strconv" "strings" "syscall" "github.com/shirou/gopsutil/internal/common" ) // 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, // every network interface installed on the system is returned // separately. func IOCounters(pernic bool) ([]IOCountersStat, error) { filename := common.HostProc("net/dev") return IOCountersByFile(pernic, filename) } func IOCountersByFile(pernic bool, filename string) ([]IOCountersStat, error) { lines, err := common.ReadLines(filename) if err != nil { return nil, err } parts := make([]string, 2) statlen := len(lines) - 1 ret := make([]IOCountersStat, 0, statlen) for _, line := range lines[2:] { separatorPos := strings.LastIndex(line, ":") if separatorPos == -1 { continue } parts[0] = line[0:separatorPos] parts[1] = line[separatorPos+1:] interfaceName := strings.TrimSpace(parts[0]) if interfaceName == "" { continue } fields := strings.Fields(strings.TrimSpace(parts[1])) bytesRecv, err := strconv.ParseUint(fields[0], 10, 64) if err != nil { return ret, err } packetsRecv, err := strconv.ParseUint(fields[1], 10, 64) if err != nil { return ret, err } errIn, err := strconv.ParseUint(fields[2], 10, 64) if err != nil { return ret, err } dropIn, err := strconv.ParseUint(fields[3], 10, 64) 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 } packetsSent, err := strconv.ParseUint(fields[9], 10, 64) if err != nil { return ret, err } errOut, err := strconv.ParseUint(fields[10], 10, 64) if err != nil { return ret, err } dropOut, err := strconv.ParseUint(fields[11], 10, 64) if err != nil { return ret, err } fifoOut, err := strconv.ParseUint(fields[12], 10, 64) if err != nil { return ret, err } nic := IOCountersStat{ Name: interfaceName, BytesRecv: bytesRecv, PacketsRecv: packetsRecv, Errin: errIn, Dropin: dropIn, Fifoin: fifoIn, BytesSent: bytesSent, PacketsSent: packetsSent, Errout: errOut, Dropout: dropOut, Fifoout: fifoOut, } ret = append(ret, nic) } if pernic == false { return getIOCountersAll(ret) } return ret, nil } var netProtocols = []string{ "ip", "icmp", "icmpmsg", "tcp", "udp", "udplite", } // 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. // Available protocols: // ip,icmp,icmpmsg,tcp,udp,udplite func ProtoCounters(protocols []string) ([]ProtoCountersStat, error) { if len(protocols) == 0 { protocols = netProtocols } stats := make([]ProtoCountersStat, 0, len(protocols)) protos := make(map[string]bool, len(protocols)) for _, p := range protocols { protos[p] = true } filename := common.HostProc("net/snmp") lines, err := common.ReadLines(filename) if err != nil { return nil, err } linecount := len(lines) for i := 0; i < linecount; i++ { line := lines[i] r := strings.IndexRune(line, ':') if r == -1 { return nil, errors.New(filename + " is not fomatted correctly, expected ':'.") } proto := strings.ToLower(line[:r]) if !protos[proto] { // skip protocol and data line i++ continue } // Read header line statNames := strings.Split(line[r+2:], " ") // Read data line i++ statValues := strings.Split(lines[i][r+2:], " ") if len(statNames) != len(statValues) { return nil, errors.New(filename + " is not fomatted correctly, expected same number of columns.") } stat := ProtoCountersStat{ Protocol: proto, Stats: make(map[string]int64, len(statNames)), } for j := range statNames { value, err := strconv.ParseInt(statValues[j], 10, 64) if err != nil { return nil, err } stat.Stats[statNames[j]] = value } stats = append(stats, stat) } return stats, nil } // NetFilterCounters returns iptables conntrack statistics // the currently in use conntrack count and the max. // If the file does not exist or is invalid it will return nil. func FilterCounters() ([]FilterStat, error) { countfile := common.HostProc("sys/net/netfilter/nf_conntrack_count") maxfile := common.HostProc("sys/net/netfilter/nf_conntrack_max") count, err := common.ReadInts(countfile) if err != nil { return nil, err } stats := make([]FilterStat, 0, 1) max, err := common.ReadInts(maxfile) if err != nil { return nil, err } payload := FilterStat{ ConnTrackCount: count[0], ConnTrackMax: max[0], } stats = append(stats, payload) return stats, nil } // http://students.mimuw.edu.pl/lxr/source/include/net/tcp_states.h var TCPStatuses = map[string]string{ "01": "ESTABLISHED", "02": "SYN_SENT", "03": "SYN_RECV", "04": "FIN_WAIT1", "05": "FIN_WAIT2", "06": "TIME_WAIT", "07": "CLOSE", "08": "CLOSE_WAIT", "09": "LAST_ACK", "0A": "LISTEN", "0B": "CLOSING", } 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 kindUNIX = netConnectionKindType{ family: syscall.AF_UNIX, filename: "unix", } var netConnectionKindMap = map[string][]netConnectionKindType{ "all": {kindTCP4, kindTCP6, kindUDP4, kindUDP6, kindUNIX}, "tcp": {kindTCP4, kindTCP6}, "tcp4": {kindTCP4}, "tcp6": {kindTCP6}, "udp": {kindUDP4, kindUDP6}, "udp4": {kindUDP4}, "udp6": {kindUDP6}, "unix": {kindUNIX}, "inet": {kindTCP4, kindTCP6, kindUDP4, kindUDP6}, "inet4": {kindTCP4, kindUDP4}, "inet6": {kindTCP6, kindUDP6}, } type inodeMap struct { pid int32 fd uint32 } type connTmp struct { fd uint32 family uint32 sockType uint32 laddr Addr raddr Addr status string pid int32 boundPid int32 path string } // Return a list of network connections opened. func Connections(kind string) ([]ConnectionStat, error) { return ConnectionsPid(kind, 0) } // Return a list of network connections opened returning at most `max` // connections for each running process. func ConnectionsMax(kind string, max int) ([]ConnectionStat, error) { return ConnectionsPidMax(kind, 0, max) } // Return a list of network connections opened by a process. func ConnectionsPid(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", pid) } return statsFromInodes(root, pid, tmap, inodes) } // Return up to `max` network connections opened by a process. func ConnectionsPidMax(kind string, pid int32, max int) ([]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, max) } else { inodes, err = getProcInodes(root, pid, max) 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", pid) } return statsFromInodes(root, pid, tmap, inodes) } func statsFromInodes(root string, pid int32, tmap []netConnectionKindType, inodes map[string][]inodeMap) ([]ConnectionStat, error) { dupCheckMap := make(map[string]struct{}) var ret []ConnectionStat var err error for _, t := range tmap { var path string var connKey string var ls []connTmp path = fmt.Sprintf("%s/net/%s", root, t.filename) switch t.family { case syscall.AF_INET: fallthrough case syscall.AF_INET6: ls, err = processInet(path, t, inodes, pid) case syscall.AF_UNIX: ls, err = processUnix(path, t, inodes, pid) } if err != nil { return nil, err } for _, c := range ls { // Build TCP key to id the connection uniquely // socket type, src ip, src port, dst ip, dst port and state should be enough // to prevent duplications. connKey = fmt.Sprintf("%d-%s:%d-%s:%d-%s", c.sockType, c.laddr.IP, c.laddr.Port, c.raddr.IP, c.raddr.Port, c.status) if _, ok := dupCheckMap[connKey]; ok { continue } conn := ConnectionStat{ Fd: c.fd, Family: c.family, Type: c.sockType, Laddr: c.laddr, Raddr: c.raddr, Status: c.status, Pid: c.pid, } if c.pid == 0 { conn.Pid = c.boundPid } else { conn.Pid = c.pid } // 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{}{} } } return ret, nil } // getProcInodes returnes fd of the pid. func getProcInodes(root string, pid int32, max int) (map[string][]inodeMap, error) { ret := make(map[string][]inodeMap) dir := fmt.Sprintf("%s/%d/fd", root, pid) f, err := os.Open(dir) if err != nil { return ret, err } defer f.Close() files, err := f.Readdir(max) if err != nil { return ret, err } for _, fd := range files { inodePath := fmt.Sprintf("%s/%d/fd/%s", root, pid, fd.Name()) inode, err := os.Readlink(inodePath) if err != nil { continue } if !strings.HasPrefix(inode, "socket:[") { continue } // the process is using a socket l := len(inode) inode = inode[8 : l-1] _, ok := ret[inode] if !ok { ret[inode] = make([]inodeMap, 0) } fd, err := strconv.Atoi(fd.Name()) if err != nil { continue } i := inodeMap{ pid: pid, fd: uint32(fd), } ret[inode] = append(ret[inode], i) } return ret, nil } // Pids retunres all pids. // Note: this is a copy of process_linux.Pids() // FIXME: Import process occures import cycle. // move to common made other platform breaking. Need consider. func Pids() ([]int32, error) { var ret []int32 d, err := os.Open(common.HostProc()) if err != nil { return nil, err } defer d.Close() fnames, err := d.Readdirnames(-1) if err != nil { return nil, err } for _, fname := range fnames { pid, err := strconv.ParseInt(fname, 10, 32) if err != nil { // if not numeric name, just skip continue } ret = append(ret, int32(pid)) } return ret, nil } // Note: the following is based off process_linux structs and methods // we need these to fetch the owner of a process ID // FIXME: Import process occures import cycle. // see remarks on pids() type process struct { Pid int32 `json:"pid"` uids []int32 } // Uids returns user ids of the process as a slice of the int func (p *process) getUids() ([]int32, error) { err := p.fillFromStatus() if err != nil { return []int32{}, err } return p.uids, nil } // Get status from /proc/(pid)/status func (p *process) fillFromStatus() error { pid := p.Pid statPath := common.HostProc(strconv.Itoa(int(pid)), "status") contents, err := ioutil.ReadFile(statPath) if err != nil { return err } lines := strings.Split(string(contents), "\n") for _, line := range lines { tabParts := strings.SplitN(line, "\t", 2) if len(tabParts) < 2 { continue } value := tabParts[1] switch strings.TrimRight(tabParts[0], ":") { case "Uid": p.uids = make([]int32, 0, 4) for _, i := range strings.Split(value, "\t") { v, err := strconv.ParseInt(i, 10, 32) if err != nil { return err } p.uids = append(p.uids, int32(v)) } } } return nil } func getProcInodesAll(root string, max int) (map[string][]inodeMap, error) { pids, err := Pids() if err != nil { return nil, err } ret := make(map[string][]inodeMap) for _, pid := range pids { t, err := getProcInodes(root, pid, max) if err != nil { return ret, err } if len(t) == 0 { continue } // TODO: update ret. ret = updateMap(ret, t) } return ret, nil } // decodeAddress decode addresse represents addr in proc/net/* // ex: // "0500000A:0016" -> "10.0.0.5", 22 // "0085002452100113070057A13F025401:0035" -> "2400:8500:1301:1052:a157:7:154:23f", 53 func decodeAddress(family uint32, src string) (Addr, error) { t := strings.Split(src, ":") if len(t) != 2 { return Addr{}, fmt.Errorf("does not contain port, %s", src) } addr := t[0] port, err := strconv.ParseInt("0x"+t[1], 0, 64) if err != nil { return Addr{}, fmt.Errorf("invalid port, %s", src) } decoded, err := hex.DecodeString(addr) if err != nil { return Addr{}, fmt.Errorf("decode error, %s", err) } var ip net.IP // Assumes this is little_endian if family == syscall.AF_INET { ip = net.IP(Reverse(decoded)) } else { // IPv6 ip, err = parseIPv6HexString(decoded) if err != nil { return Addr{}, err } } return Addr{ IP: ip.String(), Port: uint32(port), }, nil } // Reverse reverses array of bytes. func Reverse(s []byte) []byte { for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 { s[i], s[j] = s[j], s[i] } return s } // parseIPv6HexString parse array of bytes to IPv6 string func parseIPv6HexString(src []byte) (net.IP, error) { if len(src) != 16 { return nil, fmt.Errorf("invalid IPv6 string") } buf := make([]byte, 0, 16) for i := 0; i < len(src); i += 4 { r := Reverse(src[i : i+4]) buf = append(buf, r...) } return net.IP(buf), nil } func processInet(file string, kind netConnectionKindType, inodes map[string][]inodeMap, filterPid int32) ([]connTmp, error) { if strings.HasSuffix(file, "6") && !common.PathExists(file) { // IPv6 not supported, return empty. return []connTmp{}, nil } // Read the contents of the /proc file with a single read sys call. // This minimizes duplicates in the returned connections // For more info: // https://github.com/shirou/gopsutil/pull/361 contents, err := ioutil.ReadFile(file) if err != nil { return nil, err } lines := bytes.Split(contents, []byte("\n")) var ret []connTmp // skip first line for _, line := range lines[1:] { l := strings.Fields(string(line)) if len(l) < 10 { continue } laddr := l[1] raddr := l[2] status := l[3] inode := l[9] pid := int32(0) fd := uint32(0) i, exists := inodes[inode] if exists { pid = i[0].pid fd = i[0].fd } if filterPid > 0 && filterPid != pid { continue } if kind.sockType == syscall.SOCK_STREAM { status = TCPStatuses[status] } else { status = "NONE" } la, err := decodeAddress(kind.family, laddr) if err != nil { continue } ra, err := decodeAddress(kind.family, raddr) if err != nil { continue } ret = append(ret, connTmp{ fd: fd, family: kind.family, sockType: kind.sockType, laddr: la, raddr: ra, status: status, pid: pid, }) } return ret, nil } func processUnix(file string, kind netConnectionKindType, inodes map[string][]inodeMap, filterPid int32) ([]connTmp, error) { // Read the contents of the /proc file with a single read sys call. // This minimizes duplicates in the returned connections // For more info: // https://github.com/shirou/gopsutil/pull/361 contents, err := ioutil.ReadFile(file) if err != nil { return nil, err } lines := bytes.Split(contents, []byte("\n")) var ret []connTmp // skip first line for _, line := range lines[1:] { tokens := strings.Fields(string(line)) if len(tokens) < 6 { continue } st, err := strconv.Atoi(tokens[4]) if err != nil { return nil, err } inode := tokens[6] var pairs []inodeMap pairs, exists := inodes[inode] if !exists { pairs = []inodeMap{ {}, } } for _, pair := range pairs { if filterPid > 0 && filterPid != pair.pid { continue } var path string if len(tokens) == 8 { path = tokens[len(tokens)-1] } ret = append(ret, connTmp{ fd: pair.fd, family: kind.family, sockType: uint32(st), laddr: Addr{ IP: path, }, pid: pair.pid, status: "NONE", path: path, }) } } return ret, nil } func updateMap(src map[string][]inodeMap, add map[string][]inodeMap) map[string][]inodeMap { for key, value := range add { a, exists := src[key] if !exists { src[key] = value continue } src[key] = append(a, value...) } return src } golang-github-shirou-gopsutil-2.17.08/net/net_linux_test.go000066400000000000000000000107021315167550200237610ustar00rootroot00000000000000package 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)) } golang-github-shirou-gopsutil-2.17.08/net/net_openbsd.go000066400000000000000000000063641315167550200232260ustar00rootroot00000000000000// +build openbsd package net import ( "errors" "os/exec" "strconv" "strings" "github.com/shirou/gopsutil/internal/common" ) func ParseNetstat(output string, mode string, iocs map[string]IOCountersStat) error { lines := strings.Split(output, "\n") exists := make([]string, 0, len(lines)-1) columns := 6 if mode == "ind" { columns = 10 } for _, line := range lines { values := strings.Fields(line) if len(values) < 1 || values[0] == "Name" { continue } if common.StringsHas(exists, values[0]) { // skip if already get continue } if len(values) < columns { continue } base := 1 // sometimes Address is ommitted if len(values) < columns { base = 0 } parsed := make([]uint64, 0, 8) var vv []string if mode == "inb" { vv = []string{ values[base+3], // BytesRecv values[base+4], // BytesSent } } else { vv = []string{ values[base+3], // Ipkts values[base+4], // Ierrs values[base+5], // Opkts values[base+6], // Oerrs values[base+8], // Drops } } for _, target := range vv { if target == "-" { parsed = append(parsed, 0) continue } t, err := strconv.ParseUint(target, 10, 64) if err != nil { return err } parsed = append(parsed, t) } exists = append(exists, values[0]) n, present := iocs[values[0]] if !present { n = IOCountersStat{Name: values[0]} } if mode == "inb" { n.BytesRecv = parsed[0] n.BytesSent = parsed[1] } else { n.PacketsRecv = parsed[0] n.Errin = parsed[1] n.PacketsSent = parsed[2] n.Errout = parsed[3] n.Dropin = parsed[4] n.Dropout = parsed[4] } iocs[n.Name] = n } return nil } func IOCounters(pernic bool) ([]IOCountersStat, error) { netstat, err := exec.LookPath("/usr/bin/netstat") if err != nil { return nil, err } out, err := invoke.Command(netstat, "-inb") if err != nil { return nil, err } out2, err := invoke.Command(netstat, "-ind") if err != nil { return nil, err } iocs := make(map[string]IOCountersStat) lines := strings.Split(string(out), "\n") ret := make([]IOCountersStat, 0, len(lines)-1) err = ParseNetstat(string(out), "inb", iocs) if err != nil { return nil, err } err = ParseNetstat(string(out2), "ind", iocs) if err != nil { return nil, err } for _, ioc := range iocs { ret = append(ret, ioc) } if pernic == false { return getIOCountersAll(ret) } return ret, nil } // NetIOCountersByFile is an method which is added just a compatibility for linux. func IOCountersByFile(pernic bool, filename string) ([]IOCountersStat, error) { return IOCounters(pernic) } func FilterCounters() ([]FilterStat, error) { return nil, errors.New("NetFilterCounters not implemented for openbsd") } // 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. // Not Implemented for OpenBSD func ProtoCounters(protocols []string) ([]ProtoCountersStat, error) { return nil, errors.New("NetProtoCounters not implemented for openbsd") } // Return a list of network connections opened. // Not Implemented for OpenBSD func Connections(kind string) ([]ConnectionStat, error) { return nil, errors.New("Connections not implemented for openbsd") } golang-github-shirou-gopsutil-2.17.08/net/net_test.go000066400000000000000000000117041315167550200225450ustar00rootroot00000000000000package 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) } } } golang-github-shirou-gopsutil-2.17.08/net/net_unix.go000066400000000000000000000033041315167550200225460ustar00rootroot00000000000000// +build freebsd darwin package net import ( "strings" "github.com/shirou/gopsutil/internal/common" ) // Return a list of network connections opened. func Connections(kind string) ([]ConnectionStat, error) { return ConnectionsPid(kind, 0) } // Return a list of network connections opened returning at most `max` // connections for each running process. func ConnectionsMax(kind string, max int) ([]ConnectionStat, error) { return []ConnectionStat{}, common.ErrNotImplementedError } // Return a list of network connections opened by a process. func ConnectionsPid(kind string, pid int32) ([]ConnectionStat, error) { var ret []ConnectionStat args := []string{"-i"} switch strings.ToLower(kind) { default: fallthrough case "": fallthrough case "all": fallthrough case "inet": args = append(args, "tcp", "-i", "udp") case "inet4": args = append(args, "4") case "inet6": args = append(args, "6") case "tcp": args = append(args, "tcp") case "tcp4": args = append(args, "4tcp") case "tcp6": args = append(args, "6tcp") case "udp": args = append(args, "udp") case "udp4": args = append(args, "6udp") case "udp6": args = append(args, "6udp") case "unix": return ret, common.ErrNotImplementedError } r, err := common.CallLsof(invoke, pid, args...) if err != nil { return nil, err } for _, rr := range r { if strings.HasPrefix(rr, "COMMAND") { continue } n, err := parseNetLine(rr) if err != nil { continue } ret = append(ret, n) } return ret, nil } // Return up to `max` network connections opened by a process. func ConnectionsPidMax(kind string, pid int32, max int) ([]ConnectionStat, error) { return []ConnectionStat{}, common.ErrNotImplementedError } golang-github-shirou-gopsutil-2.17.08/net/net_windows.go000066400000000000000000000046771315167550200232730ustar00rootroot00000000000000// +build windows package net import ( "errors" "net" "os" "github.com/shirou/gopsutil/internal/common" "golang.org/x/sys/windows" ) var ( modiphlpapi = windows.NewLazyDLL("iphlpapi.dll") procGetExtendedTCPTable = modiphlpapi.NewProc("GetExtendedTcpTable") procGetExtendedUDPTable = modiphlpapi.NewProc("GetExtendedUdpTable") ) const ( TCPTableBasicListener = iota TCPTableBasicConnections TCPTableBasicAll TCPTableOwnerPIDListener TCPTableOwnerPIDConnections TCPTableOwnerPIDAll TCPTableOwnerModuleListener TCPTableOwnerModuleConnections TCPTableOwnerModuleAll ) func IOCounters(pernic bool) ([]IOCountersStat, error) { ifs, err := net.Interfaces() if err != nil { return nil, err } var ret []IOCountersStat 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) } 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) } return ret, nil } // NetIOCountersByFile is an method which is added just a compatibility for linux. func IOCountersByFile(pernic bool, filename string) ([]IOCountersStat, error) { return IOCounters(pernic) } // Return a list of network connections opened by a process func Connections(kind string) ([]ConnectionStat, error) { var ret []ConnectionStat return ret, common.ErrNotImplementedError } // Return a list of network connections opened returning at most `max` // connections for each running process. func ConnectionsMax(kind string, max int) ([]ConnectionStat, error) { return []ConnectionStat{}, common.ErrNotImplementedError } func FilterCounters() ([]FilterStat, error) { return nil, errors.New("NetFilterCounters not implemented for windows") } // 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. // Not Implemented for Windows func ProtoCounters(protocols []string) ([]ProtoCountersStat, error) { return nil, errors.New("NetProtoCounters not implemented for windows") } golang-github-shirou-gopsutil-2.17.08/process/000077500000000000000000000000001315167550200212565ustar00rootroot00000000000000golang-github-shirou-gopsutil-2.17.08/process/process.go000066400000000000000000000115411315167550200232650ustar00rootroot00000000000000package process import ( "encoding/json" "runtime" "time" "github.com/shirou/gopsutil/cpu" "github.com/shirou/gopsutil/internal/common" "github.com/shirou/gopsutil/mem" ) var invoke common.Invoker func init() { invoke = common.Invoke{} } type Process struct { Pid int32 `json:"pid"` name string status string parent int32 numCtxSwitches *NumCtxSwitchesStat uids []int32 gids []int32 numThreads int32 memInfo *MemoryInfoStat sigInfo *SignalInfoStat lastCPUTimes *cpu.TimesStat lastCPUTime time.Time } type OpenFilesStat struct { Path string `json:"path"` Fd uint64 `json:"fd"` } type MemoryInfoStat struct { RSS uint64 `json:"rss"` // bytes VMS uint64 `json:"vms"` // bytes Data uint64 `json:"data"` // bytes Stack uint64 `json:"stack"` // bytes Locked uint64 `json:"locked"` // bytes Swap uint64 `json:"swap"` // bytes } type SignalInfoStat struct { PendingProcess uint64 `json:"pending_process"` PendingThread uint64 `json:"pending_thread"` Blocked uint64 `json:"blocked"` Ignored uint64 `json:"ignored"` Caught uint64 `json:"caught"` } type RlimitStat struct { Resource int32 `json:"resource"` Soft int32 `json:"soft"` //TODO too small. needs to be uint64 Hard int32 `json:"hard"` //TODO too small. needs to be uint64 Used uint64 `json:"used"` } type IOCountersStat struct { ReadCount uint64 `json:"readCount"` WriteCount uint64 `json:"writeCount"` ReadBytes uint64 `json:"readBytes"` WriteBytes uint64 `json:"writeBytes"` } type NumCtxSwitchesStat struct { Voluntary int64 `json:"voluntary"` Involuntary int64 `json:"involuntary"` } // Resource limit constants are from /usr/include/x86_64-linux-gnu/bits/resource.h // from libc6-dev package in Ubuntu 16.10 const ( RLIMIT_CPU int32 = 0 RLIMIT_FSIZE int32 = 1 RLIMIT_DATA int32 = 2 RLIMIT_STACK int32 = 3 RLIMIT_CORE int32 = 4 RLIMIT_RSS int32 = 5 RLIMIT_NPROC int32 = 6 RLIMIT_NOFILE int32 = 7 RLIMIT_MEMLOCK int32 = 8 RLIMIT_AS int32 = 9 RLIMIT_LOCKS int32 = 10 RLIMIT_SIGPENDING int32 = 11 RLIMIT_MSGQUEUE int32 = 12 RLIMIT_NICE int32 = 13 RLIMIT_RTPRIO int32 = 14 RLIMIT_RTTIME int32 = 15 ) func (p Process) String() string { s, _ := json.Marshal(p) return string(s) } func (o OpenFilesStat) String() string { s, _ := json.Marshal(o) return string(s) } func (m MemoryInfoStat) String() string { s, _ := json.Marshal(m) return string(s) } func (r RlimitStat) String() string { s, _ := json.Marshal(r) return string(s) } func (i IOCountersStat) String() string { s, _ := json.Marshal(i) return string(s) } func (p NumCtxSwitchesStat) String() string { s, _ := json.Marshal(p) return string(s) } func PidExists(pid int32) (bool, error) { pids, err := Pids() if err != nil { return false, err } for _, i := range pids { if i == pid { return true, err } } return false, err } // If interval is 0, return difference from last call(non-blocking). // If interval > 0, wait interval sec and return diffrence between start and end. func (p *Process) Percent(interval time.Duration) (float64, error) { cpuTimes, err := p.Times() if err != nil { return 0, err } now := time.Now() if interval > 0 { p.lastCPUTimes = cpuTimes p.lastCPUTime = now time.Sleep(interval) cpuTimes, err = p.Times() now = time.Now() if err != nil { return 0, err } } else { if p.lastCPUTimes == nil { // invoked first time p.lastCPUTimes = cpuTimes p.lastCPUTime = now return 0, nil } } numcpu := runtime.NumCPU() delta := (now.Sub(p.lastCPUTime).Seconds()) * float64(numcpu) ret := calculatePercent(p.lastCPUTimes, cpuTimes, delta, numcpu) p.lastCPUTimes = cpuTimes p.lastCPUTime = now return ret, nil } func calculatePercent(t1, t2 *cpu.TimesStat, delta float64, numcpu int) float64 { if delta == 0 { return 0 } delta_proc := t2.Total() - t1.Total() overall_percent := ((delta_proc / delta) * 100) * float64(numcpu) return overall_percent } // MemoryPercent returns how many percent of the total RAM this process uses func (p *Process) MemoryPercent() (float32, error) { machineMemory, err := mem.VirtualMemory() if err != nil { return 0, err } total := machineMemory.Total processMemory, err := p.MemoryInfo() if err != nil { return 0, err } used := processMemory.RSS return (100 * float32(used) / float32(total)), nil } // CPU_Percent returns how many percent of the CPU time this process uses func (p *Process) CPUPercent() (float64, error) { crt_time, err := p.CreateTime() if err != nil { return 0, err } cpu, err := p.Times() if err != nil { return 0, err } return (100 * (cpu.Total()) / float64(time.Now().Unix()-(crt_time/1000))), nil } golang-github-shirou-gopsutil-2.17.08/process/process_darwin.go000066400000000000000000000265101315167550200246330ustar00rootroot00000000000000// +build darwin package process import ( "bytes" "encoding/binary" "fmt" "os/exec" "strconv" "strings" "time" "unsafe" "github.com/shirou/gopsutil/cpu" "github.com/shirou/gopsutil/internal/common" "github.com/shirou/gopsutil/net" "golang.org/x/sys/unix" ) // copied from sys/sysctl.h const ( CTLKern = 1 // "high kernel": proc, limits KernProc = 14 // struct: process entries KernProcPID = 1 // by process id KernProcProc = 8 // only return procs KernProcAll = 0 // everything KernProcPathname = 12 // path to executable ) const ( ClockTicks = 100 // C.sysconf(C._SC_CLK_TCK) ) type _Ctype_struct___0 struct { Pad uint64 } // MemoryInfoExStat is different between OSes type MemoryInfoExStat struct { } type MemoryMapsStat struct { } func Pids() ([]int32, error) { var ret []int32 pids, err := callPs("pid", 0, false) if err != nil { return ret, err } for _, pid := range pids { v, err := strconv.Atoi(pid[0]) if err != nil { return ret, err } ret = append(ret, int32(v)) } return ret, nil } func (p *Process) Ppid() (int32, error) { r, err := callPs("ppid", p.Pid, false) if err != nil { return 0, err } v, err := strconv.Atoi(r[0][0]) if err != nil { return 0, err } return int32(v), err } func (p *Process) Name() (string, error) { k, err := p.getKProc() if err != nil { return "", err } return common.IntToString(k.Proc.P_comm[:]), nil } func (p *Process) Exe() (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) { r, err := callPs("command", p.Pid, false) if err != nil { return "", err } return strings.Join(r[0], " "), err } // CmdlineSlice returns the command line arguments of the process as a slice with each // element being an argument. Because of current deficiencies in the way that the command // line arguments are found, single arguments that have spaces in the will actually be // reported as two separate items. In order to do something better CGO would be needed // to use the native darwin functions. func (p *Process) CmdlineSlice() ([]string, error) { r, err := callPs("command", p.Pid, false) if err != nil { return nil, err } return r[0], err } func (p *Process) CreateTime() (int64, error) { r, err := callPs("etime", p.Pid, false) if err != nil { return 0, err } elapsedSegments := strings.Split(strings.Replace(r[0][0], "-", ":", 1), ":") var elapsedDurations []time.Duration for i := len(elapsedSegments) - 1; i >= 0; i-- { p, err := strconv.ParseInt(elapsedSegments[i], 10, 0) if err != nil { return 0, err } elapsedDurations = append(elapsedDurations, time.Duration(p)) } var elapsed = time.Duration(elapsedDurations[0]) * time.Second if len(elapsedDurations) > 1 { elapsed += time.Duration(elapsedDurations[1]) * time.Minute } if len(elapsedDurations) > 2 { elapsed += time.Duration(elapsedDurations[2]) * time.Hour } if len(elapsedDurations) > 3 { elapsed += time.Duration(elapsedDurations[3]) * time.Hour * 24 } start := time.Now().Add(-elapsed) return start.Unix() * 1000, nil } func (p *Process) Cwd() (string, error) { return "", common.ErrNotImplementedError } func (p *Process) Parent() (*Process, error) { rr, err := common.CallLsof(invoke, p.Pid, "-FR") if err != nil { return nil, err } for _, r := range rr { if strings.HasPrefix(r, "p") { // skip if process continue } l := string(r) v, err := strconv.Atoi(strings.Replace(l, "R", "", 1)) if err != nil { return nil, err } return NewProcess(int32(v)) } return nil, fmt.Errorf("could not find parent line") } func (p *Process) Status() (string, error) { r, err := callPs("state", p.Pid, false) if err != nil { return "", err } return r[0][0], err } func (p *Process) Uids() ([]int32, error) { k, err := p.getKProc() if err != nil { return nil, err } // See: http://unix.superglobalmegacorp.com/Net2/newsrc/sys/ucred.h.html userEffectiveUID := int32(k.Eproc.Ucred.UID) return []int32{userEffectiveUID}, nil } func (p *Process) Gids() ([]int32, error) { k, err := p.getKProc() if err != nil { return nil, err } gids := make([]int32, 0, 3) gids = append(gids, int32(k.Eproc.Pcred.P_rgid), int32(k.Eproc.Ucred.Ngroups), int32(k.Eproc.Pcred.P_svgid)) return gids, nil } func (p *Process) Terminal() (string, error) { return "", common.ErrNotImplementedError /* k, err := p.getKProc() if err != nil { return "", err } ttyNr := uint64(k.Eproc.Tdev) termmap, err := getTerminalMap() if err != nil { return "", err } return termmap[ttyNr], nil */ } func (p *Process) Nice() (int32, error) { k, err := p.getKProc() if err != nil { return 0, err } return int32(k.Proc.P_nice), nil } func (p *Process) IOnice() (int32, error) { return 0, common.ErrNotImplementedError } func (p *Process) Rlimit() ([]RlimitStat, error) { var rlimit []RlimitStat return rlimit, common.ErrNotImplementedError } func (p *Process) RlimitUsage(_ bool) ([]RlimitStat, error) { var rlimit []RlimitStat return rlimit, common.ErrNotImplementedError } func (p *Process) IOCounters() (*IOCountersStat, error) { return nil, common.ErrNotImplementedError } func (p *Process) NumCtxSwitches() (*NumCtxSwitchesStat, error) { return nil, common.ErrNotImplementedError } func (p *Process) NumFDs() (int32, error) { return 0, common.ErrNotImplementedError } func (p *Process) NumThreads() (int32, error) { r, err := callPs("utime,stime", p.Pid, true) if err != nil { return 0, err } return int32(len(r)), nil } func (p *Process) Threads() (map[string]string, error) { ret := make(map[string]string, 0) return ret, common.ErrNotImplementedError } func convertCPUTimes(s string) (ret float64, err error) { var t int var _tmp string if strings.Contains(s, ":") { _t := strings.Split(s, ":") hour, err := strconv.Atoi(_t[0]) if err != nil { return ret, err } t += hour * 60 * 100 _tmp = _t[1] } else { _tmp = s } _t := strings.Split(_tmp, ".") if err != nil { return ret, err } h, err := strconv.Atoi(_t[0]) t += h * 100 h, err = strconv.Atoi(_t[1]) t += h return float64(t) / ClockTicks, nil } func (p *Process) Times() (*cpu.TimesStat, error) { r, err := callPs("utime,stime", p.Pid, false) if err != nil { return nil, err } utime, err := convertCPUTimes(r[0][0]) if err != nil { return nil, err } stime, err := convertCPUTimes(r[0][1]) if err != nil { return nil, err } ret := &cpu.TimesStat{ CPU: "cpu", User: utime, System: stime, } return ret, nil } func (p *Process) CPUAffinity() ([]int32, error) { return nil, common.ErrNotImplementedError } func (p *Process) MemoryInfo() (*MemoryInfoStat, error) { r, err := callPs("rss,vsize,pagein", p.Pid, false) if err != nil { return nil, err } rss, err := strconv.Atoi(r[0][0]) if err != nil { return nil, err } vms, err := strconv.Atoi(r[0][1]) if err != nil { return nil, err } pagein, err := strconv.Atoi(r[0][2]) if err != nil { return nil, err } ret := &MemoryInfoStat{ RSS: uint64(rss) * 1024, VMS: uint64(vms) * 1024, Swap: uint64(pagein), } return ret, nil } func (p *Process) MemoryInfoEx() (*MemoryInfoExStat, error) { return nil, common.ErrNotImplementedError } func (p *Process) Children() ([]*Process, error) { pids, err := common.CallPgrep(invoke, p.Pid) if err != nil { return nil, err } ret := make([]*Process, 0, len(pids)) for _, pid := range pids { np, err := NewProcess(pid) if err != nil { return nil, err } ret = append(ret, np) } return ret, nil } func (p *Process) OpenFiles() ([]OpenFilesStat, error) { return nil, common.ErrNotImplementedError } func (p *Process) Connections() ([]net.ConnectionStat, error) { return net.ConnectionsPid("all", p.Pid) } func (p *Process) NetIOCounters(pernic bool) ([]net.IOCountersStat, error) { return nil, common.ErrNotImplementedError } func (p *Process) IsRunning() (bool, error) { return true, common.ErrNotImplementedError } func (p *Process) MemoryMaps(grouped bool) (*[]MemoryMapsStat, error) { var ret []MemoryMapsStat return &ret, common.ErrNotImplementedError } func processes() ([]Process, error) { results := make([]Process, 0, 50) mib := []int32{CTLKern, KernProc, KernProcAll, 0} buf, length, err := common.CallSyscall(mib) if err != nil { return results, err } // get kinfo_proc size k := KinfoProc{} procinfoLen := int(unsafe.Sizeof(k)) count := int(length / uint64(procinfoLen)) /* fmt.Println(length, procinfoLen, count) b := buf[0*procinfoLen : 0*procinfoLen+procinfoLen] fmt.Println(b) kk, err := parseKinfoProc(b) fmt.Printf("%#v", kk) */ // parse buf to procs for i := 0; i < count; i++ { b := buf[i*procinfoLen : i*procinfoLen+procinfoLen] k, err := parseKinfoProc(b) if err != nil { continue } p, err := NewProcess(int32(k.Proc.P_pid)) if err != nil { continue } results = append(results, *p) } return results, nil } func parseKinfoProc(buf []byte) (KinfoProc, error) { var k KinfoProc br := bytes.NewReader(buf) err := common.Read(br, binary.LittleEndian, &k) if err != nil { return k, err } return k, nil } // Returns a proc as defined here: // http://unix.superglobalmegacorp.com/Net2/newsrc/sys/kinfo_proc.h.html func (p *Process) getKProc() (*KinfoProc, error) { mib := []int32{CTLKern, KernProc, KernProcPID, p.Pid} procK := KinfoProc{} length := uint64(unsafe.Sizeof(procK)) buf := make([]byte, length) _, _, syserr := unix.Syscall6( unix.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), uintptr(len(mib)), uintptr(unsafe.Pointer(&buf[0])), uintptr(unsafe.Pointer(&length)), 0, 0) if syserr != 0 { return nil, syserr } k, err := parseKinfoProc(buf) if err != nil { return nil, err } 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) { bin, err := exec.LookPath("ps") if err != nil { return [][]string{}, err } var cmd []string if pid == 0 { // will get from all processes. cmd = []string{"-ax", "-o", arg} } else if threadOption { cmd = []string{"-x", "-o", arg, "-M", "-p", strconv.Itoa(int(pid))} } else { cmd = []string{"-x", "-o", arg, "-p", strconv.Itoa(int(pid))} } out, err := invoke.Command(bin, cmd...) if err != nil { return [][]string{}, err } lines := strings.Split(string(out), "\n") var ret [][]string for _, l := range lines[1:] { var lr []string for _, r := range strings.Split(l, " ") { if r == "" { continue } lr = append(lr, strings.TrimSpace(r)) } if len(lr) != 0 { ret = append(ret, lr) } } return ret, nil } golang-github-shirou-gopsutil-2.17.08/process/process_darwin_386.go000066400000000000000000000070161315167550200252330ustar00rootroot00000000000000// Created by cgo -godefs - DO NOT EDIT // cgo -godefs types_darwin.go package process const ( sizeofPtr = 0x8 sizeofShort = 0x2 sizeofInt = 0x4 sizeofLong = 0x8 sizeofLongLong = 0x8 ) type ( _C_short int16 _C_int int32 _C_long int64 _C_long_long int64 ) type Timespec struct { Sec int64 Nsec int64 } type Timeval struct { Sec int64 Usec int32 Pad_cgo_0 [4]byte } type Rusage struct { Utime Timeval Stime Timeval Maxrss int64 Ixrss int64 Idrss int64 Isrss int64 Minflt int64 Majflt int64 Nswap int64 Inblock int64 Oublock int64 Msgsnd int64 Msgrcv int64 Nsignals int64 Nvcsw int64 Nivcsw int64 } type Rlimit struct { Cur uint64 Max uint64 } type UGid_t uint32 type KinfoProc struct { Proc ExternProc Eproc Eproc } type Eproc struct { Paddr *uint64 Sess *Session Pcred Upcred Ucred Uucred Pad_cgo_0 [4]byte Vm Vmspace Ppid int32 Pgid int32 Jobc int16 Pad_cgo_1 [2]byte Tdev int32 Tpgid int32 Pad_cgo_2 [4]byte Tsess *Session Wmesg [8]int8 Xsize int32 Xrssize int16 Xccount int16 Xswrss int16 Pad_cgo_3 [2]byte Flag int32 Login [12]int8 Spare [4]int32 Pad_cgo_4 [4]byte } type Proc struct{} type Session struct{} type ucred struct { Link _Ctype_struct___0 Ref uint64 Posix Posix_cred Label *Label Audit Au_session } type Uucred struct { Ref int32 UID uint32 Ngroups int16 Pad_cgo_0 [2]byte Groups [16]uint32 } type Upcred struct { Pc_lock [72]int8 Pc_ucred *ucred P_ruid uint32 P_svuid uint32 P_rgid uint32 P_svgid uint32 P_refcnt int32 Pad_cgo_0 [4]byte } type Vmspace struct { Dummy int32 Pad_cgo_0 [4]byte Dummy2 *int8 Dummy3 [5]int32 Pad_cgo_1 [4]byte Dummy4 [3]*int8 } type Sigacts struct{} type ExternProc struct { P_un [16]byte P_vmspace uint64 P_sigacts uint64 Pad_cgo_0 [3]byte P_flag int32 P_stat int8 P_pid int32 P_oppid int32 P_dupfd int32 Pad_cgo_1 [4]byte User_stack uint64 Exit_thread uint64 P_debugger int32 Sigwait int32 P_estcpu uint32 P_cpticks int32 P_pctcpu uint32 Pad_cgo_2 [4]byte P_wchan uint64 P_wmesg uint64 P_swtime uint32 P_slptime uint32 P_realtimer Itimerval P_rtime Timeval P_uticks uint64 P_sticks uint64 P_iticks uint64 P_traceflag int32 Pad_cgo_3 [4]byte P_tracep uint64 P_siglist int32 Pad_cgo_4 [4]byte P_textvp uint64 P_holdcnt int32 P_sigmask uint32 P_sigignore uint32 P_sigcatch uint32 P_priority uint8 P_usrpri uint8 P_nice int8 P_comm [17]int8 Pad_cgo_5 [4]byte P_pgrp uint64 P_addr uint64 P_xstat uint16 P_acflag uint16 Pad_cgo_6 [4]byte P_ru uint64 } type Itimerval struct { Interval Timeval Value Timeval } type Vnode struct{} type Pgrp struct{} type UserStruct struct{} type Au_session struct { Aia_p *AuditinfoAddr Mask AuMask } type Posix_cred struct { UID uint32 Ruid uint32 Svuid uint32 Ngroups int16 Pad_cgo_0 [2]byte Groups [16]uint32 Rgid uint32 Svgid uint32 Gmuid uint32 Flags int32 } type Label struct{} type AuditinfoAddr struct { Auid uint32 Mask AuMask Termid AuTidAddr Asid int32 Flags uint64 } type AuMask struct { Success uint32 Failure uint32 } type AuTidAddr struct { Port int32 Type uint32 Addr [4]uint32 } type UcredQueue struct { Next *ucred Prev **ucred } golang-github-shirou-gopsutil-2.17.08/process/process_darwin_amd64.go000066400000000000000000000070161315167550200256260ustar00rootroot00000000000000// Created by cgo -godefs - DO NOT EDIT // cgo -godefs types_darwin.go package process const ( sizeofPtr = 0x8 sizeofShort = 0x2 sizeofInt = 0x4 sizeofLong = 0x8 sizeofLongLong = 0x8 ) type ( _C_short int16 _C_int int32 _C_long int64 _C_long_long int64 ) type Timespec struct { Sec int64 Nsec int64 } type Timeval struct { Sec int64 Usec int32 Pad_cgo_0 [4]byte } type Rusage struct { Utime Timeval Stime Timeval Maxrss int64 Ixrss int64 Idrss int64 Isrss int64 Minflt int64 Majflt int64 Nswap int64 Inblock int64 Oublock int64 Msgsnd int64 Msgrcv int64 Nsignals int64 Nvcsw int64 Nivcsw int64 } type Rlimit struct { Cur uint64 Max uint64 } type UGid_t uint32 type KinfoProc struct { Proc ExternProc Eproc Eproc } type Eproc struct { Paddr *uint64 Sess *Session Pcred Upcred Ucred Uucred Pad_cgo_0 [4]byte Vm Vmspace Ppid int32 Pgid int32 Jobc int16 Pad_cgo_1 [2]byte Tdev int32 Tpgid int32 Pad_cgo_2 [4]byte Tsess *Session Wmesg [8]int8 Xsize int32 Xrssize int16 Xccount int16 Xswrss int16 Pad_cgo_3 [2]byte Flag int32 Login [12]int8 Spare [4]int32 Pad_cgo_4 [4]byte } type Proc struct{} type Session struct{} type ucred struct { Link _Ctype_struct___0 Ref uint64 Posix Posix_cred Label *Label Audit Au_session } type Uucred struct { Ref int32 UID uint32 Ngroups int16 Pad_cgo_0 [2]byte Groups [16]uint32 } type Upcred struct { Pc_lock [72]int8 Pc_ucred *ucred P_ruid uint32 P_svuid uint32 P_rgid uint32 P_svgid uint32 P_refcnt int32 Pad_cgo_0 [4]byte } type Vmspace struct { Dummy int32 Pad_cgo_0 [4]byte Dummy2 *int8 Dummy3 [5]int32 Pad_cgo_1 [4]byte Dummy4 [3]*int8 } type Sigacts struct{} type ExternProc struct { P_un [16]byte P_vmspace uint64 P_sigacts uint64 Pad_cgo_0 [3]byte P_flag int32 P_stat int8 P_pid int32 P_oppid int32 P_dupfd int32 Pad_cgo_1 [4]byte User_stack uint64 Exit_thread uint64 P_debugger int32 Sigwait int32 P_estcpu uint32 P_cpticks int32 P_pctcpu uint32 Pad_cgo_2 [4]byte P_wchan uint64 P_wmesg uint64 P_swtime uint32 P_slptime uint32 P_realtimer Itimerval P_rtime Timeval P_uticks uint64 P_sticks uint64 P_iticks uint64 P_traceflag int32 Pad_cgo_3 [4]byte P_tracep uint64 P_siglist int32 Pad_cgo_4 [4]byte P_textvp uint64 P_holdcnt int32 P_sigmask uint32 P_sigignore uint32 P_sigcatch uint32 P_priority uint8 P_usrpri uint8 P_nice int8 P_comm [17]int8 Pad_cgo_5 [4]byte P_pgrp uint64 P_addr uint64 P_xstat uint16 P_acflag uint16 Pad_cgo_6 [4]byte P_ru uint64 } type Itimerval struct { Interval Timeval Value Timeval } type Vnode struct{} type Pgrp struct{} type UserStruct struct{} type Au_session struct { Aia_p *AuditinfoAddr Mask AuMask } type Posix_cred struct { UID uint32 Ruid uint32 Svuid uint32 Ngroups int16 Pad_cgo_0 [2]byte Groups [16]uint32 Rgid uint32 Svgid uint32 Gmuid uint32 Flags int32 } type Label struct{} type AuditinfoAddr struct { Auid uint32 Mask AuMask Termid AuTidAddr Asid int32 Flags uint64 } type AuMask struct { Success uint32 Failure uint32 } type AuTidAddr struct { Port int32 Type uint32 Addr [4]uint32 } type UcredQueue struct { Next *ucred Prev **ucred } golang-github-shirou-gopsutil-2.17.08/process/process_fallback.go000066400000000000000000000105021315167550200251000ustar00rootroot00000000000000// +build !darwin,!linux,!freebsd,!openbsd,!windows package process import ( "syscall" "github.com/shirou/gopsutil/cpu" "github.com/shirou/gopsutil/internal/common" "github.com/shirou/gopsutil/net" ) type MemoryMapsStat struct { Path string `json:"path"` Rss uint64 `json:"rss"` Size uint64 `json:"size"` Pss uint64 `json:"pss"` SharedClean uint64 `json:"sharedClean"` SharedDirty uint64 `json:"sharedDirty"` PrivateClean uint64 `json:"privateClean"` PrivateDirty uint64 `json:"privateDirty"` Referenced uint64 `json:"referenced"` Anonymous uint64 `json:"anonymous"` Swap uint64 `json:"swap"` } type MemoryInfoExStat struct { } func Pids() ([]int32, error) { return []int32{}, common.ErrNotImplementedError } func NewProcess(pid int32) (*Process, error) { return nil, common.ErrNotImplementedError } func (p *Process) Ppid() (int32, error) { return 0, common.ErrNotImplementedError } func (p *Process) Name() (string, error) { return "", common.ErrNotImplementedError } func (p *Process) Exe() (string, error) { return "", common.ErrNotImplementedError } func (p *Process) Cmdline() (string, error) { return "", common.ErrNotImplementedError } func (p *Process) CmdlineSlice() ([]string, error) { return []string{}, common.ErrNotImplementedError } func (p *Process) CreateTime() (int64, error) { return 0, common.ErrNotImplementedError } func (p *Process) Cwd() (string, error) { return "", common.ErrNotImplementedError } func (p *Process) Parent() (*Process, error) { return nil, common.ErrNotImplementedError } func (p *Process) Status() (string, error) { return "", common.ErrNotImplementedError } func (p *Process) Uids() ([]int32, error) { return []int32{}, common.ErrNotImplementedError } func (p *Process) Gids() ([]int32, error) { return []int32{}, common.ErrNotImplementedError } func (p *Process) Terminal() (string, error) { return "", common.ErrNotImplementedError } func (p *Process) Nice() (int32, error) { return 0, common.ErrNotImplementedError } func (p *Process) IOnice() (int32, error) { return 0, common.ErrNotImplementedError } func (p *Process) Rlimit() ([]RlimitStat, error) { return nil, common.ErrNotImplementedError } func (p *Process) RlimitUsage(_ bool) ([]RlimitStat, error) { return nil, common.ErrNotImplementedError } func (p *Process) IOCounters() (*IOCountersStat, error) { return nil, common.ErrNotImplementedError } func (p *Process) NumCtxSwitches() (*NumCtxSwitchesStat, error) { return nil, common.ErrNotImplementedError } func (p *Process) NumFDs() (int32, error) { return 0, common.ErrNotImplementedError } func (p *Process) NumThreads() (int32, error) { return 0, common.ErrNotImplementedError } func (p *Process) Threads() (map[string]string, error) { return nil, common.ErrNotImplementedError } func (p *Process) Times() (*cpu.TimesStat, error) { return nil, common.ErrNotImplementedError } func (p *Process) CPUAffinity() ([]int32, error) { return nil, common.ErrNotImplementedError } func (p *Process) MemoryInfo() (*MemoryInfoStat, error) { return nil, common.ErrNotImplementedError } func (p *Process) MemoryInfoEx() (*MemoryInfoExStat, error) { return nil, common.ErrNotImplementedError } func (p *Process) Children() ([]*Process, error) { return nil, common.ErrNotImplementedError } func (p *Process) OpenFiles() ([]OpenFilesStat, error) { return []OpenFilesStat{}, common.ErrNotImplementedError } func (p *Process) Connections() ([]net.ConnectionStat, error) { return []net.ConnectionStat{}, common.ErrNotImplementedError } func (p *Process) NetIOCounters(pernic bool) ([]net.IOCountersStat, error) { return []net.IOCountersStat{}, common.ErrNotImplementedError } func (p *Process) IsRunning() (bool, error) { return true, common.ErrNotImplementedError } func (p *Process) MemoryMaps(grouped bool) (*[]MemoryMapsStat, error) { return nil, common.ErrNotImplementedError } func (p *Process) SendSignal(sig syscall.Signal) error { return common.ErrNotImplementedError } func (p *Process) Suspend() error { return common.ErrNotImplementedError } func (p *Process) Resume() error { return common.ErrNotImplementedError } func (p *Process) Terminate() error { return common.ErrNotImplementedError } func (p *Process) Kill() error { return common.ErrNotImplementedError } func (p *Process) Username() (string, error) { return "", common.ErrNotImplementedError } golang-github-shirou-gopsutil-2.17.08/process/process_freebsd.go000066400000000000000000000156641315167550200247710ustar00rootroot00000000000000// +build freebsd package process import ( "bytes" "encoding/binary" "strings" cpu "github.com/shirou/gopsutil/cpu" "github.com/shirou/gopsutil/internal/common" net "github.com/shirou/gopsutil/net" "golang.org/x/sys/unix" ) // MemoryInfoExStat is different between OSes type MemoryInfoExStat struct { } type MemoryMapsStat struct { } func Pids() ([]int32, error) { var ret []int32 procs, err := processes() if err != nil { return ret, nil } for _, p := range procs { ret = append(ret, p.Pid) } return ret, nil } func (p *Process) Ppid() (int32, error) { k, err := p.getKProc() if err != nil { return 0, err } return k.Ppid, nil } func (p *Process) Name() (string, error) { k, err := p.getKProc() if err != nil { return "", err } return common.IntToString(k.Comm[:]), nil } func (p *Process) Exe() (string, error) { return "", common.ErrNotImplementedError } func (p *Process) Cmdline() (string, error) { mib := []int32{CTLKern, KernProc, KernProcArgs, p.Pid} buf, _, err := common.CallSyscall(mib) if err != nil { return "", err } ret := strings.FieldsFunc(string(buf), func(r rune) bool { if r == '\u0000' { return true } return false }) return strings.Join(ret, " "), nil } func (p *Process) CmdlineSlice() ([]string, error) { mib := []int32{CTLKern, KernProc, KernProcArgs, p.Pid} buf, _, err := common.CallSyscall(mib) if err != nil { return nil, err } if len(buf) == 0 { return nil, nil } if buf[len(buf)-1] == 0 { buf = buf[:len(buf)-1] } parts := bytes.Split(buf, []byte{0}) var strParts []string for _, p := range parts { strParts = append(strParts, string(p)) } return strParts, nil } func (p *Process) CreateTime() (int64, error) { return 0, common.ErrNotImplementedError } func (p *Process) Cwd() (string, error) { return "", common.ErrNotImplementedError } func (p *Process) Parent() (*Process, error) { return p, common.ErrNotImplementedError } func (p *Process) Status() (string, error) { k, err := p.getKProc() if err != nil { return "", err } var s string switch k.Stat { case SIDL: s = "I" case SRUN: s = "R" case SSLEEP: s = "S" case SSTOP: s = "T" case SZOMB: s = "Z" case SWAIT: s = "W" case SLOCK: s = "L" } return s, nil } func (p *Process) Uids() ([]int32, error) { k, err := p.getKProc() if err != nil { return nil, err } uids := make([]int32, 0, 3) uids = append(uids, int32(k.Ruid), int32(k.Uid), int32(k.Svuid)) return uids, nil } func (p *Process) Gids() ([]int32, error) { k, err := p.getKProc() if err != nil { return nil, err } gids := make([]int32, 0, 3) gids = append(gids, int32(k.Rgid), int32(k.Ngroups), int32(k.Svgid)) return gids, nil } func (p *Process) Terminal() (string, error) { k, err := p.getKProc() if err != nil { return "", err } ttyNr := uint64(k.Tdev) termmap, err := getTerminalMap() if err != nil { return "", err } return termmap[ttyNr], nil } func (p *Process) Nice() (int32, error) { k, err := p.getKProc() if err != nil { return 0, err } return int32(k.Nice), nil } func (p *Process) IOnice() (int32, error) { return 0, common.ErrNotImplementedError } func (p *Process) Rlimit() ([]RlimitStat, error) { var rlimit []RlimitStat return rlimit, common.ErrNotImplementedError } func (p *Process) RlimitUsage(_ bool) ([]RlimitStat, error) { var rlimit []RlimitStat return rlimit, common.ErrNotImplementedError } func (p *Process) IOCounters() (*IOCountersStat, error) { k, err := p.getKProc() if err != nil { return nil, err } return &IOCountersStat{ ReadCount: uint64(k.Rusage.Inblock), WriteCount: uint64(k.Rusage.Oublock), }, nil } func (p *Process) NumCtxSwitches() (*NumCtxSwitchesStat, error) { return nil, common.ErrNotImplementedError } func (p *Process) NumFDs() (int32, error) { return 0, common.ErrNotImplementedError } func (p *Process) NumThreads() (int32, error) { k, err := p.getKProc() if err != nil { return 0, err } return k.Numthreads, nil } func (p *Process) Threads() (map[string]string, error) { ret := make(map[string]string, 0) return ret, common.ErrNotImplementedError } func (p *Process) Times() (*cpu.TimesStat, error) { k, err := p.getKProc() if err != nil { return nil, err } return &cpu.TimesStat{ CPU: "cpu", User: float64(k.Rusage.Utime.Sec) + float64(k.Rusage.Utime.Usec)/1000000, System: float64(k.Rusage.Stime.Sec) + float64(k.Rusage.Stime.Usec)/1000000, }, nil } func (p *Process) CPUAffinity() ([]int32, error) { return nil, common.ErrNotImplementedError } func (p *Process) MemoryInfo() (*MemoryInfoStat, error) { k, err := p.getKProc() if err != nil { return nil, err } v, err := unix.Sysctl("vm.stats.vm.v_page_size") if err != nil { return nil, err } pageSize := common.LittleEndian.Uint16([]byte(v)) return &MemoryInfoStat{ RSS: uint64(k.Rssize) * uint64(pageSize), VMS: uint64(k.Size), }, nil } func (p *Process) MemoryInfoEx() (*MemoryInfoExStat, error) { return nil, common.ErrNotImplementedError } func (p *Process) Children() ([]*Process, error) { pids, err := common.CallPgrep(invoke, p.Pid) if err != nil { return nil, err } ret := make([]*Process, 0, len(pids)) for _, pid := range pids { np, err := NewProcess(pid) if err != nil { return nil, err } ret = append(ret, np) } return ret, nil } func (p *Process) OpenFiles() ([]OpenFilesStat, error) { return nil, common.ErrNotImplementedError } func (p *Process) Connections() ([]net.ConnectionStat, error) { return nil, common.ErrNotImplementedError } func (p *Process) NetIOCounters(pernic bool) ([]net.IOCountersStat, error) { return nil, common.ErrNotImplementedError } func (p *Process) IsRunning() (bool, error) { return true, common.ErrNotImplementedError } func (p *Process) MemoryMaps(grouped bool) (*[]MemoryMapsStat, error) { var ret []MemoryMapsStat return &ret, common.ErrNotImplementedError } func processes() ([]Process, error) { results := make([]Process, 0, 50) mib := []int32{CTLKern, KernProc, KernProcProc, 0} buf, length, err := common.CallSyscall(mib) if err != nil { return results, err } // get kinfo_proc size count := int(length / uint64(sizeOfKinfoProc)) // parse buf to procs for i := 0; i < count; i++ { b := buf[i*sizeOfKinfoProc : (i+1)*sizeOfKinfoProc] k, err := parseKinfoProc(b) if err != nil { continue } p, err := NewProcess(int32(k.Pid)) if err != nil { continue } results = append(results, *p) } return results, nil } func parseKinfoProc(buf []byte) (KinfoProc, error) { var k KinfoProc br := bytes.NewReader(buf) err := common.Read(br, binary.LittleEndian, &k) return k, err } func (p *Process) getKProc() (*KinfoProc, error) { mib := []int32{CTLKern, KernProc, KernProcPID, p.Pid} buf, length, err := common.CallSyscall(mib) if err != nil { return nil, err } if length != sizeOfKinfoProc { return nil, err } k, err := parseKinfoProc(buf) if err != nil { return nil, err } return &k, nil } func NewProcess(pid int32) (*Process, error) { p := &Process{Pid: pid} return p, nil } golang-github-shirou-gopsutil-2.17.08/process/process_freebsd_386.go000066400000000000000000000067311315167550200253640ustar00rootroot00000000000000// Created by cgo -godefs - DO NOT EDIT // cgo -godefs types_freebsd.go package process const ( CTLKern = 1 KernProc = 14 KernProcPID = 1 KernProcProc = 8 KernProcPathname = 12 KernProcArgs = 7 ) const ( sizeofPtr = 0x4 sizeofShort = 0x2 sizeofInt = 0x4 sizeofLong = 0x4 sizeofLongLong = 0x8 ) const ( sizeOfKinfoVmentry = 0x488 sizeOfKinfoProc = 0x300 ) const ( SIDL = 1 SRUN = 2 SSLEEP = 3 SSTOP = 4 SZOMB = 5 SWAIT = 6 SLOCK = 7 ) type ( _C_short int16 _C_int int32 _C_long int32 _C_long_long int64 ) type Timespec struct { Sec int32 Nsec int32 } type Timeval struct { Sec int32 Usec int32 } type Rusage struct { Utime Timeval Stime Timeval Maxrss int32 Ixrss int32 Idrss int32 Isrss int32 Minflt int32 Majflt int32 Nswap int32 Inblock int32 Oublock int32 Msgsnd int32 Msgrcv int32 Nsignals int32 Nvcsw int32 Nivcsw int32 } type Rlimit struct { Cur int64 Max int64 } type KinfoProc struct { Structsize int32 Layout int32 Args int32 /* pargs */ Paddr int32 /* proc */ Addr int32 /* user */ Tracep int32 /* vnode */ Textvp int32 /* vnode */ Fd int32 /* filedesc */ Vmspace int32 /* vmspace */ Wchan int32 Pid int32 Ppid int32 Pgid int32 Tpgid int32 Sid int32 Tsid int32 Jobc int16 Spare_short1 int16 Tdev 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 uint32 Rssize int32 Swrss int32 Tsize int32 Dsize int32 Ssize int32 Xstat uint16 Acflag uint16 Pctcpu uint32 Estcpu uint32 Slptime uint32 Swtime uint32 Cow uint32 Runtime uint64 Start Timeval Childtime Timeval Flag int32 Kiflag int32 Traceflag int32 Stat int8 Nice int8 Lock int8 Rqindex int8 Oncpu uint8 Lastcpu uint8 Tdname [17]int8 Wmesg [9]int8 Login [18]int8 Lockname [9]int8 Comm [20]int8 Emul [17]int8 Loginclass [18]int8 Sparestrings [50]int8 Spareints [7]int32 Flag2 int32 Fibnum int32 Cr_flags uint32 Jid int32 Numthreads int32 Tid int32 Pri Priority Rusage Rusage Rusage_ch Rusage Pcb int32 /* pcb */ Kstack int32 Udata int32 Tdaddr int32 /* thread */ Spareptrs [6]int32 Sparelongs [12]int32 Sflag int32 Tdflags int32 } 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 uint32 Flags int32 Resident int32 Private_resident int32 Protection int32 Ref_count int32 Shadow_count int32 Vn_type int32 Vn_size uint64 Vn_rdev uint32 Vn_mode uint16 Status uint16 X_kve_ispare [12]int32 Path [1024]int8 } golang-github-shirou-gopsutil-2.17.08/process/process_freebsd_amd64.go000066400000000000000000000067311315167550200257570ustar00rootroot00000000000000// Created by cgo -godefs - DO NOT EDIT // cgo -godefs 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 int64 Pid int32 Ppid int32 Pgid int32 Tpgid int32 Sid int32 Tsid int32 Jobc int16 Spare_short1 int16 Tdev 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 int8 Nice int8 Lock int8 Rqindex int8 Oncpu uint8 Lastcpu uint8 Tdname [17]int8 Wmesg [9]int8 Login [18]int8 Lockname [9]int8 Comm [20]int8 Emul [17]int8 Loginclass [18]int8 Sparestrings [50]int8 Spareints [7]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 int64 Udata int64 Tdaddr int64 /* thread */ Spareptrs [6]int64 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 uint32 Flags int32 Resident int32 Private_resident int32 Protection int32 Ref_count int32 Shadow_count int32 Vn_type int32 Vn_size uint64 Vn_rdev uint32 Vn_mode uint16 Status uint16 X_kve_ispare [12]int32 Path [1024]int8 } golang-github-shirou-gopsutil-2.17.08/process/process_freebsd_arm.go000066400000000000000000000067311315167550200256230ustar00rootroot00000000000000// Created by cgo -godefs - DO NOT EDIT // cgo -godefs types_freebsd.go package process const ( CTLKern = 1 KernProc = 14 KernProcPID = 1 KernProcProc = 8 KernProcPathname = 12 KernProcArgs = 7 ) const ( sizeofPtr = 0x4 sizeofShort = 0x2 sizeofInt = 0x4 sizeofLong = 0x4 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 int32 _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 int32 Ixrss int32 Idrss int32 Isrss int32 Minflt int32 Majflt int32 Nswap int32 Inblock int32 Oublock int32 Msgsnd int32 Msgrcv int32 Nsignals int32 Nvcsw int32 Nivcsw int32 } type Rlimit struct { Cur int32 Max int32 } type KinfoProc struct { Structsize int32 Layout int32 Args int32 /* pargs */ Paddr int32 /* proc */ Addr int32 /* user */ Tracep int32 /* vnode */ Textvp int32 /* vnode */ Fd int32 /* filedesc */ Vmspace int32 /* vmspace */ Wchan int32 Pid int32 Ppid int32 Pgid int32 Tpgid int32 Sid int32 Tsid int32 Jobc int16 Spare_short1 int16 Tdev 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 uint32 Rssize int32 Swrss int32 Tsize int32 Dsize int32 Ssize int32 Xstat uint16 Acflag uint16 Pctcpu uint32 Estcpu uint32 Slptime uint32 Swtime uint32 Cow uint32 Runtime uint64 Start Timeval Childtime Timeval Flag int32 Kiflag int32 Traceflag int32 Stat int8 Nice int8 Lock int8 Rqindex int8 Oncpu uint8 Lastcpu uint8 Tdname [17]int8 Wmesg [9]int8 Login [18]int8 Lockname [9]int8 Comm [20]int8 Emul [17]int8 Loginclass [18]int8 Sparestrings [50]int8 Spareints [4]int32 Flag2 int32 Fibnum int32 Cr_flags uint32 Jid int32 Numthreads int32 Tid int32 Pri Priority Rusage Rusage Rusage_ch Rusage Pcb int32 /* pcb */ Kstack int32 Udata int32 Tdaddr int32 /* thread */ Spareptrs [6]int64 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 uint32 Flags int32 Resident int32 Private_resident int32 Protection int32 Ref_count int32 Shadow_count int32 Vn_type int32 Vn_size uint64 Vn_rdev uint32 Vn_mode uint16 Status uint16 X_kve_ispare [12]int32 Path [1024]int8 } golang-github-shirou-gopsutil-2.17.08/process/process_linux.go000066400000000000000000000601221315167550200245030ustar00rootroot00000000000000// +build linux package process import ( "bufio" "bytes" "encoding/json" "errors" "fmt" "io/ioutil" "math" "os" "path/filepath" "strconv" "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()) ) const ( PrioProcess = 0 // linux/resource.h ClockTicks = 100 // C.sysconf(C._SC_CLK_TCK) ) // MemoryInfoExStat is different between OSes type MemoryInfoExStat struct { RSS uint64 `json:"rss"` // bytes VMS uint64 `json:"vms"` // bytes Shared uint64 `json:"shared"` // bytes Text uint64 `json:"text"` // bytes Lib uint64 `json:"lib"` // bytes Data uint64 `json:"data"` // bytes Dirty uint64 `json:"dirty"` // bytes } func (m MemoryInfoExStat) String() string { s, _ := json.Marshal(m) return string(s) } type MemoryMapsStat struct { Path string `json:"path"` Rss uint64 `json:"rss"` Size uint64 `json:"size"` Pss uint64 `json:"pss"` SharedClean uint64 `json:"sharedClean"` SharedDirty uint64 `json:"sharedDirty"` PrivateClean uint64 `json:"privateClean"` PrivateDirty uint64 `json:"privateDirty"` Referenced uint64 `json:"referenced"` Anonymous uint64 `json:"anonymous"` Swap uint64 `json:"swap"` } // String returns JSON value of the process. func (m MemoryMapsStat) String() string { s, _ := json.Marshal(m) 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) { _, ppid, _, _, _, _, err := p.fillFromStat() if err != nil { return -1, err } return ppid, nil } // Name returns name of the process. func (p *Process) Name() (string, error) { if p.name == "" { if err := p.fillFromStatus(); err != nil { return "", err } } return p.name, nil } // Exe returns executable path of the process. func (p *Process) Exe() (string, error) { return p.fillFromExe() } // 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) { return p.fillFromCmdline() } // CmdlineSlice returns the command line arguments of the process as a slice with each // element being an argument. func (p *Process) CmdlineSlice() ([]string, error) { return p.fillSliceFromCmdline() } // CreateTime returns created time of the process in milliseconds since the epoch, in UTC. func (p *Process) CreateTime() (int64, error) { _, _, _, createTime, _, _, err := p.fillFromStat() if err != nil { return 0, err } return createTime, nil } // Cwd returns current working directory of the process. func (p *Process) Cwd() (string, error) { return p.fillFromCwd() } // Parent returns parent Process of the process. func (p *Process) Parent() (*Process, error) { err := p.fillFromStatus() if err != nil { return nil, err } if p.parent == 0 { return nil, fmt.Errorf("wrong number of parents") } return NewProcess(p.parent) } // Status returns the process status. // 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. func (p *Process) Status() (string, error) { err := p.fillFromStatus() if err != nil { return "", err } return p.status, nil } // Uids returns user ids of the process as a slice of the int func (p *Process) Uids() ([]int32, error) { err := p.fillFromStatus() if err != nil { return []int32{}, err } return p.uids, nil } // Gids returns group ids of the process as a slice of the int func (p *Process) Gids() ([]int32, error) { err := p.fillFromStatus() if err != nil { return []int32{}, err } return p.gids, nil } // Terminal returns a terminal which is associated with the process. func (p *Process) Terminal() (string, error) { terminal, _, _, _, _, _, err := p.fillFromStat() if err != nil { return "", err } return terminal, nil } // Nice returns a nice value (priority). // Notice: gopsutil can not set nice value. func (p *Process) Nice() (int32, error) { _, _, _, _, _, nice, err := p.fillFromStat() if err != nil { return 0, err } return nice, nil } // IOnice returns process I/O nice value (priority). func (p *Process) IOnice() (int32, error) { return 0, common.ErrNotImplementedError } // Rlimit returns Resource Limits. func (p *Process) Rlimit() ([]RlimitStat, error) { return p.RlimitUsage(false) } // RlimitUsage returns Resource Limits. // If gatherUsed is true, the currently used value will be gathered and added // to the resulting RlimitStat. func (p *Process) RlimitUsage(gatherUsed bool) ([]RlimitStat, error) { rlimits, err := p.fillFromLimits() if !gatherUsed || err != nil { return rlimits, err } _, _, _, _, rtprio, nice, err := p.fillFromStat() if err != nil { return nil, err } if err := p.fillFromStatus(); err != nil { return nil, err } for i := range rlimits { rs := &rlimits[i] switch rs.Resource { case RLIMIT_CPU: times, err := p.Times() if err != nil { return nil, err } rs.Used = uint64(times.User + times.System) case RLIMIT_DATA: rs.Used = uint64(p.memInfo.Data) case RLIMIT_STACK: rs.Used = uint64(p.memInfo.Stack) case RLIMIT_RSS: rs.Used = uint64(p.memInfo.RSS) case RLIMIT_NOFILE: n, err := p.NumFDs() if err != nil { return nil, err } rs.Used = uint64(n) case RLIMIT_MEMLOCK: rs.Used = uint64(p.memInfo.Locked) case RLIMIT_AS: rs.Used = uint64(p.memInfo.VMS) case RLIMIT_LOCKS: //TODO we can get the used value from /proc/$pid/locks. But linux doesn't enforce it, so not a high priority. case RLIMIT_SIGPENDING: rs.Used = p.sigInfo.PendingProcess case RLIMIT_NICE: // The rlimit for nice is a little unusual, in that 0 means the niceness cannot be decreased beyond the current value, but it can be increased. // So effectively: if rs.Soft == 0 { rs.Soft = rs.Used } rs.Used = uint64(nice) case RLIMIT_RTPRIO: rs.Used = uint64(rtprio) } } return rlimits, err } // IOCounters returns IO Counters. func (p *Process) IOCounters() (*IOCountersStat, error) { return p.fillFromIO() } // NumCtxSwitches returns the number of the context switches of the process. func (p *Process) NumCtxSwitches() (*NumCtxSwitchesStat, error) { err := p.fillFromStatus() if err != nil { return nil, err } return p.numCtxSwitches, nil } // NumFDs returns the number of File Descriptors used by the process. func (p *Process) NumFDs() (int32, error) { _, fnames, err := p.fillFromfdList() return int32(len(fnames)), err } // NumThreads returns the number of threads used by the process. func (p *Process) NumThreads() (int32, error) { err := p.fillFromStatus() if err != nil { return 0, err } return p.numThreads, nil } // Threads returns a map of threads // // Notice: Not implemented yet. always returns empty map. func (p *Process) Threads() (map[string]string, error) { ret := make(map[string]string, 0) return ret, nil } // Times returns CPU times of the process. func (p *Process) Times() (*cpu.TimesStat, error) { _, _, cpuTimes, _, _, _, err := p.fillFromStat() if err != nil { return nil, err } return cpuTimes, nil } // CPUAffinity returns CPU affinity of the process. // // Notice: Not implemented yet. func (p *Process) CPUAffinity() ([]int32, error) { return nil, common.ErrNotImplementedError } // MemoryInfo returns platform in-dependend memory information, such as RSS, VMS and Swap func (p *Process) MemoryInfo() (*MemoryInfoStat, error) { meminfo, _, err := p.fillFromStatm() if err != nil { return nil, err } return meminfo, nil } // MemoryInfoEx returns platform dependend memory information. func (p *Process) MemoryInfoEx() (*MemoryInfoExStat, error) { _, memInfoEx, err := p.fillFromStatm() if err != nil { return nil, err } return memInfoEx, nil } // Children returns a slice of Process of the process. func (p *Process) Children() ([]*Process, error) { pids, err := common.CallPgrep(invoke, p.Pid) if err != nil { if pids == nil || len(pids) == 0 { return nil, ErrorNoChildren } return nil, err } ret := make([]*Process, 0, len(pids)) for _, pid := range pids { np, err := NewProcess(pid) if err != nil { return nil, err } ret = append(ret, np) } return ret, nil } // OpenFiles returns a slice of OpenFilesStat opend by the process. // OpenFilesStat includes a file path and file descriptor. func (p *Process) OpenFiles() ([]OpenFilesStat, error) { _, ofs, err := p.fillFromfd() if err != nil { return nil, err } ret := make([]OpenFilesStat, len(ofs)) for i, o := range ofs { ret[i] = *o } return ret, nil } // Connections returns a slice of net.ConnectionStat used by the process. // This returns all kind of the connection. This measn TCP, UDP or UNIX. func (p *Process) Connections() ([]net.ConnectionStat, error) { return net.ConnectionsPid("all", p.Pid) } // NetIOCounters returns NetIOCounters of the process. func (p *Process) NetIOCounters(pernic bool) ([]net.IOCountersStat, error) { filename := common.HostProc(strconv.Itoa(int(p.Pid)), "net/dev") return net.IOCountersByFile(pernic, filename) } // IsRunning returns whether the process is running or not. // Not implemented yet. func (p *Process) IsRunning() (bool, error) { return true, common.ErrNotImplementedError } // MemoryMaps get memory maps from /proc/(pid)/smaps func (p *Process) MemoryMaps(grouped bool) (*[]MemoryMapsStat, error) { pid := p.Pid var ret []MemoryMapsStat smapsPath := common.HostProc(strconv.Itoa(int(pid)), "smaps") contents, err := ioutil.ReadFile(smapsPath) if err != nil { return nil, err } lines := strings.Split(string(contents), "\n") // function of parsing a block getBlock := func(first_line []string, block []string) (MemoryMapsStat, error) { m := MemoryMapsStat{} m.Path = first_line[len(first_line)-1] for _, line := range block { if strings.Contains(line, "VmFlags") { continue } field := strings.Split(line, ":") if len(field) < 2 { continue } v := strings.Trim(field[1], " kB") // remove last "kB" t, err := strconv.ParseUint(v, 10, 64) if err != nil { return m, err } switch field[0] { case "Size": m.Size = t case "Rss": m.Rss = t case "Pss": m.Pss = t case "Shared_Clean": m.SharedClean = t case "Shared_Dirty": m.SharedDirty = t case "Private_Clean": m.PrivateClean = t case "Private_Dirty": m.PrivateDirty = t case "Referenced": m.Referenced = t case "Anonymous": m.Anonymous = t case "Swap": m.Swap = t } } return m, nil } blocks := make([]string, 16) for _, line := range lines { field := strings.Split(line, " ") if strings.HasSuffix(field[0], ":") == false { // new block section if len(blocks) > 0 { g, err := getBlock(field, blocks) if err != nil { return &ret, err } ret = append(ret, g) } // starts new block blocks = make([]string, 16) } else { blocks = append(blocks, line) } } return &ret, nil } /** ** Internal functions **/ func limitToInt(val string) (int32, error) { if val == "unlimited" { return math.MaxInt32, nil } else { res, err := strconv.ParseInt(val, 10, 32) if err != nil { return 0, err } return int32(res), nil } } // Get num_fds from /proc/(pid)/limits func (p *Process) fillFromLimits() ([]RlimitStat, error) { pid := p.Pid limitsFile := common.HostProc(strconv.Itoa(int(pid)), "limits") d, err := os.Open(limitsFile) if err != nil { return nil, err } defer d.Close() var limitStats []RlimitStat limitsScanner := bufio.NewScanner(d) for limitsScanner.Scan() { var statItem RlimitStat str := strings.Fields(limitsScanner.Text()) // Remove the header line if strings.Contains(str[len(str)-1], "Units") { continue } // Assert that last item is a Hard limit statItem.Hard, err = limitToInt(str[len(str)-1]) if err != nil { // On error remove last item an try once again since it can be unit or header line str = str[:len(str)-1] statItem.Hard, err = limitToInt(str[len(str)-1]) if err != nil { return nil, err } } // Remove last item from string str = str[:len(str)-1] //Now last item is a Soft limit statItem.Soft, err = limitToInt(str[len(str)-1]) if err != nil { return nil, err } // Remove last item from string str = str[:len(str)-1] //The rest is a stats name resourceName := strings.Join(str, " ") switch resourceName { case "Max cpu time": statItem.Resource = RLIMIT_CPU case "Max file size": statItem.Resource = RLIMIT_FSIZE case "Max data size": statItem.Resource = RLIMIT_DATA case "Max stack size": statItem.Resource = RLIMIT_STACK case "Max core file size": statItem.Resource = RLIMIT_CORE case "Max resident set": statItem.Resource = RLIMIT_RSS case "Max processes": statItem.Resource = RLIMIT_NPROC case "Max open files": statItem.Resource = RLIMIT_NOFILE case "Max locked memory": statItem.Resource = RLIMIT_MEMLOCK case "Max address space": statItem.Resource = RLIMIT_AS case "Max file locks": statItem.Resource = RLIMIT_LOCKS case "Max pending signals": statItem.Resource = RLIMIT_SIGPENDING case "Max msgqueue size": statItem.Resource = RLIMIT_MSGQUEUE case "Max nice priority": statItem.Resource = RLIMIT_NICE case "Max realtime priority": statItem.Resource = RLIMIT_RTPRIO case "Max realtime timeout": statItem.Resource = RLIMIT_RTTIME default: continue } limitStats = append(limitStats, statItem) } if err := limitsScanner.Err(); err != nil { return nil, err } return limitStats, nil } // Get list of /proc/(pid)/fd files func (p *Process) fillFromfdList() (string, []string, error) { pid := p.Pid statPath := common.HostProc(strconv.Itoa(int(pid)), "fd") d, err := os.Open(statPath) if err != nil { return statPath, []string{}, err } defer d.Close() fnames, err := d.Readdirnames(-1) return statPath, fnames, err } // Get num_fds from /proc/(pid)/fd func (p *Process) fillFromfd() (int32, []*OpenFilesStat, error) { statPath, fnames, err := p.fillFromfdList() if err != nil { return 0, nil, err } numFDs := int32(len(fnames)) var openfiles []*OpenFilesStat for _, fd := range fnames { fpath := filepath.Join(statPath, fd) filepath, err := os.Readlink(fpath) if err != nil { continue } t, err := strconv.ParseUint(fd, 10, 64) if err != nil { return numFDs, openfiles, err } o := &OpenFilesStat{ Path: filepath, Fd: t, } openfiles = append(openfiles, o) } return numFDs, openfiles, nil } // Get cwd from /proc/(pid)/cwd func (p *Process) fillFromCwd() (string, error) { pid := p.Pid cwdPath := common.HostProc(strconv.Itoa(int(pid)), "cwd") cwd, err := os.Readlink(cwdPath) if err != nil { return "", err } return string(cwd), nil } // Get exe from /proc/(pid)/exe func (p *Process) fillFromExe() (string, error) { pid := p.Pid exePath := common.HostProc(strconv.Itoa(int(pid)), "exe") exe, err := os.Readlink(exePath) if err != nil { return "", err } return string(exe), nil } // Get cmdline from /proc/(pid)/cmdline func (p *Process) fillFromCmdline() (string, error) { pid := p.Pid cmdPath := common.HostProc(strconv.Itoa(int(pid)), "cmdline") cmdline, err := ioutil.ReadFile(cmdPath) if err != nil { return "", err } ret := strings.FieldsFunc(string(cmdline), func(r rune) bool { if r == '\u0000' { return true } return false }) return strings.Join(ret, " "), nil } func (p *Process) fillSliceFromCmdline() ([]string, error) { pid := p.Pid cmdPath := common.HostProc(strconv.Itoa(int(pid)), "cmdline") cmdline, err := ioutil.ReadFile(cmdPath) if err != nil { return nil, err } if len(cmdline) == 0 { return nil, nil } if cmdline[len(cmdline)-1] == 0 { cmdline = cmdline[:len(cmdline)-1] } parts := bytes.Split(cmdline, []byte{0}) var strParts []string for _, p := range parts { strParts = append(strParts, string(p)) } return strParts, nil } // Get IO status from /proc/(pid)/io func (p *Process) fillFromIO() (*IOCountersStat, error) { pid := p.Pid ioPath := common.HostProc(strconv.Itoa(int(pid)), "io") ioline, err := ioutil.ReadFile(ioPath) if err != nil { return nil, err } lines := strings.Split(string(ioline), "\n") ret := &IOCountersStat{} for _, line := range lines { field := strings.Fields(line) if len(field) < 2 { continue } t, err := strconv.ParseUint(field[1], 10, 64) if err != nil { return nil, err } param := field[0] if strings.HasSuffix(param, ":") { param = param[:len(param)-1] } switch param { case "syscr": ret.ReadCount = t case "syscw": ret.WriteCount = t case "read_bytes": ret.ReadBytes = t case "write_bytes": ret.WriteBytes = t } } return ret, nil } // Get memory info from /proc/(pid)/statm func (p *Process) fillFromStatm() (*MemoryInfoStat, *MemoryInfoExStat, error) { pid := p.Pid memPath := common.HostProc(strconv.Itoa(int(pid)), "statm") contents, err := ioutil.ReadFile(memPath) if err != nil { return nil, nil, err } fields := strings.Split(string(contents), " ") vms, err := strconv.ParseUint(fields[0], 10, 64) if err != nil { return nil, nil, err } rss, err := strconv.ParseUint(fields[1], 10, 64) if err != nil { return nil, nil, err } memInfo := &MemoryInfoStat{ RSS: rss * PageSize, VMS: vms * PageSize, } shared, err := strconv.ParseUint(fields[2], 10, 64) if err != nil { return nil, nil, err } text, err := strconv.ParseUint(fields[3], 10, 64) if err != nil { return nil, nil, err } lib, err := strconv.ParseUint(fields[4], 10, 64) if err != nil { return nil, nil, err } dirty, err := strconv.ParseUint(fields[5], 10, 64) if err != nil { return nil, nil, err } memInfoEx := &MemoryInfoExStat{ RSS: rss * PageSize, VMS: vms * PageSize, Shared: shared * PageSize, Text: text * PageSize, Lib: lib * PageSize, Dirty: dirty * PageSize, } return memInfo, memInfoEx, nil } // Get various status from /proc/(pid)/status func (p *Process) fillFromStatus() error { pid := p.Pid statPath := common.HostProc(strconv.Itoa(int(pid)), "status") contents, err := ioutil.ReadFile(statPath) if err != nil { return err } lines := strings.Split(string(contents), "\n") p.numCtxSwitches = &NumCtxSwitchesStat{} p.memInfo = &MemoryInfoStat{} p.sigInfo = &SignalInfoStat{} for _, line := range lines { tabParts := strings.SplitN(line, "\t", 2) if len(tabParts) < 2 { continue } value := tabParts[1] switch strings.TrimRight(tabParts[0], ":") { case "Name": p.name = strings.Trim(value, " \t") if len(p.name) >= 15 { cmdlineSlice, err := p.CmdlineSlice() if err != nil { return err } if len(cmdlineSlice) > 0 { extendedName := filepath.Base(cmdlineSlice[0]) if strings.HasPrefix(extendedName, p.name) { p.name = extendedName } } } case "State": p.status = value[0:1] case "PPid", "Ppid": pval, err := strconv.ParseInt(value, 10, 32) if err != nil { return err } p.parent = int32(pval) case "Uid": p.uids = make([]int32, 0, 4) for _, i := range strings.Split(value, "\t") { v, err := strconv.ParseInt(i, 10, 32) if err != nil { return err } p.uids = append(p.uids, int32(v)) } case "Gid": p.gids = make([]int32, 0, 4) for _, i := range strings.Split(value, "\t") { v, err := strconv.ParseInt(i, 10, 32) if err != nil { return err } p.gids = append(p.gids, int32(v)) } case "Threads": v, err := strconv.ParseInt(value, 10, 32) if err != nil { return err } p.numThreads = int32(v) case "voluntary_ctxt_switches": v, err := strconv.ParseInt(value, 10, 64) if err != nil { return err } p.numCtxSwitches.Voluntary = v case "nonvoluntary_ctxt_switches": v, err := strconv.ParseInt(value, 10, 64) if err != nil { return err } p.numCtxSwitches.Involuntary = v case "VmRSS": value := strings.Trim(value, " kB") // remove last "kB" v, err := strconv.ParseUint(value, 10, 64) if err != nil { return err } p.memInfo.RSS = v * 1024 case "VmSize": value := strings.Trim(value, " kB") // remove last "kB" v, err := strconv.ParseUint(value, 10, 64) if err != nil { return err } p.memInfo.VMS = v * 1024 case "VmSwap": value := strings.Trim(value, " kB") // remove last "kB" v, err := strconv.ParseUint(value, 10, 64) if err != nil { return err } p.memInfo.Swap = v * 1024 case "VmData": value := strings.Trim(value, " kB") // remove last "kB" v, err := strconv.ParseUint(value, 10, 64) if err != nil { return err } p.memInfo.Data = v * 1024 case "VmStk": value := strings.Trim(value, " kB") // remove last "kB" v, err := strconv.ParseUint(value, 10, 64) if err != nil { return err } p.memInfo.Stack = v * 1024 case "VmLck": value := strings.Trim(value, " kB") // remove last "kB" v, err := strconv.ParseUint(value, 10, 64) if err != nil { return err } p.memInfo.Locked = v * 1024 case "SigPnd": v, err := strconv.ParseUint(value, 16, 64) if err != nil { return err } p.sigInfo.PendingThread = v case "ShdPnd": v, err := strconv.ParseUint(value, 16, 64) if err != nil { return err } p.sigInfo.PendingProcess = v case "SigBlk": v, err := strconv.ParseUint(value, 16, 64) if err != nil { return err } p.sigInfo.Blocked = v case "SigIgn": v, err := strconv.ParseUint(value, 16, 64) if err != nil { return err } p.sigInfo.Ignored = v case "SigCgt": v, err := strconv.ParseUint(value, 16, 64) if err != nil { return err } p.sigInfo.Caught = v } } return nil } func (p *Process) fillFromStat() (string, int32, *cpu.TimesStat, int64, uint32, int32, error) { pid := p.Pid statPath := common.HostProc(strconv.Itoa(int(pid)), "stat") contents, err := ioutil.ReadFile(statPath) if err != nil { return "", 0, nil, 0, 0, 0, err } fields := strings.Fields(string(contents)) i := 1 for !strings.HasSuffix(fields[i], ")") { i++ } termmap, err := getTerminalMap() terminal := "" if err == nil { t, err := strconv.ParseUint(fields[i+5], 10, 64) if err != nil { return "", 0, nil, 0, 0, 0, err } terminal = termmap[t] } ppid, err := strconv.ParseInt(fields[i+2], 10, 32) if err != nil { return "", 0, nil, 0, 0, 0, err } utime, err := strconv.ParseFloat(fields[i+12], 64) if err != nil { return "", 0, nil, 0, 0, 0, err } stime, err := strconv.ParseFloat(fields[i+13], 64) if err != nil { return "", 0, nil, 0, 0, 0, err } cpuTimes := &cpu.TimesStat{ CPU: "cpu", User: float64(utime / ClockTicks), System: float64(stime / ClockTicks), } bootTime, _ := host.BootTime() t, err := strconv.ParseUint(fields[i+20], 10, 64) if err != nil { return "", 0, nil, 0, 0, 0, err } ctime := (t / uint64(ClockTicks)) + uint64(bootTime) createTime := int64(ctime * 1000) rtpriority, err := strconv.ParseInt(fields[i+16], 10, 32) if rtpriority < 0 { rtpriority = rtpriority*-1 - 1 } else { rtpriority = 0 } // p.Nice = mustParseInt32(fields[18]) // use syscall instead of parse Stat file snice, _ := unix.Getpriority(PrioProcess, int(pid)) nice := int32(snice) // FIXME: is this true? return terminal, int32(ppid), cpuTimes, createTime, uint32(rtpriority), nice, nil } // Pids returns a slice of process ID list which are running now. func Pids() ([]int32, error) { var ret []int32 d, err := os.Open(common.HostProc()) if err != nil { return nil, err } defer d.Close() fnames, err := d.Readdirnames(-1) if err != nil { return nil, err } for _, fname := range fnames { pid, err := strconv.ParseInt(fname, 10, 32) if err != nil { // if not numeric name, just skip continue } ret = append(ret, int32(pid)) } return ret, nil } golang-github-shirou-gopsutil-2.17.08/process/process_openbsd.go000066400000000000000000000170321315167550200250000ustar00rootroot00000000000000// +build openbsd package process import ( "C" "bytes" "encoding/binary" "strings" "unsafe" cpu "github.com/shirou/gopsutil/cpu" "github.com/shirou/gopsutil/internal/common" mem "github.com/shirou/gopsutil/mem" net "github.com/shirou/gopsutil/net" "golang.org/x/sys/unix" ) // MemoryInfoExStat is different between OSes type MemoryInfoExStat struct { } type MemoryMapsStat struct { } func Pids() ([]int32, error) { var ret []int32 procs, err := processes() if err != nil { return ret, nil } for _, p := range procs { ret = append(ret, p.Pid) } return ret, nil } func (p *Process) Ppid() (int32, error) { k, err := p.getKProc() if err != nil { return 0, err } return k.Ppid, nil } func (p *Process) Name() (string, error) { k, err := p.getKProc() if err != nil { return "", err } return common.IntToString(k.Comm[:]), nil } func (p *Process) Exe() (string, error) { return "", common.ErrNotImplementedError } func (p *Process) CmdlineSlice() ([]string, error) { mib := []int32{CTLKern, KernProcArgs, p.Pid, KernProcArgv} buf, _, err := common.CallSyscall(mib) if err != nil { return nil, err } argc := 0 argvp := unsafe.Pointer(&buf[0]) argv := *(**C.char)(unsafe.Pointer(argvp)) size := unsafe.Sizeof(argv) var strParts []string for argv != nil { strParts = append(strParts, C.GoString(argv)) argc++ argv = *(**C.char)(unsafe.Pointer(uintptr(argvp) + uintptr(argc)*size)) } return strParts, nil } func (p *Process) Cmdline() (string, error) { argv, err := p.CmdlineSlice() if err != nil { return "", err } return strings.Join(argv, " "), nil } func (p *Process) CreateTime() (int64, error) { return 0, common.ErrNotImplementedError } func (p *Process) Cwd() (string, error) { return "", common.ErrNotImplementedError } func (p *Process) Parent() (*Process, error) { return p, common.ErrNotImplementedError } func (p *Process) Status() (string, error) { k, err := p.getKProc() if err != nil { return "", err } var s string switch k.Stat { case SIDL: case SRUN: case SONPROC: s = "R" case SSLEEP: s = "S" case SSTOP: s = "T" case SDEAD: s = "Z" } return s, nil } func (p *Process) Uids() ([]int32, error) { k, err := p.getKProc() if err != nil { return nil, err } uids := make([]int32, 0, 3) uids = append(uids, int32(k.Ruid), int32(k.Uid), int32(k.Svuid)) return uids, nil } func (p *Process) Gids() ([]int32, error) { k, err := p.getKProc() if err != nil { return nil, err } gids := make([]int32, 0, 3) gids = append(gids, int32(k.Rgid), int32(k.Ngroups), int32(k.Svgid)) return gids, nil } func (p *Process) Terminal() (string, error) { k, err := p.getKProc() if err != nil { return "", err } ttyNr := uint64(k.Tdev) termmap, err := getTerminalMap() if err != nil { return "", err } return termmap[ttyNr], nil } func (p *Process) Nice() (int32, error) { k, err := p.getKProc() if err != nil { return 0, err } return int32(k.Nice), nil } func (p *Process) IOnice() (int32, error) { return 0, common.ErrNotImplementedError } func (p *Process) Rlimit() ([]RlimitStat, error) { var rlimit []RlimitStat return rlimit, common.ErrNotImplementedError } func (p *Process) RlimitUsage(_ bool) ([]RlimitStat, error) { var rlimit []RlimitStat return rlimit, common.ErrNotImplementedError } func (p *Process) IOCounters() (*IOCountersStat, error) { k, err := p.getKProc() if err != nil { return nil, err } return &IOCountersStat{ ReadCount: uint64(k.Uru_inblock), WriteCount: uint64(k.Uru_oublock), }, nil } func (p *Process) NumCtxSwitches() (*NumCtxSwitchesStat, error) { return nil, common.ErrNotImplementedError } func (p *Process) NumFDs() (int32, error) { return 0, common.ErrNotImplementedError } func (p *Process) NumThreads() (int32, error) { /* not supported, just return 1 */ return 1, nil } func (p *Process) Threads() (map[string]string, error) { ret := make(map[string]string, 0) return ret, common.ErrNotImplementedError } func (p *Process) Times() (*cpu.TimesStat, error) { k, err := p.getKProc() if err != nil { return nil, err } return &cpu.TimesStat{ CPU: "cpu", User: float64(k.Uutime_sec) + float64(k.Uutime_usec)/1000000, System: float64(k.Ustime_sec) + float64(k.Ustime_usec)/1000000, }, nil } func (p *Process) CPUAffinity() ([]int32, error) { return nil, common.ErrNotImplementedError } func (p *Process) MemoryInfo() (*MemoryInfoStat, error) { k, err := p.getKProc() if err != nil { return nil, err } pageSize, err := mem.GetPageSize() if err != nil { return nil, err } return &MemoryInfoStat{ RSS: uint64(k.Vm_rssize) * pageSize, VMS: uint64(k.Vm_tsize) + uint64(k.Vm_dsize) + uint64(k.Vm_ssize), }, nil } func (p *Process) MemoryInfoEx() (*MemoryInfoExStat, error) { return nil, common.ErrNotImplementedError } func (p *Process) Children() ([]*Process, error) { pids, err := common.CallPgrep(invoke, p.Pid) if err != nil { return nil, err } ret := make([]*Process, 0, len(pids)) for _, pid := range pids { np, err := NewProcess(pid) if err != nil { return nil, err } ret = append(ret, np) } return ret, nil } func (p *Process) OpenFiles() ([]OpenFilesStat, error) { return nil, common.ErrNotImplementedError } func (p *Process) Connections() ([]net.ConnectionStat, error) { return nil, common.ErrNotImplementedError } func (p *Process) NetIOCounters(pernic bool) ([]net.IOCountersStat, error) { return nil, common.ErrNotImplementedError } func (p *Process) IsRunning() (bool, error) { return true, common.ErrNotImplementedError } func (p *Process) MemoryMaps(grouped bool) (*[]MemoryMapsStat, error) { var ret []MemoryMapsStat return &ret, common.ErrNotImplementedError } func processes() ([]Process, error) { results := make([]Process, 0, 50) buf, length, err := CallKernProcSyscall(KernProcAll, 0) if err != nil { return results, err } // get kinfo_proc size count := int(length / uint64(sizeOfKinfoProc)) // parse buf to procs for i := 0; i < count; i++ { b := buf[i*sizeOfKinfoProc : (i+1)*sizeOfKinfoProc] k, err := parseKinfoProc(b) if err != nil { continue } p, err := NewProcess(int32(k.Pid)) if err != nil { continue } results = append(results, *p) } return results, nil } func parseKinfoProc(buf []byte) (KinfoProc, error) { var k KinfoProc br := bytes.NewReader(buf) err := common.Read(br, binary.LittleEndian, &k) return k, err } func (p *Process) getKProc() (*KinfoProc, error) { buf, length, err := CallKernProcSyscall(KernProcPID, p.Pid) if err != nil { return nil, err } if length != sizeOfKinfoProc { return nil, err } k, err := parseKinfoProc(buf) if err != nil { return nil, err } 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) { mib := []int32{CTLKern, KernProc, op, arg, sizeOfKinfoProc, 0} mibptr := unsafe.Pointer(&mib[0]) miblen := uint64(len(mib)) length := uint64(0) _, _, err := unix.Syscall6( unix.SYS___SYSCTL, uintptr(mibptr), uintptr(miblen), 0, uintptr(unsafe.Pointer(&length)), 0, 0) if err != 0 { return nil, length, err } count := int32(length / uint64(sizeOfKinfoProc)) mib = []int32{CTLKern, KernProc, op, arg, sizeOfKinfoProc, count} mibptr = unsafe.Pointer(&mib[0]) miblen = uint64(len(mib)) // get proc info itself buf := make([]byte, length) _, _, err = unix.Syscall6( unix.SYS___SYSCTL, uintptr(mibptr), uintptr(miblen), uintptr(unsafe.Pointer(&buf[0])), uintptr(unsafe.Pointer(&length)), 0, 0) if err != 0 { return buf, length, err } return buf, length, nil } golang-github-shirou-gopsutil-2.17.08/process/process_openbsd_amd64.go000066400000000000000000000066511315167550200260000ustar00rootroot00000000000000// Created by cgo -godefs - DO NOT EDIT // cgo -godefs types_openbsd.go package process const ( CTLKern = 1 KernProc = 66 KernProcAll = 0 KernProcPID = 1 KernProcProc = 8 KernProcPathname = 12 KernProcArgs = 55 KernProcArgv = 1 KernProcEnv = 3 ) const ( ArgMax = 256 * 1024 ) const ( sizeofPtr = 0x8 sizeofShort = 0x2 sizeofInt = 0x4 sizeofLong = 0x8 sizeofLongLong = 0x8 ) const ( sizeOfKinfoVmentry = 0x50 sizeOfKinfoProc = 0x268 ) const ( SIDL = 1 SRUN = 2 SSLEEP = 3 SSTOP = 4 SZOMB = 5 SDEAD = 6 SONPROC = 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 uint64 Max uint64 } type KinfoProc struct { Forw uint64 Back uint64 Paddr uint64 Addr uint64 Fd uint64 Stats uint64 Limit uint64 Vmspace uint64 Sigacts uint64 Sess uint64 Tsess uint64 Ru uint64 Eflag int32 Exitsig int32 Flag int32 Pid int32 Ppid int32 Sid int32 X_pgid int32 Tpgid int32 Uid uint32 Ruid uint32 Gid uint32 Rgid uint32 Groups [16]uint32 Ngroups int16 Jobc int16 Tdev uint32 Estcpu uint32 Rtime_sec uint32 Rtime_usec uint32 Cpticks int32 Pctcpu uint32 Swtime uint32 Slptime uint32 Schedflags int32 Uticks uint64 Sticks uint64 Iticks uint64 Tracep uint64 Traceflag int32 Holdcnt int32 Siglist int32 Sigmask uint32 Sigignore uint32 Sigcatch uint32 Stat int8 Priority uint8 Usrpri uint8 Nice uint8 Xstat uint16 Acflag uint16 Comm [24]int8 Wmesg [8]int8 Wchan uint64 Login [32]int8 Vm_rssize int32 Vm_tsize int32 Vm_dsize int32 Vm_ssize int32 Uvalid int64 Ustart_sec uint64 Ustart_usec uint32 Uutime_sec uint32 Uutime_usec uint32 Ustime_sec uint32 Ustime_usec uint32 Pad_cgo_0 [4]byte Uru_maxrss uint64 Uru_ixrss uint64 Uru_idrss uint64 Uru_isrss uint64 Uru_minflt uint64 Uru_majflt uint64 Uru_nswap uint64 Uru_inblock uint64 Uru_oublock uint64 Uru_msgsnd uint64 Uru_msgrcv uint64 Uru_nsignals uint64 Uru_nvcsw uint64 Uru_nivcsw uint64 Uctime_sec uint32 Uctime_usec uint32 Psflags int32 Spare int32 Svuid uint32 Svgid uint32 Emul [8]int8 Rlim_rss_cur uint64 Cpuid uint64 Vm_map_size uint64 Tid int32 Rtableid uint32 } type Priority struct{} type KinfoVmentry struct { Start uint64 End uint64 Guard uint64 Fspace uint64 Fspace_augment uint64 Offset uint64 Wired_count int32 Etype int32 Protection int32 Max_protection int32 Advice int32 Inheritance int32 Flags uint8 Pad_cgo_0 [7]byte } golang-github-shirou-gopsutil-2.17.08/process/process_posix.go000066400000000000000000000043441315167550200245120ustar00rootroot00000000000000// +build linux freebsd openbsd darwin package process import ( "os" "os/user" "path/filepath" "strconv" "strings" "syscall" "golang.org/x/sys/unix" ) // POSIX func getTerminalMap() (map[uint64]string, error) { ret := make(map[uint64]string) var termfiles []string d, err := os.Open("/dev") if err != nil { return nil, err } defer d.Close() devnames, err := d.Readdirnames(-1) for _, devname := range devnames { if strings.HasPrefix(devname, "/dev/tty") { termfiles = append(termfiles, "/dev/tty/"+devname) } } var ptsnames []string ptsd, err := os.Open("/dev/pts") if err != nil { ptsnames, _ = filepath.Glob("/dev/ttyp*") if ptsnames == nil { return nil, err } } defer ptsd.Close() if ptsnames == nil { defer ptsd.Close() ptsnames, err = ptsd.Readdirnames(-1) for _, ptsname := range ptsnames { termfiles = append(termfiles, "/dev/pts/"+ptsname) } } else { termfiles = ptsnames } for _, name := range termfiles { stat := unix.Stat_t{} if err = unix.Stat(name, &stat); err != nil { return nil, err } rdev := uint64(stat.Rdev) ret[rdev] = strings.Replace(name, "/dev", "", -1) } return ret, nil } // SendSignal sends a unix.Signal to the process. // Currently, SIGSTOP, SIGCONT, SIGTERM and SIGKILL are supported. func (p *Process) SendSignal(sig syscall.Signal) error { process, err := os.FindProcess(int(p.Pid)) if err != nil { return err } err = process.Signal(sig) if err != nil { return err } return nil } // Suspend sends SIGSTOP to the process. func (p *Process) Suspend() error { return p.SendSignal(unix.SIGSTOP) } // Resume sends SIGCONT to the process. func (p *Process) Resume() error { return p.SendSignal(unix.SIGCONT) } // Terminate sends SIGTERM to the process. func (p *Process) Terminate() error { return p.SendSignal(unix.SIGTERM) } // Kill sends SIGKILL to the process. func (p *Process) Kill() error { return p.SendSignal(unix.SIGKILL) } // Username returns a username of the process. func (p *Process) Username() (string, error) { uids, err := p.Uids() if err != nil { return "", err } if len(uids) > 0 { u, err := user.LookupId(strconv.Itoa(int(uids[0]))) if err != nil { return "", err } return u.Username, nil } return "", nil } golang-github-shirou-gopsutil-2.17.08/process/process_posix_test.go000066400000000000000000000004401315167550200255420ustar00rootroot00000000000000// +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) } } golang-github-shirou-gopsutil-2.17.08/process/process_test.go000066400000000000000000000174751315167550200243400ustar00rootroot00000000000000package process import ( "fmt" "os" "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_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) { 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) } } golang-github-shirou-gopsutil-2.17.08/process/process_windows.go000066400000000000000000000272301315167550200250410ustar00rootroot00000000000000// +build windows package process import ( "fmt" "strings" "syscall" "time" "unsafe" "github.com/StackExchange/wmi" 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") ) type SystemProcessInformation struct { NextEntryOffset uint64 NumberOfThreads uint64 Reserved1 [48]byte Reserved2 [3]byte UniqueProcessID uintptr Reserved3 uintptr HandleCount uint64 Reserved4 [4]byte Reserved5 [11]byte PeakPagefileUsage uint64 PrivatePageCount uint64 Reserved6 [6]uint64 } // Memory_info_ex is different between OSes type MemoryInfoExStat struct { } type MemoryMapsStat struct { } type Win32_Process struct { 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 CSName string Caption *string CreationClassName string Description *string ExecutionState *uint16 HandleCount uint32 KernelModeTime uint64 MaximumWorkingSetSize *uint32 MinimumWorkingSetSize *uint32 OSCreationClassName string OSName string OtherOperationCount uint64 OtherTransferCount uint64 PageFaults uint32 PageFileUsage uint32 ParentProcessID uint32 PeakPageFileUsage uint32 PeakVirtualSize uint64 PeakWorkingSetSize uint32 PrivatePageCount uint64 TerminationDate *time.Time UserModeTime uint64 WorkingSetSize uint64 } func init() { wmi.DefaultClient.AllowMissingFields = true } func Pids() ([]int32, error) { var ret []int32 procs, err := processes() if err != nil { return ret, nil } for _, proc := range procs { ret = append(ret, proc.Pid) } return ret, nil } func (p *Process) Ppid() (int32, error) { dst, err := GetWin32Proc(p.Pid) if err != nil { return 0, err } return int32(dst[0].ParentProcessID), nil } func GetWin32Proc(pid int32) ([]Win32_Process, error) { var dst []Win32_Process query := fmt.Sprintf("WHERE ProcessId = %d", pid) q := wmi.CreateQuery(&dst, query) if err := wmi.Query(q, &dst); err != nil { return []Win32_Process{}, fmt.Errorf("could not get win32Proc: %s", err) } if len(dst) == 0 { return []Win32_Process{}, fmt.Errorf("could not get win32Proc: empty") } return dst, nil } func (p *Process) Name() (string, error) { dst, err := GetWin32Proc(p.Pid) if err != nil { return "", fmt.Errorf("could not get Name: %s", err) } return dst[0].Name, nil } func (p *Process) Exe() (string, error) { dst, err := GetWin32Proc(p.Pid) if err != nil { return "", fmt.Errorf("could not get ExecutablePath: %s", err) } return *dst[0].ExecutablePath, nil } func (p *Process) Cmdline() (string, error) { dst, err := GetWin32Proc(p.Pid) if err != nil { return "", fmt.Errorf("could not get CommandLine: %s", err) } return *dst[0].CommandLine, nil } // CmdlineSlice returns the command line arguments of the process as a slice with each // element being an argument. This merely returns the CommandLine informations passed // to the process split on the 0x20 ASCII character. func (p *Process) CmdlineSlice() ([]string, error) { cmdline, err := p.Cmdline() if err != nil { return nil, err } return strings.Split(cmdline, " "), nil } func (p *Process) CreateTime() (int64, error) { ru, err := getRusage(p.Pid) if err != nil { return 0, fmt.Errorf("could not get CreationDate: %s", err) } return ru.CreationTime.Nanoseconds() / 1000000, nil } func (p *Process) Cwd() (string, error) { return "", common.ErrNotImplementedError } func (p *Process) Parent() (*Process, error) { dst, err := GetWin32Proc(p.Pid) if err != nil { return nil, fmt.Errorf("could not get ParentProcessID: %s", err) } return NewProcess(int32(dst[0].ParentProcessID)) } func (p *Process) Status() (string, error) { return "", common.ErrNotImplementedError } func (p *Process) Username() (string, error) { pid := p.Pid // 0x1000 is PROCESS_QUERY_LIMITED_INFORMATION c, err := syscall.OpenProcess(0x1000, false, uint32(pid)) if err != nil { return "", err } defer syscall.CloseHandle(c) var token syscall.Token err = syscall.OpenProcessToken(c, syscall.TOKEN_QUERY, &token) if err != nil { return "", err } defer token.Close() tokenUser, err := token.GetTokenUser() user, domain, _, err := tokenUser.User.Sid.LookupAccount("") return domain + "\\" + user, err } func (p *Process) Uids() ([]int32, error) { var uids []int32 return uids, common.ErrNotImplementedError } func (p *Process) Gids() ([]int32, error) { var gids []int32 return gids, common.ErrNotImplementedError } func (p *Process) Terminal() (string, error) { return "", common.ErrNotImplementedError } // Nice returnes priority in Windows func (p *Process) Nice() (int32, error) { dst, err := GetWin32Proc(p.Pid) if err != nil { return 0, fmt.Errorf("could not get Priority: %s", err) } return int32(dst[0].Priority), nil } func (p *Process) IOnice() (int32, error) { return 0, common.ErrNotImplementedError } func (p *Process) Rlimit() ([]RlimitStat, error) { var rlimit []RlimitStat return rlimit, common.ErrNotImplementedError } func (p *Process) RlimitUsage(_ bool) ([]RlimitStat, error) { var rlimit []RlimitStat return rlimit, common.ErrNotImplementedError } func (p *Process) IOCounters() (*IOCountersStat, error) { 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 } func (p *Process) NumFDs() (int32, error) { return 0, common.ErrNotImplementedError } func (p *Process) NumThreads() (int32, error) { dst, err := GetWin32Proc(p.Pid) if err != nil { return 0, fmt.Errorf("could not get ThreadCount: %s", err) } return int32(dst[0].ThreadCount), nil } func (p *Process) Threads() (map[string]string, error) { ret := make(map[string]string, 0) return ret, common.ErrNotImplementedError } func (p *Process) Times() (*cpu.TimesStat, error) { return nil, common.ErrNotImplementedError } func (p *Process) CPUAffinity() ([]int32, error) { return nil, common.ErrNotImplementedError } func (p *Process) MemoryInfo() (*MemoryInfoStat, error) { mem, err := getMemoryInfo(p.Pid) if err != nil { return nil, err } ret := &MemoryInfoStat{ RSS: uint64(mem.WorkingSetSize), VMS: uint64(mem.PagefileUsage), } return ret, nil } func (p *Process) MemoryInfoEx() (*MemoryInfoExStat, error) { return nil, common.ErrNotImplementedError } func (p *Process) Children() ([]*Process, error) { procs, err := processes() if err != nil { return nil, err } out := []*Process{} for _, proc := range procs { parent, err := proc.Parent() if err != nil { continue } if parent.Pid == p.Pid { out = append(out, proc) } } return out, nil } func (p *Process) OpenFiles() ([]OpenFilesStat, error) { return nil, common.ErrNotImplementedError } func (p *Process) Connections() ([]net.ConnectionStat, error) { return nil, common.ErrNotImplementedError } func (p *Process) NetIOCounters(pernic bool) ([]net.IOCountersStat, error) { return nil, common.ErrNotImplementedError } func (p *Process) IsRunning() (bool, error) { return true, common.ErrNotImplementedError } func (p *Process) MemoryMaps(grouped bool) (*[]MemoryMapsStat, error) { var ret []MemoryMapsStat 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 common.ErrNotImplementedError } func (p *Process) Suspend() error { return common.ErrNotImplementedError } func (p *Process) Resume() error { return common.ErrNotImplementedError } func (p *Process) Terminate() 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 } } func (p *Process) Kill() error { return common.ErrNotImplementedError } func (p *Process) getFromSnapProcess(pid int32) (int32, int32, string, error) { snap := w32.CreateToolhelp32Snapshot(w32.TH32CS_SNAPPROCESS, uint32(pid)) if snap == 0 { return 0, 0, "", windows.GetLastError() } 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() } 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 } } return 0, 0, "", fmt.Errorf("Couldn't find pid: %d", pid) } // Get processes func processes() ([]*Process, error) { var dst []Win32_Process q := wmi.CreateQuery(&dst, "") err := wmi.Query(q, &dst) if err != nil { return []*Process{}, err } if len(dst) == 0 { return []*Process{}, fmt.Errorf("could not get Process") } results := []*Process{} for _, proc := range dst { p, err := NewProcess(int32(proc.ProcessID)) if err != nil { continue } results = append(results, p) } return results, nil } func getProcInfo(pid int32) (*SystemProcessInformation, error) { initialBufferSize := uint64(0x4000) bufferSize := initialBufferSize buffer := make([]byte, bufferSize) var sysProcInfo SystemProcessInformation ret, _, _ := common.ProcNtQuerySystemInformation.Call( uintptr(unsafe.Pointer(&sysProcInfo)), uintptr(unsafe.Pointer(&buffer[0])), uintptr(unsafe.Pointer(&bufferSize)), uintptr(unsafe.Pointer(&bufferSize))) if ret != 0 { return nil, windows.GetLastError() } return &sysProcInfo, nil } func getRusage(pid int32) (*windows.Rusage, error) { var CPU windows.Rusage c, err := windows.OpenProcess(windows.PROCESS_QUERY_INFORMATION, false, uint32(pid)) if err != nil { return nil, err } defer windows.CloseHandle(c) if err := windows.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 // PROCESS_QUERY_LIMITED_INFORMATION is 0x1000 c, err := windows.OpenProcess(0x1000, false, uint32(pid)) if err != nil { return mem, err } defer windows.CloseHandle(c) if err := getProcessMemoryInfo(c, &mem); err != nil { return mem, err } return mem, err } func getProcessMemoryInfo(h windows.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 } golang-github-shirou-gopsutil-2.17.08/process/process_windows_386.go000066400000000000000000000006521315167550200254400ustar00rootroot00000000000000// +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 } golang-github-shirou-gopsutil-2.17.08/process/process_windows_amd64.go000066400000000000000000000006521315167550200260330ustar00rootroot00000000000000// +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 } golang-github-shirou-gopsutil-2.17.08/process/testdata/000077500000000000000000000000001315167550200230675ustar00rootroot00000000000000golang-github-shirou-gopsutil-2.17.08/process/testdata/darwin/000077500000000000000000000000001315167550200243535ustar00rootroot00000000000000golang-github-shirou-gopsutil-2.17.08/process/testdata/darwin/ps-ax-opid_fail000066400000000000000000000000741315167550200272530ustar00rootroot00000000000000 PID 245 247 248 249 254 262 264 265 267 golang-github-shirou-gopsutil-2.17.08/process/types_darwin.go000066400000000000000000000056731315167550200243300ustar00rootroot00000000000000// Copyright 2009 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Hand Writing // - all pointer in ExternProc to uint64 // +build ignore /* Input to cgo -godefs. */ // +godefs map struct_in_addr [4]byte /* in_addr */ // +godefs map struct_in6_addr [16]byte /* in6_addr */ // +godefs map struct_ [16]byte /* in6_addr */ package process /* #define __DARWIN_UNIX03 0 #define KERNEL #define _DARWIN_USE_64_BIT_INODE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include enum { sizeofPtr = sizeof(void*), }; union sockaddr_all { struct sockaddr s1; // this one gets used for fields struct sockaddr_in s2; // these pad it out struct sockaddr_in6 s3; struct sockaddr_un s4; struct sockaddr_dl s5; }; struct sockaddr_any { struct sockaddr addr; char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)]; }; struct ucred_queue { struct ucred *tqe_next; struct ucred **tqe_prev; TRACEBUF }; */ 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 ) // Basic types type ( _C_short C.short _C_int C.int _C_long C.long _C_long_long C.longlong ) // Time type Timespec C.struct_timespec type Timeval C.struct_timeval // Processes type Rusage C.struct_rusage type Rlimit C.struct_rlimit type UGid_t C.gid_t type KinfoProc C.struct_kinfo_proc type Eproc C.struct_eproc type Proc C.struct_proc type Session C.struct_session type ucred C.struct_ucred type Uucred C.struct__ucred type Upcred C.struct__pcred type Vmspace C.struct_vmspace type Sigacts C.struct_sigacts type ExternProc C.struct_extern_proc type Itimerval C.struct_itimerval type Vnode C.struct_vnode type Pgrp C.struct_pgrp type UserStruct C.struct_user type Au_session C.struct_au_session type Posix_cred C.struct_posix_cred type Label C.struct_label type AuditinfoAddr C.struct_auditinfo_addr type AuMask C.struct_au_mask type AuTidAddr C.struct_au_tid_addr // TAILQ(ucred) type UcredQueue C.struct_ucred_queue golang-github-shirou-gopsutil-2.17.08/process/types_freebsd.go000066400000000000000000000041211315167550200244410ustar00rootroot00000000000000// +build ignore // We still need editing by hands. // go tool cgo -godefs types_freebsd.go | sed 's/\*int64/int64/' | sed 's/\*byte/int64/' > process_freebsd_amd64.go /* Input to cgo -godefs. */ // +godefs map struct_pargs int64 /* pargs */ // +godefs map struct_proc int64 /* proc */ // +godefs map struct_user int64 /* user */ // +godefs map struct_vnode int64 /* vnode */ // +godefs map struct_vnode int64 /* vnode */ // +godefs map struct_filedesc int64 /* filedesc */ // +godefs map struct_vmspace int64 /* vmspace */ // +godefs map struct_pcb int64 /* pcb */ // +godefs map struct_thread int64 /* thread */ // +godefs map struct___sigset [16]byte /* sigset */ package process /* #include #include enum { sizeofPtr = sizeof(void*), }; */ import "C" // Machine characteristics; for internal use. const ( CTLKern = 1 // "high kernel": proc, limits KernProc = 14 // struct: process entries KernProcPID = 1 // by process id KernProcProc = 8 // only return procs KernProcPathname = 12 // path to executable KernProcArgs = 7 // get/set arguments/proctitle ) const ( sizeofPtr = C.sizeofPtr sizeofShort = C.sizeof_short sizeofInt = C.sizeof_int sizeofLong = C.sizeof_long sizeofLongLong = C.sizeof_longlong ) const ( sizeOfKinfoVmentry = C.sizeof_struct_kinfo_vmentry sizeOfKinfoProc = C.sizeof_struct_kinfo_proc ) // from sys/proc.h const ( SIDL = 1 /* Process being created by fork. */ SRUN = 2 /* Currently runnable. */ SSLEEP = 3 /* Sleeping on an address. */ SSTOP = 4 /* Process debugging or suspension. */ SZOMB = 5 /* Awaiting collection by parent. */ SWAIT = 6 /* Waiting for interrupt. */ SLOCK = 7 /* Blocked on a lock. */ ) // Basic types type ( _C_short C.short _C_int C.int _C_long C.long _C_long_long C.longlong ) // Time type Timespec C.struct_timespec type Timeval C.struct_timeval // Processes type Rusage C.struct_rusage type Rlimit C.struct_rlimit type KinfoProc C.struct_kinfo_proc type Priority C.struct_priority type KinfoVmentry C.struct_kinfo_vmentry golang-github-shirou-gopsutil-2.17.08/process/types_openbsd.go000066400000000000000000000044001315167550200244610ustar00rootroot00000000000000// +build ignore // We still need editing by hands. // go tool cgo -godefs types_openbsd.go | sed 's/\*int64/int64/' | sed 's/\*byte/int64/' > process_openbsd_amd64.go /* Input to cgo -godefs. */ // +godefs map struct_pargs int64 /* pargs */ // +godefs map struct_proc int64 /* proc */ // +godefs map struct_user int64 /* user */ // +godefs map struct_vnode int64 /* vnode */ // +godefs map struct_vnode int64 /* vnode */ // +godefs map struct_filedesc int64 /* filedesc */ // +godefs map struct_vmspace int64 /* vmspace */ // +godefs map struct_pcb int64 /* pcb */ // +godefs map struct_thread int64 /* thread */ // +godefs map struct___sigset [16]byte /* sigset */ package process /* #include #include #include enum { sizeofPtr = sizeof(void*), }; */ import "C" // Machine characteristics; for internal use. const ( CTLKern = 1 // "high kernel": proc, limits KernProc = 66 // struct: process entries KernProcAll = 0 KernProcPID = 1 // by process id KernProcProc = 8 // only return procs KernProcPathname = 12 // path to executable KernProcArgs = 55 // get/set arguments/proctitle KernProcArgv = 1 KernProcEnv = 3 ) const ( ArgMax = 256 * 1024 // sys/syslimits.h:#define ARG_MAX ) const ( sizeofPtr = C.sizeofPtr sizeofShort = C.sizeof_short sizeofInt = C.sizeof_int sizeofLong = C.sizeof_long sizeofLongLong = C.sizeof_longlong ) const ( sizeOfKinfoVmentry = C.sizeof_struct_kinfo_vmentry sizeOfKinfoProc = C.sizeof_struct_kinfo_proc ) // from sys/proc.h const ( SIDL = 1 /* Process being created by fork. */ SRUN = 2 /* Currently runnable. */ SSLEEP = 3 /* Sleeping on an address. */ SSTOP = 4 /* Process debugging or suspension. */ SZOMB = 5 /* Awaiting collection by parent. */ SDEAD = 6 /* Thread is almost gone */ SONPROC = 7 /* Thread is currently on a CPU. */ ) // Basic types type ( _C_short C.short _C_int C.int _C_long C.long _C_long_long C.longlong ) // Time type Timespec C.struct_timespec type Timeval C.struct_timeval // Processes type Rusage C.struct_rusage type Rlimit C.struct_rlimit type KinfoProc C.struct_kinfo_proc type Priority C.struct_priority type KinfoVmentry C.struct_kinfo_vmentry golang-github-shirou-gopsutil-2.17.08/v2migration.sh000066400000000000000000000117751315167550200224100ustar00rootroot00000000000000# This script is a helper of migration to gopsutil v2 using gorename # # go get golang.org/x/tools/cmd/gorename IFS=$'\n' ## Part 1. rename Functions to pass golint. ex) cpu.CPUTimesStat -> cpu.TimesStat # # Note: # process has IOCounters() for file IO, and also NetIOCounters() for Net IO. # This scripts replace process.NetIOCounters() to IOCounters(). # So you need hand-fixing process. TARGETS=`cat < TimesStat CPUInfoStat -> InfoStat CPUTimes -> Times CPUInfo -> Info CPUCounts -> Counts CPUPercent -> Percent DiskUsageStat -> UsageStat DiskPartitionStat -> PartitionStat DiskIOCountersStat -> IOCountersStat DiskPartitions -> Partitions DiskIOCounters -> IOCounters DiskUsage -> Usage HostInfoStat -> InfoStat HostInfo -> Info GetVirtualization -> Virtualization GetPlatformInformation -> PlatformInformation LoadAvgStat -> AvgStat LoadAvg -> Avg NetIOCountersStat -> IOCountersStat NetConnectionStat -> ConnectionStat NetProtoCountersStat -> ProtoCountersStat NetInterfaceAddr -> InterfaceAddr NetInterfaceStat -> InterfaceStat NetFilterStat -> FilterStat NetInterfaces -> Interfaces getNetIOCountersAll -> getIOCountersAll NetIOCounters -> IOCounters NetIOCountersByFile -> IOCountersByFile NetProtoCounters -> ProtoCounters NetFilterCounters -> FilterCounters NetConnections -> Connections NetConnectionsPid -> ConnectionsPid Uid -> UID Id -> ID convertCpuTimes -> convertCPUTimes EOF` for T in $TARGETS do echo $T gofmt -w -r "$T" ./*.go done ###### Part 2 rename JSON key name ## Google JSOn style ## https://google.github.io/styleguide/jsoncstyleguide.xml sed -i "" 's/guest_nice/guestNice/g' cpu/*.go sed -i "" 's/vendor_id/vendorId/g' cpu/*.go sed -i "" 's/physical_id/physicalId/g' cpu/*.go sed -i "" 's/model_name/modelName/g' cpu/*.go sed -i "" 's/cache_size/cacheSize/g' cpu/*.go sed -i "" 's/core_id/coreId/g' cpu/*.go sed -i "" 's/inodes_total/inodesTotal/g' disk/*.go sed -i "" 's/inodes_used/inodesUsed/g' disk/*.go sed -i "" 's/inodes_free/inodesFree/g' disk/*.go sed -i "" 's/inodes_used_percent/inodesUsedPercent/g' disk/*.go sed -i "" 's/read_count/readCount/g' disk/*.go sed -i "" 's/write_count/writeCount/g' disk/*.go sed -i "" 's/read_bytes/readBytes/g' disk/*.go sed -i "" 's/write_bytes/writeBytes/g' disk/*.go sed -i "" 's/read_time/readTime/g' disk/*.go sed -i "" 's/write_time/writeTime/g' disk/*.go sed -i "" 's/io_time/ioTime/g' disk/*.go sed -i "" 's/serial_number/serialNumber/g' disk/*.go sed -i "" 's/used_percent/usedPercent/g' disk/*.go sed -i "" 's/inodesUsed_percent/inodesUsedPercent/g' disk/*.go sed -i "" 's/total_cache/totalCache/g' docker/*.go sed -i "" 's/total_rss_huge/totalRssHuge/g' docker/*.go sed -i "" 's/total_rss/totalRss/g' docker/*.go sed -i "" 's/total_mapped_file/totalMappedFile/g' docker/*.go sed -i "" 's/total_pgpgin/totalPgpgin/g' docker/*.go sed -i "" 's/total_pgpgout/totalPgpgout/g' docker/*.go sed -i "" 's/total_pgfault/totalPgfault/g' docker/*.go sed -i "" 's/total_pgmajfault/totalPgmajfault/g' docker/*.go sed -i "" 's/total_inactive_anon/totalInactiveAnon/g' docker/*.go sed -i "" 's/total_active_anon/totalActiveAnon/g' docker/*.go sed -i "" 's/total_inactive_file/totalInactiveFile/g' docker/*.go sed -i "" 's/total_active_file/totalActiveFile/g' docker/*.go sed -i "" 's/total_unevictable/totalUnevictable/g' docker/*.go sed -i "" 's/mem_usage_in_bytes/memUsageInBytes/g' docker/*.go sed -i "" 's/mem_max_usage_in_bytes/memMaxUsageInBytes/g' docker/*.go sed -i "" 's/memory.limit_in_bytes/memoryLimitInBbytes/g' docker/*.go sed -i "" 's/memory.failcnt/memoryFailcnt/g' docker/*.go sed -i "" 's/mapped_file/mappedFile/g' docker/*.go sed -i "" 's/container_id/containerID/g' docker/*.go sed -i "" 's/rss_huge/rssHuge/g' docker/*.go sed -i "" 's/inactive_anon/inactiveAnon/g' docker/*.go sed -i "" 's/active_anon/activeAnon/g' docker/*.go sed -i "" 's/inactive_file/inactiveFile/g' docker/*.go sed -i "" 's/active_file/activeFile/g' docker/*.go sed -i "" 's/hierarchical_memory_limit/hierarchicalMemoryLimit/g' docker/*.go sed -i "" 's/boot_time/bootTime/g' host/*.go sed -i "" 's/platform_family/platformFamily/g' host/*.go sed -i "" 's/platform_version/platformVersion/g' host/*.go sed -i "" 's/virtualization_system/virtualizationSystem/g' host/*.go sed -i "" 's/virtualization_role/virtualizationRole/g' host/*.go sed -i "" 's/used_percent/usedPercent/g' mem/*.go sed -i "" 's/bytes_sent/bytesSent/g' net/*.go sed -i "" 's/bytes_recv/bytesRecv/g' net/*.go sed -i "" 's/packets_sent/packetsSent/g' net/*.go sed -i "" 's/packets_recv/packetsRecv/g' net/*.go sed -i "" 's/conntrack_count/conntrackCount/g' net/*.go sed -i "" 's/conntrack_max/conntrackMax/g' net/*.go sed -i "" 's/read_count/readCount/g' process/*.go sed -i "" 's/write_count/writeCount/g' process/*.go sed -i "" 's/read_bytes/readBytes/g' process/*.go sed -i "" 's/write_bytes/writeBytes/g' process/*.go sed -i "" 's/shared_clean/sharedClean/g' process/*.go sed -i "" 's/shared_dirty/sharedDirty/g' process/*.go sed -i "" 's/private_clean/privateClean/g' process/*.go sed -i "" 's/private_dirty/privateDirty/g' process/*.go golang-github-shirou-gopsutil-2.17.08/windows_memo.rst000066400000000000000000000012061315167550200230400ustar00rootroot00000000000000Windows memo ===================== Size ---------- DWORD 32-bit unsigned integer DWORDLONG 64-bit unsigned integer DWORD_PTR unsigned long type for pointer precision DWORD32 32-bit unsigned integer DWORD64 64-bit unsigned integer HALF_PTR _WIN64 = int, else short INT 32-bit signed integer INT_PTR _WIN64 = __int64 else int LONG 32-bit signed integer LONGLONG 64-bit signed integer LONG_PTR _WIN64 = __int64 else long SHORT 16-bit integer SIZE_T maximum number of bytes to which a pointer can point. typedef ULONG_PTR SIZE_T; SSIZE_T signed version of SIZE_T. typedef LONG_PTR SSIZE_T; WORD 16-bit unsigned integer