跳至內容

Linux如何殺掉殭屍進程

更新時間
连续6年不跑路的安全速度最适合国人VPN
连续6年不跑路的安全速度最适合国人VPN

本文主要介紹linux殭屍進程以及清理殭屍進程的方法。

1、什麼是殭屍進程?

Linux中的殭屍進程(Zombie processes)有時也被稱爲失效或死亡進程。

它們是已執行完畢的進程,但其條目並未從進程表中刪除。

1.1 進程狀態

Linux 會維護一個進程表,其中包含所有正在運行的進程及其狀態。

下面簡要介紹一下各種進程狀態: 

(1)Running (R): 表示這些進程目前正在運行或可運行,用字母 R 表示。需要說明:進程是 R 狀態,不代表正在運行,代表可被調度。換句話說,進程只有是 R 狀態纔可被調度,其他狀態要先轉爲 R 狀態,才能被 OS 調度;

(2)Waiting (S/D): 表示這些進程正在等待事件完成或某種資源就緒,用字母 S/D 表示,等待可以是可中斷休眠 S(interruptible sleep) 或不中斷休眠 D (uninterruptible sleep);

(3)Stopped (T):  可以通過發送 SIGSTOP 信號給進程來停止(T)進程。這個被暫停的進程可以通過發送 SIGCONT 信號讓進程繼續運行。

(4)Zombie (Z): 一個比較特殊的狀態。當子進程退出並且父進程沒有讀取到子進程退出的返回代碼時,就會產生僵死(屍)進程。僵死進程會以終止狀態保持在進程表中,並且會一直在等待父進程讀取退出狀態代碼。所以,只要子進程退出,父進程還在運行,但父進程沒有讀取子進程狀態,子進程進入 Z 狀態。

1.2 殭屍進程是如何產生的?

當一個進程完成其工作時,Linux 內核會通過發送 SIGCHLD 信號通知其父進程。然後,父進程執行 wait() 系統調用,讀取子進程的狀態並讀取其退出代碼。這會清除進程表中子進程條目,從而結束進程。

但是,如果父進程沒有在創建子進程時執行 wait() 系統調用,就不會進行適當的清理。在這種情況下,父進程無法監控子進程的狀態變化,最終會忽略 SIGCHLD 信號。這將導致已完成進程的殭屍狀態留在進程表中,從而使其作爲殭屍進程出現在進程列表中。

另一種情況是,父進程無法處理或接收來自子進程的 SIGCHLD 信號,這種情況也會導致殭屍的產生。

1.3 搜索殭屍進程

使用 ps 命令來檢索殭屍進程列表:

ps uxUSER PID %CPU %MEMVSZ RSS TTYSTAT START TIME COMMANDshubh90.00.0169162760 tty1 SDec19 0:00 /bin/bash --loginshubh1080.00.00 0 tty1 Z16:25 0:00 [zombie] <defunct> shubh1090.00.0173841928 tty2 R16:25 0:00 ps ux</defunct>
登錄後複製

從輸出中可以看出,STAT 列中的 Z 即爲殭屍進程狀態,或者使用 awk 命令根據 Z 進程狀態進一步過濾輸出:

ps ux | awk '{if($8=="Z") print}'shubh 1080.00.00 0 tty1 Z16:25 0:00 [zombie] <defunct></defunct>
登錄後複製

另一種方法是使用 top 命令:

topTasks: 8 total, 1 running, 6 sleeping, 0 stopped, 1 zombie%Cpu(s):0.7 us,1.6 sy,0.0 ni, 96.5 id,0.0 wa,1.2 hi,0.0 si,0.0 stKiB Mem :8269412 total,3161228 free,4878832 used, 229352 buff/cacheKiB Swap: 15483260 total, 14830144 free, 653116 used.3256848 avail MemPID USERPRNIVIRTRESSHR S%CPU %MEM TIME+ COMMAND1 root20 08936192148 S 0.00.0 0:00.17 init8 root20 08936 96 56 S 0.00.0 0:00.00 init9 shubh 20 0 16916 2748 2640 S 0.00.0 0:00.43 bash 76 root20 08936224184 S 0.00.0 0:00.00 init 77 shubh 20 0 16784 3432 3332 S 0.00.0 0:00.35 bash161 shubh 20 0 000 Z 0.00.0 0:00.00 zombie162 shubh 20 0 17624 2084 1508 R 0.00.0 0:00.00 top
登錄後複製

top 除了輸出其他詳細信息外,還可以在輸出頂部的摘要中看到殭屍進程的數量。

2、清理殭屍進程

我們無法真正殺死殭屍進程,因爲本身它已經結束了。但是,可以使用一些方法來清理殭屍進程。

2.1 使用 SIGCHLD 信號

可以手動向殭屍進程的父進程發送 SIGCHLD 信號。這樣,父進程就會主動觸發 wait()系統調用,從而從進程表中清除已失效的子進程。

找到殭屍進程的父進程 PID: 

ps -A -ostat,pid,ppid | grep -e '[zZ]'Z108 103
登錄後複製

這裏 108 表示殭屍進程 PID,103 表示其父進程 PID,接下來,可以使用 kill 命令向父進程發送 SIGCHLD 信號:

kill -s SIGCHLD 103
登錄後複製

不過,並不能保證向父進程發送 SIGCHLD 信號就能殺死殭屍進程。只有在父進程可以處理 SIGCHLD 信號的情況下,它纔會起作用。

2.2 kill 父過程

如果上一節的方法無法清除失效進程,就需要考慮殺死其父進程:

kill -9 103
登錄後複製

但是,殺死父進程會影響其所有子進程。因此,應該格外謹慎,在殺死父進程之前必須確定其影響。

如果存在大量殭屍進程,或者殭屍進程的父進程是 init 進程(pid=1),可以考慮重啓系統來清除失效進程。

以上就是Linux如何殺掉殭屍進程的詳細內容,更多請關注本站其它相關文章!

更新時間

發表留言

請注意,留言須先通過審核才能發佈。