使用Python监控Linux系统
一、Python编写的监控工具
一)多功能系统资源统计工具dstat
1、dstat介绍
dstat是一个用Python语言实现的多功能系统资源统计工具,用来取代Linux下的vmstat、iostat、netstat和ifstat等命令。并且,dstat克服了这些命令的限制,增加了额外的功能、以及更多的计数器与更好的灵活性。dstat可以在一个界面上展示非常全面的监控信息。
dstat将以列表的形式显示监控信息,并且用不同的颜色进行输出,以可读性较强的单位展示监控数值。例如,对于字节数值,dstat自动根据数值的大小,以K、M、G等单位进行显示,避免了开发者使用其他命令时因为数值太大造成的困惑和错误。此外,使用dstat还可以非常方便地编写插件用来收集默认情况下没有收集的监控信息。dstat是专门为人们实时查看监控信息设计的,因此,默认将监控结果输出到屏幕终端。
2、dstat的特性
1 综合了 vmstat, iostat, ifstat, netstat 等监控工具的功能,并且提供了更多的监控信息;
2 实时显示监控数据;
3 在问题分析和故障排查时,可以监视最重要的计数器,也可以对计数器进行排序;
4 模块化设计;
5 使用 Python 语言编写,更方便扩展现有的工作任务;
6 容易扩展,便于添加自定义的计数器;
7 包含许多扩展插件;
8 可以分组统计块设备/网络设备,并给出、汇总信息;
9 可以显示每台设备中断信息;
10 非常准确的时间精度,即便是系统负荷较高也不会延迟显示;
11 准确显示单位,限制转换误差范围;
12 用不同的颜色显示不同的单位,增加可读性;
13 支持 csv 格式输出,便于将监控信息导人 Gnumeric 和 Excel 以生成图形。
3、安装使用
yum install -y dstat
dstat命令的--version选项,除了显示出tat的版本以外,还会显示操作系统的版本、Python语言的版本、cpu的个数,以及dstat支持的插件列表等详细信息。
dstat --list获取dstat的插件列表
直接在终端输入dstat命令,dstat将以默认参数运行。默认情况下,dstat会收集cpu、磁盘、网络、换页和系统信息,并以一秒钟一次的频率进行输出,直到我们按 ctrl+c 结束。
4、dstat常用选项
执行 dstat 命令的时候,默认他会 收集-cpu-、-disk-、-net-、-paging-、-system-的数据,一秒钟收集一次。默认输入 dstat 等于输入了dstat -cdngy 1
或dstat -a 1。
1 CPU状态:CPU的使用率。这项报告更有趣的部分是显示了用户,系统和空闲部分,这更好地分析了CPU当前的使用状况。如果你看到”wait”一栏中,CPU的状态是一个高使用率值,那说明系统存在一些其它问题。当CPU的状态处在”waits”时,那是因为它正在等待I/O设备(例如内存,磁盘或者网络)的响应而且还没有收到。
2 磁盘统计:磁盘的读写操作,这一栏显示磁盘的读、写总数。
3 网络统计:网络设备发送和接受的数据,这一栏显示的网络收、发数据总数。
4 分页统计:系统的分页活动。分页指的是一种内存管理技术用于查找系统场景,一个较大的分页表明系统正在使用大量的交换空间,或者说内存非常分散,大多数情况下你都希望看到page in(换入)和page out(换出)的值是0 0。
5 系统统计:这一项显示的是中断(int)和上下文切换(csw)。这项统计仅在有比较基线时才有意义。这一栏中较高的统计值通常表示大量的进程造成拥塞,需要对CPU进行关注。你的服务器一般情况下都会运行运行一些程序,所以这项总是显示一些数值。
默认情况下,dstat每秒都会刷新数据。dstat可以通过传递2个参数运行来控制报告间隔和报告数量。
dstat输出默认监控、报表输出的时间间隔为3秒钟,并且报表中输出10个结果:
dstat命令中有很多参数可选,你可以通过man dstat命令查看,大多数常用的参数有这些:
1 -l :显示负载统计量
2 -m :显示内存使用率(包括used,buffer,cache,free值)
3 -r :显示I/O统计
4 -s :显示交换分区使用情况
5 -t :将当前时间显示在第一行
6 –fs :显示文件系统统计数据(包括文件总数量和inodes值)
7 –nocolor :不显示颜色(有时候有用)
8 –socket :显示网络统计数据
9 –tcp :显示常用的TCP统计
10 –udp :显示监听的UDP接口及其当前用量的一些动态数据
dstat附带了一些插件很大程度地扩展了它的功能。你可以通过查看/usr/share/dstat目录来查看它们的一些使用方法,常用的有这些:
1 -–disk-util :显示某一时间磁盘的忙碌状况
2 -–freespace :显示当前磁盘空间使用率
3 -–proc-count :显示正在运行的程序数量
4 -–top-bio :指出块I/O最大的进程
5 -–top-cpu :图形化显示CPU占用最大的进程
6 -–top-io :显示正常I/O最大的进程
7 -–top-mem :显示占用最多内存的进程
5、dstat的使用
dstat的强大之处不仅仅是因为它聚合了多种工具的监控结果,还因为它能通过附带的插件实现一些高级功能,如找出占用资源最高的进程和用户。
1、查看全部内存都有谁在占用
dstat -g -l -m -s --top-mem
结果如下
2、显示一些关于CPU资源损耗的数据:
dstat -c -y -l --proc-count --top-cpu
结果如下:
3、查看当前占用I/O、CPU、内存等最高的进程信息
dstat --top-mem --top-io --top-cpu
结果如下:
4、将结果输出到CSV文件,并输出到桌面
dstat --output dstat_output.csv
二)交互性监控工具glances
1、glances简介
glances是一款使用Python语言开发、基于psutil的跨平台系统监控工具。在所有的Linux命令行工具中,它与top命令最相似,都是命令行交互式监控工具。但是,glances实现了比top命令更齐全的监控,提供了更加丰富的功能。
glances可以在用户终端上实时显示重要的系统信息,并动态刷新内容。glances每隔3秒钟对其进行刷新,我们也可以使用命令行参数修改刷新的频率。与dstat相同的是,glances可以将捕获到的数据保存到文件中;而不同的是glances提供了API接口以便应用程序从glances中获取数据。
2、glances 提供的系统信息
1 CPU使用率;
2 内存使用情况;
3 内核统计信息和运行队列信息;
4 磁盘I/O速度、传输和读/写比率;
5 文件系统中的可用空间;
6 磁盘适配器;
7 网络I/O速度、传输和读/写比率;
8 页面空间和页面速度;
9 消耗资源最多的进程;
10 计算机信息和系统资源。
3、安装glances
#需要python-devel yum isntall python-devel -y pip install glances
报错如下
#include <Python.h> ^ compilation terminated. error: command 'gcc' failed with exit status 1
解决办法如下
yum install python-devel
4、glances的使用
1、glances的默认输出
glances的使用非常简单,直接输入glances命令便进入了一个类似于top命令的交互式界面。在这个界面中,显示了比top更加全面,更加具有可读性的信息。
为了增加可读性,glances会以不同的颜色表示不同的状态。其中,绿色表示性能良好,元须做任何额外工作;蓝色表示系统性能有一些小问题,用户应当开始关注系统性能;紫色表示性能报警,应当采取措施;红色表示性能问题严重,应当立即处理。
glances是一个交互式的工具.因此,我们也可以输入命令来控制glances的行为。
2、glances中常见的命令
1 h:显示帮助信息;
2 q:离开程序退出;
3 c:按照 CPU 实时负载对系统进程排序;
4 m:按照内存使用状况对系统进程排序;
5 i:按照 I/O 使用状况对系统进程排序;
6 p:按照进程名称排序;
7 d:显示或隐藏磁盘读写状况;
8 f:显示或隐藏文件系统信息;
9 1:分开显示每个 CPU 的使用情况。
3、如果我们安装了 Bottle 这个 web 框架,还能够通过 web 浏览器显示和命令行终端相同的监控界面。
glances还支持将采集的数据导人到其他服务中心,包括InfluxDB,Cassandra,CouchDB,OpenTSDB,Prometheus,StatsD,ElasticSearch,RabbitMQ/ActiveMQ,ZeroMQ,Kafka和Riemann。
pip install bottle # glances -w ##默认端口是61208,访问地址没有限制 Glances web server started on http://0.0.0.0:61208/
web访问如下图:
二、使用Python开源库psutil监控Linux
在Python生态中广泛使用的开源项目,即psutil。
一)psutil介绍
psutil是一个开源且跨平台的库,其提供了便利的函数用来获取操作系统的信息,如cpu、内存、磁盘、网络等信息。此外,psutil还可以用来进行进程管理,包括判断进程是否存在、获取进程列表、获取进程的详细信息等。psutil广泛应用于系统监控、进程管理、资源限制等场景。此外,psutil还提供了许多命令行工具提供的功能,包括ps,top,lsof,netstat,ifconfig,who,df,kill,free,nice,ionice,iostat,iotop,uptime,pidof,tty,taskset,pmap。
psutil是一个跨平台的库,支持Linux,Windows,OSX,SunSolaris,FreeBSD,OpenBSD以及NetBSD等操作系统。同时,psutil也支持32位与64位的系统架构,支持Python2.6到Python3.6之间所有的Python版本。psutil具有简单易用、功能强大、跨平台等诸多优点,广泛应用于开源项目中,比较有名的有glances、facebook的osquery、google的grr等。psutil不但广泛应用于Python语言开发的开源项目中,还被移植到了其他编程语言中,如Go语言的gopsutil、C语言的cpslib、Rust语言的rust-psutil、Ruby语言的posixpsutil等。作为一个不算复杂的开源项目,psutil可以说是非常成功了。
psutil是一个第三方的开源项目,因此,需要先安装才能够使用。
pip install psutil
psutil包含了若干异常、类、功能函数和常量。其中,功能函数用来获取系统的信息,如cpu、内存、磁盘、网络和用户等信息。类用来实现进程管理的功能。
二)psutil提供的功能函数
psutil来简化使用shell脚本获取监控信息的程序,并获取cpu、内存、磁盘和网络等不同维度。
1、CPU
与CPU相关的功能函数
1、cpu_count默认返回cpu的个数,也可以指定logical=Flase获取物理CPU的个数
import psutil LogicalCpuCount = psutil.cpu_count() CpuCount = psutil.cpu_count(logical=False)
2、cpu_percent返回cpu的利用率。
可以通过interval参数阻塞式地获取interval时间范围内的cpu利用率,否则,获取上一次调用cpu_percent这段时间以来的cpu利用率。可以使用pericpu参数指定获取每个cpu的利用率,默认获取整体的cpu利用率。
三)综合案例:使用psutil
收集系统的监控信息并通过邮件的形式发送给管理员。使用psutil收集了cpu的信息、开机时间、内存信息以及磁盘空间等信息,读者也可以根据需要收集磁盘io信息与网络io信息。
1、Python自动发邮件——yagmail库
yagmail与smtplib、email模块的区别:https://www.cnblogs.com/fighter007/p/8454532.html
1、安装yagmail
#pip install yagmail Collecting yagmail Downloading https://files.pythonhosted.org/packages/60/05/8000b8c5e3fb7ea2d6c886f647d43ea2cb1bae8ff1a1d6dca96c4b971ba0/yagmail-0.10.212-py2.py3-none-any.whl Installing collected packages: yagmail Successfully installed yagmail-0.10.212
2、给单个接受者发送邮箱
相对email、smtp模块而已,yagmail实现起来简单多了。
import yagmail # 链接邮箱服务器 yag = yagmail.SMTP(user="sender@126.com", password="126邮箱授权码", host="smtp.126.com") # 邮箱正文 contents = ['This is the body, and here is just text http://somedmain/image.png', 'You can find an audio file attached.', '/loacl/path/sond.mp3'] # 给单个接受者发送邮件 yag.send('receiver@qq.com', 'subject', contents)
3、给多个接受者发送邮件
yag.send(['aa@126.com', 'bb@qq.com', 'cc@gmail.com'], 'subject', contents)
4、发送带附件的邮件
yag.send('aa@126.com', '发送附件', contents, ["E://whitelist.txt","E://baidu_img.jpg"])
2、代码实现
将所有收集到的监控数据保存在一个字典中,并以解引用的方式传递给render函数。render函数的作用非常简单,在默认情况下根据模板的名称在当前目录下查找模板,然后使用Jinja2进行模板渲染。模板渲染以后,就得到一个HTML形式的字符串。在这个例子中,我们的模板将不同的监控项以表格的形式进行组织。
模板渲染完成以后,使用yagmail将监控数据以邮件的形式发送给收件人。需要注意的是,在我们的程序中使用Unicode表示中文,因此,在发送邮件时需要将Unicode进行编码。
from __future__ import unicode_literals import os import socket from datetime import datetime import jinja2 import yagmail import psutil EMAIL_USER = 'aa@126.com' EMAIL_PASSWORD = '123456' RECIPIENTS = ['wangzhen@wzs.com'] def render(tpl_path, **kwargs): path, filename = os.path.split(tpl_path) return jinja2.Environment( loader=jinja2.FileSystemLoader(path or './') ).get_template(filename).render(**kwargs) 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 def get_cpu_info(): ''' cpu info :return: ''' cpu_count = psutil.cpu_count() cpu_percent = psutil.cpu_percent(interval=1) return dict(cpu_count=cpu_count, cpu_percent=cpu_percent) def get_memory_info(): virtual_mem = psutil.virtual_memory() mem_total = bytes2human(virtual_mem.total) mem_percent = virtual_mem.percent mem_free = bytes2human(virtual_mem.free + virtual_mem.buffers + virtual_mem.cached) mem_used = bytes2human(virtual_mem.total * virtual_mem.percent) return dict(mem_total=mem_total, mem_percent=mem_percent, mem_free=mem_free, mem_used=mem_used) def get_dist_info(): disk_usage = psutil.disk_usage('/') disk_total = bytes2human(disk_usage.total) disk_percent = disk_usage.percent disk_free = bytes2human(disk_usage.free) disk_used = bytes2human(disk_usage.used) return dict(disk_total=disk_total, disk_percent=disk_percent, disk_free=disk_free, disk_used=disk_used) def get_boot_info(): boot_time = datetime.fromtimestamp(psutil.boot_time()).strftime("%Y-%m-%d %H:%M:%S") return dict(boot_time=boot_time) def collect_monitor_data(): data = {} data.update(get_boot_info()) data.update(get_cpu_info()) data.update(get_memory_info()) data.update(get_dist_info()) return data def main(): hostname = socket.gethostname() data = collect_monitor_data() data.update(dict(hostname=hostname)) content = render('monitor.html', **data) with yagmail.SMTP(user=EMAIL_USER, password=EMAIL_PASSWORD, host='smtp.163.com', port=25) as yag: for recipent in RECIPIENTS: yag.send(recipent, "监控信息".encode('utf-8'), content.encode('utf-8')) if __name__ == '__main__': main()
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>监控信息</title> </head> <body> <table border="1"> <tr><td>服务器名称</td><td>{{ hostname }}</td></tr> <tr><td>开机时间</td><td>{{boot_time}}</td></tr> <tr><td>cpu个数</td><td>{{ cpu_count }}</td></tr> <tr><td>cpu利用率</td><td>{{ cpu_percent }}</td></tr> <tr><td>内存总量</td><td>{{ mem_percent }}</td></tr> <tr><td>内存利用率</td><td>{{ mem_total }}</td></tr> <tr><td>内存已用空间</td><td>{{ mem_used }}</td></tr> <tr><td>内存可用空间</td><td>{{ mem_free }}</td></tr> <tr><td>磁盘空间总量</td><td>{{ disk_total }}</td></tr> <tr><td>磁盘空间利用率</td><td>{{ disk_percent }}</td></tr> <tr><td>磁盘已用空间</td><td>{{ disk_used }}</td></tr> <tr><td>磁盘可用空间</td><td>{{ disk_free }}</td></tr> </table> </body> </html>