如何編寫一個(從不)匹配零字節的 pgrep 模式?
我想終止一個以 . 結尾的長名稱的程序
foo
。目前我的計劃是使用pkill
(儘管為了測試,為了對過程友好,我一直在檢查我的模式pgrep
)。我已經看到這個問題表明對於長程序名稱,您必須使用-f
來獲取整個命令行。這對於獲取長程序名稱的其餘部分非常有用;問題是該模式與整個命令行匹配,而不僅僅是程序名稱,我不想意外殺死碰巧foo
作為參數的不同程序。所以我相信我想寫一個這樣的模式:
pgrep -f '^[^\0]*foo'
我所寫的意思是零字節——在程序的每個參數之前放置
\0
的分隔符。-f
當然\0
行不通;此模式實際上匹配任何不是\
或 (ASCII)的字元序列0
。我也試過這個:pgrep -f '^[^'`echo -n '\0'`']*foo'
在這裡,我已經確認我的 shell 為
echo -n '\0'
. 不幸的是,由於參數的傳遞方式,pgrep
當它看到實際的 0 字節時停止掃描模式,因此該命令的行為與將完全相同pgrep -f '^[^'
- 也就是說,它會引發有關接收無效模式的錯誤。如何編寫一個引用其中零字節的模式(或者,好吧,任何不是零字節的字節)?
pgrep -f
與傳遞給程序執行的最後一個命令的參數的 SPC 字元的串聯匹配(如在/proc/pid/cmdline
Linux 上所見)。那從不包含 NUL 字元。所以你需要這樣做:
pgrep -f '^[^ ]*foo( |$)'
儘管您會錯過使用
/path/with space/foo
as執行某些命令的程序,argv[0]
但它會報告使用 as 執行命令的foo bar
程序argv[0]
。在任何情況下,您都不能將參數中的 NUL 傳遞給執行的命令,因為命令參數是 NUL 分隔的字元串。
在
zsh
中,您可以將 NUL 傳遞給內置命令和函式(因為它們不受該限制的影響,execve()
因為它們未執行)。所以在 Linux 上,你可以這樣做:print -rC1 /proc/<->(Ne[$'[[ "${$(<$REPLY/cmdline)%%\0*}" = *foo ]]']:t)
找到
argv[0]
結束於的程序foo
。或者:
print -rC1 /proc/<->/exe(N-.e['[[ $REPLY:A = *foo ]]']:h:t)
對於那些正在執行路徑以結尾的命令的人
foo
(儘管您可能僅限於自己的程序)。在 Linux 上,程序名稱限制為 15 個字節,並且在每次呼叫時更改為第一個參數的基本名稱的前 15 個字節
execve()
,但也可以通過寫入/proc/pid/comm
或使用來更改prctl(PR_SET_NAME)
。程序也可以改變/proc/pid/cmdline
. 參見例如:$ perl -lne 'BEGIN{$0 = "foo bar 90123456789"}; print "$ARGV: $_"' /proc/self/{cmdline,comm} /proc/self/cmdline: foo bar 90123456789 /proc/self/comm: foo bar 9012345