ssh -t
バックグラウンドジョブが完了するのを待つとどうなりますか?
例:
ssh user@example 'sleep 2 &'
sshが2秒後に返されるため、これは期待どおりに機能します。
ssh user@example -t 'sleep 2 &'
完了を待たずにsleep
すぐに返します。
誰でもこれの理由を説明できますか?ssh -t
返す前にすべてのバックグラウンドプロセスを完了する方法はありますか?
私のユースケースは、次のようにスクリプトを起動し、そのスクリプトが基本スクリプトがssh -t
完了した後もアクティブなままにする必要があるいくつかのバックグラウンドタスクを開始することです。これまではこれはssh -t
不可能でした。
答え1
それ以外の場合は、-t
2つのパイプを介してsshd
リモートシェルのstdout(およびサブシェル)とstderrを取得しますsleep
(別のパイプを介してクライアントからの入力も送信します)。
sshd
ユーザーのログインシェルを開始したプロセスを待ちますが、そのプロセスが終了した後、stdoutパイプ(少なくともstderrパイプではなくopensshの場合)でeofを待ちます。
eofは、パイプの書き込み側プロセスに対して開いているファイル記述子がない場合に発生します。これは通常、stdoutが他にリダイレクトされていないすべてのプロセスが消えた場合にのみ発生します。
を使用すると、-t
パイプsshd
は使用されません。代わりに、リモートシェルとその子孫(stdin、stdout、stderr)とのすべての対話は、一対の擬似端末を使用して行われます。
擬似端末ペアの場合、sshd
マスターと対話するための同様のeof処理はありませんが、少なくとも一部のシステムは、疑似端末のスレーブ側にまだ開いているプロセスがあるかどうかを知るための代替方法を提供します(下記の@JdeBP注釈を参照)。 )、sshd
使用しないので、リモートユーザーのログインシェルを実行するプロセスが終了するのを待ってから終了します。
終了すると、ptyペアのマスター側が閉じます。これはptyが破壊されることを意味するので、スレーブ制御プロセスはSIGHUP(デフォルトで終了)を受け取ります。
編集する:最終結果は同じですが、最後の部分が正しくありません。バラより@UNIX.rootの答え正確に何が起こったのかを正確に説明してください。
答え2
(より多くの情報を含めるためにコメントをここに移動しました。)
許可された回答の一部SIGHUP
が正しくありません。
終了すると、ptyペアのマスター側が閉じます。これはptyが破壊されることを意味するので、スレーブが制御するプロセスはSIGHUPを受信します。
そうではありません。 POSIXによると、「制御端末の端末インターフェースがモデムの切断を検出したときにSIGHUP
信号を送信する必要があります。[...]プロセスを制御するの場合、ssh -t 'sleep 2 &'
ttyの接続が切断され、すでにSIGHUP
終了しているために制御プロセスに送信できないのは、終了する制御プロセスです。実際にsleep
殺されたSIGHUP
理由はいつでしたか?セッションリーダーの終了「このSIGHUP
信号はすべてのプロセスに送信する必要があります。フォアグラウンドプロセスグループで」。
混乱した部分はそうですsleep 2 &
。これはバックグラウンドで実行されるコマンドですが、そうではありません。バックグラウンドプロセスグループ。バックグラウンドプロセスグループ関連職業管理デフォルトでは、非対話型シェル(例ssh ... 'sleep 2 &'
:)では無効になっています。実際にsleep 2 &
走っているフォアグラウンドプロセスグループ。たとえば、
$ ssh -t localhost 'sleep 2 & ps jt'
PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
88819 88825 88825 88825 pts/36 88825 Ss+ 0 0:00 bash -c sleep 2 & ps jt
88825 88826 88825 88825 pts/36 88825 S+ 0 0:00 sleep 2
88825 88827 88825 88825 pts/36 88825 R+ 0 0:00 ps jt
ご覧のとおり、すべてのプロセスのPGID(88825)はbashシェルのPIDと同じで、TPGIDも88825です。つまり、バックグラウンドプロセスsleep 2 &
もここにあります。フォアグラウンドプロセスグループ。
比較については、以下を参照してください。
$ pgrep -af sleep
$ ssh -t localhost 'set -m; sleep 123 & ps jt'
PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
89002 89008 89008 89008 pts/3 89010 Ss 0 0:00 bash -c set -m; sleep 123 & ps jt
89008 89009 89009 89008 pts/3 89010 S 0 0:00 sleep 123
89008 89010 89010 89008 pts/3 89010 R+ 0 0:00 ps jt
Connection to localhost closed.
$ ps j 89009
PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
1 89009 89009 89008 ? -1 S 0 0:00 sleep 123
$
set -m
ジョブ制御が有効になっていると(sleep 2 &
独自のプロセスグループ(PGID 89009)で実行されていることがわかります。バックグラウンドプロセスグループ。そして、ssh
終了後もsleep
実行を続けています。
(詳細については、次のようなシナリオを参照してください。+ "ssh -f"が機能しないと予想されます。)
答え3
使用wait
:
ssh user@example -t 'sleep 2 & wait'