目前 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 、系統負載、內存和 網絡使用狀況的監控腳本的編寫方法。