kill 程式時遇到的一件有意思的事情

鹹魚運維雜談發表於2023-04-06

案例現象

一般來講,我們在 kill 掉一個程式的時候通常有兩個選擇:

  1. 找到程式的 pid 號,然後執行 kill 命令

  2. 找到程式的名字,然後執行 pkill 命令

pkill 和 kill 命令都是向指定的程式傳送訊號,從而完成終結程式的操作,主要區別在於 pkill 命令與 pgrep 配套使用,能夠踢出指定終端使用者、同時根據 UID 和使用者名稱來終止程式


今天給大家分享一件我在使用 pkill 命令時遇到的比較有意思的事情


這臺機器上(Cent OS7)執行著一個程式 after_sleep60s_output




執行 pkill 命令


然後當我使用 ps 命令檢視的時候,我發現這個程式還在,而且返回了狀態碼 1


用 kill 命令試試,發現成功了


奇怪?為什麼用 pkill 命令 kill 不掉這個程式?

定位問題

透過 man pkill 我發現,pkill 命令是預設結合 pgrep 來使用的


pgrep 首先找出目標程式(running),然後 pkill 再根據 pgrep 的結果來 kill 目標程式


pgrep 找目標程式是透過獲取 /proc/[pid]/stat 檔案中的程式名來實現的,但是這個檔案中的程式名是有長度限制的—— 只有15個字元


Linux 中的每一個程式都維護了一個 struct_task_struct 結構體,這個結構體在 /usr/src/kernels/核心版本/include/linux/sched.h 裡面


這裡面有一個欄位定義了不包括路徑的可執行檔案的名字,最大長度是 16 bytes,除去最後一個留給 null 的,就只有最多 15 個字元


然後我們看一下上面例子中程式對應的 stat 檔案


可以看到檔案裡面的程式名字被截斷成了15個字元: after_sleep60s_


如果要使用 pkill 命令,正確方式如下:


你也可以加一個 -f 引數


這個引數會告訴 pkill 不去 /proc/[pid]/stat 檔案找程式,而是去 /proc/[pid]/cmdline

裡面找


這個檔案裡面包含了程式啟動的時候的完整命令,包括引數


解決問題

想要準確的 kill 掉一個程式,可以使用下面的方法:

  • pidof 命令獲取到程式對應的 PID,再使用 kill 命令

  • 使用 systemd 啟動的,透過 systemctl 命令來控制

  • 使用 pkill 命令的時候建議加上 -f 引數

最後附上相關 issue 連結:

1、


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70028327/viewspace-2944092/,如需轉載,請註明出處,否則將追究法律責任。

相關文章