使用Python监控Linux系统
Linux下有许多使用Python语言编写的监控工具,如inotify-sync, dstat和glances. 此外,如果要根据业务编写简单的监控脚本,很多工程师也会选择Python语言。Python语言是一门简单 易学/语法清晰/表达能力强的编程语言,非常适合于编写监控程序的场景。使用Python语言编写监控程序具有以下几个优势:
- Python语言开发效率高。 Python语言有自 己的优势与劣势,使用Python开发监控程序是一个充分发挥Python优势,避免Python劣势的领域。对于监控程序来说,能够利用Python语言开发效率高的优势尽快完成程序的编写工作。同时,监控程序也不要求性能,因此避免了Python语言性能不如C、C++和Java的劣势。
- Python语言表达能力强。相信任何-个学习Linux的工程师都使用过shel脚本编写过监控程序。虽然Linux下有很多监控工具,也有很多文本处理程序,但是获取监控与解析结果是完全不同的工具。解析监控结果的程序不理解监控程序输出结果的具体含义。Python语言中有非常丰富的数据结构,可以用各种方式保存监控结果,以便后续处理。
- 利用第三方库开发监控程序。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格式输出到文件,以便后续处理。
2、dstat介绍
作为一个多功能系统资源统计工具, dstat具有以下特性:
- 结合了 vmstat, iostat, ifstat, netstat 等监控工具的功能,并且提供了更多的监控信息;
- 实时显示监控数据;
- 在问题分析和故障排查时,可以监视最重要的计数器,也可以对计数器进行排序;
- 模块化设计;
- 使用 Python 语言编写,更方便扩展现有的工作任务;
- 容易扩展,便于添加自定义的计数器;
- 包含的许多扩展插件充分说明了增加新的监控项目是很方便的;
- 可以分组统计块设备/网络设备,并给出、汇总信息;
- 可以显示每台设备中断信息;
- 非常准确的时间精度,即便是系统负荷较高也不会延迟显示;
- 准确显示单位,限制转换误差范围;
- 用不同的颜色显示不同的单位,增加可读性;
- 显示中间结果延时小于1秒
- 支持 csv 格式输出,便于将监控信息导人 Gnumeric 和 Excel 以生成图形。
3、安装使用
如果操作系统默认没有安装dstat.那么需要我们手动进行安装。如下所示:
[root@python ~]# yum -y install dstat
<1>dstat命令的--version选项,除了显示出tat的版本以外,还会显示操作系统的版本、Python语言的版本、cpu的个数,以及dstat支持的插件列表等详细信息。如下所示:
[root@python ~]# dstat --version
<2>dstat --list获取dstat的插件列表
dstat --list
<3>直接在终端输入dstat命令,dstat将以默认参数运行。默认情况下,dstat会收集cpu、磁盘、网络、换页和系统信息,并以一秒钟一次的频率进行输出,直到我们按 ctrl+c 结束。
[root@python ~]# dstat
4、常用选项如下: .
直接跟数字,表示#秒收集一次数据,默认为1秒; 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秒钟输出1条监控信息,并在输出10条监控信息以后退出dstat。如下所示:
[root@python ~]# dstat 2 10
You did not select any stats, using -cdngy by default.
Terminal width too small, trimming output.
----total-cpu-usage---- -dsk/total- -net/total- ---paging-->
usr sys idl wai hiq siq| read writ| recv send| in out >
2 1 96 0 0 0| 270k 233k| 0 0 | 75B 1812B>
0 0 100 0 0 0| 0 0 | 60B 510B| 0 0 >
0 0 100 0 0 0| 0 0 | 60B 294B| 0 0 >
0 1 100 0 0 0| 0 0 | 60B 294B| 0 0 >
0 0 100 0 0 0| 0 0 | 182B 294B| 0 0 >
1 0 100 0 0 0| 0 0 | 60B 294B| 0 0 >
0 1 99 0 0 0| 0 0 | 60B 294B| 0 0 >
0 1 100 0 0 0| 0 0 | 60B 294B| 0 0 >
0 0 100 0 0 0| 0 0 | 60B 294B| 0 0 >
1 0 100 0 0 0| 0 0 | 60B 294B| 0 0 >
0 0 100 0 0 0| 0 25k| 60B 298B| 0 0 >
dstat命令中有很多参数可选,你可以通过man dstat命令查看,大多数常用的参数有这些:
- -l :显示负载统计量
- -m :显示内存使用率(包括used,buffer,cache,free值)
- -r :显示I/O统计
- -s :显示交换分区使用情况
- -t :将当前时间显示在第一行
- –fs :显示文件系统统计数据(包括文件总数量和inodes值)
- –nocolor :不显示颜色(有时候有用)
- –socket :显示网络统计数据
- –tcp :显示常用的TCP统计
- –udp :显示监听的UDP接口及其当前用量的一些动态数据
dstat附带了一些插件很大程度地扩展了它的功能。你可以通过查看/usr/share/dstat目录来查看它们的一些使用方法,常用的有这些:
- -–disk-util :显示某一时间磁盘的忙碌状况
- -–freespace :显示当前磁盘空间使用率
- -–proc-count :显示正在运行的程序数量
- -–top-bio :指出块I/O最大的进程
-
:图形化显示CPU占用最大的进程-–top-cpu
- -–top-io :显示正常I/O最大的进程
- -–top-mem :显示占用最多内存的进程
5、 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@python scripts]# dstat --top-mem --top-io --top-cpu
//查看当前占用I/O、CPU、内存等最高的进程信息
--most-expensive- ----most-expensive---- -most-expensive-
memory process | i/o process | cpu process
gnome-shell 53.0M|bash 420k 119k|vmtoolsd 0.1
gnome-shell 53.0M|BT-Task 1026B 0 |
gnome-shell 53.0M|gnome-shell 352B 82k|kworker/0:0 1.0
gnome-shell 53.0M|sshd: root@ 230B 196B|
gnome-shell 53.0M|sshd: root@ 155B 196B|
gnome-shell 53.0M|sshd: root@ 155B 196B|
gnome-shell 53.0M|sshd: root@ 155B 196B|
gnome-shell 53.0M|BT-Task 1406B 0 |
dstat的插件保存在/usr/share/dstat目录下, 我们可以参考它们的实现,编写自己的插件。
6、将结果输出到CSV文件
dstat还可以将监控信息保存到CSV文件中,以便后续进行处理。通过--output选项指定监控数据输出的文件。如下所示:
[root@python ~]# dstat -a --output dstat_output.csv
Terminal width too small, trimming output.
----total-cpu-usage---- -dsk/total- -net/total- ---paging-->
usr sys idl wai hiq siq| read writ| recv send| in out >
2 1 97 0 0 0| 175k 158k| 0 0 | 59B 1973B>
0 0 100 0 0 0| 0 0 | 150B 822B| 0 0 >
0 0 100 0 0 0| 0 0 | 60B 298B| 0 0 >
0 0 100 0 0 0| 0 0 | 60B 298B| 0 0 >
0 0 100 0 0 0| 0 0 | 60B 298B| 0 0 >
0 1 99 0 0 0| 0 0 | 60B 298B| 0 0 >
0 0 100 0 0 0| 0 0 | 210B 448B| 0 0 >
1 0 99 0 0 0| 0 49k| 60B 298B| 0 0 >
0 0 100 0 0 0| 0 0 | 210B 396B| 0 0 >
0 0 100 0 0 0| 0 0 | 60B 298B| 0 0 >^C
用excel查看信息
[root@python ~]# sz dstat_output.csv
//导出本地文件到windows指定位置
二、交互性监控工具glances
1、glances简介
glances是一款使用Python语言开发、基于psutil的跨平台系统监控工具。在所有的Linux命令行工具中,它与top命令最相似,都是命令行交互式监控工具。但是,glances实现了比top命令更齐全的监控,提供了更加丰富的功能。
在紧急情况下,工程师需要在尽可能短的时间内查看尽可能多的信息。此时,glances是一个不错的选择。 glances的设计初衷就是在当前窗口中尽可能多地显示系统消息。
glances可以在用户终端上实时显示重要的系统信息,并动态刷新内容。glances每隔3秒钟对其进行刷新,我们也可以使用命令行参数修改刷新的频率。与dstat相同的是,glances可以将捕获到的数据保存到文件中;而不同的是glances提供了API接口以便应用程序从glances中获取数据。
2、glances 提供的系统信息
- CPU使用率;
- 内存使用情况;
- 内核统计信息和运行队列信息;
- 磁盘I/O速度、传输和读/写比率;
- 文件系统中的可用空间;
- 磁盘适配器;
- 网络I/O速度、传输和读/写比率;
- 页面空间和页面速度;
- 消耗资源最多的进程;
- 计算机信息和系统资源。
glances 工具可以在用户的终端上实时显示重要的系统信息,并动态地对其进行更新。这个高效的工具可以工作于任何终端屏幕。另外它并不会消耗大量的 CPU 资源,通常低于百分之二。glances 在屏幕上对数据进行显示,并且每隔2秒钟对其进行更新。您也可以自己将这个时间间隔更改为更长或更短的数值。
glances 工具还可以将相同的数据捕获到一个文件,便于以后对报告进行分析和绘制图形。输出文件可以是电子表格的格式 (.csv) 或者 html 格式。
3、Linux下安装glances
#需要epel-release
yum -y install epel-release
yum -y install glances
或
#需要python-devel
yum -y install python-devel -y
pip install glances
4、glances的使用
(1)glances的默认输出
glances的使用非常简单,直接输入glances命令便进入了一个类似于top命令的交互式界面。在这个界面中,显示了比top更加全面,更加具有可读性的信息。
为了增加可读性,glances会以不同的颜色表示不同的状态。其中,绿色:性能xingnenglaingh良好,元须做任何额外工作;蓝色表示系统性能有一些小问题,用户应当开始关注系统性能;紫色:性能报警,应当采取措施;红色:性能问题严重,应当立即处理。
lances是一个交互式的工具.因此,我们也可以输入命令来控制glances的行为。
[root@python ~]# glances
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 表示僵死状态。
(2)glances的可读性
对比可以发现,glances对屏幕的利用率比top明显高很多,信息量很大,有许多top所没有显示的数据。而且,glances的实时变动比top颜值高太多了。
Glances 会用一下几种颜色来代表状态,如下所示:
- 绿色:OK(一切正常)
- 蓝色:CAREFUL(需要注意)
- 紫色:WARNING(警告)
- 红色:CRITICAL(严重)
(3)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.
(4)如果我们安装了 Bottle 这个 web 框架,还能够通过 web 浏览器显示和命令行终端相同的监控界面。
glances还支持将采集的数据导人到其他服务中心,包括InfluxDB,Cassandra,CouchDB,OpenTSDB,Prometheus,StatsD,ElasticSearch,RabbitMQ/ActiveMQ,ZeroMQ,Kafka和Riemann。
[root@python ~]# pip install bottle
//安装Bottle框架
[root@python ~]# glances -w ##默认端口是61208,访问地址没有限制
Glances Web User Interface started on http://0.0.0.0:61208/
web访问如下图:
三、Python监控Linux
shell查看磁盘的监控信息,如下所示:
[root@python 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
1、使用shell脚本监控
(1)安装转换工具
dos2unix 和 unix2dos 命令将纯文本文件从 DOS 或 Mac 格式转换为 Unix,反之亦然。
[root@python scripts]# yum -y install dos2unix
//下载dos2unix
(2)编写shell脚本
[root@python scripts]# vim monitor.sh
#/bin/sh
cpu_idle=$(top -n2 | grep 'Cpu' | tail -n 1 | awk '{print $8}')
cpu_usage=$(printf "%.2f" `echo "scale=2; 100 - $cpu_idle" | bc`)
mem_free=$(free -m | awk '/Mem:/{print $4 + $6 +$7}')
mem_total=$(free -m | awk '/Mem:/{print $2}')
mem_used=$(echo "$mem_total - $mem_free" | bc)
mem_rate=$(echo "$mem_used * 100 / $mem_total" | bc)
disk_usage=$(df -h / | tail -n 1 | awk '{print $5}')
disk_used=$(df -h / | tail -n 1 | awk '{print $3}')
echo "CPU利用率:$cpu_usage %"
echo "内存使用量: $mem_used M"
echo "内存利用率:$mem_rate %"
echo "磁盘空间使用量:$disk_used"
echo "磁盘空间利用率:$disk_usage"
(3)转换并执行
[root@python scripts]# dos2unix monitor.sh
//转换为格式为Unix
[root@python scripts]# cat monitor.sh
#/bin/sh
cpu_idle=$(top -n2 | grep 'Cpu' | tail -n 1 | awk '{print $8}')
cpu_usage=$(printf "%.2f" `echo "scale=2; 100 - $cpu_idle" | bc`)
mem_free=$(free -m | awk '/Mem:/{print $4 + $6 +$7}')
mem_total=$(free -m | awk '/Mem:/{print $2}')
mem_used=$(echo "$mem_total - $mem_free" | bc)
mem_rate=$(echo "$mem_used * 100 / $mem_total" | bc)
disk_usage=$(df -h / | tail -n 1 | awk '{print $5}')
disk_used=$(df -h / | tail -n 1 | awk '{print $3}')
echo "CPU利用率:$cpu_usage %"
echo "内存使用量: $mem_used M"
echo "内存利用率:$mem_rate %"
echo "磁盘空间使用量:$disk_used"
echo "磁盘空间利用率:$disk_usage"
[root@python scripts]# sh monitor.sh
//执行编写好的脚本
2、使用python脚本监控
(1)查看服务启动情况
[root@python scripts]# vim proc_count.py
import os
n = 0
for item in os.listdir('/proc'):
if item.isdigit():
n = n+1
# print(len(item))
print(n)
执行结果如下:
[root@python scripts]# python3 proc_count.py
175
(2)简易版
[root@python scripts]# vim monitor_dick.py
# coding=utf-8
# !/usr/bin/python
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()
执行脚本:
[root@python scripts]# python3 monitor_dick.py
(3)直观图
# coding=utf-8
# !/usr/bin/python
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(device):
disk_info = get_disk_info(device)
print(disk_info)
print("磁盘写入次数:{0}".format(disk_info.write_count))
print("磁盘写入的字节数:{0}".format(float(disk_info.write_sections) * 512))
print("磁盘写入的延时:{0}".format(disk_info.time_spent_write))
if __name__ == '__main__':
main('sda1')
[root@python scripts]# python3 monitor_dick.py