使用Python监控Linux系统
Linux下有许多使用Python语言编写的监控工具,如inotify-sync、dstat和glances。此外,如果要根据业务编写简单的监控脚本,很多工程师也会选择Python语言。Python语言是一门简单易学/语法清晰/表达能力强的编程语言,非常适合于编写监控程序的场景。使用Python语言编写监控程序具有以下几个优势:
1、Python语言开发效率高。Python语言有自己的优势与劣势,使用Python开发监控程序是一个充分发挥Python优势,避免Python劣势的领域。对于监控程序来说,能够利用Python语言开发效率高的优势尽快完成程序的编写工作。同时,监控程序也不要求性能,因此避免了Python语言性能不如C、C++和Java的劣势。
2、Python语言表达能力强。相信任何一个学习Linux的工程师都使用过shell脚本编写过监控程序。虽然Linux下有很多监控工具,也有很多文本处理程序,但是获取监控与解析结果是完全不同的工具。解析监控结果的程序不理解监控程序输出结果的具体含义。Python语言中有非常丰富的数据结构,可以用各种方式保存监控结果,以便后续处理。
3、利用第三方库开发监控程序。Python的标准库本身非常强大,被称为“连电池都包含在内”。对于一个问题,如果标准库没有提供相应的工具,那么也会有开源的项目来填补这个空白。监控程序正式这样一种情况,在Python语言中,具有非常成熟的第三方库帮助开发者简化监控程序的编写工作。
一、Python编写的监控工具
我们将介绍两个Python语言编写的监控工具,分别是dstat和glances。
1、多功能系统资源统计工具dstat
dstat是一个用Python语言实现的多功能系统资源统计工具,用来取代Linux下的vmstat、iostat、netstat、和ifstat等命令。并且,dstat克服了这些命令的限制,增加了额外的功能,以及更多的计数器与更好的灵活性。dstat可以在一个界面上展示非常全面的监控信息,因此,在系统监控、基准测试和故障排除等应用场景下特别有用。
我们可以使用dstat监控所有系统资源的使用情况,并且可以结合不同的场景定制监控的资源。例如,在同一时间段以相同的时间频率比较网络带宽与磁盘的吞吐率。
dstat将以列表的形式显示监控信息,并且使用不同的颜色进行输出,以可读性较强的单位展示监控数值。例如,对于字节数值,dstat自动根据数值的大小,以K、M、G等单位进行显示,避免了开发者使用其他命令时因为数值太大造成的困惑和错误。此外,使用dstat还可以非常方便地编写插件,用来收集默认情况下没有收到的监控信息。dstat是专门为人们实时查看监控信息设计的,因此默认将监控结果输出到屏幕终端。我们也可以将监控信息以CSV格式输出到文件,以便后续处理。
(1)dstat介绍
作为一个多功能系统资源统计工具,dstat具有以下特性:
结合了vmstat,iostat,ifstat,netstat以及更多的信息
实时显示统计情况
在分析和排障时可以通过启用监控项并排序
模块化设计
使用python编写的,更方便扩展现有的工作任务
容易扩展和添加你的计数器(请为此做出贡献)
包含的许多扩展插件充分说明了增加新的监控项目是很方便的
可以分组统计块设备/网络设备,并给出总数
可以显示每台设备的当前状态
极准确的时间精度,即便是系统负荷较高也不会延迟显示
显示准确地单位和和限制转换误差范围
用不同的颜色显示不同的单位
显示中间结果延时小于1秒
支持输出CSV格式报表,并能导入到Gnumeric和Excel以生成图形
如果操作系统默认没有安装dstat,那么需要我们手动进行安装。如下所示:
yum install dstat
查看dstat命令的帮助信息与支持选项,如下所示:
dstat --help
dstat命令的–version选项,处理显示dstat的版本以外,还会显示操作系统的版本、Python语言的版本、CPU的个数,以及dstat支持的插件列表等详细信息。如下所示:
[root@192 ~]# dstat --version
Dstat 0.7.2
Written by Dag Wieers <dag@wieers.com>
Homepage at http://dag.wieers.com/home-made/dstat/
Platform posix/linux2
Kernel 3.10.0-957.el7.x86_64
Python 2.7.5 (default, Oct 30 2018, 23:45:53)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-36)]
Terminal type: xterm (color support)
Terminal size: 16 lines, 83 columns
Processors: 1
Pagesize: 4096
Clock ticks per secs: 100
internal:
aio, cpu, cpu24, disk, disk24, disk24old, epoch, fs, int, int24, io, ipc,
load, lock, mem, net, page, page24, proc, raw, socket, swap, swapold,
sys, tcp, time, udp, unix, vm
/usr/share/dstat:
battery, battery-remain, cpufreq, dbus, disk-tps, disk-util, dstat,
dstat-cpu, dstat-ctxt, dstat-mem, fan, freespace, gpfs, gpfs-ops,
helloworld, innodb-buffer, innodb-io, innodb-ops, lustre, memcache-hits,
mysql-io, mysql-keys, mysql5-cmds, mysql5-conn, mysql5-io, mysql5-keys,
net-packets, nfs3, nfs3-ops, nfsd3, nfsd3-ops, ntp, postfix, power,
proc-count, qmail, rpc, rpcd, sendmail, snooze, squid, test, thermal,
top-bio, top-bio-adv, top-childwait, top-cpu, top-cpu-adv, top-cputime,
top-cputime-avg, top-int, top-io, top-io-adv, top-latency,
top-latency-avg, top-mem, top-oom, utmp, vm-memctl, vmk-hba, vmk-int,
vmk-nic, vz-cpu, vz-io, vz-ubc, wifi
[root@192 ~]#
除了使用dstat命令的–version选项查看dstat的详细信息获取可支持的插件以外,还可以使用dstat命令的–list选项获取dstat的插件列表。如下所示:
[root@192 ~]# dstat --list
internal:
aio, cpu, cpu24, disk, disk24, disk24old, epoch, fs, int, int24, io, ipc, load, lock, mem, net, page, page24,
proc, raw, socket, swap, swapold, sys, tcp, time, udp, unix, vm
/usr/share/dstat:
battery, battery-remain, cpufreq, dbus, disk-tps, disk-util, dstat, dstat-cpu, dstat-ctxt, dstat-mem, fan,
freespace, gpfs, gpfs-ops, helloworld, innodb-buffer, innodb-io, innodb-ops, lustre, memcache-hits, mysql-io,
mysql-keys, mysql5-cmds, mysql5-conn, mysql5-io, mysql5-keys, net-packets, nfs3, nfs3-ops, nfsd3, nfsd3-ops, ntp,
postfix, power, proc-count, qmail, rpc, rpcd, sendmail, snooze, squid, test, thermal, top-bio, top-bio-adv,
top-childwait, top-cpu, top-cpu-adv, top-cputime, top-cputime-avg, top-int, top-io, top-io-adv, top-latency,
top-latency-avg, top-mem, top-oom, utmp, vm-memctl, vmk-hba, vmk-int, vmk-nic, vz-cpu, vz-io, vz-ubc, wifi
[root@192 ~]#
直接在终端输入dstat命令,dstat将以默认参数运行。默认情况下,dstat会收集CPU、磁盘、网络、交换页和系统消息,并以1秒钟1次的频率进行输出,直到我们按Ctrl+C结束。
(2)dstat常用选项
如下所示,dstat会提示我们没有指定任何参数,因此使用-cdngy参数运行。
[root@192 ~]# dstat
You did not select any stats, using -cdngy by default.
----total-cpu-usage---- -dsk/total- -net/total- ---paging-- ---system--
usr sys idl wai hiq siq| read writ| recv send| in out | int csw
9 3 88 0 0 0| 219k 60k| 0 0 |2682B 5427B| 163 1542
20 5 75 0 0 0| 0 0 | 66B 894B| 0 0 | 326 4218
19 6 75 0 0 0| 0 0 | 126B 410B| 0 0 | 330 4431
18 7 75 0 0 0| 0 0 | 66B 416B| 0 0 | 341 2998
20 6 74 0 0 0| 0 0 | 66B 350B| 0 0 | 340 4098
19 6 75 0 0 0| 0 0 | 66B 350B| 0 0 | 319 4010
20 5 75 0 0 0| 0 0 | 66B 350B| 0 0 | 326 4378
19 6 75 0 0 0| 0 0 | 66B 350B| 0 0 | 322 4407
20 5 75 0 0 0| 0 0 | 66B 350B| 0 0 | 332 4520
21 6 73 0 0 0|1140k 0 | 66B 350B| 0 0 | 345 3341
20 7 72 0 0 1| 0 0 | 66B 358B| 0 0 | 348 3821
常用选项如下:
直接跟数字,表示#秒收集一次数据,默认为一秒;dstat 5表示5秒更新一次
-c,--cpu 统计CPU状态,包括system, user, idle, wait, hardware interrupt, software interrupt等;
-d, --disk 统计磁盘读写状态
-D total,sda 统计指定磁盘或汇总信息
-l, --load 统计系统负载情况,包括1分钟、5分钟、15分钟平均值
-m, --mem 统计系统物理内存使用情况,包括used, buffers, cache, free
-s, --swap 统计swap已使用和剩余量
-n, --net 统计网络使用情况,包括接收和发送数据
-N eth1,total 统计eth1接口汇总流量
-r, --io 统计I/O请求,包括读写请求
-p, --proc 统计进程信息,包括runnable、uninterruptible、new
-y, --sys 统计系统信息,包括中断、上下文切换
-t 显示统计时时间,对分析历史数据非常有用
--fs 统计文件打开数和inodes数
除了前面介绍的与监控相关的参数以外,dstat还可以像vmstat和iostat一样使用参数控制报告的时间间隔,或者同事指定时间间隔与报告次数。
例如,下面的命令表示以默认的选项运行dstat,每2秒钟输出一条监控信息,并在输出10条监控信息以后退出dstat。如下所示:
[root@192 ~]# dstat 2 10
You did not select any stats, using -cdngy by default.
----total-cpu-usage---- -dsk/total- -net/total- ---paging-- ---system--
usr sys idl wai hiq siq| read writ| recv send| in out | int csw
9 3 88 0 0 0| 218k 60k| 0 0 |2674B 5409B| 164 1550
20 6 74 0 0 0| 0 0 | 66B 594B| 0 0 | 326 3956
21 6 73 0 0 0| 0 147k| 66B 346B| 0 0 | 360 4114
20 5 76 0 0 0| 0 0 | 66B 346B| 0 0 | 320 4494
20 6 74 0 0 0| 0 0 | 96B 372B| 0 0 | 349 4144
20 5 75 0 0 0| 0 0 | 66B 342B| 0 0 | 331 4360
21 6 74 0 0 0| 0 0 | 66B 342B| 0 0 | 344 3607
19 6 75 0 0 0| 0 0 | 66B 342B| 0 0 | 334 4475
21 6 74 0 0 0| 0 0 | 66B 342B| 0 0 | 338 4580
20 7 73 0 0 1| 0 0 | 66B 342B| 0 0 | 340 4341
20 6 74 0 0 0| 0 0 | 66B 342B| 0 0 | 344 3899
[root@192 ~]#
(3)dstat高级用法
dstat的强大之处不仅仅是因为它聚合了多种工具的监控结果,还因为它能通过附带的插件实现一些更高级功能。如:找出磁盘中占用资源最高的进程和用户。
dstat -cdlmnpsyt 5 可以得到较全面的系统性能数据。
dstat的–top-(io|bio|cpu|cputime|cputime-avg|mem) 通过这几个选项,可以看到具体是哪个用户哪个进程占用了相关系统资源,对系统调优非常有效。如查看当前占用I/O、cpu、内存等最高的进程信息可以使用dstat –top-mem –top-io –top-cpu选项。以下示例演示了如何找出占用资源最多的进程。
[root@192 ~]# dstat --top-mem --top-io --top-cpu
--most-expensive- ----most-expensive---- -most-expensive-
memory process | i/o process | cpu process
gnome-shell 115M|polkitd 203k 10k|polkitd 3.8
gnome-shell 115M|polkitd 459k 23k|polkitd 10
gnome-shell 115M|polkitd 625k 31k|polkitd 9.0
gnome-shell 115M|polkitd 592k 29k|dbus-daemon 8.0
gnome-shell 115M|polkitd 606k 30k|polkitd 9.0
gnome-shell 115M|polkitd 525k 26k|polkitd 10
gnome-shell 115M|polkitd 525k 26k|dbus-daemon 8.0
dstat的插件保存在/usr/share/dstat目录下,我们可以参考它们的实现,编写自己的插件。
(4)将结果输出到CSV文件
dstat还可以将监控信息保存到CSV文件中,以便后续进行处理。通过–output选项指定监控数据输出的文件。如下所示:
[root@192 ~]# dstat -a --output dstat_output.csv
----total-cpu-usage---- -dsk/total- -net/total- ---paging-- ---system--
usr sys idl wai hiq siq| read writ| recv send| in out | int csw
9 3 88 0 0 0| 217k 60k| 0 0 |2656B 5370B| 165 1568
19 8 50 22 0 0| 11M 50k| 66B 838B| 128k 0 | 428 3116
19 6 75 0 0 0| 0 0 | 66B 374B| 0 0 | 325 4514
25 7 25 43 0 0|5284k 0 | 66B 350B| 476k 0 | 448 4227
18 7 74 0 0 1| 32k 144k| 66B 366B| 52k 0 | 334 4524
31 11 6 52 0 0|1944k 4096B| 66B 374B| 868k 0 | 613 3846
19 6 69 6 0 0| 116k 4096B| 66B 374B| 116k 0 | 337 4367
20 6 74 0 0 0| 0 0 | 66B 374B| 0 0 | 331 4573
20 7 73 0 0 0| 0 0 | 66B 350B| 0 0 | 339 3787
18 6 76 0 0 0| 0 0 | 66B 350B| 0 0 | 317 4472
20 6 74 0 0 0| 0 0 | 66B 350B| 0 0 | 338 3675
20 5 75 0 0 0| 0 0 | 66B 350B| 0 0 | 324 4633
21 5 74 0 0 0| 0 0 | 66B 350B| 0 0 | 318 4597
19 6 75 0 0 0| 0 0 | 66B 350B| 0 0 | 333 4847
18 6 76 0 0 0| 0 0 | 66B 350B| 0 0 | 308 4742 ^C
[root@192 ~]# cat dstat_output.csv
"Dstat 0.7.2 CSV output"
"Author:","Dag Wieers <dag@wieers.com>",,,,"URL:","http://dag.wieers.com/home-made/dstat/"
"Host:","192.168.32.138",,,,"User:","root"
"Cmdline:","dstat -a --output dstat_output.csv",,,,"Date:","22 Feb 2020 00:22:08 CST"
"total cpu usage",,,,,,"dsk/total",,"net/total",,"paging",,"system",
"usr","sys","idl","wai","hiq","siq","read","writ","recv","send","in","out","int","csw"
8.683,2.816,88.156,0.313,0.0,0.032,222019.623,61103.678,0.0,0.0,2655.691,5370.227,164.807,1568.447
19.388,8.163,50.0,22.449,0.0,0.0,11702272.0,51200.0,66.0,838.0,131072.0,0.0,428.0,3116.0
19.192,6.061,74.747,0.0,0.0,0.0,0.0,0.0,66.0,374.0,0.0,0.0,325.0,4514.0
24.510,6.863,25.490,43.137,0.0,0.0,5410816.0,0.0,66.0,350.0,487424.0,0.0,448.0,4227.0
18.182,7.071,73.737,0.0,0.0,1.010,32768.0,147456.0,66.0,366.0,53248.0,0.0,334.0,4524.0
30.928,11.340,6.186,51.546,0.0,0.0,1990656.0,4096.0,66.0,374.0,888832.0,0.0,613.0,3846.0
19.192,6.061,68.687,6.061,0.0,0.0,118784.0,4096.0,66.0,374.0,118784.0,0.0,337.0,4367.0
19.802,5.941,74.257,0.0,0.0,0.0,0.0,0.0,66.0,374.0,0.0,0.0,331.0,4573.0
20.0,7.0,73.0,0.0,0.0,0.0,0.0,0.0,66.0,350.0,0.0,0.0,339.0,3787.0
18.367,6.122,75.510,0.0,0.0,0.0,0.0,0.0,66.0,350.0,0.0,0.0,317.0,4472.0
20.0,6.0,74.0,0.0,0.0,0.0,0.0,0.0,66.0,350.0,0.0,0.0,338.0,3675.0
20.202,5.051,74.747,0.0,0.0,0.0,0.0,0.0,66.0,350.0,0.0,0.0,324.0,4633.0
21.0,5.0,74.0,0.0,0.0,0.0,0.0,0.0,66.0,350.0,0.0,0.0,318.0,4597.0
19.192,6.061,74.747,0.0,0.0,0.0,0.0,0.0,66.0,350.0,0.0,0.0,333.0,4847.0
18.182,6.061,75.758,0.0,0.0,0.0,0.0,0.0,66.0,350.0,0.0,0.0,308.0,4742.0
[root@192 ~]#
2、交互式监控工具glances
在紧急情况下,工程师需要在尽可能短的时间内查看尽可能多的信息。此时,glances是一个不错的选择。glances的设计初衷就是在当前窗口中尽可能多地显示系统消息。
glances是一款使用Python语言开发、基于psutil的跨平台系统监控工具,在所有Linux命令行工具中,它与top命令最相似,都是命令行交互监控工具。但是,glances实现了比top命令更齐全的接口,提供了更加丰富的功能。
(1)glances提供的系统信息
glances提供的系统信息如下所示:
CPU 使用率
内存使用情况
内核统计信息和运行队列信息
磁盘 I/O 速度、传输和读/写比率
文件系统中的可用空间
磁盘适配器
网络 I/O 速度、传输和读/写比率
页面空间和页面速度
消耗资源最多的进程
计算机信息和系统资源
glances 工具可以在用户的终端上实时显示重要的系统信息,并动态地对其进行更新。这个高效的工具可以工作于任何终端屏幕。另外它并不会消耗大量的 CPU 资源,通常低于百分之二。glances 在屏幕上对数据进行显示,并且每隔2秒钟对其进行更新。您也可以自己将这个时间间隔更改为更长或更短的数值。
glances 工具还可以将相同的数据捕获到一个文件,便于以后对报告进行分析和绘制图形。输出文件可以是电子表格的格式 (.csv) 或者 html 格式。
(2)Linux下glances的安装
在Linux系统中,可以使用yum命令或者pip命令安装glances。如下所示:
yum install epel-release
yum install glances
glances的使用非常简单,直接输入glances命令便进入了一个类似top命令的交互式界面。在这个界面中,显示了比top更加全面,更加具有可读性的信息。如下所示:
glances 工作界面的说明 :
在图 1 的上部是 CPU 、Load(负载)、Mem(内存使用)、 Swap(交换分区)的使用情况。在图 1 的中上部是网络接口、Processes(进程)的使用情况。通常包括如下字段:
VIRT: 虚拟内存大小
RES: 进程占用的物理内存值
%CPU:该进程占用的 CPU 使用率
%MEM:该进程占用的物理内存和总内存的百分比
PID: 进程 ID 号
USER: 进程所有者的用户名
TIME+: 该进程启动后占用的总的 CPU 时间
IO_R 和 IO_W: 进程的读写 I/O 速率
NAME: 进程名称
NI: 进程优先级
S: 进程状态,其中 S 表示休眠,R 表示正在运行,Z 表示僵死状态。
(3)glances的可读性
对比可以发现,glances对屏幕的利用率比top明显高很多,信息量很大,有许多top所没有显示的数据。而且,glances的实时变动比top颜值高太多了。
Glances 会用一下几种颜色来代表状态,如下所示:
绿色:OK(一切正常)
蓝色:CAREFUL(需要注意)
紫色:WARNING(警告)
红色:CRITICAL(严重)
(4)glances常见命令
glances是一个交互式的工具,因此我们也可以输入命令来控制glances的行为。glances常见的命令有:
h:显示帮助信息
q:离开程序退出
c:按照 CPU 实时负载对系统进程进行排序
m:按照内存使用状况对系统进程排序
i:按照 I/O 使用状况对系统进程排序
p:按照进程名称排序
d:显示磁盘读写状况
w:删除日志文件
l:显示日志
s:显示传感器信息
f:显示系统信息
1:轮流显示每个 CPU 内核的使用情况(次选项仅仅使用在多核 CPU 系统)
glances还支持将采集的数据导入到其他服务中心,包括InfluxDB、Cassandra、CouchDB、OpenTSDB、Prometheus、StatsD、ElasticSearch、RabbitMQ/ActiveMQ、ZeroMQ、Kafaka和Riemann。
二、Python监控Linux
shell查看磁盘的监控信息,如下所示:
[root@bogon proc]# cat /proc/diskstats
8 0 sda 85935 21845 10913707 101067 3119 81257 743486 15647 0 31410 109079
8 1 sda1 1822 0 12456 397 4 0 4096 74 0 457 462
8 2 sda2 84082 21845 10897907 100659 3115 81257 739390 15573 0 30950 108604
11 0 sr0 0 0 0 0 0 0 0 0 0 0 0
253 0 dm-0 80726 0 10688467 99971 2275 0 82606 10224 0 27927 110196
253 1 dm-1 25123 0 205184 7367 82098 0 656784 616558 0 5167 623924
编写一个Python脚本,监控磁盘信息,如下所示:
#/usr/bin/python
#_*_ coding:utf-8 _*_
from __future__ import print_function
from collections import namedtuple
disk = namedtuple('Disk','major_number minor_number device_name'
' read_count read_merged_count read_sections'
' time_spent_reading write_count write_merged_count'
' write_sections time_spent_write io_requests'
' time_spent_doing_io weighted_time_spent_dong_io')
def get_disk_info(device):
with open('/proc/diskstats') as f:
for line in f:
if line.split()[2] == device:
return disk(*(line.split()))
raise RuntimeError('设备({0})没找到。。。'.format(device))
def main():
disk_info = get_disk_info('sda1')
print(disk_info)
if __name__ == '__main__':
main()
三、使用开源库监控Linux
在这一小节,我们将介绍一个在Python生态中广泛使用的开源项目,即psutil。随后,我们将使用psutil重构前一小节编写的监控程序。另外,还会简单介绍psutil提供的进程管理功能。
1、psutil介绍
psutil = process and system utilities
psutil是一个开源且跨平台的库,其提供了便利的函数用来获取操作系统的信息,比如CPU,内存,磁盘,网络等。此外,psutil还可以用来进行进程管理,包括判断进程是否存在、获取进程列表、获取进程详细信息等。而且psutil还提供了许多命令行工具提供的功能,包括:ps,top,lsof,netstat,ifconfig, who,df,kill,free,nice,ionice,iostat,iotop,uptime,pidof,tty,taskset,pmap。
psutil是一个跨平台的库,支持Linux、Windows、OSX、FreeBSD、OpenBSD、NetBSD、Sun Solaris、AIX等操作系统。同时,psutil也支持32位与64位的系统架构,支持Python2.6到Python3.x之间的所有Python版本。
psutil具有简单易用、功能强大、跨平台等诸多优点,广泛应用于开源项目中,比较有名的有glances、Facebook的osquery、Google的grr等。psutil不但广泛应用于Python语言开发的开源项目中,还被移植到了其他编程语言中,如Go语言的gopsutil、C语言的cpslib、Rust语言的rust-psutil、Ruby语言的posixpsutil等。
psutil是一个第三方的开源项目,因此,需要先安装才能够使用。如果安装了Anaconda,psutil就已经可用了。否则,需要在命令行下通过pip安装:
[root@localhost ~]# pip install psutil
Collecting psutil
Downloading psutil-5.7.0.tar.gz (449 kB)
|████████████████████████████████| 449 kB 4.6 kB/s
Installing collected packages: psutil
Running setup.py install for psutil ... done
Successfully installed psutil-5.7.0
psutil包含了异常、类、功能函数和常量,其中功能函数用来获取系统的信息,如CPU、磁盘、内存、网络等。类用来实现进程的管理功能。
2、psutil提供的功能函数
根据函数的功能,主要分为CPU、磁盘、内存、网络几类,下面将会总几个方面来介绍psutil提供的功能函数。在这一小节,我们也将学习如何使用psutil来简化使用shell脚本获取监控信息的程序,并获取CPU、内存、磁盘和网络等不同维度。
(1)CPU
与CPU相关的功能函数如下:
函数 | 描述 |
---|---|
psutil.cpu_count() | cpu_count(,[logical]):默认返回逻辑CPU的个数,当设置logical的参数为False时,返回物理CPU的个数。 |
psutil.cpu_percent() | cpu_percent(,[percpu],[interval]):返回CPU的利用率,percpu为True时显示所有物理核心的利用率,interval不为0时,则阻塞时显示interval执行的时间内的平均利用率 |
psutil.cpu_times() | cpu_times(,[percpu]):以命名元组(namedtuple)的形式返回cpu的时间花费,percpu=True表示获取每个CPU的时间花费 |
psutil.cpu_times_percent() | cpu_times_percent(,[percpu]):功能和cpu_times大致相同,看字面意思就能知道,该函数返回的是耗时比例。 |
psutil.cpu_stats() | cpu_stats()以命名元组的形式返回CPU的统计信息,包括上下文切换,中断,软中断和系统调用次数。 |
psutil.cpu_freq() | cpu_freq([percpu]):返回cpu频率 |
1)cpu_count
默认返回逻辑CPU的个数,当设置logical的参数为False时,返回物理CPU的个数。
In [1]: import psutil
In [2]: psutil.cpu_count()
Out[2]: 2
In [3]: psutil.cpu_count(logical=False)
Out[3]: 1
2)cpu_percent
返回CPU的利用率,percpu为True时显示所有物理核心的利用率,interval不为0时,则阻塞时显示interval执行的时间内的平均利用率。
In [4]: psutil.cpu_percent()
Out[4]: 1.5
In [5]: psutil.cpu_percent(percpu=True)
Out[5]: [1.3, 1.5]
In [6]: psutil.cpu_percent(percpu=True,interval=2)
Out[6]: [1.0, 0.0]
3)cpu_times
以命名元组(namedtuple)的形式返回cpu的时间花费,percpu=True表示获取每个CPU的时间花费。
In [7]: psutil.cpu_times()
Out[7]: scputimes(user=41.51, nice=2.05, system=35.36, idle=2096.05, iowait=5.45, irq=0.0, softirq=1.31, steal=0.0, guest=0.0, guest_nice=0.0)
In [8]: psutil.cpu_times_percent()
Out[8]: scputimes(user=0.3, nice=0.0, system=0.1, idle=99.5, iowait=0.0, irq=0.0, softirq=0.0, steal=0.0, guest=0.0, guest_nice=0.0)
4)cpu_stats
以命名元组的形式返回CPU的统计信息,包括上下文切换,中断,软中断和系统调用次数。
In [10]: psutil.cpu_stats()
Out[10]: scpustats(ctx_switches=538642, interrupts=238329, soft_interrupts=273448, syscalls=0)
5)cpu_freq
返回cpu频率。
In [11]: psutil.cpu_freq()
Out[11]: scpufreq(current=2394.464, min=0.0, max=0.0)
(2)内存
与内存相关的功能函数如下:
1)virtual_memory
以命名元组的形式返回内存使用情况,包括总内存、可用内存、内存利用率、buffer和cache等。除了内存利用率,其它字段都以字节为单位返回。
In [1]: import psutil
In [2]: psutil.virtual_memory()
Out[2]: svmem(total=1019797504, available=95744000, percent=90.6, used=758079488, free=67502080, active=295485440, inactive=417394688, buffers=0, cached=194215936, shared=19103744, slab=92905472)
单位转换
#/usr/bin/python
#-*- conding:utf-8 _*_
import psutil
def bytes2human(n):
symbols = ('K','M','G','T','P','E','Z','Y')
prefix = {}
for i,s in enumerate(symbols):
prefix[s] = 1 << (i + 1) * 10
for s in reversed(symbols):
if n >= prefix[s]:
value = float(n) / prefix[s]
return '%.1f%s' % (value,s)
return '%sB' % n
print(bytes2human(psutil.virtual_memory().total))
运行结果如下所示:
[root@localhost ~]# python mem.py
972.6M
2)swap_memory
以命名元组的形式返回swap/memory使用情况,包含swap中页的换入和换出。
In [3]: psutil.swap_memory()
Out[3]: sswap(total=2147479552, used=141819904, free=2005659648, percent=6.6, sin=24666112, sout=147292160)
(3)磁盘
与磁盘相关的功能如下:
函数 | 描述 |
---|---|
psutil.disk_io_counters() | disk_io_counters([perdisk]):以命名元组的形式返回磁盘io统计信息(汇总的),包括读、写的次数,读、写的字节数等。 当perdisk的值为True,则分别列出单个磁盘的统计信息(字典:key为磁盘名称,value为统计的namedtuple)。 |
psutil.disk_partitions() | disk_partitions([all=False]):以命名元组的形式返回所有已挂载的磁盘,包含磁盘名称,挂载点,文件系统类型等信息。 当all等于True时,返回包含/proc等特殊文件系统的挂载信息 |
psutil.disk_usage() | disk_usage(path):以命名元组的形式返回path所在磁盘的使用情况,包括磁盘的容量、已经使用的磁盘容量、磁盘的空间利用率等。 |
1)psutil.disk_io_counters
以命名元组的形式返回磁盘io统计信息(汇总的),包括读、写的次数,读、写的字节数等。 当perdisk的值为True,则分别列出单个磁盘的统计信息(字典:key为磁盘名称,value为统计的namedtuple)。有了disk_io_counters函数,省去了解析/proc/diskstats文件的烦恼。
In [1]: import psutil
In [2]: psutil.disk_io_counters()
Out[2]: sdiskio(read_count=86913, write_count=46560, read_bytes=5038501376, write_bytes=408987648, read_time=77974, write_time=79557, read_merged_count=5933, write_merged_count=35916, busy_time=42153)
In [3]: psutil.disk_io_counters(perdisk=True)
Out[3]:
{'sda': sdiskio(read_count=41472, write_count=5340, read_bytes=2524417024, write_bytes=205662720, read_time=38302, write_time=4484, read_merged_count=5933, write_merged_count=35916, busy_time=21074),
'sda1': sdiskio(read_count=1854, write_count=4, read_bytes=6441472, write_bytes=2097152, read_time=370, write_time=35, read_merged_count=0, write_merged_count=0, busy_time=396),
'sda2': sdiskio(read_count=39587, write_count=5337, read_bytes=2516263424, write_bytes=203570688, read_time=37925, write_time=4449, read_merged_count=5933, write_merged_count=35916, busy_time=20675),
'sr0': sdiskio(read_count=0, write_count=0, read_bytes=0, write_bytes=0, read_time=0, write_time=0, read_merged_count=0, write_merged_count=0, busy_time=0),
'dm-0': sdiskio(read_count=38566, write_count=5197, read_bytes=2483773952, write_bytes=55885312, read_time=37685, write_time=3546, read_merged_count=0, write_merged_count=0, busy_time=19410),
'dm-1': sdiskio(read_count=6875, write_count=36059, read_bytes=30310400, write_bytes=147697664, read_time=1987, write_time=71537, read_merged_count=0, write_merged_count=0, busy_time=1673)}
2)psutil.disk_partitions
以命名元组的形式返回所有已挂载的磁盘,包含磁盘名称,挂载点,文件系统类型等信息。当all等于True时,返回包含/proc等特殊文件系统的挂载信息。
In [4]: psutil.disk_partitions()
Out[4]:
[sdiskpart(device='/dev/mapper/centos-root', mountpoint='/', fstype='xfs', opts='rw,seclabel,relatime,attr2,inode64,noquota'),
sdiskpart(device='/dev/sda1', mountpoint='/boot', fstype='xfs', opts='rw,seclabel,relatime,attr2,inode64,noquota')]
In [5]: [device for device in psutil.disk_partitions() if device.mountpoint == '/']
Out[5]: [sdiskpart(device='/dev/mapper/centos-root', mountpoint='/', fstype='xfs', opts='rw,seclabel,relatime,attr2,inode64,noquota')]
In [6]: def get_disk_via_mountpoint(point):
...: disk = [item for item in psutil.disk_partitions() if item.mountpoint == point]
...: return disk[0].device
...:
In [7]: get_disk_via_mountpoint('/')
Out[7]: '/dev/mapper/centos-root'
In [8]: get_disk_via_mountpoint('/boot')
Out[8]: '/dev/sda1'
3)psutil.disk_usage
以命名元组的形式返回path所在磁盘的使用情况,包括磁盘的容量、已经使用的磁盘容量、磁盘的空间利用率等。
In [9]: psutil.disk_usage('/')
Out[9]: sdiskusage(total=18238930944, used=6775488512, free=11463442432, percent=37.1)
In [10]: psutil.disk_usage('/').percent
Out[10]: 37.2
In [11]: type(psutil.disk_usage('/').percent)
Out[11]: float
(4)网络
与网络相关的函数如下:
函数 | 详情 |
---|---|
psutil.net_io_counter([pernic]) | 以命名元组的形式返回当前系统中每块网卡的网络io统计信息,包括收发字节数,收发包的数量、出错的情况和删包情况。当pernic为True时,则列出所有网卡的统计信息。 |
psutil.net_connections([kind]) | 以列表的形式返回每个网络连接的详细信息(namedtuple)。命名元组包含fd, family, type, laddr, raddr, status, pid等信息。kind表示过滤的连接类型,支持的值如下:(默认为inet) |
psutil.net_if_addrs() | 以字典的形式返回网卡的配置信息,包括IP地址和mac地址、子网掩码和广播地址。 |
psutil.net_if_stats() | 返回网卡的详细信息,包括是否启动、通信类型、传输速度与mtu。 |
psutil.users() | 以命名元组的方式返回当前登陆用户的信息,包括用户名,登陆时间,终端,与主机信息 |
psutil.boot_time() | 以时间戳的形式返回系统的启动时间 |
1)psutil.net_io_counter
以命名元组的形式返回当前系统中每块网卡的网络io统计信息,包括收发字节数,收发包的数量、出错的情况和删包情况。当pernic为True时,则列出所有网卡的统计信息。使用net_io_counter函数与自己解析/proc/net/dev文件内容实现的功能相同。
In [1]: import psutil
In [2]: psutil.net_io_counters()
Out[2]: snetio(bytes_sent=720405, bytes_recv=3661606, packets_sent=5520, packets_recv=14886, errin=0, errout=0, dropin=0, dropout=0)
In [3]: psutil.net_io_counters(pernic=True)
Out[3]:
{'ens37': snetio(bytes_sent=724145, bytes_recv=3365944, packets_sent=5538, packets_recv=10017, errin=0, errout=0, dropin=0, dropout=0),
'lo': snetio(bytes_sent=0, bytes_recv=0, packets_sent=0, packets_recv=0, errin=0, errout=0, dropin=0, dropout=0),
'virbr0-nic': snetio(bytes_sent=0, bytes_recv=0, packets_sent=0, packets_recv=0, errin=0, errout=0, dropin=0, dropout=0),
'virbr0': snetio(bytes_sent=0, bytes_recv=0, packets_sent=0, packets_recv=0, errin=0, errout=0, dropin=0, dropout=0),
'ens33': snetio(bytes_sent=0, bytes_recv=298202, packets_sent=0, packets_recv=4899, errin=0, errout=0, dropin=0, dropout=0)}
2)net_connections
以列表的形式返回每个网络连接的详细信息(namedtuple),可以使用该函数查看网络连接状态,统计连接个数以及处于特定状态的网络连接个数。
In [4]: psutil.net_connections()
Out[4]:
[sconn(fd=6, family=<AddressFamily.AF_INET6: 10>, type=<SocketKind.SOCK_STREAM: 1>, laddr=addr(ip='::', port=111), raddr=(), status='LISTEN', pid=6558),
sconn(fd=7, family=<AddressFamily.AF_INET6: 10>, type=<SocketKind.SOCK_DGRAM: 2>, laddr=addr(ip='::', port=111), raddr=(), status='NONE', pid=6558),
sconn(fd=8, family=<AddressFamily.AF_INET6: 10>, type=<SocketKind.SOCK_STREAM: 1>, laddr=addr(ip='::1', port=6010), raddr=(), status='LISTEN', pid=9047),
sconn(fd=6, family=<AddressFamily.AF_INET: 2>, type=<SocketKind.SOCK_STREAM: 1>,
......
In [5]: conns = psutil.net_connections()
In [6]: len([conn for conn in conns if conn.status == 'TIME_WAIT'])
Out[6]: 0
3)net_if_addrs
以字典的形式返回网卡的配置信息,包括IP地址和mac地址、子网掩码和广播地址。
In [7]: psutil.net_if_addrs()
Out[7]:
{'lo': [snicaddr(family=<AddressFamily.AF_INET: 2>, address='127.0.0.1', netmask='255.0.0.0', broadcast=None, ptp=None),
snicaddr(family=<AddressFamily.AF_INET6: 10>, address='::1', netmask='ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff', broadcast=None, ptp=None),
snicaddr(family=<AddressFamily.AF_PACKET: 17>, address='00:00:00:00:00:00', netmask=None, broadcast=None, ptp=None)],
'ens37': [snicaddr(family=<AddressFamily.AF_INET: 2>, address='192.168.1.131', netmask='255.255.255.255', broadcast='192.168.1.131', ptp=None),
snicaddr(family=<AddressFamily.AF_INET6: 10>, address='240e:82:e03:7342:4378:7be3:558c:fc88', netmask='ffff:ffff:ffff:ffff::', broadcast=None, ptp=None)
......
4)psutil.net_if_stats
返回网卡的详细信息,包括是否启动、通信类型、传输速度与mtu。
In [8]: psutil.net_if_stats()
Out[8]:
{'ens37': snicstats(isup=True, duplex=<NicDuplex.NIC_DUPLEX_FULL: 2>, speed=1000, mtu=1500),
'lo': snicstats(isup=True, duplex=<NicDuplex.NIC_DUPLEX_UNKNOWN: 0>, speed=0, mtu=65536),
'virbr0-nic': snicstats(isup=False, duplex=<NicDuplex.NIC_DUPLEX_FULL: 2>, speed=10, mtu=1500),
'virbr0': snicstats(isup=True, duplex=<NicDuplex.NIC_DUPLEX_UNKNOWN: 0>, speed=0, mtu=1500),
'ens33': snicstats(isup=True, duplex=<NicDuplex.NIC_DUPLEX_FULL: 2>, speed=1000, mtu=1500)}
(5)其他
1)users
以命名元组的方式返回当前登陆用户的信息,包括用户名,登陆时间,终端,与主机信息。
In [9]: psutil.users()
Out[9]:
[suser(name='root', terminal=':0', host='localhost', started=1582366080.0, pid=7991),
suser(name='root', terminal='pts/0', host='localhost', started=1582366208.0, pid=8927),
suser(name='root', terminal='pts/1', host='192.168.1.4', started=1582370816.0, pid=10099),
suser(name='root', terminal='pts/3', host='192.168.1.4', started=1582369408.0, pid=9787)]
2)boot_time
以时间戳的形式返回系统的启动时间。
In [10]: psutil.boot_time()
Out[10]: 1582527367.0
In [11]: datetime.datetime.fromtimestamp(psutil.boot_time()).strftime('%Y-%m-%d %H:%M:%S')
Out[11]: '2020-02-24 14:56:07'
3、综合案例:使用psutil实现监控程序
4、psutil进程管理
psutil还提供了作为进程管理的功能函数,包括获取进程列表,判断是否存在,以及进程管理的类封装。
函数 | 详情 |
---|---|
psutil.Process() | 对进程进行封装,可以使用该类的方法获取进行的详细信息,或者给进程发送信号。 |
psutil.pids() | 以列表的形式返回当前正在运行的进程 |
psutil.pid_exists(1) | 判断给点定的pid是否存在 |
psutil.process_iter() | 迭代当前正在运行的进程,返回的是每个进程的Process对象 |
1)Process类
对进程进行封装,可以使用该类的方法获取进行的详细信息,或者给进程发送信号。
In [1]: import psutil
In [2]: init_process = psutil.Process()
In [3]: init_process.cmdline()
Out[3]: ['/usr/local/python38/bin/python3.8', '/usr/local/python38/bin/ipython']
Process类包含很多方法来获取进程的详细信息。下面是几个较常用的方法:
name:获取进程的名称
cmdline:获取启动进程的命令行参数
create_time:获取进程的创建时间(时间戳格式)
num_fds:进程打开的文件个数
num_threads:进程的子进程个数
is_running:判断进程是否正在运行
send_signal:给进程发送信号,类似与os.kill等
kill:发送SIGKILL信号结束进程
terminate:发送SIGTEAM信号结束进程
2)pids
以列表的形式返回当前正在运行的进程。
In [1]: import psutil
In [2]: init_process = psutil.Process()
In [3]: init_process.cmdline()
Out[3]: ['/usr/local/python38/bin/python3.8', '/usr/local/python38/bin/ipython']
In [4]: psutil.pids()[:5]
Out[4]: [1, 2, 3, 5, 7]
3)pid_exists
判断给点定的pid是否存在。
In [5]: psutil.pid_exists(1)
Out[5]: True
In [6]: psutil.pid_exists(10245)
Out[6]: False
4)process_iter
迭代当前正在运行的进程,返回的是每个进程的Process对象,而pids返回的是进程的列表。
四、使用Python监控MongoDB
对于MongoDB数据库来说,获取监控的方法比较简单,因为MongoDB本身流返回给我们一个字典形式的数据。如下所示:
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pymongo
#/usr/bin/python
#_*_ coding:utf-8 _*_
from __future__ import print_function
import pymongo
client = pymongo.MongoClient(host='127.0.0.1:27017')
client.admin.authenticate('laoyu','laoyu')
rs = client.admin.command('replSetGetStatus')
print("set:",rs['set'])
print("myState:",rs['myState'])
print('num of members:',len(rs['members']))
3)pid_exists
判断给点定的pid是否存在。
In [5]: psutil.pid_exists(1)
Out[5]: True
In [6]: psutil.pid_exists(10245)
Out[6]: False
4)process_iter
迭代当前正在运行的进程,返回的是每个进程的Process对象,而pids返回的是进程的列表。
四、使用Python监控MongoDB
对于MongoDB数据库来说,获取监控的方法比较简单,因为MongoDB本身流返回给我们一个字典形式的数据。如下所示:
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pymongo
#/usr/bin/python
#_*_ coding:utf-8 _*_
from __future__ import print_function
import pymongo
client = pymongo.MongoClient(host='127.0.0.1:27017')
client.admin.authenticate('laoyu','laoyu')
rs = client.admin.command('replSetGetStatus')
print("set:",rs['set'])
print("myState:",rs['myState'])
print('num of members:',len(rs['members']))