想知道 Linux 在跑哪些鬼,就用 man ps

ps

預設情況下,只列出同一個終端機(terminal, tty)觸發請求,現行使用者 – 也就是「你」 – 的所有進程(相同的 euid, effective user ID)。

加上 a 參數,就能列出不同終端機下「所有的」進程:

ps a

來看一下這個參數的解釋

a      Lift the BSD-style "only yourself" restriction, which is 
imposed upon the set of all processes when some BSD-style 
(without "-") options are used or when the ps personality setting 
is BSD-like.  The set of processes selected in this manner is in 
addition to the set of processes selected by other means.  An 
alternate description is that this option causes ps to list all 
processes with a terminal (tty), or to list all processes when 
used together with the x option.

這種沒有加上一個橫槓(-)的,印出來的會是 BSD 格式。想要顯示 UNIX(POSIX) 格式,就得在參數前加上一個橫槓(-),想要顯示 GNU 格式,就得在參數前加上兩個橫槓(–)。

但還是有很多進程沒有被列出來,因為不是由終端機觸發請求的,像是 daemon。所以加上 x 參數,就會解除「由終端機觸發」的限制:

ps x

這個參數的解釋

x      Lift the BSD-style "must have a tty" restriction, which is 
imposed upon the set of all processes when some BSD-style 
(without "-") options are used or when the ps personality setting 
is BSD-like.  The set of processes selected in this manner is in 
addition to the set of processes selected by other means.  An 
alternate description is that this option causes ps to list all 
processes owned by you (same EUID as ps), or to list all processes 
when used together with the a option.

指定輸出格式的參數

常常使用 ps aux,u 又是什麼意思呢?

用來顯示使用者導向的格式

ps u

什麼叫做使用者導向?我也不曉得,只知道下面這些資訊就是它所謂的使用者導向:

USER        命令的執行者
PID         進程 ID
CPU         進程的 CPU 利用率。CPU 的使用時間/進程執行的時間。
MEM         進程常駐集大小在主機實體記憶體的占比。
VSZ         虛擬記憶體大小(KB)
RSS         常駐集大小(resident set size),一個任務已經使用且非交換(swap)的實體記憶體。(KB)
TTY         控制終端機(controlling terminal)
STAT        多字元(multi-character)進程狀態。狀態碼解釋請洽 PROCESS STATE CODES 章節。
START       命令開始的時間。如果在 24 小時內,則時間格式為 HH:MM,否則是 Mmm:DD (Mmm 是月份字母)
TIME        累計的 cpu + user + system 時間。
COMMAND     命令

STAT 狀態碼說明

詳細的還是自行去查 PROCESS STATE CODE ,以下只列出部分常見的。

D    uninterruptible sleep (usually IO)
R    running or runnable (on run queue)
S    interruptible sleep (waiting for an event to complete)

接下來這邊的狀態碼,是 BSD 樣式才有:

<    high-priority (not nice to other users)
N    low-priority (nice to other users)
L    has pages locked into memory (for real-time and custom IO)
s    is a session leader
l    is multi-threaded (using CLONE_THREAD, like NPTL pthreads do)
+    is in the foreground process group

用來決定輸出格式的參數還有很多種,像是 v, j , -l ,-o,以下只針對目前有興趣的做補充。

用來顯示虛擬記憶體格式

ps v

欄位跟 u 重複的就不贅述:

PID
TTY
STAT
TIME
MAJFL       這個進程已經發生的主要錯誤頁數   
TRS         程式碼常駐集大小(text/code resident set size)
DRS         資料常駐集大小(data resident set size)
RSS
MEM
COMMAND

如果要說吸引力最大的,莫過於接下來這個參數,因為它可以讓我們自定輸出欄位。

ps -o pid,ppid,lwp,nlwp

要注意,要加上橫槓了,然後後面接想要的自定欄位串就可以了。至於有哪些欄位可以自定,就可以 man ps 去看看 STANDARD FORMAT SPECIFIERS 這個章節的描述。

其他覺得有趣的參數

用來顯示 UNIX(POSIX) 格式的參數

顯示所有進程

ps -e

顯示不包含 session leader 的所有進程

ps -d

那如果只想要顯示所有的 session leader 進程呢?這時候可以搭配一個很有趣的參數 -N,意義是「反向」。

ps -Nd

其他還有很多好用的參數,只是目前我會用到的還沒那麼多,等到需要的時候再查囉。

什麼是 Session Leader Process

其實說直白一點就是 SID (session id) 等於 PID (process id) 的進程,就是 session leader process。可以透過下列指令查看:

ps axo pid,ppid,pgid,sid,comm

還有一種 id 叫做 PGID ( process group id),其實跟 SID 都是用來分類進程,主要目的是為了方便管理進程。例如:一口氣砍掉相關的進程。SID 是大分類,GID 是小分類,所以 SID 可以包含多種 GID 的進程。

在一般人跟電腦的互動來說,session leader 可以視為對話(session)的起點,所以通常是 shell process,所以只要在同一個 shell 啟動的程式,就會被歸類在同一個對話裡。像是我故意啟動一個 vim 編輯一個檔案:

vim tmp.txt

再按下 ctrl+z 先把工作放到背景,再來查看 sid 狀態:

ps o pid,ppid,pgid,sid,comm
PID PPID PGID SID COMMAND
2414 702 2414 2414 bash
6839 6838 6839 6839 bash
6947 6839 6947 6839 vim
6949 6839 6949 6839 ps

可以看到 ps 和 vim 都是相同的 SID,因為都是在同一個 bash shell 下的指令。注意一下此時兩個進程所對應的 PGID 是不同的。

process group 則是透過管線(|)串接的同一批指令,會分類在同一個 group 裡,所以將上述指令利用管線串接:

vim tmp.txt | ps o pid,ppid,pgid,sid,comm
Vim: 注意: 輸出不是終端機(螢幕)
PID PPID PGID SID COMMAND
2414 702 2414 2414 bash
6839 6838 6839 6839 bash
6970 6839 6970 6839 vim
6971 6839 6970 6839 ps

就會看到擁有相同的 PGID 啦!(註:這兩個命令串接起來之後的畫面怪怪的,其實輸出是到 vim,只是螢幕看起來不像正常的 vim,請用 :q 離開即可。)

參考