
私の理解では、仕事はパイプラインである特定のシェルから開始され、このシェル内からこれらのジョブ ( fg
、bg
、Ctrl-Z) を管理できます。ジョブは複数のプロセス/コマンドで構成できます。
私の質問は、元のシェルが終了したときにこれらのジョブはどうなるかということです。 huponexit が設定されていないため、シェルが終了した後もバックグラウンド プロセスが実行され続けると仮定します。
私が次のことをしたとします:
$ run.sh | grep 'abc' &
[1] job_id
次に、このシェルを終了します。新しいシェルに入り、実行しても、明らかに何も表示されません。ただし、このプロセスが実行されているのを確認jobs
でき、また、実行中のプロセスも確認できます。ps aux | grep run.sh
ps aux | grep grep
grep 'abc'
パイプライン全体のジョブ ID を取得して、一度に強制終了できる方法はありますか。それとも、元のシェルを終了したら、別のシェルからすべてのプロセスを個別に強制終了する必要がありますか。(後者を試してみましたが、うまくいきましたが、すべてのプロセスを追跡するのは面倒なようです。)
答え1
シェルが終了すると、バックグラウンド ジョブに HUP シグナルが送信され、その結果、ジョブが終了することがあります。SIGHUP シグナルは、シェル自体が SIGHUP を受信した場合にのみ送信されます。つまり、ターミナルがなくなった場合 (たとえば、ターミナル エミュレータ プロセスが停止した場合) のみ送信され、シェルを通常どおり終了した場合 (組み込み関数を使用するか、 +exit
を入力して) には送信されません。CtrlDログアウト時に SIGHUP がジョブに送信されないのはどのような場合ですか?そして子プロセスが親プロセスとともに終了する UNIX バリアントはありますか?詳細については、 を参照してください。bash では、huponexit
通常の終了時にバックグラウンド ジョブにも SIGHUP を送信するオプションを設定できます。ksh、bash、zsh では、disown
ジョブを呼び出すと、そのジョブは SIGHUP を送信するジョブのリストから削除されます。SIGHUP を受信したプロセスは、シグナルを無視またはキャッチすることができ、その後は終了しません。nohup
プログラムを実行するときに を使用すると、そのプログラムは SIGHUP の影響を受けません。
プロセスが SIGHUP によって強制終了されない場合、プロセスはそのまま残ります。シェル内のジョブ番号と関連付けるものは何も残っていません。
プロセスがターミナルにアクセスしようとしたが、ターミナルが存在しない場合は、プロセスが終了してしまう可能性があります。これは、プログラムが存在しないターミナルにどのように反応するかによって異なります。
ジョブに複数のプロセス(パイプラインなど)が含まれている場合、これらのプロセスはすべて1つにまとめられます。プロセスグループプロセス グループは、複数の関連プロセスで構成されるシェル ジョブの概念を正確に捉えるために考案されました。プロセス グループ別にグループ化されたプロセスは、プロセス グループ ID (PGID、通常はグループ内の最初のプロセスのプロセス ID) を表示することで確認できます ( ps l
Linux の場合などps -o pid,pgid,tty,etime,comm
)。
に負の引数を渡すことで、グループ内のすべてのプロセスを強制終了することができますkill
。たとえば、強制終了したいパイプラインのPGIDが1234であると判定した場合、次のように強制終了することができます。
kill -TERM -1234
答え2
一般的には、それらはまだ実行されますが、忘れたり気が変わったりした場合は、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:~$