目前 Linux 下有一些使用 Python 语言编写的 Linux 系统监控工具 好比 inotify-sync(文件系统安全监控软件)、glances(资源监控工具)在实际工做中,Linux 系统管理员能够根据本身使用的服务器的具体状况编写一下简单实用的脚本实现对 Linux 服务器的监控。 本文介绍一下使用 Python 脚本实现对 Linux 服务器 CPU 内存 网络的监控脚本的编写。python
Python 版本说明
Python 是由 Guido van Rossum 开发的、可免费得到的、很是高级的解释型语言。其语法简单易懂,而其面向对象的语义功能强大(但又灵活)。Python 能够普遍使用并具备高度的可移植性。本文 Linux 服务器是 Ubuntu 12.10, Python 版本 是 2.7 。若是是 Python 3.0 版本的语法上有必定的出入。另外这里笔者所说的 Python 是 CPython,CPython 是用 C 语言实现的 Python 解释器,也是官方的而且是最普遍使用的Python 解释器。除了 CPython 之外,还有用 Java 实现的 Jython 和用.NET 实现的 IronPython,使 Python方便地和 Java 程序、.NET 程序集成。另外还有一些实验性的 Python 解释器好比 PyPy。CPython 是使用字节码的解释器,任何程序源代码在执行以前先要编译成字节码。它还有和几种其它语言(包括 C 语言)交互的外部函数接口。linux
工做原理:基于/proc 文件系统
Linux 系统为管理员提供了很是好的方法,使其能够在系统运行时更改内核,而不须要从新引导内核系统,这是经过/proc 虚拟文件系统实现的。/proc 文件虚拟系统是一种内核和内核模块用来向进程(process)发送信息的机制(因此叫作“/proc”),这个伪文件系统容许与内核内部数据结构交互,获取有关进程的有用信息,在运行中(on the fly)改变设置(经过改变内核参数)。与其余文件系统不一样,/proc 存在于内存而不是硬盘中。proc 文件系统提供的信息以下:git
- 进程信息:系统中的任何一个进程,在 proc 的子目录中都有一个同名的进程 ID,能够找到 cmdline、mem、root、stat、statm,以及 status。某些信息只有超级用户可见,例如进程根目录。每个单独含有现有进程信息的进程有一些可用的专门连接,系统中的任何一个进程都有一个单独的自连接指向进程信息,其用处就是从进程中获取命令行信息。
- 系统信息:若是须要了解整个系统信息中也能够从/proc/stat 中得到,其中包括 CPU 占用状况、磁盘空间、内存对换、中断等。
- CPU 信息:利用/proc/CPUinfo 文件能够得到中央处理器的当前准确信息。
- 负载信息:/proc/loadavg 文件包含系统负载信息。
- 系统内存信息:/proc/meminfo 文件包含系统内存的详细信息,其中显示物理内存的数量、可用交换空间的数量,以及空闲内存的数量等。
表 1 是 /proc 目录中的主要文件的说明:github
表 1 /proc 目录中的主要文件的说明
文件或目录名称 |
描 述 |
---|---|
apm |
高级电源管理信息 |
cmdline |
这个文件给出了内核启动的命令行 |
CPU info |
中央处理器信息 |
devices |
能够用到的设备(块设备/字符设备) |
dma |
显示当前使用的 DMA 通道 |
filesystems |
核心配置的文件系统 |
ioports |
当前使用的 I/O 端口 |
interrupts |
这个文件的每一行都有一个保留的中断 |
kcore |
系统物理内存映像 |
kmsg |
核心输出的消息,被送到日志文件 |
mdstat |
这个文件包含了由 md 设备驱动程序控制的 RAID 设备信息 |
loadavg |
系统平均负载均衡 |
meminfo |
存储器使用信息,包括物理内存和交换内存 |
modules |
这个文件给出可加载内核模块的信息。lsmod 程序用这些信息显示有关模块的名称,大小,使用数目方面的信息 |
net |
网络协议状态信息 |
partitions |
系统识别的分区表 |
pci |
pci 设备信息 |
scsi |
scsi 设备信息 |
self |
到查看/proc 程序进程目录的符号链接 |
stat |
这个文件包含的信息有 CPU 利用率,磁盘,内存页,内存对换,所有中断,接触开关以及赏赐自举时间 |
swaps |
显示的是交换分区的使用状况 |
uptime |
这个文件给出自从上次系统自举以来的秒数,以及其中有多少秒处于空闲 |
version |
这个文件只有一行内容,说明正在运行的内核版本。能够用标准的编程方法进行分析得到所需的系统信息 |
下面本文的几个例子都是使用
Python 脚本
读取
/proc 目录中的主要文件来实现实现对 Linux 服务器的监控的 。
web
使用 Python 脚本实现对 Linux 服务器的监控
对于 CPU(中央处理器)监测
脚本 1 名称 CPU1.py,做用获取 CPU 的信息。apache
清单 1.获取 CPU 的信息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
#!/usr/bin/env Python
from __future__ import print_function
from collections import OrderedDict
import pprint
def CPUinfo():
''' Return the information in /proc/CPUinfo
as a dictionary in the following format:
CPU_info['proc0']={...}
CPU_info['proc1']={...}
'''
CPUinfo=OrderedDict()
procinfo=OrderedDict()
nprocs = 0
with open('/proc/CPUinfo') as f:
for line in f:
if not line.strip():
# end of one processor
CPUinfo['proc%s' % nprocs] = procinfo
nprocs=nprocs+1
# Reset
procinfo=OrderedDict()
else:
if len(line.split(':')) == 2:
procinfo[line.split(':')[0].strip()] = line.split(':')[1].strip()
else:
procinfo[line.split(':')[0].strip()] = ''
return CPUinfo
if __name__=='__main__':
CPUinfo = CPUinfo()
for processor in CPUinfo.keys():
print(CPUinfo[processor]['model name'])
|
简单说明一下清单 1,读取/proc/CPUinfo 中的信息,返回 list,每核心一个 dict。其中 list 是一个使用方括号括起来的有序元素集合。List 能够做为以 0 下标开始的数组。Dict 是 Python 的内置数据类型之一, 它定义了键和值之间一对一的关系。OrderedDict 是一个字典子类,能够记住其内容增长的顺序。常规 dict 并不跟踪插入顺序,迭代处理时会根据键在散列表中存储的顺序来生成值。在 OrderedDict 中则相反,它会记住元素插入的顺序,并在建立迭代器时使用这个顺序。编程
可使用 Python 命令运行脚本 CPU1.py 结果见图 1json
1
2
|
# Python CPU1.py
Intel(R) Celeron(R) CPU E3200 @ 2.40GHz
|
图 1.运行清单 1
也可使用 chmod 命令添加权限收直接运行 CPU1.py数组
1
2
|
#chmod +x CPU1.py
# ./CPU1.py
|
对于系统负载监测
脚本 2 名称 CPU2.py,做用获取系统的负载信息
清单 2 获取系统的负载信息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
#!/usr/bin/env Python
import os
def load_stat():
loadavg = {}
f = open("/proc/loadavg")
con = f.read().split()
f.close()
loadavg['lavg_1']=con[0]
loadavg['lavg_5']=con[1]
loadavg['lavg_15']=con[2]
loadavg['nr']=con[3]
loadavg['last_pid']=con[4]
return loadavg
print "loadavg",load_stat()['lavg_15']
|
简单说明一下清单 2:清单 2 读取/proc/loadavg 中的信息,import os :Python 中 import 用于导入不一样的模块,包括系统提供和自定义的模块。其基本形式为:import 模块名 [as 别名],若是只须要导入模块中的部分或所有内容能够用形式:from 模块名 import *来导入相应的模块。OS 模块 os 模块提供了一个统一的操做系统接口函数,os 模块能在不一样操做系统平台如 nt,posix 中的特定函数间自动切换,从而实现跨平台操做。
可使用 Python 命令运行脚本 CPU1.py 结果见图 2 # Python CPU2.py
图 2.运行清单 2
对于内存信息的获取
脚本 3 名称 mem.py,做用是获取内存使用状况信息
清单 3 获取内存使用状况
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
#!/usr/bin/env Python
from __future__ import print_function
from collections import OrderedDict
def meminfo():
''' Return the information in /proc/meminfo
as a dictionary '''
meminfo=OrderedDict()
with open('/proc/meminfo') as f:
for line in f:
meminfo[line.split(':')[0]] = line.split(':')[1].strip()
return meminfo
if __name__=='__main__':
#print(meminfo())
meminfo = meminfo()
print('Total memory: {0}'.format(meminfo['MemTotal']))
print('Free memory: {0}'.format(meminfo['MemFree']))
|
简单说明一下清单 3:清单 3 读取 proc/meminfo 中的信息,Python 字符串的 split 方法是用的频率仍是比较多的。好比咱们须要存储一个很长的数据,而且按照有结构的方法存储,方便之后取数据进行处理。固然能够用 json 的形式。可是也能够把数据存储到一个字段里面,而后有某种标示符来分割。 Python 中的 strip 用于去除字符串的首位字符,最后清单 3 打印出内存总数和空闲数。
可使用 Python 命令运行脚本 mem.py 结果见图 3。 # Python mem.py
图 3.运行清单 3
对于网络接口的监测
脚本 4 名称是 net.py,做用获取网络接口的使用状况。
清单 4 net.py 获取网络接口的输入和输出
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
#!/usr/bin/env Python
import time
import sys
if len(sys.argv) > 1:
INTERFACE = sys.argv[1]
else:
INTERFACE = 'eth0'
STATS = []
print 'Interface:',INTERFACE
def rx():
ifstat = open('/proc/net/dev').readlines()
for interface in ifstat:
if INTERFACE in interface:
stat = float(interface.split()[1])
STATS[0:] = [stat]
def tx():
ifstat = open('/proc/net/dev').readlines()
for interface in ifstat:
if INTERFACE in interface:
stat = float(interface.split()[9])
STATS[1:] = [stat]
print 'In Out'
rx()
tx()
while True:
time.sleep(1)
rxstat_o = list(STATS)
rx()
tx()
RX = float(STATS[0])
RX_O = rxstat_o[0]
TX = float(STATS[1])
TX_O = rxstat_o[1]
RX_RATE = round((RX - RX_O)/1024/1024,3)
TX_RATE = round((TX - TX_O)/1024/1024,3)
print RX_RATE ,'MB ',TX_RATE ,'MB'
|
简单说明一下清单 4:清单 4 读取/proc/net/dev 中的信息,Python 中文件操做能够经过 open 函数,这的确很像 C 语言中的 fopen。经过 open 函数获取一个 file object,而后调用 read(),write()等方法对文件进行读写操做。另外 Python 将文本文件的内容读入能够操做的字符串变量很是容易。文件对象提供了三个“读”方法: read()、readline() 和 readlines()。每种方法能够接受一个变量以限制每次读取的数据量,但它们一般不使用变量。 .read() 每次读取整个文件,它一般用于将文件内容放到一个字符串变量中。然而 .read() 生成文件内容最直接的字符串表示,但对于连续的面向行的处理,它倒是没必要要的,而且若是文件大于可用内存,则不可能实现这种处理。.readline() 和 .readlines() 之间的差别是后者一次读取整个文件,象 .read() 同样。.readlines() 自动将文件内容分析成一个行的列表,该列表能够由 Python 的 for … in … 结构进行处理。另外一方面,.readline() 每次只读取一行,一般比 .readlines() 慢得多。仅当没有足够内存能够一次读取整个文件时,才应该使用 .readline()。最后清单 4 打印出网络接口的输入和输出状况。
可使用 Python 命令运行脚本 net.py 结果见图 4 #Python net.py
图 4.运行清单 4
监控 Apache 服务器进程的 Python 脚本
Apache 服务器进程可能会由于系统各类缘由而出现异常退出,致使 Web 服务暂停。因此笔者写一个 Python 脚本文件:
清单 5 crtrl.py 监控 Apache 服务器进程的 Python 脚本
1
2
3
4
5
6
7
8
9
10
11
12
13
|
#!/usr/bin/env Python
import os, sys, time
while True:
time.sleep(4)
try:
ret = os.popen('ps -C apache -o pid,cmd').readlines()
if len(ret) < 2:
print "apache 进程异常退出, 4 秒后从新启动"
time.sleep(3)
os.system("service apache2 restart")
except:
print "Error", sys.exc_info()[1]
|
设置文件权限为执行属性(使用命令 chmod +x crtrl.py),而后加入到/etc/rc.local 便可,一旦 Apache 服务器进程异常退出,该脚本自动检查而且重启。 简单说明一下清单 5 这个脚本不是基于/proc 伪文件系统的,是基于 Python 本身提供的一些模块来实现的 。这里使用的是 Python 的内嵌 time 模板,time 模块提供各类操做时间的函数。
总结
在实际工做中,Linux 系统管理员能够根据本身使用的服务器的具体状况编写一下简单实用的脚本实现对 Linux 服务器的监控。本文介绍一下使用 Python 脚本实现对 Linux 服务器 CPU 、系统负载、内存和 网络使用状况的监控脚本的编写方法。