web-dev-qa-db-ja.com

シェルを終了した後、バックグラウンドジョブはどうなりますか?

私の理解では、 ジョブはパイプラインです は特定のシェルから開始され、このシェル内からこれらのジョブ(fgbg、Ctrl-Z)を管理できます。ジョブは複数のプロセス/コマンドで構成できます。

私の質問は、シェルを含む元のジョブが終了すると、これらのジョブはどうなるのですか? huponexitが設定されていないため、シェルが終了した後もバックグラウンドプロセスが実行を続けるとします。

私がやったとしましょう:

$ run.sh | grep 'abc' &
[1] job_id

次に、このシェルを終了します。新しいシェルに入ってjobsを実行すると、何も表示されなくなります。しかし、ps aux | grep run.shを実行して、このプロセスが実行されていることを確認できます。また、ps aux | grep grepを実行して、grep 'abc'のプロセスも実行されていることを確認します。

パイプライン全体のジョブIDを取得して、一度に終了できるようにする方法はありますか?または、元のシェルを終了したら、別のシェルからすべてのプロセスを個別に終了する必要がありますか? (私は後者を試しましたが、うまくいきますが、すべてのプロセスを追跡するのは面倒のようです。)

9
user2193268

シェルが終了すると、HUPシグナルがバックグラウンドジョブに送信され、これによりジョブが終了する場合があります。 SIGHUPシグナルは、シェル自体がSIGHUPを受信した場合にのみ送信されます。つまり、ターミナルが終了した場合(たとえば、ターミナルエミュレータープロセスが終了した場合)だけで、シェルを正常に終了した場合(exit組み込みまたはタイピング Ctrl+D)。詳細については、 ログアウト時にSIGHUPがジョブに送信されない場合 および 子プロセスがその親で停止するUNIXバリアントはありますか? を参照してください。 bashでは、huponexitオプションを設定して、SIGHUPを通常の終了時にバックグラウンドジョブに送信することもできます。 ksh、bash、zshでは、ジョブでdisownを呼び出すと、SIGHUPの送信先のジョブのリストから削除されます。 SIGHUPを受信するプロセスは、シグナルを無視またはキャッチする可能性があり、その後、停止しません。プログラムの実行時にNohupを使用すると、SIGHUPの影響を受けなくなります。

SIGHUPの可能性があるためにプロセスが強制終了されなかった場合、そのプロセスは遅れたままになります。それをシェルのジョブ番号に関連付ける必要はありません。

端末にアクセスしようとしたが、端末が存在しなくなった場合でも、プロセスは停止する可能性があります。それは、プログラムが存在しない端末にどのように反応するかによって異なります。

ジョブに複数のプロセス(パイプラインなど)が含まれている場合、これらすべてのプロセスは1つにまとめられますプロセスグループ。プロセスグループは、複数の関連プロセスで構成されるシェルジョブの概念を正確に捉えるために発明されました。プロセスグループIDを表示することにより、プロセスグループごとにグループ化されたプロセスを表示できます(PGID-通常、グループ内の最初のプロセスのプロセスID)。 Linuxでのps lまたはps -o pid,pgid,tty,etime,commのようなものを移植可能にします。

killに負の引数を渡すことにより、グループ内のすべてのプロセスを強制終了できます。たとえば、強制終了するパイプラインのPGIDが1234であると判断した場合は、次のコマンドで強制終了できます。

kill -TERM -1234

一般的にはまだ動作しますが、忘れてしまった、または気が変わった場合はNohupを使用してください。

mike@mike-laptop4:~$ sleep 500
^Z
[1]+  Stopped                 sleep 500
mike@mike-laptop4:~$ bg
[1]+ sleep 500 &
mike@mike-laptop4:~$ jobs
[1]+  Running                 sleep 500 &
mike@mike-laptop4:~$ disown %1
mike@mike-laptop4:~$ jobs
mike@mike-laptop4:~$ 
2
mikejonesey