web-dev-qa-db-ja.com

「&」を使用しています。なぜプロセスがバックグラウンドで実行されないのですか?

コマンドに&を追加して、プロセスをバックグラウンドで実行できることを知っています。

Ubuntu 12.04ボックスにSSHで接続し、pythonプログラムを$python program.py &で実行しています--ターミナルウィンドウを閉じると、端末は実行中のプロセスを強制終了します。

どうしてこれなの?アンパサンドを使用して、プロセスをバックグラウンドで実行しています。 SSHを使用しているかどうかに関係なく、どうすれば実行できますか?

27
bernie2436

ターミナルウィンドウを閉じると、ターミナルエミュレータはSIGHUPを実行中のプロセスであるシェルに送信します。次に、シェルはそのSIGHUPを実行中のすべてのものに転送します。ローカルシステムでは、これはsshです。次に、sshはSIGHUPを実行中のリモートシェルに転送します。そのため、リモートシェルはバックグラウンドプログラムであるすべてのプロセスにSIGHUPを送信します。

これを回避するには2つの方法があります。

  1. シェルとバックグラウンドのプログラムの関連付けを解除します。
    1. プロセスのバックグラウンドを作成した後、disownコマンドを使用します。これにより、シェルはそのことを忘れます。
    2. コマンドの前にNohupNohup $python program.py &)を付けます。これは同じことを実現しますが、中間プロセスを使用します。基本的に、SIGHUPシグナルを無視し、設定を継承するプログラムをフォークして実行し、終了します。フォークされているため、起動されるプログラムはシェルの子ではなく、シェルはそれを認識していません。そして、SIGHUPのシグナルハンドラーをインストールしない限り、とにかく無視アクションを保持します。
  2. ターミナルウィンドウを閉じる代わりにlogoutを使用します。 logoutを使用する場合、これはSIGHUPではないため、シェルはSIGHUPをその子に送信しません。

さらに、端末が終了するとこれらの両方が存在しなくなるため、プログラムがSTDOUTまたはSTDERRを介して端末に書き込まないようにする必要があります。それらを/dev/nullのようなものにリダイレクトしない場合でも、プログラムは実行されますが、それらに書き込もうとすると、SIGPIPEを取得し、SIGPIPEのデフォルトのアクションはプロセスを強制終了することです) 。

53
Patrick

プロセスはターミナルのバックグラウンドで実行されていますが、stdout(およびstderr)からの出力はまだターミナルに送信されています。これを停止するには、> /dev/null 2>&1の前に&を追加して、両方の出力を/dev/nullにリダイレクトします。また、disownを追加すると、ターミナルを閉じた後にプロセスが強制終了されません。

COMMAND > /dev/null 2>&1 & disown

あなたの場合、これは次のようになります:

python program.py > /dev/null 2>&1 & disown
14
Wilf

&演算子は、;がコマンドを直列に実行するように分離するのと同じように、コマンドを分離して並列に実行します。どちらの種類のコマンドもシェルプロセスの子として実行のままです。

したがって、それらの子を開始したシェルを閉じると、子も閉じられます。

あなたが望むように見えるのは、デーモンプロセスです。これは、親プロセスから完全に分離する必要があるため、非常にトリッキーです。シェルには通常、それを行う簡単な方法はありません。

4
bignose

ログアウトすると、通常、ログインセッションに関連付けられているバックグラウンドプロセスも強制終了されます。セッションから切断する場合は、Nohupを使用して実行します。

Nohup python program.py &
1
Barmar

アンパサンド(&)で終わるコマンドの後、コマンドプロンプトでコマンドbgを実行します。

bash> python program.py &  
bash> bg  

これにより、「&」コマンドが背景に表示されます

bash> jobs  

これにより、バックグラウンドで実行中のジョブが一覧表示されます

bash> fg 1   

これにより、ジョブ#1が前面に表示されます

別の方法(ログアウトできるようにするため)

bash> at now  
bash> /full/path/python /full/path/program.py  
bash> ^d   `(# That is, Control-D, to run the command, Control-C to cancel)`  

^ d(Control-D)の前に、atコマンドに複数の行を送信できます。
man atを参照してください。

1
martin