Shell-Script

用於殺死先前命令提供的特定 PID 的命令

  • November 26, 2018

有時我需要殺死一個程序(原因並不重要)。而且我知道我可以使用以下命令找到該程序:lsof -i :8080,作為我的候選人,輸出表中的最後一個程序

例如,如果我執行命令,將出現如下輸出:

COMMAND   PID USER   FD   TYPE  DEVICE SIZE/OFF NODE NAME
java    15112 dani   70u  IPv4 3178183      0t0  TCP localhost:39998->localhost:http-alt (CLOSE_WAIT)
java    15112 dani  137u  IPv4 3181607      0t0  TCP localhost:39999->localhost:http-alt (CLOSE_WAIT)
java    15112 dani  138u  IPv4 3181608      0t0  TCP localhost:40000->localhost:http-alt (CLOSE_WAIT)
java    15112 dani  139u  IPv4 3181609      0t0  TCP localhost:40001->localhost:http-alt (CLOSE_WAIT)
java    15112 dani  140u  IPv4 3181610      0t0  TCP localhost:40002->localhost:http-alt (CLOSE_WAIT)
java    19509 dani   50u  IPv6 4617361      0t0  TCP *:http-alt (LISTEN)
java    19509 dani   52u  IPv6 6642445      0t0  TCP localhost:http-alt->localhost:42996 (CLOSE_WAIT)

所以,我的目標是PID 19509。使用管道,我如何挑選最後一行的 PID?

我想達到一個命令lsof -i :8080 | something here to get the PID | kill -9

我正在執行 Linux Mint KDE x64

從字面上回答您的問題,這是列出由 顯示的最後一個 PID 的一種方法lsof

lsof … | awk 'END {print $2}'

awk是一種文本處理語言,它讀取輸入並逐行處理。在程式碼中,END {…}在處理完整個輸入後執行大括號中的程式碼,並在最後一行進行有效操作。$2是該行的第二個以空格分隔的欄位。

這裡有一些殺死它的方法(每行獨立工作):

kill $(lsof … | awk 'END {print $2}')
lsof … | awk 'END {print $2}' | xargs kill
lsof … | awk 'END {system("kill " $2)}'

但是,我不同意您的說法,即正確的殺死過程總是最後一個。lsof通過增加PID來顯示程序,這是沒有意義的。即使在按順序分配程序 ID 的系統上(並非所有 Unix 變體,甚至所有 Linux 安裝都不是這種情況),一旦達到最大值(通常為 32767),它們也會包裝。因此,通過比較 PID 來決定程序是沒有意義的。

您需要一些其他資訊來決定要終止哪個程序。根據您所追求的資訊類型以及您的輸出是否可能包含“奇怪”字元(如文件或程序名稱中的空格),您可以使用 awk 之類的工具來處理 的輸出lsof,或者您可以使用產生輸出的-F選項lsof在簡單的情況下更難解析,但(幾乎)不容易產生歧義並且更容易健壯地解析。例如,如果你想殺死任何在埠 8080 上監聽的程序,你可以這樣做:

lsof -n -i :8080 -F | awk '
   sub(/^p/,"") {pid = $0}
   $0 == "n*:http-alt" {print pid}
' | xargs kill

對函式的呼叫在行首sub替換為空字元串。p如果執行此替換,則執行程式碼塊{pid = $0};這樣,pid變數包含由 顯示的最後一個 PID 值lsof。如果第二行是 awk 則列印pid變數的值"n*:http-alt",這是 lsof 報告在所有介面上偵聽埠 8080 的套接字的方式。

這個特定的標準實際上不需要任何解析(我只是在上面展示了它作為一個例子)。您可以lsof只顯示在指定埠上偵聽的程序:

lsof -n -a -iTCP:8080 -sTCP:LISTEN -Fp | sed 's/^p//' | xargs kill

或者,為此,您可以netstat改用。

netstat -lnpt | awk '$4 ~ /:8080$/ {sub(/\/.*/, "", $7); print $7}'

awk 程式碼說明:如果第 4 列以 結尾:8080,則替換第/7 列中第一列之後的所有內容(刪除程序名稱部分並僅保留 PID 部分),然後列印。

引用自:https://unix.stackexchange.com/questions/199957