在 Linux 上使用 kill 和 killall 命令來管理進(jìn)程
在 Linux 中,每個程序和守護(hù)程序都是一個“進(jìn)程”。大多數(shù)進(jìn)程代表一個正在運行的程序。而另外一些程序可以派生出其他進(jìn)程,比如說它會偵聽某些事件的發(fā)生,然后對其做出響應(yīng)。并且每個進(jìn)程都需要一定的內(nèi)存和處理能力。你運行的進(jìn)程越多,所需的內(nèi)存和 CPU 使用周期就越多。在老式電腦(例如我使用了 7 年的筆記本電腦)或輕量級計算機(例如樹莓派)上,如果你關(guān)注過后臺運行的進(jìn)程,就能充分利用你的系統(tǒng)。
你可以使用 ps 命令來查看正在運行的進(jìn)程。你通常會使用 ps 命令的參數(shù)來顯示出更多的輸出信息。我喜歡使用 -e 參數(shù)來查看每個正在運行的進(jìn)程,以及 -f 參數(shù)來獲得每個進(jìn)程的全部細(xì)節(jié)。以下是一些例子:
$ psPID TTY TIME CMD88000 pts/000:00:00bash88052 pts/000:00:00ps88053 pts/000:00:00head
$ ps-e | headPID TTY TIME CMD1? 00:00:50systemd2? 00:00:00 kthreadd3? 00:00:00 rcu_gp4? 00:00:00 rcu_par_gp6? 00:00:02 kworker/0:0H-events_highpri9? 00:00:00 mm_percpu_wq10? 00:00:01 ksoftirqd/011? 00:00:12 rcu_sched12? 00:00:00 migration/0
$ ps-ef | headUID PID PPID C STIME TTY TIME CMDroot 10013:51? 00:00:50/usr/lib/systemd/systemd--switched-root --system --deserialize 36root 20013:51? 00:00:00[kthreadd]root 32013:51? 00:00:00[rcu_gp]root 42013:51? 00:00:00[rcu_par_gp]root 62013:51? 00:00:02[kworker/0:0H-kblockd]root 92013:51? 00:00:00[mm_percpu_wq]root 102013:51? 00:00:01[ksoftirqd/0]root 112013:51? 00:00:12[rcu_sched]root 122013:51? 00:00:00[migration/0]
最后的例子顯示最多的細(xì)節(jié)。在每一行,UID(用戶 ID)顯示了該進(jìn)程的所有者。PID(進(jìn)程 ID)代表每個進(jìn)程的數(shù)字 ID,而 PPID(父進(jìn)程 ID)表示其父進(jìn)程的數(shù)字 ID。在任何 Unix 系統(tǒng)中,進(jìn)程是從 1 開始編號,是內(nèi)核啟動后運行的第一個進(jìn)程。在這里,systemd 是第一個進(jìn)程,它催生了 kthreadd,而 kthreadd 還創(chuàng)建了其他進(jìn)程,包括 rcu_gp、rcu_par_gp 等一系列進(jìn)程。

使用 kill 命令來管理進(jìn)程
系統(tǒng)會處理大多數(shù)后臺進(jìn)程,所以你不需要操心這些進(jìn)程。你只需要關(guān)注那些你所運行的應(yīng)用創(chuàng)建的進(jìn)程。雖然許多應(yīng)用一次只運行一個進(jìn)程(如音樂播放器、終端模擬器或游戲等),但其他應(yīng)用則可能創(chuàng)建后臺進(jìn)程。其中一些應(yīng)用可能當(dāng)你退出后還在后臺運行,以便下次你使用的時候能快速啟動。
當(dāng)我運行 Chromium(作為谷歌 Chrome 瀏覽器所基于的開源項目)時,進(jìn)程管理便成了問題。Chromium 在我的筆記本電腦上運行非常吃力,并產(chǎn)生了許多額外的進(jìn)程?,F(xiàn)在我僅打開五個選項卡,就能看到這些 Chromium 進(jìn)程:
$ ps-ef | fgrep chromiumjhall 66221[...] /usr/lib64/chromium-browser/chromium-browser [...]jhall 66230[...] /usr/lib64/chromium-browser/chromium-browser [...][...]jhall 66861[...] /usr/lib64/chromium-browser/chromium-browser [...]jhall 6732965132015:45 pts/000:00:00grep-F chromium
我已經(jīng)省略一些行,其中有 20 個 Chromium 進(jìn)程和一個正在搜索 “chromium" 字符的 grep 進(jìn)程。
$ ps-ef | fgrep chromium | wc-l21
但是在我退出 Chromium 之后,這些進(jìn)程仍舊運行。如何關(guān)閉它們并回收這些進(jìn)程占用的內(nèi)存和 CPU 呢?
kill 命令能讓你終止一個進(jìn)程。在最簡單的情況下,你告訴 kill 命令終止你想終止的進(jìn)程的 PID。例如,要終止這些進(jìn)程,我需要對 20 個 Chromium 進(jìn)程 ID 都執(zhí)行 kill 命令。一種方法是使用命令行獲取 Chromium 的 PID,而另一種方法針對該列表運行 kill:
$ ps-ef | fgrep /usr/lib64/chromium-browser/chromium-browser | awk '{print $2}'662216623066239662576626266283662846628566324663376636066370663866640266503665396659566734668486686169702$ ps-ef | fgrep /usr/lib64/chromium-browser/chromium-browser | awk '{print $2}'> /tmp/pids$ kill $(cat/tmp/pids)
最后兩行是關(guān)鍵。第一個命令行為 Chromium 瀏覽器生成一個進(jìn)程 ID 列表。第二個命令行針對該進(jìn)程 ID 列表運行 kill 命令。

介紹 killall 命令
一次終止多個進(jìn)程有個更簡單方法,使用 killall 命令。你或許可以根據(jù)名稱猜測出,killall 會終止所有與該名字匹配的進(jìn)程。這意味著我們可以使用此命令來停止所有流氓 Chromium 進(jìn)程。這很簡單:
$ killall/usr/lib64/chromium-browser/chromium-browser
但是要小心使用 killall。該命令能夠終止與你所給出名稱相匹配的所有進(jìn)程。這就是為什么我喜歡先使用 ps -ef 命令來檢查我正在運行的進(jìn)程,然后針對要停止的命令的準(zhǔn)確路徑運行 killall。
你也可以使用 -i 或 --interactive 參數(shù),來讓 killkill 在停止每個進(jìn)程之前提示你。
killall 還支持使用 -o 或 --older-than 參數(shù)來查找比特定時間更早的進(jìn)程。例如,如果你發(fā)現(xiàn)了一組已經(jīng)運行了好幾天的惡意進(jìn)程,這將會很有幫助。又或是,你可以查找比特定時間更晚的進(jìn)程,例如你最近啟動的失控進(jìn)程。使用 -y 或 --young-than 參數(shù)來查找這些進(jìn)程。

其他管理進(jìn)程的方式
進(jìn)程管理是系統(tǒng)維護(hù)重要的一部分。在我作為 Unix 和 Linux 系統(tǒng)管理員的早期職業(yè)生涯中,殺死非法作業(yè)的能力是保持系統(tǒng)正常運行的關(guān)鍵。在如今,你可能不需要親手在 Linux 上的終止流氓進(jìn)程,但是知道 kill 和 killall 能夠在最終出現(xiàn)問題時為你提供幫助。
你也能尋找其他方式來管理進(jìn)程。在我這個案例中,我并不需要在我退出瀏覽器后,使用 kill 或 killall 來終止后臺 Chromium 進(jìn)程。在 Chromium 中有個簡單設(shè)置就可以進(jìn)行控制:

Chromium background processes setting
不過,始終關(guān)注系統(tǒng)上正在運行哪些進(jìn)程,并且在需要的時候進(jìn)行干預(yù)是一個明智之舉。


