有沒有不包括 sudo 程序的 sudo pkill 程序的干淨方法?
我需要殺死一些以 sudo 執行的程序,按全名匹配它們,併計算原始命令呼叫的數量。
對於每個程序,有兩個程序:命令本身和
sudo
一個,但我可以解決這個問題:$ sudo -b perf record sleep 100 $ pgrep -fa '/perf record' 2245700 /usr/lib/linux-tools/.../perf record sleep 100
問題是當我呼叫時
sudo pkill
,它會發現、殺死和計算自己:$ sudo pkill -ef '/perf record' | wc -l 2
在這種情況下,是否有一種簡單的方法讓 pkill 不包含自身?
我嘗試過使用 pid 文件,這可能是可以接受的,但是缺少 pgrep/pkill 文件,而且它似乎不能以基本形式工作:
$ pgrep -f '/perf record' | tee /tmp/pids $ sudo pkill -F /tmp/pids killed (pid 2249211)
因為它只會殺死第一個。文件說:
-F, --pidfile file Read PID's from file. This option is perhaps more useful for pkill than pgrep.
但它的含義是模棱兩可的
PID's
。
嘗試:
sudo pkill -ef '/[p]erf record' | wc -l
這是一個使用僅包含單個字母的字元類的技巧
p
。正則表達式正在尋找
/perf
,但sudo pkill
命令行有/[p]erf
,不匹配。這種方法已經在命令中使用了幾十年,例如
ps aux | awk '/[f]oo/ {print $1}'
請注意,
pkill
/中的模式pgrep
是擴展的正則表達式,如grep -E
. 因此,您可以只提供一個更精確地針對所需程序的正則表達式。在您的情況下,可能是這樣的:sudo pkill -ef '^(/[^/]+)+/perf record'
甚至更好的是@cas在他的回答中描述的技巧。
可能值得解釋為什麼所有這些都是必需的:
眾所周知,
pkill
/pgrep
永遠不會匹配自己。然而,他們使用的標準是通過匹配PID,即他們檢查匹配的 PID 之一是否是他們的,並且他們精確地排除了那個。但是通過
-f
a 執行(使用完整命令行模式選項)sudo
,該pkill
命令最終也會匹配sudo
自己的程序,因為該程序也帶有一個命令行字元串,該字元串與您使用的*裸模式匹配。*顯然sudo
,自己的程序與該程序的 PID 不同pkill
,因此pkill
不會從列表中排除該sudo
程序,從而殺死產生(並仍然持有)該程序的pkill
程序。考慮:
$ sudo -b perf record sleep 1234 $ sudo pgrep -fa '/perf record' 1446 /usr/lib/linux-tools/4.2.0-42-generic/perf record sleep 1234 1466 sudo pgrep -fa /perf record # <-- if I issued a pkill, this process, the sudo, would have been killed
在上面的程式碼片段中,請注意列表中確實排除了自己的
pgrep
程序。但該過程還帶有一個與裸正則表達式匹配的命令行。sudo
通過提供更定制的正則表達式,
pkill
不再包含該sudo pkill -ef <...>
程序,因為該程序自己的命令行攜帶定制的正則表達式,與正則表達式本身不匹配。關於
-F
選項的最後說明。在我寫這篇文章的時候,那個選項仍然只從文件中讀取一個 PID 。所以是的,文件以及程序的
--help
輸出具有誤導性。消息來源中的這條評論說出了醜陋的事實。/* FreeBSD: arg 是一個包含要匹配*的PID 的文件 /