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


24

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

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

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



apt-getインストール画面、男性画面
-captcha

回答:


51

ターミナルウィンドウを閉じると、ターミナルエミュレータは実行中のプロセスであるシェルに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のデフォルトアクションはプロセスを強制終了します)。


4
技術的には、ssh死ぬと接続がドロップし、接続をドロップするとsshdもう一方の端が死にます。リモートシェルが実行される疑似端末のマスター側を制御するそのsshdは、死んだときにハングアップ(実際の端末でプラグを抜くようなものです)であるため、システムはリモートシェルにSIGHUPを送信します。
ステファンシャゼル14

@StéphaneChazelasそれは私が一度も掘ったことがないことの一つです。カーネルがそれを実行している場合、どのプロセスをSIGHUPに決定するのですか?プログラムが使用しようとしない限りプログラムは実行され続けるため、明らかに、そのTTYへのオープンファイル記述子ですべてをSIGHUPするわけではありません。では、現在STDINから読み取っているプログラムを選択しますか(一度にSTDINから読み取ることができるのは1人だけだから)?
パトリック

4
気にしないで、自分の質問に答えました。POSIX IEEE 1003.1 chap 11、モデムの切断が制御端末の端末インターフェイスによって検出された場合... SIGHUP信号が制御プロセスに送信されます
パトリック14

2
また、起動するプログラムの出力をnohup含むnohup.outファイルが生成されることに注意してください。この方法でアプリを起動するためにnohupを使用するたびに(または出力をにリダイレクトする必要があるたびに)そのファイルを削除するのは面倒です/dev/null
ルスラン

1
代わりに、代わりにnohup python program.py &使用setsid python program.pyすることをお勧めします。これにより、プログラムはすぐに無視されます。
Hitechcomputergeek

14

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

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

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

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

3

&同じように、並列に実行するようにオペレータが分離コマンド;が分離コマンドは、直列に実行します。両方の種類のコマンドは、シェルプロセスの子として実行されます

したがって、これらの子を起動したシェルを閉じると、子も閉じられます。

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


1

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

nohup python program.py &

1

アンパサンド(&)で終わるコマンドの後、コマンドプロンプトで次のコマンドを実行します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)`  

at^ d(Control-D)を
参照する前に、コマンドに複数の行を送信できますman at

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.