目录

快速使用

CPU

详细信息

时间占用

磁盘

IO 统计

分区

使用率

主机

开机时间

内核版本和平台信息

终端用户

内存

进程

Windows 服务

错误和超时

docker


gopsutil是 Python 工具库psutil 的 Golang 移植版,可以帮助我们方便地获取各种系统和硬件信息。gopsutil为我们屏蔽了各个系统之间的差异,具有非常强悍的可移植性。有了gopsutil,我们不再需要针对不同的系统使用syscall调用对应的系统方法。更棒的是gopsutil的实现中没有任何cgo的代码,使得交叉编译成为可能。

快速使用

先安装:

$ go get github.com/shirou/gopsutil

由于gopsutil库用到了golang.org/x/sys,后者在墙外,如果有类似下面的报错:

cannot find package "golang.org/x/sys/windows"

可使用下面的命令下载golang.org/x/sys在 GitHub 上的镜像:

$ git clone git@github.com:golang/sys.git $GOPATH/src/golang.org/x/sys

使用:

package mainimport ("fmt""github.com/shirou/gopsutil/mem"
)func main() {v, _ := mem.VirtualMemory()fmt.Printf("Total: %v, Available: %v, UsedPercent:%f%%\n", v.Total, v.Available, v.UsedPercent)fmt.Println(v)
}

gopsutil将不同的功能划分到不同的子包中:

  • cpu:CPU 相关;
  • disk:磁盘相关;
  • docker:docker 相关;
  • host:主机相关;
  • mem:内存相关;
  • net:网络相关;
  • process:进程相关;
  • winservices:Windows 服务相关。

想要使用对应的功能,要导入对应的子包。例如,上面代码中,我们要获取内存信息,导入的是mem子包。mem.VirtualMemory()方法返回内存信息结构mem.VirtualMemoryStat,该结构有丰富的字段,我们最常使用的无外乎Total(总内存)、Available(可用内存)、Used(已使用内存)和UsedPercent(内存使用百分比)。mem.VirtualMemoryStat还实现了fmt.Stringer接口,以 JSON 格式返回内存信息。语句fmt.Println(v)会自动调用v.String(),将返回信息输出。程序输出:

Total: 8526921728, Available: 3768975360, UsedPercent:55.000000%
{"total":8526921728,"available":3768975360,"used":4757946368,"usedPercent":55,"free":0,"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}

单位为字节,我的电脑内存 8GB,当前使用百分比为 55%,可用内存 3768975360B(即 3.51GB)。

CPU

我们知道 CPU 的核数有两种,一种是物理核数,一种是逻辑核数。物理核数就是主板上实际有多少个 CPU,一个物理 CPU 上可以有多个核心,这些核心被称为逻辑核。gopsutil中 CPU 相关功能在cpu子包中,cpu子包提供了获取物理和逻辑核数、CPU 使用率的接口:

  • Counts(logical bool):传入false,返回物理核数,传入true,返回逻辑核数;
  • Percent(interval time.Duration, percpu bool):表示获取interval时间间隔内的 CPU 使用率,percpufalse时,获取总的 CPU 使用率,percputrue时,分别获取每个 CPU 的使用率,返回一个[]float64类型的值。

例如:

func main() {physicalCnt, _ := cpu.Counts(false)logicalCnt, _ := cpu.Counts(true)fmt.Printf("physical count:%d logical count:%d\n", physicalCnt, logicalCnt)totalPercent, _ := cpu.Percent(3*time.Second, false)perPercents, _ := cpu.Percent(3*time.Second, true)fmt.Printf("total percent:%v per percents:%v", totalPercent, perPercents)
}

上面代码获取物理核数和逻辑核数,并获取 3s 内的总 CPU 使用率和每个 CPU 各自的使用率,程序输出(注意每次运行输出可能都不相同):

physical count:4 logical count:8
total percent:[30.729166666666668] per percents:[32.64248704663213 26.94300518134715 44.559585492227974 23.958333333333336 36.787564766839374 20.3125 38.54166666666667 28.125]

详细信息

调用cpu.Info()可获取 CPU 的详细信息,返回[]cpu.InfoStat

func main() {infos, _ := cpu.Info()for _, info := range infos {data, _ := json.MarshalIndent(info, "", " ")fmt.Print(string(data))}
}

为了方便查看,我使用 JSON 输出结果:

{"cpu": 0,"vendorId": "GenuineIntel","family": "198","model": "","stepping": 0,"physicalId": "BFEBFBFF000906E9","coreId": "","cores": 8,"modelName": "Intel(R) Core(TM) i7-7700 CPU @ 3.60GHz","mhz": 3601,"cacheSize": 0,"flags": [],"microcode": ""
}

由结果可以看出,CPU 是 Intel 的 i7-7700 系列,频率 3.60GHz。上面是我在 Windows 上运行的返回结果,内部使用了github.com/StackExchange/wmi库。在 Linux 下每个逻辑 CPU 都会返回一个InfoStat结构。

时间占用

调用cpu.Times(percpu bool)可以获取从开机算起,总 CPU 和 每个单独的 CPU 时间占用情况。传入percpu=false返回总的,传入percpu=true返回单个的。每个 CPU 时间占用情况是一个TimeStat结构:

// src/github.com/shirou/gopsutil/cpu/cpu.go
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"`
}
  • CPU:CPU 标识,如果是总的,该字段为cpu-total,否则为cpu0cpu1...;
  • User:用户时间占用(用户态);
  • System:系统时间占用(内核态);
  • Idle:空闲时间;
  • ...

例如:

func main() {infos, _ := cpu.Times(true)for _, info := range infos {data, _ := json.MarshalIndent(info, "", " ")fmt.Print(string(data))}
}

为了方便查看,我用 JSON 输出结果,下面是其中一个输出:

{"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
}

磁盘

子包disk用于获取磁盘信息。disk可获取 IO 统计、分区和使用率信息。下面依次介绍。

IO 统计

调用disk.IOCounters()函数,返回的 IO 统计信息用map[string]IOCountersStat类型表示。每个分区一个结构,键为分区名,值为统计信息。这里摘取统计结构的部分字段,主要有读写的次数、字节数和时间:

// 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"`// ...
}

例如:

func main() {mapStat, _ := disk.IOCounters()for name, stat := range mapStat {fmt.Println(name)data, _ := json.MarshalIndent(stat, "", "  ")fmt.Println(string(data))}
}

输出包括所有分区,我这里只展示一个:

C:
{"readCount": 184372,"mergedReadCount": 0,"writeCount": 42252,"mergedWriteCount": 0,"readBytes": 5205152768,"writeBytes": 701583872,"readTime": 333,"writeTime": 27,"iopsInProgress": 0,"ioTime": 0,"weightedIO": 0,"name": "C:","serialNumber": "","label": ""
}

注意,disk.IOCounters()可传入可变数量的字符串参数用于标识分区,此参数在 Windows 上无效

分区

调用disk.PartitionStat(all bool)函数,返回分区信息。如果all = false,只返回实际的物理分区(包括硬盘、CD-ROM、USB),忽略其它的虚拟分区。如果all = true则返回所有的分区。返回类型为[]PartitionStat,每个分区对应一个PartitionStat结构:

// src/github.com/shirou/gopsutil/disk/
type PartitionStat struct {Device     string `json:"device"`Mountpoint string `json:"mountpoint"`Fstype     string `json:"fstype"`Opts       string `json:"opts"`
}
  • Device:分区标识,在 Windows 上即为C:这类格式;
  • Mountpoint:挂载点,即该分区的文件路径起始位置;
  • Fstype:文件系统类型,Windows 常用的有 FAT、NTFS 等,Linux 有 ext、ext2、ext3等;
  • Opts:选项,与系统相关。

例如:

func main() {infos, _ := disk.Partitions(false)for _, info := range infos {data, _ := json.MarshalIndent(info, "", "  ")fmt.Println(string(data))}
}

我的 Windows 机器输出(只展示第一个分区):

{"device": "C:","mountpoint": "C:","fstype": "NTFS","opts": "rw.compress"
}

由上面的输出可知,我的第一个分区为C:,文件系统类型为NTFS

使用率

调用disk.Usage(path string)即可获得路径path所在磁盘的使用情况,返回一个UsageStat结构:

// src/github.com/shirou/gopsutil/disk.go
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"`
}
  • Path:路径,传入的参数;
  • Fstype:文件系统类型;
  • Total:该分区总容量;
  • Free:空闲容量;
  • Used:已使用的容量;
  • UsedPercent:使用百分比。

例如:

func main() {info, _ := disk.Usage("D:/code/golang")data, _ := json.MarshalIndent(info, "", "  ")fmt.Println(string(data))
}

由于返回的是磁盘的使用情况,所以路径D:/code/golangD:返回同样的结果,只是结构中的Path字段不同而已。程序输出:

{"path": "D:/code/golang","fstype": "","total": 475779821568,"free": 385225650176,"used": 90554171392,"usedPercent": 19.032789388496106,"inodesTotal": 0,"inodesUsed": 0,"inodesFree": 0,"inodesUsedPercent": 0
}

主机

子包host可以获取主机相关信息,如开机时间、内核版本号、平台信息等等。

开机时间

host.BootTime()返回主机开机时间的时间戳:

func main() {timestamp, _ := host.BootTime()t := time.Unix(int64(timestamp), 0)fmt.Println(t.Local().Format("2006-01-02 15:04:05"))
}

上面先获取开机时间,然后通过time.Unix()将其转为time.Time类型,最后输出2006-01-02 15:04:05格式的时间:

2020-04-06 20:25:32

内核版本和平台信息

func main() {version, _ := host.KernelVersion()fmt.Println(version)platform, family, version, _ := host.PlatformInformation()fmt.Println("platform:", platform)fmt.Println("family:", family,fmt.Println("version:", version)
}

在我的 Win10 上运行输出:

10.0.18362 Build 18362
platform: Microsoft Windows 10 Pro
family: Standalone Workstation
version: 10.0.18362 Build 18362

终端用户

host.Users()返回终端连接上来的用户信息,每个用户一个UserStat结构:

// 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"`
}

字段一目了然,看示例:

func main() {users, _ := host.Users()for _, user := range users {data, _ := json.MarshalIndent(user, "", " ")fmt.Println(string(data))}
}

内存

快速开始中,我们演示了如何使用mem.VirtualMemory()来获取内存信息。该函数返回的只是物理内存信息。我们还可以使用mem.SwapMemory()获取交换内存的信息,信息存储在结构SwapMemoryStat中:

// src/github.com/shirou/gopsutil/mem/
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"`PgIn        uint64  `json:"pgin"`PgOut       uint64  `json:"pgout"`PgFault     uint64  `json:"pgfault"`
}

字段含义很容易理解,PgIn/PgOut/PgFault这三个字段我们重点介绍一下。交换内存是以为单位的,如果出现缺页错误(page fault),操作系统会将磁盘中的某些页载入内存,同时会根据特定的机制淘汰一些内存中的页。PgIn表征载入页数,PgOut淘汰页数,PgFault缺页错误数。

例如:

func main() {swapMemory, _ := mem.SwapMemory()data, _ := json.MarshalIndent(swapMemory, "", " ")fmt.Println(string(data))
}

进程

process可用于获取系统当前运行的进程信息,创建新进程,对进程进行一些操作等。

func main() {var rootProcess *process.Processprocesses, _ := process.Processes()for _, p := range processes {if p.Pid == 0 {rootProcess = pbreak}}fmt.Println(rootProcess)fmt.Println("children:")children, _ := rootProcess.Children()for _, p := range children {fmt.Println(p)}
}

先调用process.Processes()获取当前系统中运行的所有进程,然后找到Pid为 0 的进程,即操作系统的第一个进程,最后调用Children()返回其子进程。还有很多方法可获取进程信息,感兴趣可查看文档了解~

Windows 服务

winservices子包可以获取 Windows 系统中的服务信息,内部使用了golang.org/x/sys包。在winservices中,一个服务对应一个Service结构:

// src/github.com/shirou/gopsutil/winservices/winservices.go
type Service struct {Name   stringConfig mgr.ConfigStatus ServiceStatus// contains filtered or unexported fields
}

mgr.Config为包golang.org/x/sys中的结构,该结构详细记录了服务类型、启动类型(自动/手动)、二进制文件路径等信息:

// src/golang.org/x/sys/windows/svc/mgr/config.go
type Config struct {ServiceType      uint32StartType        uint32ErrorControl     uint32BinaryPathName   stringLoadOrderGroup   stringTagId            uint32Dependencies     []stringServiceStartName stringDisplayName      stringPassword         stringDescription      stringSidType          uint32DelayedAutoStart bool
}

ServiceStatus结构记录了服务的状态:

// src/github.com/shirou/gopsutil/winservices/winservices.go
type ServiceStatus struct {State         svc.StateAccepts       svc.AcceptedPid           uint32Win32ExitCode uint32
}
  • State:为服务状态,有已停止、运行、暂停等;
  • Accepts:表示服务接收哪些操作,有暂停、继续、会话切换等;
  • Pid:进程 ID;
  • Win32ExitCode:应用程序退出状态码。

下面程序中,我将系统中所有服务的名称、二进制文件路径和状态输出到控制台:

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)}
}

注意,调用winservices.ListServices()返回的Service对象信息是不全的,我们通过NewService()以该服务名称创建一个服务,然后调用GetServiceDetail()方法获取该服务的详细信息。不能直接通过service.GetServiceDetail()来调用,因为ListService()返回的对象缺少必要的系统资源句柄(为了节约资源),调用GetServiceDetail()方法会panic!!!

错误和超时

由于大部分函数都涉及到底层的系统调用,所以发生错误和超时是在所难免的。几乎所有的接口都有两个返回值,第二个作为错误。在前面的例子中,我们为了简化代码都忽略了错误,在实际使用中,建议对错误进行处理。

另外,大部分接口都是一对,一个不带context.Context类型的参数,另一个带有该类型参数,用于做上下文控制。在内部调用发生错误或超时后能及时处理,避免长时间等待返回。实际上,不带context.Context参数的函数内部都是以context.Background()为参数调用带有context.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) {// ...
}

docker

引入库:import "github.com/shirou/gopsutil/docker"

常用api

func GetDockerStat() ([]CgroupDockerStat, error) {return GetDockerStatWithContext(context.Background())
}

GetDockerStat 返回docker基本信息列表 类似于 docker ps -a 相关信息

type CgroupDockerStat struct {ContainerID string `json:"containerID"`Name        string `json:"name"`Image       string `json:"image"`Status      string `json:"status"`Running     bool   `json:"running"`
}

实例:

dockerList, err := docker.GetDockerStat()
if err != nil {return
}
for _, v := range dockerList {fmt.Printf("ContainerID=%s\n", v.ContainerID)fmt.Printf("Image=%s\n", v.Image)fmt.Printf("Status=%s\n", v.Status)fmt.Printf("Running=%t\n", v.Running)fmt.Printf("Name=%s\n\n", v.Name)
}

运行结果:

ContainerID=e60ea41fab20fe4f5a93d51d95c82c41b48b8f96dd0b4998cd1a43e3c47a446e
Image=centos:7
Status=Up 15 minutes
Running=true
Name=centosContainerID=a575fe5583dd2580e05ab86fd6d644dc13f15b01a337c66f29230866839d12e5
Image=mysql:8.0.18
Status=Up 15 minutes
Running=true
Name=db

golang gopsutil 进程 系统硬件 docker 信息获取相关推荐

  1. C/C++通过WMI和系统API函数获取获取系统硬件配置信息(转)

    前段时间由于项目需要,要求做一个服务器的实时性能监控(CPU.内存.网络利用率等)和读取服务器的硬件配置参数的接口供项目组使用,就是一个类似于鲁大师之类的东东吧... 当然第一想法肯定是利用Windo ...

  2. linux 系统硬件信息检测工具,美国Linux服务器查看硬件信息工具

    在美国Linux服务器上有许多查看工具可用于查找系统硬件规格,其中有一些是美国Linux系统已经默认预装的,用户可以直接进行使用.下面小编就来介绍一些美国Linux服务器上预装的查看硬件信息的工具. ...

  3. C/C++通过WMI和系统API函数获取获取系统硬件(cpu,内存,显卡,网卡)配置信息

     转自:http://blog.csdn.net/ly402609921/article/details/7446943 前段时间由于项目需要,要求做一个服务器的实时性能监控(CPU.内存.网络利 ...

  4. R语言sys方法:sys.getpid函数获取R会话的进程ID、sys.glob函数和file.path函数匹配文件夹下的所有特定类型文件、sys.info函数获取系统和用户信息

    R语言sys方法:sys.getpid函数获取R会话的进程ID.sys.glob函数和file.path函数匹配文件夹下的所有特定类型文件.sys.info函数获取系统和用户信息 目录

  5. python获取系统硬件信息

    python获取系统硬件信息 github项目 https://github.com/giampaolo/psutil cpu,内存,etc.

  6. python 获取Dmidecode 输出的系统硬件信息

    目的: 熟悉利用python 分析文本的信息.分析的文件信息是通过dmidecode 工具抓取的系统硬件信息. 本文结构: (1) 分析dmidecode 工具的输出信息结构 (2) 分别用两种方式对 ...

  7. c++获得cpu厂商_【C++】WMI获取系统硬件信息(CPU/DISK/NetWork etc)

    原创 2016年05月14日 01:50:22 标签: c++ / WMI / CPU 官网找到一个例子,根据例子修改下可以获取很多信息 [cpp] #define _WIN32_DCOM #incl ...

  8. 使用Python获取Linux系统的各种信息

    From: http://www.jb51.net/article/52058.htm 这篇文章主要介绍了使用Python获取Linux系统的各种信息,例如系统类型.CPU信息.内存信息.块设备等,需 ...

  9. C++通过WMI获取硬件配置信息

    C++通过WMI获取硬件配置信息 WMI即Windows管理规范.通过它可以访问.配置.管理和监视几乎所有的Windows资源. WMI提供程序在WMI和托管资源之间扮演着中间方的角色.提供程序代表使 ...

最新文章

  1. undefined symbol: ap_log_rerror;apache2.4与weblogic点so文件
  2. Selenium自动化测试驱动下载
  3. android singleTop 不起作用
  4. iphone备忘录突然没了_苹果突然下架12 天猫:双11有惊喜!iPhone12 mini配色缩水
  5. js页面传值php页面,php实现跳转传值有什么方法,js页面跳转传值
  6. sql2005关闭c2审核_C2审核–使用C2审核模式SQL Server审核和通用标准合规性
  7. 【渝粤题库】国家开放大学2021春2605经济法律基础题目
  8. Java开发十二大框架
  9. win10电脑虚拟网络设置方法
  10. 【通信电子电路】谐振功率放大电路multisim仿真
  11. 为啥显示器用RGB而打印机用CMYK
  12. DirectX11 交换链是什么
  13. 传统企业:转型互联网,机遇大,挑战也大
  14. Revisiting Over-Smoothness in Text to Speech
  15. linux drm 架构 基础
  16. python 线程thread详解
  17. WebStorm+Vue-cli 配置alias 点击跳转无效问题
  18. oc错误:control reaches end of non-void function
  19. css3ps插件,实用的PS插件推荐:长投影设计和CSS3Ps插件
  20. Win10系统下提示“系统组策略禁止安装此设备”的解决方案

热门文章

  1. 5G + 边缘计算系列文章
  2. DPDK — PDUMP 抓包工具
  3. SecureCRT自动保存窗口数据到文件,自动保存日志,每行添加时间戳
  4. R语言修改标题、坐标轴刻度、坐标轴名称的大小(cex.axis、cex.lab、cex.main函数)...
  5. 学习虚幻4需要储备的知识(2D游戏开发者向)
  6. Debian8.8解决双系统访问windows磁盘时,有时能成功挂载,有时不能成功挂载的情况...
  7. Python常用内置函数(二)
  8. 使用 Android Studio 进行测试 (二) UI 测试
  9. [Codeforces] Round #320 (Div.2)
  10. 分区视图(转自小春BOOK)