2015-09-03 9 views
10

私は最近、sshでコマンドを実行するときに少し奇妙な動作に陥りました。私は以下の行動の説明を聞くことに興味があります。予想通りssh localhost 'touch foobar &'を実行擬似ttyが割り当てられていると、ssh経由でバックグラウンドタスクを実行できないのはなぜですか?

foobarと呼ばれるファイルを作成します。

[[email protected] ~]$ ssh localhost 'touch foobar &' 
[[email protected] ~]$ ls foobar 
foobar 

は、しかし、同じコマンドを実行しているが、仮想端末の割り当てを強制的に-tオプションを使用して作成に失敗したfoobar

[[email protected] ~]$ ssh -t localhost 'touch foobar &' 
Connection to localhost closed. 
[[email protected] ~]$ echo $? 
0 
[[email protected] ~]$ ls foobar 
ls: cannot access foobar: No such file or directory 

マイ現在の理論は、タッチプロセスがバックグラウンド化されているため、プロセスが実行される前に疑似ttyが割り当てられ、割り当てられていないということです。誰もが、私はそれを聞いて非常に興味がある決定的な説明を持っている場合

[[email protected] ~]$ ssh -t localhost 'touch foobar & sleep 1' 
Connection to localhost closed. 
[[email protected] ~]$ ls foobar 
foobar 

:確かに1秒のスリープを追加すると、期待通りに実行するためにタッチすることができます。ありがとう。

+0

私はそれがまさにそれだと思います。バックグラウンドプロセスはttyに接続され、ttyがそれを殺します。 'nohup touch foobar&'を試して、それが動作するかどうか、そして/または 'foobar/dev/null 2>&1'に触れてみてください。 –

+0

'ssh -t localhost 'touch foobar < /dev/null >/dev/null 2>&1&''と 'ssh -t localhost 'nohup touch foobar&' 'はどちらも同じ動作をします。 – user414310

+0

ファイルを作成できませんでしたか?レコードの元のバージョンでもここに作成されたファイルを取得します。 –

答えて

22

ああ、それは良いことです。

これはプロセスグループの仕組み、非対話型シェルとして呼び出されたときにbashがどのように動作し、-c、入力コマンドに&の効果があるかに関係します。

答えは、UNIXでジョブ制御がどのように機能するかを理解していることを前提としています。すべてのプロセスがプロセスグループに属しています(同じグループのプロセスがコマンドパイプラインの一部として配置されることが多い)。cat(1)sort(1)、およびgrep(1)のプロセスを実行するのはcat file | sort | grep 'word'です。同じプロセスグループ)。 bashは他のプロセスと同様のプロセスであり、プロセスグループにも属します。プロセスグループはセッションの一部です(セッションは1つ以上のプロセスグループで構成されています)。セッションでは、フォアグラウンド・プロセス・グループと呼ばれるプロセス・グループは最大で1つだけであり、多くのバックグラウンド・プロセス・グループが存在します。フォアグラウンドプロセスグループは、端末の制御権を持っています(制御端末がセッションに接続されている場合)。セッションリーダー(bash)は、tcsetpgrp(3)でプロセスをバックグラウンドからフォアグラウンドに、フォアグラウンドからバックグラウンドに移動します。プロセスグループに送信された信号は、そのグループ内のすべてのプロセスに配信されます。

プロセスグループとジョブコントロールの概念が全く新しい場合は、この回答を完全に理解するためにそれを読んでおく必要があります。これを学ぶには、第9章UNIX環境での高度プログラミング(第3版)があります。

ここで、何が起こっているのか見てみましょう。私たちはパズルのすべての部分を合わせなければなりません。

どちらの場合でも、sshリモート側はbash(1)-cで呼び出します。 -cフラグは、bash(1)を非対話型シェルとして実行します。マンページから:

インタラクティブシェル1は、その標準入力と誤差両端子に接続 (isatty(3)により決定される)、またはある-cオプションなしで、非オプションの引数なしで開始し れます1つは-iオプションで を起動しました。bashが 対話型の場合はPS1が設定され、$ - iはシェルスクリプトまたは起動ファイルが の状態をテストできるようにします。

また、bashのは、非対話モードで開始されたときジョブ制御が無効になっていることを知っておくことが重要です。これは、ジョブ制御が無効であるため、このコマンドをフォアグラウンドとバックグラウンドの間で移動する必要はないため、bashはコマンドを実行するために別のプロセスグループを作成しないことを意味します。 。これは、-tでsshでPTY割り当てを強制したかどうかにかかわらず発生します。

ただし、&を使用すると、シェルがコマンドの終了を待たないという副作用があります(ジョブ制御が無効になっていても)。 manページから:コマンドが制御演算子&によって終了された場合

、シェル はサブシェルでバックグラウンドでコマンドを実行します。シェルは コマンドが終了するのを待たず、戻りステータスは0です。 コマンドはaで区切られています。順次実行される。各コマンドが終了するまで、シェルは を待ちます。戻りステータスは、最後に実行されたコマンドの終了ステータス( )です。

ので、両方のケースでは、bashはコマンドの実行を待機しません、とtouch(1)bash(1)と同じプロセスグループで実行されます。

ここで、セッションリーダーが終了したときにどうなるかを考えてみましょう。 setpgid(2) manページから引用:セッションが制御端末を持っており、その 端末に対してCLOCALフラグが設定されていない、と端末ハングアップは、セッション リーダーがSIGHUPを送信し、発生し

場合。 セッションリーダーが終了すると、SIGHUP シグナルも、制御端末のフォアグラウンドプロセス グループの各プロセスに送信されます。

(重点鉱山)

あなたが-tを使用しない場合は、あなたが-t

を使用していない、リモート側にはPTYの割り当てがないので、bashがない

実際には新しいセッションは作成されません。 sshdはデーモンとして実行されているので、fork + exec()のdashプロセスには制御端末はありません。そのため、bashはセッションリーダーではない(制御端末がない)ため、シェルが非常に早く終了する(おそらくtouch(1)の前に)、プロセスグループにはSIGHUPが送信されません。だからすべてが動作します。

あなたはSSHリモート側が、setsid(2)を呼び出すforkpty(3)と新しいプロセスをフォーク擬似端子+を割り当て、PTYマスター機器の入力を接続してなることを意味-t

-t力PTYの割り当てを、使用あなたのマシンにつながるソケットエンドポイントに出力し、最後にbash(1)を実行します。 forkpty(3)はbashになるforkedプロセスでPTYスレーブ側を開きます。現在のセッションには制御端末がなく、端末装置が開かれているので、PTY装置はセッションの制御端末になり、bashはセッションのリーダーになります。

同じことが再び起こります。touch(1)は、同じプロセスグループなどで実行されます。yadda yadda。要は、今度はであり、であり、セッションリーダーと制御端末である。したがって、bashは&のために待っているので、終了時にSIGHUPがプロセスグループに配送され、touch(1)が早期に死ぬことになります。

についてnohup

nohup(1)まだ競合状態があるので、ここでは動作しません。 bash(1)

nohup(1)は、必要な信号処理やファイルのリダイレクトを設定するための機会を得る前に、それは(何が起こるか、おそらくある)は効果がありません

を可能に修正終了した場合は強制的に再有効化ジョブ制御それを修正する。 bashでは、あなたはset -mでそれを行います。これは動作します:

ssh -t localhost 'set -m ; touch foobar &' 

または力bashが完了するのtouch(1)を待つ:

ssh -t localhost 'touch foobar & wait `pgrep touch`' 
+0

このような明確で詳細な説明をいただきありがとうございます。 – user414310

+1

@ user414310喜んで私は助けることができました。私は言わなければならない、私は質問を愛した。このような偉大な質問をありがとう:) –

関連する問題