ssh 終了後、ssh コマンドが予期せず他のシステムで続行される

ssh 終了後、ssh コマンドが予期せず他のシステムで続行される

次のコマンドを実行し、他のシステムで出力ファイルを監視しています。

ssh $ip_address 'for n in 1 2 3 4 5; do sleep 10; echo $n >>/tmp/count; done'

^Cログインした端末を使用するか、単にシャットダウンしてsshコマンドを終了すると、リモートコマンドも終了することが予想されます。しかし、そのようなことは起こりません。/tmp/countとにかく、1〜5のすべての数字を取得し、シェルとその子ps -ejHプロセスがsleep引き続き実行されているとマークされます。

これが予想される動作ですか?どこに文書化されていますか?無効にできますか?読んで、この動作をデフォルトの動作にするのではなく、nohupを使用して明示的に有効にする必要があると予想しました。

sshとsshdのマニュアルページを見ましたが、明確な内容が見つかりませんでした。

私は両方のシステムでrootログインとbashシェルを使用してRed Hat Enterprise Linux 6.2を実行しています。

答え1

ウーサーの答え端末を割り当てるように指示しますが、その理由は説明しません。その理由はsshだけに限られているのではなく、信号生成と伝播の問題です。私はあなたを招待します。さまざまな信号が送信される原因は何ですか?背景の詳細​​をご覧ください。

リモートホストには2つの関連プロセスがあります。

  • sshdリモートプログラムの入出力をローカル端末に中継する ssh デーモン ( ) のインスタンスです。
  • ループを実行するシェルですfor

シェルはループの終わりに達したり、致命的なエラーが発生した場合は自然に死ぬことがあり、シグナルによって死ぬ可能性があります。問題は、シェルが信号を受信するのはなぜですか?

リモートシェルがパイプを介して接続されている場合sshd(コマンドラインでコマンドを指定したときに発生)ssh、終了します。信号パイプライン終了し、sshdシェルがパイプに書き込もうとした場合。シェルがパイプに書き込まない限り、SIGPIPE を受信しません。ここでは、シェルは標準出力に何も書き込まないため、永久に持続する可能性があります。

-tこのオプションをsshに渡して、リモート側で端末をエミュレートし、この端末で指定されたコマンドを実行するように指示できます。その後、SSH クライアントが消えたら、sshd接続を閉じて終了して端末を破壊します。端末デバイスが消えた場合、その中で実行されているすべてのプロセスはため息をつく。したがって、SSHクライアントをシャットダウンすると(killクライアントが実行されている端末を使用または閉じて)、リモートシェルはSIGHUP信号をエクスポートします。

この-tオプションが渡されると、SSHもリレーします。知能を知らせるCtrl+を押すと、CリモートシェルがSIGINTを受け取ります。

答え2

コマンドを使用してpsuedo-ttyを割り当ててみてくださいssh

ssh -t $ip_address 'for n in 1 2 3 4 5; do sleep 10; echo $n >>/tmp/count; done'

SSH セッションを切断すると、プロセスは終了します。

これは疑似ttyなので、シェルの初期化時に構成ファイルのソースコードを取得できず、コマンドが非常に公開された環境に残ることがあります。.ssh/environment環境変数(PATHなど)を定義するファイルを設定する必要があるかもしれません。 ~からman 1 ssh

Additionally, ssh reads ~/.ssh/environment, and adds lines of the format 
“VARNAME=value” to the environment if the file exists and users are allowed
to change their environment.  For more information, see the 
PermitUserEnvironment option in sshd_config(5).

答え3

-tsshクライアントのシャットダウンまたはシャットダウン時にリモートコマンドを終了させるオプションを使用する代わりに、標準入力を閉じるときに名前付きパイプをssh使用してsshd「EOFをSIGHUP」に変換できます(参照)。バグ396 - ptyが割り当てられていない場合、sshdは孤立プロセスになります。)。

# sample code in Bash
# press ctrl-d for EOF
ssh localhost '
TUBE=/tmp/myfifo.fifo
rm -f "$TUBE"
mkfifo "$TUBE"
#exec 3<>"$TUBE"

<"$TUBE" sleep 100 &  appPID=$!

# cf. "OpenSSH and non-blocking mode", 
# http://lists.mindrot.org/pipermail/openssh-unix-dev/2005-July/023090.html
#cat >"$TUBE"
#socat -u STDIN "PIPE:$TUBE"
dd of="$TUBE" bs=1 2>/dev/null
#while IFS="" read -r -n 1 char; do printf '%s' "$char"; done > "$TUBE"

#kill -HUP -$appPID 
kill $appPID

rm -f "$TUBE"
'

答え4

無効にするには(デフォルトの動作として見える)、有効にする必要があります。SSHは生きているクライアントまたはサーバー側。

ssh-keep-alive-optionsのマニュアルページを見ると、デフォルトでは無効になっていることがわかります。

関連情報