這裡介紹如何在 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

ps 指令輸出

若要找出系統上最耗費 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

ps 指令輸出

 

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

top 指令輸出

若要找出最耗費 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 指令是最常見的處理方式。