ログアウトした後もプロセスが実行されているのはなぜですか?


10

からログインした後ssh、次のコマンドを入力しbashます。

sleep 50000000000000 &

次に、私kill -9sleepプロセスの親プロセス(つまり、bash)です。次に、ターミナルウィンドウが同時に切断されます。

再度ログインすると、sleepプロセスがまだ生きていることがわかります。

質問sleepログアウトしてターミナルを閉じてもプロセスが存続するのはなぜですか?私の考えでは、デーモンとnohupプログラム以外のすべてはログアウト中に強制終了されます。sleepこの方法で生き残ることができる場合、nohupコマンドの代わりにこの方法を使用できるということですか?


3
&プロセスを(デーモンのように)バックグラウンドにフォークし、ログアウトしている場合でも実行を継続します。
Aizuddin Zali、2015年

回答:


6

Tl; dr:

sleepログアウトしてターミナルを閉じてもプロセスが存続するのはなぜですか?私の考えでは、デーモンとnohupプログラム以外のすべてはログアウト中に強制終了されます。sleepこの方法で生き残ることができる場合、nohupコマンドの代わりにこの方法を使用できるということですか?

bashによって生成されたインスタンスにオプションが設定されsshていない限り、huponexitプロセスは終了/ログアウト時に決して終了しません。huponexitオプションが設定されている場合、シェルでのkill -9使用nohupはシェルの子プロセスでの使用に代わる適切な方法ではありません。nohupシェルの子プロセスでは、シェルからのSIGHUPからプロセスを保護します。それが重要nohupでない場合でも、シェルを正常に終了できるため、これを優先することをお勧めします。


bash呼ばれるオプションがありますhuponexitセットが作れば、bashSIGHUP終了/ログアウト時にその子は、

によって生成されたインスタンスなどのインタラクティブな非ログイン bashインスタンスでは、このオプションは無視されます。が設定されているかどうかにかかわらず、終了時にの子がSIGHUPされることはありません。bashgnome-terminalhuponexitbashbash

によって生成されたインスタンスなどの対話型ログイン bashインスタンスでは、このオプションは無視されません(ただし、デフォルトでは設定されていません)。が設定されている場合、の子は、終了/ログアウト時にSIGHUPされます。場合は設定されていない、の子供たちがでSIGHUPpedされることはありません終了/ログアウト時。bashsshhuponexitbashbashhuponexitbashbash

したがって、一般に、対話型ログインbashインスタンスからの終了/ログアウトhuponexitは、オプションが設定されていない限り、シェルを子にSIGHUPせず、対話型非ログインbashインスタンスから終了/ログアウトしても、シェルを子にSIGHUPしません関係なく;

ただし、これはこの場合は無関係です。kill -9 sleep親プロセス(bash)を強制終了して、後者が前者に何かをする機会がなくなるため(たとえば、現在のbashインスタンスがログインbashインスタンスである場合)、およびhuponexitオプション)は、それをSIGHUPし、設定しました。

これに加えて、他のシグナル(に送信されるSIGHUPシグナルなど)とは異なりbash、SIGKILLシグナルはプロセスの子プロセスに伝播されないため、強制終了されることsleepさえありません。

nohupSIGHUPシグナルの影響を受けないプロセスを開始します。これは別のものです。これは、SIGHUPシグナルの受信時にプロセスがハングアップするのを防ぎます。SIGHUPシグナルは、このbash場合、huponexitオプションが設定されてシェルが終了した場合に、インタラクティブログインインスタンスによって受信されます。したがって、技術的には、オプションが設定されていないnohup対話型ログインbashインスタンスでプロセスを開始するために使用するhuponexitと、SIGHUPシグナルの受信時にプロセスがハングアップするのを防ぐことができます。

ただし、一般に、nohupSIGHUPシグナルが親シェルから送信されるのを防ぐ必要がある場合は、子メソッドよりkill -9親メソッドのほうを優先する理由はありませんnohup。代わりに、それは逆になります。

使用親死滅kill -9使用子の起動中の方法は、親が正常に終了するための機会を残さないnohup方法と、親コンテキストで意味をなす例を作るようSIGHUPなどの他の信号、(によって終了されることを可能にしますの使用を開始した子のnohup)により、正常に終了できます。


つまり、バックグラウンドで配置されたスクリプトがある場合、親プロセスを強制終了しても、それでも実行されます。そのスクリプトを殺す方法は何でしょうか?
Sergiy Kolodyazhnyy 2015年

@Serg PIDがある場合は、単にPIDを強制終了します。PIDを保存しなかったが、彼の名前でプロセスを識別できる場合は、プロセスをps -e | grep processPIDと一緒にリストする必要があります(またはpgrep -x process、単一のプロセスと一致していて、エッジのないものではないことが確実である場合のみ)。問題は、あなたがプロセスを強制終了する場合ということでkill -9その子が所有しますupstartので、その元PPIDが失われ、そのPPIDは(私の知る限り)それらを認識できない作り、成り上がりのPIDに変更しますが、自分の名前やPIDのために、
KOS

@kos nohup親プロセスからSIGHUPシグナルを受信したときにプロセスがハングアップしないようにするのに失敗するのはどのような場合ですか?バックグラウンドで(PuTTY SSHシェルターミナルで)プロセスを実行しようとしていますnohup <command> <arg> &。PuTTY Xボタンをクリックしてログアウトすると、バックグラウンドプロセスがすぐに終了します。exitPuTTY SSHシェルターミナルに入力してログアウトすると、プロセスは引き続きバックグラウンドで実行されます。
userpal

3

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シグナルを受信し、要求に応じて終了しました。


@kos ---ええ、あなたは正しいです...しかし、なぜ私sleep 1000 & ; exitsleep生き残ったら?お知らせ私があれば、そのプロセスにはなります終了します。そして設定されても、生き残ります。混乱しています...(私は理解を深め、修正を試みます。それ以外の場合は削除します)。kill -HUPsleephuponexitsleep
Rmano 2015年

2

sleepこの方法で生き残ることができる場合、nohupコマンドの代わりにこの方法を使用できることを意味しますか?

kill -9本当にそうすべきではありません。テレビで銃を撃って消すようなものです。コメディの要素以外に利点はありません。プロセスはキャッチまたは無視できませんSIGKILL。プロセスが実行中の処理を完了してクリーンアップする機会を与えないと、破損したファイル(または他の状態)が残り、再開できなくなる可能性があります。kill -9他に何も機能しない最後の希望です。


ログアウトしてターミナルを閉じたときにスリーププロセスが維持できるのはなぜですか。私の考えでは、デーモンとnohupプログラム以外のすべてはログアウト時に殺されます。

あなたの場合はどうなりますか:

の親プロセスsleepは、現在実行中のbashシェルです。あなたの場合はkill -9そのbashのは、bashのプロセスが送信する機会はない持っているSIGHUPので、その子プロセスのいずれかにするSIGKILL(で送信されるkill -9)プロセスによって捕捉可能ではありません。スリーププロセスは実行を継続します。睡眠は孤児のプロセスになりました。

init(PID 1)プロセスは、親の変更と呼ばれるメカニズムを実行します。これは、初期化プロセスが孤立したプロセスの親になることを意味します。initは例外であり、元の親プロセスを失ったプロセスを収集するため、プロセスは子になることができます。ところで:デーモン(などsshd)は、「バックグラウンドで移動する」ときにそれを行います。

それが起こらない場合、孤立したプロセスは後で(終了したときに)ゾンビプロセスになります。これは、がwaitpid()呼び出されなかった場合に発生します(そのプロセスが強制終了されたときにフルフィルできない親プロセスの責任)。initはwaitpid()ゾンビの子供を避けるために特定の間隔で呼び出します。


プロセスは次のように丁寧な信号でも、生き残っているTERMHUP
heemayl

@heemayl HUPはシェル構成に依存しhuponextます:。そしてTERMはスリープが終了するまで待ちます。OPのスリープコマンドの場合、それは数千年になるでしょう=)
混乱

1

&バックグラウンドでプロセスを開始します。と入力ps -efすると、スリープの親プロセスID(PPID)がbashであることがわかります。次に、ログアウトして再度ログインします。ログアウト後もプロセスは実行されたままになります。2回目のログイン後、ps -ef再度実行します。スリーププロセスの親がID "1"のプロセスになることがわかります。つまり、すべてのプロセスの親であるinitです。


0

を使用&すると、プログラムがバックグラウンドで実行されます。プログラムをバックグラウンドで表示するにはbgcommandを使用し、プログラムを再びフォアグラウンドで実行するには、を実行しfgます。

はい、メインターミナルが終了してもプログラムを実行し続ける方法はたくさんあります。


ありがとう。bashのmanページは少し混乱しています。それは言った: "終了する前に、対話型シェルはSIGHUPを実行中または停止中のすべてのジョブに再送信します。" しかし、実際には、シェルはSIGHUPをフォアグラウンドジョブにのみ送信します。バックグラウンドプロセスはSIGHUPシグナルを受信する機会がありません( 'huponexit'シェルオプションを変更しない限り)
tom_cat

@kos多分あなたは正しいです。私はこのポストから上記の結論を引き出す:stackoverflow.com/questions/4298741/...は 今、私は自分自身がもっと混乱してしまいます。
tom_cat

@tom_catこれに戻って、もう一度考えてみましょう:シェルがフォアグラウンドプロセスの実行中に終了することはありません。SIGHUPされているか何かである可能性がありますが、それは終了していません。正解です。逆は意味がないため、バックグラウンドプロセスにのみ適用されます。ただし、さらに調査すると、huponexit経由で取得されたシェルなどのログインシェルでのみ機能することに注意してくださいssh(たとえば、経由で取得されたシェルでは機能しませんgnome-terminal
kos
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.