web-dev-qa-db-ja.com

前のコマンドで提供された特定のPIDを強制終了するコマンド

プロセスを強制終了する必要がある場合があります(理由は重要ではありません)。そして、次のコマンドでそのプロセスを見つけることができることを私は知っています: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 KDEx64を実行しています

3
Dani Sancas

あなたの質問に文字通り答えて、これがlsofによって表示された最後のPIDをリストする1つの方法です:

_lsof … | awk 'END {print $2}'
_

Awk は、入力を読み取り、それを1行ずつ処理するテキスト処理言語です。コードでは、_END {…}_は、入力全体が処理された後、中括弧内のコードを実行し、最後の行で効果的に動作します。 _$2_は、行の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の出力を処理することも、 lsofに_-F_オプションを使用すると、単純なケースでは解析が少し難しくなりますが、(ほとんど)あいまいになりにくく、堅牢に解析しやすい出力が生成されます。たとえば、ポート8080でリッスンしているプロセスを強制終了する場合は、次の方法で実行できます。

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

sub関数を呼び出すと、行の先頭にあるpが空の文字列に置き換えられます。この置換が実行されると、コードブロック_{pid = $0}_が実行されます。このように、pid変数には、lsofによって表示される最後のPID値が含まれます。 2番目のawk行は、行が正確に_"n*:http-alt"_である場合、pid変数の値を出力します。これは、すべてのインターフェイスのポート8080でリッスンしているソケットを報告するlsofの方法です。

この特定の基準は、実際には解析を必要としません(例として上に示しただけです)。指定されたポートでリッスンしているプロセスだけを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の部分のみを保持するため)、それを出力します。