一、簡介
psutil 全稱是 process and system utilities。psutil 是一個跨平台的應用於系統監控、分析、以及對系統進程進行一定管理的 Python 第三方庫。它不僅能夠輕松獲取系統中正常運行的進程和系統利用率(例如 CPU、內存、磁盤、網絡等)信息,還實現了跟 UNIX 系統命令行工具類似的功能。可以說是運維工作的“必備品”。運維工程師經常使用 Python 編寫腳本程序來做監控系統運行的狀態。如果自己手動使用 Python 的標准庫執行系統命令來獲取信息,會顯得非常麻煩。既要兼容不同操作系統,又要自己處理解析信息。為了解決的痛點問題,psutil 就橫空出世。它的出現無疑是運維工程師的福音。運維小伙伴通過它執行一兩行代碼即可實現系統監控。
它功能強大,操作簡單。這也促使很多開源項目都集成它到自己項目中,不妨有谷歌的 GRR 項目、臉書的 osquery 項目等。
github 地址:https://github.com/giampaolo/psutil
二、安裝
安裝 psutil 是有多種辦法:通過 pip 安裝,通過源碼方式安裝,通過下載 tar 壓縮包來安裝。其中通過 pip 的方式是最簡單的。
pip install psutil
三、使用
3.1 獲取CPU信息
- 我先獲取自己電腦 CPU 的核心數,我電腦的 CPU 型號是 I5 4590。我通過搜索引擎得知該型號 CPU 是四核四線。
import psutil psutil.cpu_count() # 獲取 CPU 的邏輯核心數,默認logical=True psutil.cpu_count(logical=False) # 獲取 CPU 的物理核心數 >> 4 >> 4 # 這說明該 CPU 型號是真四核。
- 統計CPU的時間
import psutil psutil.cpu_times() >> scputimes(user=9276.365234375, system=5034.5390625, idle=96077.0703125, interrupt=181.78796863555908, dpc=298.227108001709)
cpu_times() 返回的是帶有系統所有邏輯 CPU 運行時間的元組,單位是秒。返回元組的字段中有這幾個常用字段:
-
- user:執行用戶進程的時間,Linux 系統還包括訪客的時間
- system:執行內核進程時間
- idle:閑置時間
- iowait(Linux 特有):等待 I/O 操作的時間
- irp(Linux 特有):打斷服務硬件的時間
- interrupt(Windows 特有):跟 irp 字段類似
- dpc(Windows 特有):服務延遲程序調用(DPCs)的時間
如果增加參數 percpu=True, cpu_times() 會以列表的形式輸出每個邏輯 CPU 的時間。
- 獲取當前 CPU 的利用率的百分比:
import psutil psutil.cpu_percent() >> 16.5
cpu_percent() 默認的參數是 interval=None, percpu=False。當 interval 為0或者None時,表示的是 interval 時間內的sys的利用率。當 percpu 為 False 表示所有邏輯 CPU 的使用率。
如果你想統計 15 秒中內,間隔 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]
- 獲取 CPU 頻率信息:
import psutil psutil.cpu_freq() >> [scpufreq(current=931.42925, min=0.0, max=3301.0)]
可知 cpu_freq() 返回的帶有所有邏輯 CPU 頻率的元組,包括當前、最小和最大頻率。
3.2 獲取內存信息
- 獲取物理內存信息:
import psutil psutil.virtual_memory() >> svmem(total=8509177856, available=1692307456, percent=80.1, used=6816870400, free=1692307456)
virtual_memory() 返回一個記載當前電腦設備中可用的物理內存信息的元組,單位是字節。從返回結果得知,當前內存總大小為 8509177856 Byte = 8 GB,可用內存(閑置內存) 1692307456 Byte = 1.6 GB`,當前內存使用率為 80.1%。值得注意的是,內存總大小不等於 Used 和 available 兩者的總和
available 字段在 Linux 系統下,計算方式則不同。available = free + buffers +cached。buffers 指的是 Linux 系統下的 Buffers 內存, 表示塊設備(block device)所占用的緩存頁; 而 cached 指的是 Linux 系統下的 Cache 內存,顧名思義為高速緩存。
- 獲取交換內存信息:
import psutil psutil.swap_memory() >> sswap(total=17016451072, used=7407996928, free=9608454144, percent=43.5, sin=0, sout=0)
swap_memory() 獲取的是系統的交換內存的信息,也就是我們常說的虛擬內存。前面四個字段跟物理內存含義一樣。而 sin 表示從磁盤調入是 swap 的大小, sout 表示從swap調出到 disk 的大小。這兩個字段在 Windows 系統下是沒有意義。因此,獲取結果為 0。
3.3 獲取磁盤信息
- 獲取磁盤分區信息:
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) 返回所有掛載磁盤分區信息的列表。有點類似 Linux 的 df 命令。各個字段的含有分別為:
-
- device:分區
- mountpoint:掛載點
- fstype:文件系統格式
- opts:掛載參數
大部分人都對 Windows 系統的分區信息了解比較多,對 Linux 系統所知甚少。因此,我給出虛擬機 Ubuntu 系統的磁盤信息, 方便大家學習。
[sdiskpart(device='/dev/sda1', mountpoint='/', fstype='ext4', opts='rw,errors=remount-ro'), sdiskpart(device='/dev/sda2', mountpoint='', fstype='swap', opts='rw')]
- 獲取磁盤使用率
disk_usage() 統計參數中路徑目錄的磁盤使用情況。它需要傳入一個路徑參數;我傳入的參數是 "/",意味着獲取當前整個硬盤的使用率。
import psutil psutil.disk_usage('/') >> sdiskusage(total=128033574912, used=81997942784, free=46035632128, percent=64.0)
- 獲取磁盤 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)
3.4 獲取網絡信息
- 獲取整個系統的網絡信息
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() 返回整個系統所有網卡(包括有線網卡、無限網卡)的進行網絡讀寫數據、發包數等信息。個人認為可以使用該方法來抓包。各個字段含義如下:
-
- bytes_sent:發送的字節數
- bytes_recv:收的字節數
- packets_sent:發送到數據包的個數
- packets_recv:接受的數據包的個數
- errout:發送數據包錯誤的總數
- dropin:接收時丟棄的數據包的總數
- dropout:發送時丟棄的數據包的總數( OSX 和 BSD 系統總是 0 )
如果增加參數 pernic=True,disk_io_counters() 則會分別輸出各個網卡的網絡信息數據。
- 獲取當前網絡連接信息
net_connections() 的作用跟系統命令 "netstat -an" 是一樣的。輸出當前系統中所有類型的網絡連接數據。
import psutil psutil.net_connections() # 數據過多,我就不打印輸出結果。
- 獲取網絡接口信息
我們能通過 net_if_addrs() 函數來獲取到各個網卡的 IP 地址、網關等信息
import psutil psutil.net_if_addrs()
- 獲取網絡接口狀態
net_if_stats() 獲取的是各個網卡的狀態信息,例如網卡是否處於激活狀態、當前網速等
import psutil psutil.net_if_addrs()
3.5 獲取系統相關信息
- 獲取當前登錄用戶信息
import psutil psutil.users() >> [suser(name='monkey', terminal=None, host='0.125.2.117', started=1515585444.0, p id=None)]
users() 是返回當前登錄用戶的信息。例如用戶的名稱 name、運行的終端 terminal, 在 Windows 系統下就是我們常說的 CMD 窗口、登錄的 IP 地址 host、登錄的時長 started 以及登錄的進程 pid,在 Windows 和 OpenBSD 系統中,該字段為 None。
- 獲取系統啟動時間
psutil.boot_time() 獲取的是系統啟動的時間點,而不會啟動消耗時長。
3.6 獲取進程信息
- 如果查看當前系統的所有進程信息,你可以使用 process_iter() 方法。跟 Windows 系統下的 "tasklist" 命令作用類似。
import psutil for each_process in psutil.process_iter(): print(each_process,each_process.name(),each_process.pid)
運行結果:
psutil.Process(pid=0, name='System Idle Process', started='2019-12-31 12:54:20') System Idle Process 0 psutil.Process(pid=4, name='System', started='2019-12-31 12:54:20') System 4 psutil.Process(pid=408, name='svchost.exe', started='2019-12-31 12:54:34') svchost.exe 408 psutil.Process(pid=524, name='smss.exe', started='2019-12-31 12:54:32') smss.exe 524 psutil.Process(pid=608, name='svchost.exe', started='2019-12-31 12:54:34') svchost.exe 608 psutil.Process(pid=620, name='fontdrvhost.exe', started='2019-12-31 12:54:34') fontdrvhost.exe 620
- 獲取進程ID
diskmark_pid = None for each_process in psutil.process_iter(): if each_process.name() == tool_name: diskmark_pid = each_process.pid
- 獲取進程相關信息
- 進程名
diskmark_pid.name()
-
- 獲取進程bin路徑,即安裝路徑
diskmark_pid.exe()
-
- 獲取進程的工作目錄
diskmark_pid.cwd()
-
- 獲取進程的工作狀態
diskmark_pid.status()
-
- 獲取進程創建時間點
diskmark_pid.create_time()
-
-
獲取進程使用 CPU 時間信息
-
diskmark_pid.cpu_times()
-
- 獲取進程使用的內存
diskmark_pid.memory_info()
-
- 獲取進程打開的文件
diskmark_pid.open_files()
-
- 獲取進程相關網絡連接
diskmark_pid.connections()
-
- 獲取進程的線程數量
diskmark_pid.num_threads()
參考文檔1:https://cloud.tencent.com/developer/article/1187789
參考文檔2:https://blog.csdn.net/chenyi7243/article/details/100630008