這裡介紹如何在 Linux 中使用 ps
與 top
指令列出系統上最吃 CPU 與記憶體的程式。
作為 Linux 系統的管理者,時常都需要查看系統的負載狀況,如果系統中出現不正常的程式,吃掉太多的 CPU 或記憶體資源,就會影響系統的效能,太嚴重的話甚至會造成當機等狀況。
查閱系統負載(loading)與行程(process)的狀況最常用的就是
ps
與 top
這兩個指令,以下我們示範如何利用這兩個指令撰寫簡單的指令稿,自動找出系統上最耗費資源的程式。
ps
指令
這行指令可利用 ps
指令列出行程的一些基本資訊,按照每個行程所使用的記憶體排序後,列出排名最前面的幾個行程,也就是列出系統上最耗費記憶體的程式:
ps -eo pid,ppid,cmd,%mem,%cpu --sort=-%mem | head
這裡的 -e
參數是代表輸出所有行程的資訊,而 -o
參數則是用來指定輸出欄位用的,後面接著所有想要輸出的欄位名稱,這裡我們讓 ps
輸出以下幾個欄位:
pid
:行程 ID(process ID)。ppid
:父行程 ID(parent process ID)。cmd
:程式名稱。%mem
:記憶體使用量(百分比)。%cpu
:CPU 使用量(百分比)。
而 --sort
參數則是指定排序的依據欄位,預設會依照數值由小到大排序,若要由大到小的方式排序的話,可以在欄位名稱前加上一個負號。以這個例子來說,我們將排序的欄位指定為 -%mem
,這樣就可以依照記憶體使用量,從大到小排序。
最後將 ps
的輸出以 Linux 管線(pipe)導向至 head
,只保留前 10 行的資料,其餘的都丟棄,以下是輸出的結果。
PID PPID CMD %MEM %CPU 2124 1278 /usr/lib/chromium-browser/c 25.0 14.4 1446 1278 /usr/lib/chromium-browser/c 21.5 15.4 1253 1 /usr/lib/chromium-browser/c 19.2 13.0 1328 1278 /usr/lib/chromium-browser/c 7.6 2.9 1392 1278 /usr/lib/chromium-browser/c 7.6 0.5 732 669 /usr/bin/X :0 -seat seat0 - 5.7 2.0 1060 1 /usr/lib/arm-linux-gnueabih 1.8 0.0 1086 758 pcmanfm --desktop --profile 1.5 0.2 1085 758 lxpanel --profile LXDE-pi 1.5 0.3
若要找出系統上最耗費 CPU 的程式,也是使用類似的指令,只是在排序時,將排序的欄位換成 CPU 使用量:
ps -eo pid,ppid,cmd,%mem,%cpu --sort=-%cpu | head
輸出為:
PID PPID CMD %MEM %CPU 1446 1278 /usr/lib/chromium-browser/c 33.8 19.6 1253 1 /usr/lib/chromium-browser/c 19.6 12.1 2124 1278 /usr/lib/chromium-browser/c 20.5 11.2 2555 1 gvim -f 2.5 6.3 1328 1278 /usr/lib/chromium-browser/c 6.1 3.0 732 669 /usr/bin/X :0 -seat seat0 - 7.1 2.2 1392 1278 /usr/lib/chromium-browser/c 6.7 0.5 1085 758 lxpanel --profile LXDE-pi 1.5 0.3 1060 1 /usr/lib/arm-linux-gnueabih 1.3 0.1
top
指令
top
指令是一個互動式(interactive)的工具,可以顯示即時的系統負載狀態,而它也可以用於指令稿中,輸出各種系統資訊。
這行指令可將系統行程以記憶體的使用賴排序後,以 batch 模式輸出報表,並且只保留前 10 個最耗費記憶體的行程:
top -b -o +%MEM | head -n 17
其中 -b
參數是 batch 模式的意思,而 -o
參數則是設定以記憶體用量來排序行程,最後面的 head -n 17
則是篩選 top
輸出的文字內容,只保留前 17 行,剩餘的內容則捨棄。輸出會類似這樣:
top - 14:54:24 up 7 min, 3 users, load average: 0.99, 1.52, 0.87 Tasks: 164 total, 1 running, 163 sleeping, 0 stopped, 0 zombie %Cpu(s): 17.0 us, 2.7 sy, 0.1 ni, 68.2 id, 11.9 wa, 0.0 hi, 0.1 si, 0.0 st KiB Mem: 947732 total, 757336 used, 190396 free, 9892 buffers KiB Swap: 1914876 total, 8588 used, 1906288 free. 288704 cached Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 1392 pi 20 0 557272 206424 90776 S 0.0 21.8 1:46.69 chromium-b+ 1223 pi 20 0 674816 194156 126276 S 0.0 20.5 1:42.47 chromium-b+ 1490 pi 20 0 459804 164732 76728 S 5.6 17.4 0:44.62 chromium-b+ 732 root 20 0 245288 84204 52640 S 0.0 8.9 0:15.90 Xorg 1353 pi 20 0 366756 82720 47504 S 0.0 8.7 0:07.21 chromium-b+ 1357 pi 20 0 355952 77080 55684 S 0.0 8.1 0:09.30 chromium-b+ 1293 pi 20 0 354048 73844 51024 S 0.0 7.8 0:13.32 chromium-b+ 1084 pi 20 0 105612 29380 24928 S 0.0 3.1 0:02.43 lxpanel 1243 pi 20 0 189852 28780 23760 S 0.0 3.0 0:00.16 chromium-b+ 1086 pi 20 0 147124 26976 24256 S 0.0 2.8 0:01.63 pcmanfm
若要找出最耗費 CPU 資源的行程,則改用 CPU 使用量來排序即可:
top -b -o +%CPU | head -n 17
輸出會類似這樣:
top - 15:12:19 up 25 min, 4 users, load average: 1.66, 1.43, 1.08 Tasks: 173 total, 1 running, 172 sleeping, 0 stopped, 0 zombie %Cpu(s): 13.4 us, 1.8 sy, 0.1 ni, 79.0 id, 5.6 wa, 0.0 hi, 0.1 si, 0.0 st KiB Mem: 947732 total, 870680 used, 77052 free, 5588 buffers KiB Swap: 1914876 total, 148740 used, 1766136 free. 267360 cached Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 1959 pi 20 0 327404 49012 22340 S 107.0 5.2 0:02.75 java 1490 pi 20 0 459804 99192 49040 S 5.9 10.5 1:26.10 chromium-b+ 1809 pi 20 0 576268 162008 55228 S 5.9 17.1 0:57.49 chromium-b+ 1969 pi 20 0 7052 2380 2060 R 5.9 0.3 0:00.03 top 1 root 20 0 22948 2768 2120 S 0.0 0.3 0:04.85 systemd 2 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kthreadd 3 root 20 0 0 0 0 S 0.0 0.0 0:00.14 ksoftirqd/0 5 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 kworker/0:+ 6 root 20 0 0 0 0 S 0.0 0.0 0:02.67 kworker/u8+ 7 root 20 0 0 0 0 S 0.0 0.0 0:01.41 rcu_sched
通常如果發現異常的程式佔用了太多的 CPU 或記憶體,最好的處理方式就是把這些程式正常關閉,如果程式當掉無法關閉的話,就可以使用 kill
或 killall
這類的指令,中止不正常程式的執行,由於上面的報表中都有每個程式的 PID,所以使用 PID 來中止特定的程式是最直接的方式。
假設我們想要中止的程式其 PID 是 1959
,首先我們會用一般的方式嘗試讓程式正常結束:
kill 1959
如過執行這行之後,沒有效果的話,再嘗試強制關閉程式:
kill -9 1959
這兩種 kill
指令是最常見的處理方式。