2023年11月29日发(作者:)
第6章:使⽤Python监控Linux系统
编写的监控⼯具
1).多功能系统资源统计⼯具dstat
dstat是⼀个⽤Python编写的多功能系统资源统计⼯具,⽤来取代Linux下的vmstat,iostat,netstat和ifstat等命令
dstat可以在⼀个界⾯上展⽰⾮常全⾯的监控信息
# yum install dstat
# dstat 2 10
dstat的强⼤之处不仅仅是因为它聚合了很多种⼯具的监控结果,还因为它能通过附带的插件实现⼀些⾼级功能,如找出占⽤资源最⾼的进程和⽤户
dstat的--top-(io|bio|cpu|cputime|cputime-avg|mem)这⼏个选项可以看到具体是哪个⽤户和哪个进程占⽤了相关系统资源,对系统调优⾮常有效
# dstat --top-mem --top-io --top-cpu
# dstat -a --output dstat_
2).交互式监控⼯具glances
glances是⼀款使⽤Python开发的,基于psutil的跨平台系统监控⼯具
glances可以在⽤户终端上实时显⽰重要的系统信息,并动态刷新内容
# pip install glances
# glances
类似top命令的交互式界⾯
# pip install Bottle
# glances -w
2.使⽤Python打造⾃⼰的监控⼯具
1).Linux系统的/proc⽬录介绍
Linux系统将监控数据保存在proc⽬录下
proc⽬录是⼀个控制中⼼,⽤户可以通过更改其中某些⽂件来改变内核的运⾏状态
2).proc⽬录下常⽤⽂件介绍
/proc/loadavg
/proc/meminfo
/proc/diskstats
/proc/net/dev
/proc/cpuinfo
3).进程⽬录下常⽤⽂件介绍
proc⽬录下有很多名字为数字的⽬录,⽬录的名称与进程的id对应
4).利⽤/proc⽬录找到被删除的⽂件
由于有进程(MySQL进程)打开了该⽂件,当我们从外部执⾏删除命令时⽂件并没有被真正的删除
只有当进程关闭该⽂件的句柄时,⽂件才会被真正删除
可以使⽤lsof命令查看已经被删除的⽂件
[root@kettle1 test]# lsof | grep
mysqld 2933 mysql 37uW REG 253,0 98304 524406 /app/mysqldata/3306/data/test/ (deleted)
虽然从⽂件系统层⾯已经⽆法找到被删除的⽂件,我们还可以在proc⽬录下找到该⽂件的⽂件句柄
[root@kettle1 fd]# ll /proc/2933/fd/37
lrwx------. 1 root root 64 Aug 10 16:34 /proc/2933/fd/37 -> /app/mysqldata/3306/data/test/ (deleted)
为了恢复出⼀个⼀致性的数据⽂件,可以先在MySQL数据库中为该表加上表锁,以免在恢复⽂件的过程中还有新的写⼊
(root@localhost) [test]> lock table tt read;
Query OK, 0 rows affected (0.00 sec)
恢复的⽅式也很简单,直接对⽂件句柄进⾏cp即可
[root@kettle1 fd]# cp /proc/2933/fd/37 /app/mysqldata/3306/data/test/
[root@kettle1 fd]# chown mysql:mysql /app/mysqldata/3306/data/test/
重启数据库
5).使⽤shell脚本监控Linux
# cat 在CentOS7上的监控
cpu_idle=$(top -n2 | grep 'Cpu' | tail -n 1 | awk '{ print $8 }')
cpu_usage=$(echo "100 - $cpu_idle" | bc)
mem_free=$(free -m | awk '/Mem:/{ print $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"
6).使⽤Python监控Linux
使⽤Python监控Linux磁盘IO
# -*- coding: UTF-8 -*-
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
def get_disk_info(device):
with open("/proc/diskstats") as f:
for line in f:
if ()[2] == device:
return Disk(*(()))
raise RuntimeError("device ({0}) not found!".format(device))
def main():
disk_info = get_disk_info('sda')
print(disk_info)
print("磁盘写次数:{0}".format(disk__count))
print("磁盘写字节数:{0}".format(long(disk__sections)*512))
print("磁盘写延时:{0}".format(disk__spent_write))
if __name__ == '__main__':
main()
3.使⽤开源库监控Linux
1).psutil介绍
psutil是⼀个开源且跨平台的库,其提供了便利的函数⽤来获取操作系统的信息,如cpu,内存,磁盘,⽹络等信息
psutil可以⽤来进⾏进程管理,包括判断进程是否存在、获取进程列表、获取进程的详细信息等
psutil⼴泛应⽤于系统监控、进程管理、资源限制等场景
# pip install psutil
2).psutil提供的功能函数
与cpu相关的功能函数
cpu_count默认返回逻辑cpu的个数
import psutil
_count()
_count(logical=False)
cpu_percent返回cpu的使⽤率
import psutil
_percent()
_percent(percpu=True)
_percent(interval=2,percpu=True)
virtual_memory以命名元组的形式返回内存使⽤情况,包括总内存、可⽤内存、内存使⽤率、buffer和cached等
import psutil
l_memory()
def bytes2human(n):
symbols = ('K','M','G','T','P')
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
bytes2human(l_memory().total)
swap_memory以命名元组的形式返回swap memory的使⽤情况
_memory()
与磁盘相关的功能函数
disk_partitions返回所有已经挂载的磁盘,包含磁盘名称、挂载点、⽂件系统类型等信息
_partitions()
disk_usage获取磁盘的使⽤情况,包括磁盘的容量、已经使⽤的磁盘容量、磁盘的空间利⽤率等
_usage('/')
disk_io_counters返回磁盘io统计信息,包括读的次数、写的次数、读写字节、写字节等
_io_counters()
与⽹络相关的功能函数
net_io_counter返回每块⽹卡的⽹络io的统计信息,包括收发字节数、收发包的数量、出错情况与删包情况
_io_counters()
net_connections返回每个⽹络链接的详细信息
_connections()
net_if_addrs返回⽹卡的配置信息,包括ip地址,mac地址,⼦⽹掩码和⼴播地址
3).综合案例:使⽤psutil实现监控程序
使⽤psutil收集了cpu的信息,开机时间,内存信息以及磁盘空间等信息,以及磁盘io与⽹络io信息
import os
import socket
from datetime import datetime
import psutil
import jinja2
import yagmail
EMAIL_USER = 'hugaochao320@'
EMAIL_PASSWORD = 'hgc3177678'
RECIPIENTS = ['hugc@']
def render(tpl_path, **kwargs):
path, filename = (tpl_path)
return nment(loader=stemLoader(path or './')).get_template(filename).render(**kwargs)
def bytes2human(n):
symbols = ('K','M','G','T','P')
prefix = {}
for i,s in enumerate(symbols):
prefix[s] = 1 << (i + i) * 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_count = _count()
cpu_percent = _percent(interval=1)
return dict(cpu_count=cpu_count, cpu_percent=cpu_percent)
def get_memory_info():
hostname = tname()
data = collect_monitor_data()
(dict(hostname=hostname))
content = render('', **data)
with (user=EMAIL_USER, password=EMAIL_PASSWORD, host='', port=465) as yag:
for recipient in RECIPIENTS:
(recipient, "monitor information".encode('utf-8'), ('utf-8'))
if __name__ == '__main__':
main()
4.使⽤pyinotify监控⽂件系统变化
1).pyinotify模块介绍
pyinotify⽤来检测⽂件系统变化
inotify是⼀个事件驱动的通知器
pip install pyinotify
python -m pyinotify /tmp
2).pyinotify模块API
pyinotify模块API
WatchManager保存了需要监视的⽂件和⽬录,以及监视⽂件和⽬录的哪些事件
import pyinotify
wm = anager()
_watch('/tmp', _EVENTS)
notifier = er(wm)
()
仅监视创建和删除事件
import pyinotify
wm = anager()
mask = _DELETE | _CREATE
_watch('/tmp', mask)
notifier = er(wm)
()
3).事件标志与事件处理器
事件标志 事件含义
IN_CREATE 在被监控⽬录中创建⼦⽬录或⽂件
IN_DELETE 在被监控⽬录中有⼦⽬录或⽂件被删除
IN_MODIFY 被监控⽬录中的条⽬被修改
IN_MOVE
...
import pyinotify
wm = anager()
mask = _DELETE | _CREATE
class EventHandler(sEvent):
def process_IN_CREATE(self, event):
print("Creating:", me)
def process_IN_DELETE(self, event):
print("Removing:", me)
handler = EventHandler()
notifier = er(wm, handler)
wdd = _watch('/tmp', mask, rec=True)
()
5.监控应⽤程序
1).使⽤Python监控MySQL
数据库作为应⽤程序的核⼼组件,⼀般都需要进⾏细粒度的监控
以MySQL数据库为例:
对MySQL数据库的监控应该包括数据库连接数、qps、tps、Buffer Pool命中率、复制延迟、Binlog⽂件⼤⼩等
2).使⽤Python监控MongoDB
MongoDB本⾝就返回⼀个数据字典
from __future__ import print_function
import pymongo
client = lient(host='127.0.0.1:27017')
ticate('laimingxing','laimingxing')
rs = d('replSetGetStatus')
print("set:",rs['set'])
print("myState:",rs['myState'])
print("num of members:",len(rs['members']))


发布评论