または、sshコマンドでtrueを使用します。

または、sshコマンドでtrueを使用します。

SSHを介してリモートで実行しようとしていて、pkill -f可能なエラーコードを削除しようとすると(プロセスが見つからない場合でも残りのスクリプトを実行し続ける)、|| true期待どおりに機能しません。

$ pkill asdf || true
$ echo $?
0
$ pkill -f asdf || true
$ echo $?
0
$ ssh [email protected] "pkill asdf || true"
$ echo $?
0
$ ssh [email protected] "pkill -f asdf || true"
255

そう思います。SSH引用符間のコマンドの代わりに255を返しますが、なぜですか?

答え1

sshそれ自体が255終了ステータスを返すという仮定は正しいです。マニュアルsshページには次のように記載されています。

ssh はリモートコマンドの終了状態で終了するか、エラーが発生すると 255 で終了します。

ちょうど実行すると、"に対応する終了状態を取得する可能性が高いです。ssh [email protected] "pkill -f asdf"1pkill一致するプロセスはありません。」。

難しい部分は理解ですなぜSSHの実行中にエラーが発生しました。

ssh [email protected] "pkill -f asdf || true"

SSHリモートコマンド

SSH サーバは、リモートコマンドを実行するためにシェルを起動します。実際の例は次のとおりです。

$ ssh server "ps -elf | tail -5"
4 S root     35323  1024 12  80   0 - 43170 poll_s 12:01 ?        00:00:00 sshd: anthony [priv]
5 S anthony  35329 35323  0  80   0 - 43170 poll_s 12:01 ?        00:00:00 sshd: anthony@notty
0 S anthony  35330 35329  0  80   0 - 28283 do_wai 12:01 ?        00:00:00 bash -c ps -elf | tail -5
0 R anthony  35341 35330  0  80   0 - 40340 -      12:01 ?        00:00:00 ps -elf
0 S anthony  35342 35330  0  80   0 - 26985 pipe_w 12:01 ?        00:00:00 tail -5

デフォルトのシェルは、bashリモートコマンドは単純なコマンドではありません管路、「制御演算子で区切られた1つ以上の命令シーケンス|」。

Bashシェルは、渡されたオプションが次のようになることを認識するのに十分スマートです-c簡単なコマンド、実際に新しいプロセスを分岐しないことで最適化できます。つまり、実行前にexec追加の手順を実行するのではなく、単純なコマンドを直接実行します。以下は、リモート単純コマンドを実行したときに発生することの例です(この場合)。forkexecps -elf

$ ssh server "ps -elf" | tail -5
1 S root     34740     2  0  80   0 -     0 worker 11:49 ?        00:00:00 [kworker/0:1]
1 S root     34762     2  0  80   0 -     0 worker 11:50 ?        00:00:00 [kworker/0:3]
4 S root     34824  1024 31  80   0 - 43170 poll_s 11:51 ?        00:00:00 sshd: anthony [priv]
5 S anthony  34829 34824  0  80   0 - 43170 poll_s 11:51 ?        00:00:00 sshd: anthony@notty
0 R anthony  34830 34829  0  80   0 - 40340 -      11:51 ?        00:00:00 ps -elf

私は以前このような行動を経験したことがありますが、このAskUbuntuの答え

削除動作

pkill -f asdf || trueこれは単純なコマンドではないので(コマンドリスト)、上記の最適化は発生しないため、実行するとプロセスが分岐して実行されます。ssh [email protected] "pkill -f asdf || true"sshdbash -c "pkill -f asdf || true"

ctxの答えが示すように、pkill独自のプロセスは終了しません。しかしそれは〜するコマンドラインがこのパターンと一致する-f他のプロセスを終了します。コマンドbash -cはこのパターンと一致するため、このプロセス、つまり独自の親プロセス(発生した場合)を終了します。

その後、SSHサーバーは、リモートコマンドの実行を開始したシェルプロセスが予期せず終了したことを発見し、SSHクライアントにエラーを報告します。

答え2

リモートコマンドは自動的に終了します。

$ ssh 10.0.3.70 'pgrep -af asdf'
$ ssh 10.0.3.70 'pgrep -af asdf || true'
1018 bash -c pgrep -af asdf || true

pgrepとpkillは独自のプロセスを無視しますが、-fフラグを使用すると親シェルを見つけることができます。

$ pgrep -af asdf
$ pgrep -af asdf || true
$ bash -c 'pgrep -af asdf'
$ bash -c 'pgrep -af asdf || true'
9803 bash -c pgrep -af asdf || true

答え3

pkillに「asdf」と一致するすべてのエントリを終了するように依頼しました。 "asdf"という名前のエントリは引き続き検索されますが、それ自体は表示されないように[a] sdfと一致するように指示する必要があります(asdfを[a] sdfと並べ替える場合は、sは]と並べられていないことに注意してください。 )

ssh 10.0.3.70 'pgrep -af "[a]sdf" || true'

これは、grep/egrep/awk/etcでも使用される一般的なトリックです。

ps -ef | grep "something"  # will sometimes match itself too
ps -ef | grep "[s]omething" # will not match itself

# why it works:
# the commandline contains:     ps -ef | grep [s]omething
# and grep tries to find:                      something

このヒントは古いものです。数十年前にUnix FAQで見たことがあります(まだ読む価値があります!)。

"自動化"するのは簡単ではありませんが、通常は変数文字列regexp = "something"をgrepする必要があるたびに次のことを行うことができます。

grep "$(echo "${regexp}" | LC_ALL='C' sed -e 's/[a-zA-Z0-9_-]/[&]/')" 
#  if regexp="something",  it does: grep "[s]omething"
#  if regexp="otherthing", it does: grep "[o]therthing"
#  if regexp="^thirdthing", it does: grep "^[t]hirdthing" #ok, kept the "^"
#BUT fails on : regexp="[abc]def", as it does: grep "[[a]bc]def" instead of grep "[abc][d]ef" ...

関連情報