將兩個 PID 的列表傳遞給 xargs 只會使用 ssh 殺死第一個
我正在檢索我想要殺死的兩個 PID 的列表。我的管道看起來像
ps -ef | grep foo | grep -v grep | awk {'print $2'} | xargs kill -9
在本地執行此操作時,兩個程序都會被殺死。但是當它與 ssh 一起使用時
ssh foo@<IP Address> "ps -ef | grep foo | grep -v grep | awk {'print $2'} | xargs kill -9"
兩個中只有一個 PID 被刪除。它輸出
kill: <PID>: No such process
. 它會試圖在本地殺死第二個程序嗎?
位於
$2
本地 shell 命令行上的雙引號內,因此由本地 shell 擴展(可能為空字元串)。所以在遠端主機上執行的命令是這樣的:
ps -ef | grep foo | grep -v grep | awk {'print '} | xargs kill -9
該
awk
命令是無操作的(列印所有行),xargs
最終將執行:kill -9 <all-the-words-present-in-the-output-of-ps|grep...>
這包括pid和ppid,使用者名……
此外,如果 kill 命令的 pid 在該列表中,它將殺死自己,因此無法殺死列表中剩餘的那些。
在這裡,你會想要:
ssh foo@<IP Address> 'pkill -KILL -f foo'
(殺死命令行(至少前幾千字節)包含的所有程序
foo
)。或者如果遠端系統沒有
pkill
命令:ssh foo@<IP Address> ' ps -Ao pid= -o args= | awk "/[f]oo/ {print \$1}" | xargs kill -s KILL'
我們在本地使用單引號(所以那裡沒有變數擴展),而在遠端 shell 命令行中的 awk 程式碼使用雙引號,所以我們需要對 in 進行轉義
$
,$1
這樣它就不會被遠端 shell 擴展。
awk
是 的超集grep
,您通常不需要將它們連接在一起。最好是告訴ps
只輸出你想匹配的東西,這裡假設你想foo
在 ps 顯示的參數列表中搜尋你的使用-f
建議。如果你想殺死遠端使用者的所有程序(這裡是使用者 foo 和 sshing as foo),你可以這樣做:
ssh foo@<IP Address> 'kill -s KILL -- -1'
這將殺死使用者有權殺死的所有程序。對於普通使用者來說,就是所有程序的真實或保存的使用者id與殺死程序的真實或有效使用者id相同的程序。
或者:
ssh foo@<IP Address> 'pkill -KILL -U "$(id -u)"'
(或
pkill -U foo
)。殺死所有真實使用者ID與遠端使用者的有效使用者ID相同的程序。或者你可以這樣做:
ssh foo@<IP Address> ' trap "" HUP ps -Ao sid= -o pid= -U "$(id -u)" | awk "\$1 != $(ps -eo sid= -p "\$\$") {print \$2}" | xargs kill -s KILL'
(檢查
sid
以確保kill
不會殺死自己、shellawk
或xargs
,並忽略 SIGHUP 以防殺死使用者sshd
程序導致發送該信號)我們假設遠端使用者的登錄 shell 類似於 Bourne。如果遠端使用者的登錄 shell 屬於 csh 或 rc 系列,例如具有不同的語法,則必須調整這些命令。
用信號的名稱而不是數字來引用信號也是更好的做法,因為這樣會更清楚,並且信號編號可以隨系統而變化(儘管 SIGKILL 的 9 非常普遍)。