brief introduction
Gopsutil is a Python tool library * * [psutil]( https://link.zhihu.com/?target=https%3A//github.com/giampaolo/psutil )**The transplanted version of Golang can help us easily obtain various system and hardware information. Gopsutil shields the differences between various systems for us and has very strong portability. With gopsutil, we no longer need to use syscall to call corresponding system methods for different systems. Even better, there is no cgo code in the implementation of gopsutil, which makes cross compilation possible.
gopsutil divides different functions into different sub packages:
- CPU: CPU related;
- Disk: disk related;
- Docker: docker related;
- Host: host related;
- mem: memory related;
- net: network related;
- Process: process related;
- winservices: Windows service related.
Import package
import github.com/shirou/gopsutil
Collect CPU Information
We know that there are two types of CPU cores, one is physical core and the other is logical core. The number of physical cores is the actual number of CPUs on the motherboard. A physical CPU can have multiple cores. These cores are called logical cores. CPU related functions in gopsutil are in the CPU sub package, which provides interfaces for obtaining the number of physical and logical cores and CPU utilization:
- Counts(logical bool): pass in false to return the number of physical cores; pass in true to return the number of logical cores;
- Percent(interval time.Duration, percpu bool): indicates to obtain the CPU utilization within the interval. When percpu is false, obtain the total CPU utilization. When percpu is true, obtain the utilization of each CPU respectively, and return a value of [] float64 type.
physicalCnt, _ := cpu.Counts(false) // cpu physical cores logicalCnt, _ := cpu.Counts(true) // Number of cpu logical cores fmt.Printf("physical count:%d logical count:%d\n", physicalCnt, logicalCnt) // Obtain the total CPU utilization rate and the respective utilization rate of each CPU within 3s totalPercent, _ := cpu.Percent(3*time.Second, false) // Total CPU utilization perPercents, _ := cpu.Percent(3*time.Second, true) // Utilization of each CPU fmt.Printf("total percent:%v per percents:%v", totalPercent, perPercents)
The above code output:
physical count:6 logical count:12 total percent:[1.078981441519206] per percents:[13.19796954314721 1.5706806282722512 23.036649214659686 2.094240837696335 13.541666666666666 1.5625 8.854166666666668 1.0471204188481675 4.6875 1.5625 4.712041884816754 1.0416666666666665]
detailed information
Call CPU Info() to get the details of CPU and return [] CPU InfoStat:
func main() { infos, _ := cpu.Info() for _, info := range infos { data, _ := json.MarshalIndent(info, "", " ") fmt.Print(string(data)) } }
To facilitate viewing, I use JSON to output the results:
{ "cpu": 0, "vendorId": "GenuineIntel", "family": "205", "model": "", "stepping": 0, "physicalId": "BFEBFBFF000A0653", "coreId": "", "cores": 12, // Number of cpu logical cores "modelName": "Intel(R) Core(TM) i5-10400 CPU @ 2.90GHz", "mhz": 2904, "cacheSize": 0, "flags": [], "microcode": "" }
It can be seen from the results that the CPU is Intel's i5-10400 series, with a frequency of 2.90GHz. The above is the return result of my running on Windows. GitHub is used internally COM / stackexchange / WMI library. Under Linux, each logical CPU will return an InfoStat structure.
CPU load
info, _ := load.Avg() fmt.Printf("%v\n", info)
{ "load1":0, "load5":0, "load15":0 }
Time occupation
Call CPU Times (percpu bool) can obtain the total CPU and the time occupation of each individual CPU from startup. Passing in percpu=false returns the total, and passing in percpu=true returns the single. The time usage of each CPU is a TimeStat structure:
// src/github.com/shirou/gopsutil/cpu/cpu.go type TimesStat struct { CPU string `json:"cpu"` //CPU identification. If it is total, this field is' CPU total ', otherwise it is' cpu0', 'cpu1'; User float64 `json:"user"` //User time occupation (user status) System float64 `json:"system"` //System time occupation (kernel state) Idle float64 `json:"idle"` //free time 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"` }
For example:
func main() { infos, _ := cpu.Times(true) for _, info := range infos { data, _ := json.MarshalIndent(info, "", " ") fmt.Print(string(data)) } }
To facilitate viewing, I use JSON to output the results. Here is one of the outputs:
{ "cpu": "cpu0", "user": 674.46875, "system": 1184.984375, "idle": 7497.1875, "nice": 0, "iowait": 0, "irq": 75.578125, "softirq": 0, "steal": 0, "guest": 0, "guestNice": 0 }
Collect disk information
The sub package disk is used to obtain disk information. Disk can obtain IO statistics, partition and utilization information. The following are introduced in turn.
IO statistics
Call disk Iocounters() function, the returned IO statistics are represented by map[string]IOCountersStat type. Each partition has a structure, the key is the partition name, and the value is statistical information. Some fields of the statistical structure are extracted here, mainly including the number of reads and writes, bytes and time:
// src/github.com/shirou/gopsutil/disk/disk.go 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"` // ... }
For example:
func main() { mapStat, _ := disk.IOCounters() // IO statistics for name, stat := range mapStat { fmt.Println(name) data, _ := json.MarshalIndent(stat, "", " ") fmt.Println(string(data)) } }
The output includes all partitions. I only show one here:
C: // c disk { "readCount": 2249456, "mergedReadCount": 0, "writeCount": 6522173, "mergedWriteCount": 0, "readBytes": 59965126656, "writeBytes": 142391553536, "readTime": 5406, "writeTime": 3562, "iopsInProgress": 0, "ioTime": 0, "weightedIO": 0, "name": "C:", "serialNumber": "", "label": "" }
Note that disk Iocounters() can pass in a variable number of string parameters to identify the partition, which is not valid on Windows.
partition
Call disk The PartitionStat (all bool) function returns partition information. If all = false, only the actual physical partition (including hard disk, CD-ROM and USB) is returned, and other virtual partitions are ignored. If all = true, all partitions are returned. The return type is [] PartitionStat, and each partition corresponds to a PartitionStat structure:
// src/github.com/shirou/gopsutil/disk/ type PartitionStat struct { Device string `json:"device"` // Partition ID is in the format of 'C:' on Windows Mountpoint string `json:"mountpoint"` // Mount point is the starting location of the file path of the partition Fstype string `json:"fstype"` // File system types: FAT, NTFS, etc. are commonly used in Windows, and ext, ext2, ext3, etc. are used in Linux Opts string `json:"opts"` // Options, system related }
For example:
func main() { infos, _ := disk.Partitions(false) for _, info := range infos { data, _ := json.MarshalIndent(info, "", " ") fmt.Println(string(data)) } }
My Windows machine output (only show the first partition):
{ "device": "C:", "mountpoint": "C:", "fstype": "NTFS", "opts": "rw.compress" }
According to the above output, my first partition is C:, and the file system type is NTFS.
Utilization rate
Call disk Usage (path string) to obtain the usage of the disk where the path path is located, and return a UsageStat structure:
// src/github.com/shirou/gopsutil/disk.go type UsageStat struct { Path string `json:"path"` // Path, passed in parameters Fstype string `json:"fstype"` // file system type Total uint64 `json:"total"` // Total capacity of this zone Free uint64 `json:"free"` // Free capacity Used uint64 `json:"used"` // Used capacity UsedPercent float64 `json:"usedPercent"` // Percentage used InodesTotal uint64 `json:"inodesTotal"` InodesUsed uint64 `json:"inodesUsed"` InodesFree uint64 `json:"inodesFree"` InodesUsedPercent float64 `json:"inodesUsedPercent"` }
For example:
func main() { info, _ := disk.Usage("E:/code") data, _ := json.MarshalIndent(info, "", " ") fmt.Println(string(data)) }
Since the usage of the disk is returned, the paths E:/code and E: return the same result, but the Path field in the structure is different. Program output:
{ "path": "E:/code", "fstype": "", "total": 339303460864, "free": 336575107072, "used": 2728353792, "usedPercent": 0.804104321557033, "inodesTotal": 0, "inodesUsed": 0, "inodesFree": 0, "inodesUsedPercent": 0 }
Collect host information
The sub package host can obtain host related information, such as boot time, kernel version number, platform information and so on.
Startup time
host.BootTime() returns the timestamp of the host boot time:
func main() { timestamp, _ := host.BootTime() t := time.Unix(int64(timestamp), 0) fmt.Println(t.Local().Format("2006-01-02 15:04:05")) }
Get the boot time first, and then go through the above. Time UNIX () converts it to time Time type, the last output time in 2006-01-02 15:04:05 format:
2020-04-06 20:25:32
Kernel version and platform information
func main() { version, _ := host.KernelVersion() fmt.Println(version) platform, family, version, _ := host.PlatformInformation() fmt.Println("platform:", platform) // Operating system information fmt.Println("family:", family) fmt.Println("version:", version) }
Run output on my Win10:
10.0.19042 Build 19042 platform: Microsoft Windows 10 Pro family: Standalone Workstation version: 10.0.19042 Build 19042
end user
host.Users() returns the user information connected to the terminal. Each user has a UserStat structure:
// src/github.com/shirou/gopsutil/host/host.go type UserStat struct { User string `json:"user"` Terminal string `json:"terminal"` Host string `json:"host"` Started int `json:"started"` }
The fields are clear at a glance. See the example:
func main() { users, _ := host.Users() for _, user := range users { data, _ := json.MarshalIndent(user, "", " ") fmt.Println(string(data)) } }
Collect memory information
Get physical memory information
We demonstrated how to use mem Virtualmemory() to get memory information. This function returns only physical memory information.
import "github.com/shirou/gopsutil/mem" //mem. The memory structure information returned by the virtual memory () method VirtualMemoryStat v, _ := mem.VirtualMemory() fmt.Println(v)
The output is as follows:
{ "total": 17013055488, // Total memory "available": 8491429888, // Available memory "used": 8521625600, // Used memory "usedPercent": 50, // Memory usage percentage "free": 8491429888, // Unused memory "active": 0, "inactive": 0, "wired": 0, "laundry": 0, "buffers": 0, "cached": 0, "writeBack": 0, "dirty": 0, "writeBackTmp": 0, "shared": 0, "slab": 0, "sreclaimable": 0, "sunreclaim": 0, "pageTables": 0, "swapCached": 0, "commitLimit": 0, "committedAS": 0, "highTotal": 0, "highFree": 0, "lowTotal": 0, "lowFree": 0, "swapTotal": 0, "swapFree": 0, "mapped": 0, "vmallocTotal": 0, "vmallocUsed": 0, "vmallocChunk": 0, "hugePagesTotal": 0, "hugePagesFree": 0, "hugePageSize": 0 }
Get swap memory information
We can also use mem Swapmemory() gets the information of swap memory, which is stored in the structure SwapMemoryStat:
// src/github.com/shirou/gopsutil/mem/ type SwapMemoryStat struct { Total uint64 `json:"total"` // Total memory Used uint64 `json:"used"` // Memory used Free uint64 `json:"free"` // idle memory UsedPercent float64 `json:"usedPercent"` // Memory usage Sin uint64 `json:"sin"` Sout uint64 `json:"sout"` PgIn uint64 `json:"pgin"` // Number of pages loaded PgOut uint64 `json:"pgout"` // Pages eliminated PgFault uint64 `json:"pgfault"` // Number of page missing errors }
The meaning of the field is easy to understand. We will focus on the three fields PgIn/PgOut/PgFault. Swap memory is in pages. If a page fault occurs, the operating system will load some pages from the disk into memory and eliminate some pages in memory according to a specific mechanism. PgIn indicates the number of loaded pages, PgOut eliminated pages, and PgFault page missing errors.
For example:
func main() { swapMemory, _ := mem.SwapMemory() data, _ := json.MarshalIndent(swapMemory, "", " ") fmt.Println(string(data)) }
The output is as follows:
{ "total": 24093069312, "used": 12682260480, "free": 11410808832, "usedPercent": 52.638625306587095, "sin": 0, "sout": 0, "pgin": 0, "pgout": 0, "pgfault": 0, "pgmajfault": 0 }
Collect process information
Process can be used to obtain the process information currently running in the system, create a new process, and perform some operations on the process.
func main() { var rootProcess *process.Process processes, _ := process.Processes() for _, p := range processes { if p.Pid == 0 { rootProcess = p break } } fmt.Println(rootProcess) fmt.Println("children:") children, _ := rootProcess.Children() for _, p := range children { fmt.Println(p) } }
Call process first Processes () gets all the processes running in the current system, then finds the Pid 0 process, the first process of the operating system, and finally calls Children() to return to its sub process. There are also many ways to obtain process information. If you are interested, you can check the documentation~
Collect Windows service information
The winservices sub package can obtain the Service information in the Windows system, and golang.com is used internally Org / X / sys package. In winservices, a Service corresponds to a Service structure:
// src/github.com/shirou/gopsutil/winservices/winservices.go type Service struct { Name string Config mgr.Config Status ServiceStatus // contains filtered or unexported fields }
mgr.Config is the package golang Org / X / sys, which records the service type, startup type (automatic / manual), binary file path and other information in detail:
// src/golang.org/x/sys/windows/svc/mgr/config.go type Config struct { ServiceType uint32 StartType uint32 ErrorControl uint32 BinaryPathName string LoadOrderGroup string TagId uint32 Dependencies []string ServiceStartName string DisplayName string Password string Description string SidType uint32 DelayedAutoStart bool }
The ServiceStatus structure records the status of the service:
// src/github.com/shirou/gopsutil/winservices/winservices.go type ServiceStatus struct { State svc.State //It is in service status, including stopped, running, suspended, etc Accepts svc.Accepted // Indicates which operations the service receives, including pause, resume and session switching Pid uint32 // Process ID Win32ExitCode uint32 // Application exit status code }
In the following program, I output the names, binary file paths and status of all services in the system to the console:
func main() { services, _ := winservices.ListServices() for _, service := range services { newservice, _ := winservices.NewService(service.Name) newservice.GetServiceDetail() fmt.Println("Name:", newservice.Name, "Binary Path:", newservice.Config.BinaryPathName, "State: ", newservice.Status.State) } }
Notice that you call WinServices The Service object information returned by ListServices () is incomplete. We create a service with the name of the service through NewService(), and then call the GetServiceDetail () method to get the details of the service. You cannot directly use service Call GetServiceDetail() because the object returned by ListService() lacks the necessary system resource handle (to save resources), calling GetServiceDetail() method will panic!!!
Error and timeout
Since most functions involve bottom-level system calls, errors and timeouts are inevitable. Almost all interfaces have two return values, the second as an error. In the previous example, we ignored the error in order to simplify the code. In practical use, it is recommended to deal with the error.
In addition, most interfaces are a pair, one without context A parameter of type context. The other parameter with this type is used for context control. In case of internal call error or timeout, it can be handled in time to avoid waiting for a long time to return. In fact, without context The function of context parameter is internally based on context Background() is a parameter call with context Function of context:
// src/github.com/shirou/gopsutil/cpu_windows.go func Times(percpu bool) ([]TimesStat, error) { return TimesWithContext(context.Background(), percpu) } func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) { // ... }