nohup
ssh でバックグラウンド コマンドを使用する必要性を理解しようとしています。私のシェルは CentOS 上の csh です。
以下のバックグラウンド コマンドは、ssh が終了した後も実行され続けます。これは、
nohup
コマンドの前に が付いていた場合にのみ発生すると予想していました。どのようなシナリオが
nohup
必要になるのでしょうか?ssh host 'sleep 80 >& /dev/null &'
対話型シェルも試してみましたが、ssh が終了した後もバックグラウンド ジョブの PID はホスト上にまだ存在しています。
ssh host sleep 80 >& /dev/null & exit
kill -HUP PID
また、ではなく を使用して対話型セッションを終了しようとしましたがexit
、ssh が終了した後もバックグラウンド ジョブの PID がホスト上に存在し続けます。
何か間違っているのでしょうか?
答え1
いや背景セッション リーダー (シェル) が終了したとき、またはその制御端末が破棄されたときには、プロセス グループ (ジョブ) はデフォルトでは終了されません。
それが起こるのは、いくつかの特別なケースのみです:
(1)バックグラウンドジョブは停止、その場合、信号ペアが送信さSIGHUP
れSIGCONT
ますカーネルSIGHUP
シグナルがプロセスによってキャッチまたは無視されない場合、プロセスは終了します。
停止したジョブの定義は、停止したプロセスを含むジョブです。プロセス睡眠nanosleep(2)
またはのようなブロッキング システム コールでは、read(2)
停止しているとは見なされません。
(2)プロセスは、もはや存在しない端末に対して読み取りまたは書き込みを試行し、その試行時にエラーが発生したために(自発的に)終了します。
(3)この仕事は実際には前景仕事。カーネルSIGHUP
セッション リーダー/制御プロセス (つまりシェル) が終了すると、フォアグラウンド プロセス グループにシグナルが送信されます。制御プロセスはSIGHUP
、制御端末が破棄されるとシグナルを受け取り、通常は終了します。
で始まるコマンドも、&
実際には前景ジョブ制御のないシェルから起動されたプロセスグループ(ほとんどのシェルでは、cshではデフォルトですが、スクリプトそしてサブシェル)。
(4)bash
または のようなシェルを使用していますzsh
。これらのシェルは、 でシグナルを受け取ったとき(上記のポイント 3 に従い、シェルが制御プロセスです)、または単に終了したとき (後者は ではデフォルトのみですが、 bash ではデフォルトではなくオプションに従います)、SIGHUP
すべてのジョブにシグナルを送信します。SIGHUP
zsh
shopt huponexit
のcshシェル(本物か偽物csh
かtcsh
)そのような行動をとらないbash
またはからzsh
。 ではtcsh
(実際の ではそうではありません) 、シェルの終了時にコマンドを hup するために、組み込みcsh
コマンドを使用してコマンドを開始できます。hup
tcsh% hup sleep 3600 &
tcsh% exit
$ pgrep sleep
[nothing]
(5)initシステムは終了したユーザーセッションをクリーンアップするために全力を尽くします。デフォルトの設定では、システムすべてのプロセスに信号を送ります範囲遅延後SIGTERM
に が続くので、いずれにしてもその点では役に立ちません。また、systemdのSIGKILL
nohup
範囲は Unix プロセス セッションと一致しないため、 でコマンドを実行しても、setsid(1)
それを回避することはできません。
KillUserProcesses=yes
、、KillMode=control-group
およびオプションKillSignal=SIGTERM
をデフォルトから微調整することで、systemd の動作を変更できる可能性がありますSendSIGKILL=yes
。