からログインした後ssh
、 で次のコマンドを入力しますbash
:
sleep 50000000000000 &
次に、プロセスの親プロセス (つまり ) を切断しますkill -9
。sleep
その後bash
、ターミナル ウィンドウが同時に切断されます。
再度ログインすると、sleep
プロセスがまだ実行されていることがわかります。
質問:sleep
ログアウトしてターミナルを閉じてもプロセスが存続できるのはなぜですか? 私の考えでは、デーモンとnohup
プログラム以外はすべてログアウト中に終了するはずです。sleep
このように存続できる場合、コマンドの代わりにこの方法を使用できるということですかnohup
?
答え1
要約:
sleep
ログアウトしてターミナルを閉じてもプロセスが存続できるのはなぜですか? 私の考えでは、デーモンとnohup
プログラム以外はすべてログアウト中に終了するはずです。sleep
このように存続できる場合、コマンドの代わりにこの方法を使用できるということですかnohup
?
bash
によって生成されたインスタンスにssh
オプションが設定されていない限りhuponexit
、終了/ログアウト時にプロセスが終了されることはありません。また、huponexit
オプションが設定されている場合、kill -9
シェルで を使用することはnohup
、シェルの子プロセスで を使用することの代わりとしては適切ではありません。nohup
シェルの子プロセスで を使用すると、シェルからではない SIGHUP から子プロセスが保護されます。また、それが重要でない場合でも、nohup
シェルを正常に終了できるため、 を使用することをお勧めします。
にbash
は というオプションがありhuponexit
、これを設定すると、bash
終了/ログアウト時に子プロセスが SIGHUP されるようになります。
インタラクティブ非ログイン bash
インスタンス、たとえばbash
によって生成されたインスタンスではgnome-terminal
、このオプションは無視されます。huponexit
が設定されているかどうかに関係なく、bash
の子はbash
終了時に によって SIGHUP されることはありません。
インタラクティブログイン bash
インスタンス、たとえばbash
によって生成されたインスタンスではssh
、このオプションは無視されません (ただし、デフォルトでは設定されていません)。 がhuponexit
設定されている場合、bash
の子はbash
終了/ログアウト時にによって SIGHUP されます。huponexit
が設定されていない場合、bash
の子は終了/ログアウト時に によって SIGHUP されませんbash
。
したがって、一般に、オプションが設定されてbash
いない限りhuponexit
、対話型ログイン インスタンスを終了/ログアウトしても、シェルは子に対して SIGHUP を実行しません。また、対話型非ログインbash
インスタンスを終了/ログアウトしても、シェルは子に対して SIGHUP を実行しません。
しかし、この場合はこれは無関係です。 を使用すると、親プロセス( )を終了しても、後者が実行する機会が残らないkill -9
sleep
ため、いずれにせよ存続します。bash
何でも前者(つまり、現在のbash
インスタンスがログインbash
インスタンスであり、huponexit
オプションが設定されている場合は、SIGHUP する)に変更します。
これに加えて、他のシグナル( に送信される SIGHUP シグナルなどbash
)とは異なり、 SIGKILL シグナルはプロセスの子プロセスに伝播されることはなく、したがってsleep
強制終了されることもありません。
nohup
SIGHUP シグナルの影響を受けないプロセスを開始しますが、これは別のものです。SIGHUP シグナルを受信してもプロセスがハングアップするのを防ぎます。この場合、オプションが設定されてシェルが終了しbash
た場合、対話型ログイン インスタンスによってこのシグナルが受信される可能性があります。したがって、技術的には、オプションを設定せずに対話型ログイン インスタンスでプロセスを開始すると、SIGHUP シグナルを受信してもプロセスがハングアップするのを防ぎますが、シェルを終了/ログアウトしても SIGHUP は行われません。huponexit
nohup
bash
huponexit
ただし、一般的に、親シェルからの SIGHUP シグナルを防ぐ必要がある場合、子シェルのメソッドよりも親シェルのメソッドnohup
を優先する理由はありません。代わりに、その逆を行う必要があります。kill -9
nohup
メソッドを使用して親kill -9
を終了しても、親が正常に終了する機会は残されませんが、nohup
メソッドを使用して子を開始すると、親は SIGHUP ( を使用して開始された子のコンテキストで意味をなす例nohup
) などの他のシグナルによって終了され、正常に終了できるようになります。
答え2
bash
デフォルトで終了時に子プロセスにHUPシグナルを送信しない. 詳しくは(@kosさんありがとう)、非ログインシェル。
bashを設定すると、ログインシェルオプションを設定する場合はhuponexit
、ターミナルで次のようにします。
[romano:~] % bash -l
(これにより新しい「ログイン」シェルが起動します)
romano@pern:~$ shopt -s huponexit
romano@pern:~$ sleep 1234 &
[1] 32202
romano@pern:~$ exit
logout
次にsleep
プロセスを確認します。
[romano:~] % ps augx | grep sleep
romano 32231 0.0 0.0 16000 2408 pts/11 S+ 15:23 0:00 grep sleep
...実行されていません: HUP シグナルを受信し、要求どおりに終了しました。
答え3
この方法で生き残ることができる場合、コマンド
sleep
の代わりにこのメソッドを使用できることを意味しますか?nohup
kill -9
は、本当にやるべき方法ではありません。テレビの電源を切るために銃でテレビを撃つようなものです。コメディ要素以外に利点はありません。プロセスは をキャッチしたり無視したりすることはできませんSIGKILL
。プロセスに実行中の処理を終了してクリーンアップする機会を与えないと、破損したファイル (またはその他の状態) が残ってしまい、再起動できなくなります。はkill -9
、他に何も機能しない場合の最後の希望です。
ログアウトしてターミナルが閉じられているのに、スリープ プロセスが存続できるのはなぜでしょうか。私の考えでは、デーモンと nohup プログラム以外のすべてがログアウト時に終了されると思います。
あなたの場合は何が起きますか:
の親プロセスはsleep
現在実行中のbash
シェルです。kill -9
その bash を実行すると、bash プロセスはSIGHUP
子プロセスに を送信する機会がありません。これは、 SIGKILL
( によって送信されるkill -9
) がプロセスによってキャッチできないためです。スリープ プロセスは実行を続けます。スリープは、孤立プロセス。
init (PID 1) プロセスは、再親付けと呼ばれるメカニズムを実行します。つまり、init プロセスは孤立したプロセスの親になります。init は例外で、元の親プロセスを失ったプロセスを収集するため、プロセスは init の子になることができます。ちなみに、デーモン (などsshd
) は「バックグラウンドで実行」するときにこれを実行します。
そうしないと、孤立したプロセスは後で (終了したときに) ゾンビ プロセスになります。これは、がwaitpid()
呼び出されない場合に発生します (そのプロセスが強制終了されたときには果たせない親プロセスの責任)。init は、waitpid()
ゾンビの子プロセスを回避するために、特定の間隔で呼び出します。
答え4
を使用すると、&
プログラムはバックグラウンドで実行されます。バックグラウンドでプログラムを確認するにはbg
、コマンド を使用し、再度フォアグラウンドで実行させるには、 を実行しますfg
。
はい、メインターミナルが終了してもプログラムを実行し続ける方法は多数あります。