SSHを切断すると実行したコマンドはどうなるのか気になって試してみた。
検証
検証は、Amazon Linuxで行った。
順序
①以下コマンドをsshログインしたリモートホストで実行。
# !/bin/bash
current_dir=$(dirname $0)
sleep 60 &
wait
echo -e "実行終了!" >> "${current_dir}/test.log"
exit $?
②ローカルPCでsshプロセスをkill
③60秒後再度sshログイン
cat test.log
=>
何も出力されていない。。。
④ ①を600秒にし、600秒以内にログイン
以下を実行。
プロセスが消えている。
ps aux |grep test
=>
結果
SSHを切断すると実行したコマンドは、実行終了する。
考察
なぜSSHを切断するとコマンドが止まるのか、
SSHログインして実行したコマンドは、sshdプロセスの子プロセスとして起動される訳だが(以下コマンド参照)、
おそらくsshdデーモンはkillされるとforkした子プロセスに対してkillシグナルを出すように設計されているのではないだろうか。
と思っていたのだが、コメント欄でそれは違うよとご指摘いただいたので以下で再度検証する。
@angel_p_57 さんありがとうございます!
pstree -p | grep sshd
|-sshd(1560)---sshd(7877)---sshd(7881)---bash(7882)-+-grep(8020)
sshが切れてもコマンドを止めないようにするには、以下の記事のが参考になりました。
コメントをいただき再度検証
以下コメント引用。
つまり、sshdが終了するから遠隔コマンドが終了する訳ではない。
その例として、非対話型でコマンドを実行した場合は遠隔コマンドのプロセスは残るとのこと。
実際にやってみる。
デーモンsshdは直接手を下しません。sshがkillされることで、対向のsshdは静かに終了するだけです。
実際、今回は sshでログイン→遠隔のログインシェルと対話処理→対話処理の途中で手元のsshをkill という環境で試されているようですが、ssh ユーザ@ホスト 遠隔コマンド で遠隔コマンド起動→遠隔コマンド実行中に手元のsshをkill だと、sshdは終了して実行されている遠隔コマンドは残ります。
ここでキーとなるのが、対話処理かどうかという点です。sshのコマンドラインオプション-tの有無と言っても良いです。( 遠隔ログインならデフォルトで-t有効 )
検証
①以下コマンド実行
ssh -i ****.pem host sh /***/test.sh
# !/bin/bash
current_dir=$(dirname $0)
sleep 600 &
wait
echo -e "実行終了!" >> "${current_dir}/test.log"
exit $?
②手元のsshをkill
③sshログインしプロセスを確認
ほんとだ、プロセスが残ってる。。
じゃあなぜ、対話処理なら実行中のコマンドが終了するのか。。
それもコメントで解説してくださった。
ps aux | grep test.sh
=>
*** 29953 0.0 0.0 113148 2708 ? Ss 17:39 0:00 sh /***/test.sh
なぜ、対話処理なら実行中のコマンドが終了するのか
以下コメント引用。
自分なりにまとめると。
sshdとログインシェルの間のOSが終了させている。
OSが回線切断(Hang UP、略してHUP)と判断することにより、管理下のジョブを終了させている。
難しい。。
なぜ対話処理なら実行中のコマンドが終了するのか、それは「TTY/PTYに関するクイズ」の「A1」の話題と深い縁があります。
このA1の内容をざっくり言うと、「対話処理用のPTYを扱うkernelドライバが、Ctrl-Cの入力を横取りして、コマンドへのシグナル送信に替えて処理する」ということになります。
今回の場合は、sshdの終了によりPTYでのデータの遣り取りも終わるということで、kernelドライバが「回線切断(Hang UP、略してHUP)」と判断することによります。
HUPという判断により、kernelドライバがログインシェルにHUPシグナルを送り、それを受けてシェルが管理下にある各ジョブへHUPシグナルを送る、それでジョブも終了になる、というのが基本路線になります。