
運維工程師經(jīng)常使用 Python 編寫腳本程序來做監(jiān)控系統(tǒng)運行的狀態(tài)。如果自己手動使用 Python 的標(biāo)準(zhǔn)庫執(zhí)行系統(tǒng)命令來獲取信息,會顯得非常麻煩。既要兼容不同操作系統(tǒng),又要自己處理解析信息。為了解決的痛點問題,psutil 就橫空出世。它的出現(xiàn)無疑是運維工程師的福音。運維小伙伴通過它執(zhí)行一兩行代碼即可實現(xiàn)系統(tǒng)監(jiān)控。
1 簡介
psutil全稱是process and system utilities。psutil 是一個跨平臺的應(yīng)用于系統(tǒng)監(jiān)控、分析、以及對系統(tǒng)進(jìn)程進(jìn)行一定管理的 Python 第三方庫。它不僅能夠輕松獲取系統(tǒng)中正常運行的進(jìn)程和系統(tǒng)利用率(例如 CPU、內(nèi)存、磁盤、網(wǎng)絡(luò)等)信息,還實現(xiàn)了跟 UNIX 系統(tǒng)命令行工具類似的功能??梢哉f是運維工作的“必備品”。
它功能強大,操作簡單。這也促使很多開源項目都集成它到自己項目中,不妨有谷歌的 GRR 項目、臉書的 osquery 項目等。
2 安裝
安裝 psutil 是有多種辦法:通過 pip 安裝,通過源碼方式安裝,通過下載 tar 壓縮包來安裝。其中通過 pip 的方式是最簡單的。
pip install psutil
# 如果出現(xiàn)因下載失敗導(dǎo)致安裝不上的情況,建議使用代理
pip --proxy http://代理ip:端口 install psutil
3 使用
前面說到 psutil 能監(jiān)聽到 CPU、內(nèi)存、磁盤、網(wǎng)絡(luò)、傳感器、進(jìn)程等,現(xiàn)在跟著我來學(xué)習(xí)下。
3.1 獲取 CPU 信息
1)我先獲取自己電腦 CPU 的核心數(shù),我電腦的 CPU 型號是 I5 4590。我通過搜索引擎得知該型號 CPU 是四核四線。
import psutil
psutil.cpu_count() # 獲取 CPU 的邏輯核心數(shù),默認(rèn)logical=True
psutil.cpu_count(logical=False) # 獲取 CPU 的物理核心數(shù)
>> 4
>> 4
# 這說明該 CPU 型號是真四核。
2)統(tǒng)計 CPU 的時間:
import psutil
psutil.cpu_times()
>> scputimes(user=9276.365234375, system=5034.5390625, idle=96077.0703125, interrupt=181.78796863555908, dpc=298.227108001709)
cpu_times() 返回的是帶有系統(tǒng)所有邏輯 CPU 運行時間的元組,單位是秒。返回元組的字段中有這幾個常用字段:
- user:執(zhí)行用戶進(jìn)程的時間,Linux 系統(tǒng)還包括訪客的時間
- system:執(zhí)行內(nèi)核進(jìn)程時間
- idle:閑置時間
- iowait(Linux 特有):等待 I/O 操作的時間
- irp(Linux 特有):打斷服務(wù)硬件的時間
- interrupt(Windows 特有):跟 irp 字段類似
- dpc(Windows 特有):服務(wù)延遲程序調(diào)用(DPCs)的時間
如果增加參數(shù) percpu=True, cpu_times() 會以列表的形式輸出每個邏輯 CPU 的時間。
3)獲取當(dāng)前 CPU 的利用率的百分比:
import psutil
psutil.cpu_percent()
>> 16.5
cpu_percent() 默認(rèn)的參數(shù)是 interval=None, percpu=False。當(dāng) interval 為0或者None時,表示的是 interval 時間內(nèi)的sys的利用率。當(dāng) percpu 為 False 表示所有邏輯 CPU 的使用率。
如果你想統(tǒng)計 15 秒中內(nèi),間隔 5 秒每個邏輯 CPU 的使用率,你可以這么做:
import psutil
for i in range(3):
psutil.cpu_percent(interval=5, percpu=True)
>> [9.1, 7.2, 7.2, 6.2]
>> [5.9, 3.8, 9.0, 8.4]
>> [12.3, 8.4, 3.4, 4.1]
4)獲取 CPU 頻率信息:
import psutil
psutil.cpu_freq()
>> [scpufreq(current=931.42925, min=0.0, max=3301.0)]
可知 cpu_freq() 返回的帶有所有邏輯 CPU 頻率的元組,包括當(dāng)前、最小和最大頻率。
3.2 獲取內(nèi)存信息
1)獲取物理內(nèi)存信息:
import psutil
psutil.virtual_memory()
>> svmem(total=8509177856,
available=1692307456, percent=80.1, used=6816870400, free=1692307456)
virtual_memory() 返回一個記載當(dāng)前電腦設(shè)備中可用的物理內(nèi)存信息的元組,單位是字節(jié)。從返回結(jié)果得知,當(dāng)前內(nèi)存總大小為 8509177856 Byte = 8 GB,可用內(nèi)存(閑置內(nèi)存) 1692307456 Byte = 1.6 GB,當(dāng)前內(nèi)存使用率為 80.1%。值得注意的是,內(nèi)存總大小不等于 Used 和 available 兩者的總和
available 字段在 Linux 系統(tǒng)下,計算方式則不同。available = free + buffers +cached。buffers 指的是 Linux 系統(tǒng)下的 Buffers 內(nèi)存, 表示塊設(shè)備(block device)所占用的緩存頁; 而 cached 指的是 Linux 系統(tǒng)下的 Cache 內(nèi)存,顧名思義為高速緩存。
2)獲取交換內(nèi)存信息:
import psutil
psutil.swap_memory()
>> sswap(total=17016451072, used=7407996928, free=9608454144, percent=43.5, sin=0, sout=0)
swap_memory() 獲取的是系統(tǒng)的交換內(nèi)存的信息,也就是我們常說的虛擬內(nèi)存。前面四個字段跟物理內(nèi)存含義一樣。而 sin 表示從磁盤調(diào)入是 swap 的大小, sout 表示從swap調(diào)出到 disk 的大小。這兩個字段在 Windows 系統(tǒng)下是沒有意義。因此,獲取結(jié)果為 0。
3.3 獲取磁盤信息
1)獲取磁盤分區(qū)信息:
import psutil
psutil.disk_partitions()
>>
[sdiskpart(device='C:\\', mountpoint='C:\\', fstype='NTFS', opts='rw,fixed'),
sdiskpart(device='D:\\', mountpoint='D:\\', fstype='NTFS', opts='rw,fixed'),
sdiskpart(device='E:\\', mountpoint='E:\\', fstype='NTFS', opts='rw,fixed'),
sdiskpart(device='F:\\', mountpoint='F:\\', fstype='NTFS', opts='rw,fixed')]
disk_partitions(all=False) 返回所有掛載磁盤分區(qū)信息的列表。有點類似 Linux 的 df 命令。各個字段的含有分別為:
- device:分區(qū)
- mountpoint:掛載點
- fstype:文件系統(tǒng)格式
- opts:掛載參數(shù)
大部分人都對 Windows 系統(tǒng)的分區(qū)信息了解比較多,對 Linux 系統(tǒng)所知甚少。因此,我給出虛擬機 Ubuntu 系統(tǒng)的磁盤信息, 方便大家學(xué)習(xí)。
[sdiskpart(device='/dev/sda1', mountpoint='/', fstype='ext4', opts='rw,errors=remount-ro'),
sdiskpart(device='/dev/sda2', mountpoint='', fstype='swap', opts='rw')]
2)獲取磁盤使用率:
disk_usage() 統(tǒng)計參數(shù)中路徑目錄的磁盤使用情況。它需要傳入一個路徑參數(shù);我傳入的參數(shù)是 "/",意味著獲取當(dāng)前整個硬盤的使用率。
import psutil
psutil.disk_usage('/')
>> sdiskusage(total=128033574912, used=81997942784, free=46035632128, percent=64.0)
3)獲取磁盤 IO 信息:
import psutil
psutil.disk_io_counters()
>> sdiskio(read_count=510749, write_count=505110, read_bytes=13353246720, write_bytes=8962015232, read_time=275, write_time=238)
disk_io_counters() 獲取當(dāng)前磁盤的 I/O 數(shù)據(jù)信息情況,也就是讀取和寫入信息。
3.4 獲取網(wǎng)絡(luò)信息
1)獲取整個系統(tǒng)的網(wǎng)絡(luò)信息
import psutil
psutil.disk_io_counters()
>> snetio(bytes_sent=77587966, bytes_recv=1113555204, packets_sent=500638, packets_recv=1048467, errin=0, errout=0, dropin=0, dropout=0)
disk_io_counters() 返回整個系統(tǒng)所有網(wǎng)卡(包括有線網(wǎng)卡、無限網(wǎng)卡)的進(jìn)行網(wǎng)絡(luò)讀寫數(shù)據(jù)、發(fā)包數(shù)等信息。個人認(rèn)為可以使用該方法來抓包。各個字段含義如下:
- bytes_sent:發(fā)送的字節(jié)數(shù)
- bytes_recv:收的字節(jié)數(shù)
- packets_sent:發(fā)送到數(shù)據(jù)包的個數(shù)
- packets_recv:接受的數(shù)據(jù)包的個數(shù)
- errout:發(fā)送數(shù)據(jù)包錯誤的總數(shù)
- dropin:接收時丟棄的數(shù)據(jù)包的總數(shù)
- dropout:發(fā)送時丟棄的數(shù)據(jù)包的總數(shù)( OSX 和 BSD 系統(tǒng)總是 0 )
如果增加參數(shù) pernic=True,disk_io_counters() 則會分別輸出各個網(wǎng)卡的網(wǎng)絡(luò)信息數(shù)據(jù)。
2)獲取當(dāng)前網(wǎng)絡(luò)連接信息
net_connections() 的作用跟系統(tǒng)命令 netstat -an 是一樣的。輸出當(dāng)前系統(tǒng)中所有類型的網(wǎng)絡(luò)連接數(shù)據(jù)。
import psutil
psutil.net_connections()
# 數(shù)據(jù)過多,我就不打印輸出結(jié)果。
3)獲取網(wǎng)絡(luò)接口信息
我們能通過 net_if_addrs() 函數(shù)來獲取到各個網(wǎng)卡的 IP 地址、網(wǎng)關(guān)等信息
import psutil
psutil.net_if_addrs()
4)獲取網(wǎng)絡(luò)接口狀態(tài)
net_if_stats() 獲取的是各個網(wǎng)卡的狀態(tài)信息,例如網(wǎng)卡是否處于激活狀態(tài)、當(dāng)前網(wǎng)速等
import psutil
psutil.net_if_stats()
3.5 獲取系統(tǒng)相關(guān)信息
- 獲取當(dāng)前登錄用戶信息
import psutil
psutil.users()
>> [suser(name='monkey', terminal=None, host='0.125.2.117', started=1515585444.0, p
id=None)]
users() 是返回當(dāng)前登錄用戶的信息。例如用戶的名稱 name、運行的終端 terminal, 在 Windows 系統(tǒng)下就是我們常說的 CMD 窗口、登錄的 IP 地址 host、登錄的時長 started以及登錄的進(jìn)程 pid,在 Windows 和 OpenBSD 系統(tǒng)中,該字段為 None。
2)獲取系統(tǒng)啟動時間
psutil.boot_time() 獲取的是系統(tǒng)啟動的時間點,而不會啟動消耗時長。
3.6 獲取進(jìn)程信息
如果查看當(dāng)前系統(tǒng)的所有進(jìn)程信息,你可以使用 test() 方法。跟 Windows 系統(tǒng)下的 tasklist 命令作用類似。
import psutil
psutil.test()
psutil 還提供一列的方法來查看系統(tǒng)進(jìn)程的信息。
import psutil
psutil.pids() # 列出所有進(jìn)程的PID
>> [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, 37, 38, 40, 41, 71, 199, 203, 218, 219, 220, 325, 327, 344, 345, 364, 417, 569, 764, 765, 817, 1042, 1058, 1070, 1110, 1186, 1194, 1197, 1209, 1211, 1213, 1215, 1217, 1219, 1228, 1229, 1231, 1298, 1643, 1745, 1794, 1796, 1829, 1846, 2004, 2039, 2154, 2175]
p = psutil.Process(2154) # 實例化一個Process對象,參數(shù)為一個進(jìn)程的PID
p.name() # 獲取進(jìn)程名
>> 'python'
p.exe() # 獲取進(jìn)程 bin 路徑, 即安裝路徑
>>'/usr/bin/python'
p.cwd() # 獲取進(jìn)程的工作目錄
>> '/root'
p.status() # 獲取進(jìn)程的運行狀態(tài)
>>'running'
p.create_time() # 獲取進(jìn)程創(chuàng)建時間點
>> 1427469528.49
p.cpu_times() # 獲取進(jìn)程使用 CPU 時間信息
>> pcputimes(user=0.081150144, system=0.053269812, children_user=0.0, children_system=0.0)
p.memory_info() # 獲取進(jìn)程使用的內(nèi)存
>> pmem(rss=8310784, vms=2481725440, pfaults=3207, pageins=18)
p.open_files() # 獲取進(jìn)程打開的文件
>> []
p.connections() # 獲取進(jìn)程相關(guān)網(wǎng)絡(luò)連接
>> []
p.num_threads() # 獲取進(jìn)程的線程數(shù)量
>> 1
上篇閱讀:Scrapy 框架插件之 IP 代理池
推薦閱讀:Python 實現(xiàn)識別弱圖片驗證碼