web-dev-qa-db-ja.com

2つのPIDのリストをxargsに渡すと、sshを使用して最初のPIDのみが強制終了されます

強制終了する2つの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"

2つのうち1つのPIDのみが削除されます。 kill: <PID>: No such processを出力します。ローカルで2番目のプロセスを強制終了しようとしているのでしょうか?

3
Steve

$2は、ローカルシェルコマンドラインの二重引用符内にあるため、ローカルシェルによって(おそらく空の文字列に)展開されます。

したがって、リモートホストで実行されるコマンドは次のようになります。

 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がそのリストにある場合は、それ自体がkillされるため、リスト内の残りのコマンドをkillすることはできません。

ここでは、次のようにします。

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'

ローカル側では一重引用符を使用し(そこでは変数を展開しない)、リモートシェルコマンドラインでawkコードを二重引用符で囲んでいるため、リモートシェルによって展開されないように$$1をエスケープする必要があります。

awkgrepのスーパーセットです。通常、それらをパイプでつなぐ必要はありません。 psに一致させたいものだけを出力するように指示するのが最善です。ここでは、-fの使用法が示唆するように、psによって表示される引数のリストでfooを検索するとします。

リモートユーザーのすべてのプロセス(ここでは、ユーザーfooで、fooとしてsshing)を強制終了する場合は、次のようにします。

 ssh foo@<IP Address> 'kill -s KILL -- -1'

これにより、ユーザーが強制終了する権限を持つすべてのプロセスが強制終了されます。通常のユーザーの場合、それは、実際のまたは保存されたユーザーIDが、強制終了プロセスの実際のユーザー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が自分自身、シェル、awkまたはxargsを殺さないようにし、ユーザーを殺した場合にSIGHUPを無視しますsshdプロセスにより、そのシグナルが送信されます)

リモートユーザーのログインシェルはBourneに似ていると想定しています。リモートユーザーのログインシェルが、たとえば、異なる構文を持つcshまたはrcファミリーのものである場合、これらのコマンドを適合させる必要があります。

また、信号を番号ではなく名前で参照することをお勧めします。これにより、信号が明確になり、信号番号がシステムごとに変わる可能性があります(ただし、SIGKILLの9は非常に一般的です)。

9

要するにこれを試してください

 ssh user_name@ip_address "pkill -9 foo"

または長いものが欲しいなら

 ssh user_name@ip_address "ps aux | grep '[f]oo' | awk '{print \"kill -9 \"\$2}' | bash -v"
3
Gaurav Pundir