プロセスを正常にシャットダウンするために、どのような順序でシグナルを送信する必要がありますか?


88

別の質問のこの回答に対するコメントで、コメント投稿は次のように述べています。

どうしても必要な場合を除いて、kill-9を使用しないでください。SIGKILLをトラップできないため、強制終了されたプログラムは、一時ファイルを消去するなどのシャットダウンルーチンを実行できません。最初にHUP(1)、次にINT(2)、次にQUIT(3)を試してください。

原則的には同意しますSIGKILLが、残りは私にとってのニュースです。によって送信されるデフォルトのシグナルkillSIGTERMであるとすると、任意のプロセスを正常にシャットダウンするために最も一般的に期待されるシグナルであると思います。また、SIGHUPデーモンに「構成ファイルを再読み取り」するように指示するなど、終了しない理由で使用されることもあります。そして、SIGINT(Ctrl-Cで通常発生するのと同じ割り込みですよね?)は、本来あるべきほど広くサポートされていないか、かなり不自然に終了しているように思われます。

それSIGKILLが最後の手段であるとすると、可能な限り正常にシャットダウンするためにどのシグナルをどの順序で任意のプロセスに送信する必要がありますか?

可能であれば、(個人的な好みや意見を超えて)裏付けとなる事実や参考文献であなたの答えを実証してください。

注:bash / Cygwinの検討を含むベストプラクティスに特に興味があります。

編集:これまでのところ、INTやQUITについては誰も言及していないようで、HUPについての言及は限られています。これらを整然としたプロセス殺害に含める理由はありますか?


4
プロセスを本当に強制終了するためにSIGKILLに頼らなければならない場合、それはプログラムのバグだと思います。
sigjuice 2009年

回答:


114

SIGTERMは、アプリケーションに終了を指示します。 他のシグナルは、シャットダウンとは関係のない他のことをアプリケーションに通知しますが、同じ結果になる場合があります。それらを使用しないでください。アプリケーションをシャットダウンする場合は、に指示してください。誤解を招くようなシグナルを与えないでください。

一部の人々は、プロセスを終了するスマートな標準的な方法は、HUP、INT、TERM、最後にKILLなどの多数のシグナルを送信することであると信じています。ばかげてる。終了の正しいシグナルはSIGTERMであり、SIGTERMがプロセスを即座に終了しない場合は、お好みで、アプリケーションがシグナルの処理を選択したためです。つまり、すぐに終了しないのには非常に正当な理由があります。クリーンアップ作業を行う必要があります。そのクリーンアップ作業を他の信号で中断​​した場合、メモリからディスクにまだ保存されていないデータ、ハングしたままになっているクライアントアプリケーション、または事実上データの破損である「文の途中」で中断しているかどうかはわかりません。

シグナルの本当の意味の詳細については、sigaction(2)を参照してください。「デフォルトのアクション」と「説明」を混同しないでください。同じものではありません。

SIGINTは、プロセスのインタラクティブな「キーボード割り込み」を通知するために使用されます。一部のプログラムは、端末ユーザーの目的のために特別な方法で状況を処理する場合があります。

SIGHUPは、端末が消えてプロセスを監視しなくなったことを通知するために使用されます。以上です。一部のプロセスは、それに応じてシャットダウンすることを選択します。一般に、端末なしでは操作が意味をなさないため、一部のプロセスは、構成ファイルの再チェックなどの他のことを行うことを選択します。

SIGKILLは、カーネルからプロセスを強制的に削除するために使用されます。これは、実際にはプロセスへのシグナルではなく、カーネルによって直接解釈されるという意味で特別です。

SIGKILLを送信しないでください。 SIGKILLは、スクリプトによって送信されるべきではありません。アプリケーションがSIGTERMを処理する場合、クリーンアップに1秒かかる場合があり、1分かかる場合があり、1時間かかる場合があります。アプリケーションを終了する前に何をしなければならないかによって異なります。アプリケーションのクリーンアップシーケンスに十分な時間がかかり、X秒後にショートカットまたはSIGKILLする必要があると「想定する」ロジックは、まったく間違っています。

アプリケーションを終了するためにSIGKILLが必要になる唯一の理由は、クリーンアップシーケンス中に何かがバグアウトした場合です。その場合、ターミナルを開いて手動でSIGKILLすることができます。あなたがいるのでそれはさておき、あなたが何かをSIGKILLたい理由を一つだけ他の理由があるWANT自体をクリーンアップするからそれを防ぐために。

世界の半分が5秒後に盲目的にSIGKILLを送信しますが、それでもそれを行うのはひどく間違っています。


13
SIGKILLの誤用がたくさんあるのは確かです。しかし、スクリプトからでも、それを使用する時間と場所があります。多くのアプリがSIGTERMをトラップし、1秒未満またはわずか数秒で正常に終了します。そのうちの1つは、くさびであるため、30秒後も実行されています。
dwc 2009年

4
@dwc:1時間に1回実行してみてください。それが死なない場合、それは「くさび」で修正されるか、怠惰になり、将来的にはしばらくしてからSIGKILLします。 あなたはおそらく何かを破壊していることに注意してください、そしてこれはあなたが「デフォルトで」すべきことではないことを覚えておいてください。
lhunath 2009年

2
@lhunath:よろしければ、質問からより直接的かつ明確に回答できるように、段落を再配置しました。反SIGKILLの暴言は良いものですが、二次的なポイントです。優れた教育的な回答をありがとうございました。
システム一時停止

8
SIGKILLを送信しないでください。これまで。まったく間違っています。本当に?無限ループのおかげでシステムがすでに燃えている場合でも。幸運を。-1
konsolebox 2014

//、これ
Nathan Basanese 2018年

17

短い答え:送信SIGTERM 30秒後にSIGKILLます。つまり、送信しSIGTERMて少し待ちます(プログラムによって異なる場合があります。システムの知識は豊富ですが、5〜30秒で十分です。マシンをシャットダウンすると、最大1分30秒待機することがあります。結局、なぜ急いでいるのですか?)、次に送信しますSIGKILL

合理的な回答SIGTERMSIGINTSIGKILL これは十分すぎるほどです。プロセスがします非常におそらく前に終了しますSIGKILL

ロング回答SIGTERMSIGINTSIGQUITSIGABRTSIGKILL

これは不要ですが、少なくともメッセージに関するプロセスを誤解させることはありません。これらのシグナルすべて、プロセスが実行していることを停止して終了することを意味します。

この説明からどのような答えを選んだとしても、それを覚えておいてください!

他の何かを意味するシグナルを送信する場合、プロセスはそれを非常に異なる方法で処理する可能性があります(一方で)。一方、プロセスがシグナルを処理しない場合は、何を送信してもかまいません。とにかくプロセスは終了します(もちろん、デフォルトのアクションが終了する場合)。

したがって、プログラマーとして自分自身として考える必要があります。たとえば、SIGHUP何かに接続するプログラムを終了するための関数ハンドラーをコーディングしますか、それともループして再接続を試みますか?それがここでの主な質問です!そのため、意図したことを意味する信号を送信することが重要です。

ほとんど愚かな長い答え

次の表には、関連するシグナルと、プログラムがそれらを処理しない場合のデフォルトのアクションが含まれています。

本当にすべてを試す必要がある場合は、使用することを提案する順序で注文しました(BTW、ここではなく、合理的な回答を使用することをお勧めします)。彼らが引き起こすかもしれない破壊、しかしそれは完全に真実ではありません)。

アスタリスク(*)の付いた信号は推奨されません。これらについての重要なことは、それが何をするようにプログラムされているかを決して知らないかもしれないということです。特にSIGUSR!それは黙示録を始めるかもしれません(それはプログラマーが彼/彼女が望むことを何でもするための無料の合図です!)。ただし、処理されない場合、またはまれに終了するように処理される場合、プログラムは終了します。

この表では、コアダンプを終了して生成するためのデフォルトのオプションを持つ信号は、最後のの直前に残されていSIGKILLます。

Signal     Value     Action   Comment
----------------------------------------------------------------------
SIGTERM      15       Term    Termination signal
SIGINT        2       Term    Famous CONTROL+C interrupt from keyboard
SIGHUP        1       Term    Disconnected terminal or parent died
SIGPIPE      13       Term    Broken pipe
SIGALRM(*)   14       Term    Timer signal from alarm
SIGUSR2(*)   12       Term    User-defined signal 2
SIGUSR1(*)   10       Term    User-defined signal 1
SIGQUIT       3       Core    CONTRL+\ or quit from keyboard
SIGABRT       6       Core    Abort signal from abort(3)
SIGSEGV      11       Core    Invalid memory reference
SIGILL        4       Core    Illegal Instruction
SIGFPE        8       Core    Floating point exception
SIGKILL       9       Term    Kill signal

それから私はこれをお勧めしますほとんど愚かな長い答えSIGTERMSIGINTSIGHUPSIGPIPESIGQUITSIGABRTSIGKILL

そして最後に、

間違いなく愚かな長い長い答え

家でこれを試さないでください。

SIGTERMSIGINTSIGHUPSIGPIPESIGALRMSIGUSR2SIGUSR1SIGQUITSIGABRTSIGSEGVSIGILLSIGFPEと、何も働いていない場合SIGKILL

SIGUSR2SIGUSR1プログラムがシグナルを処理しない方が良いので、前に試してみる必要があります。そしてSIGUSR1、それらの1つだけを処理する場合、処理する可能性がはるかに高くなります。

ところで、キルSIGKILL他の答えが述べたように、プロセスに送信することは間違いではありません。さて、shutdownコマンドを送信するとどうなるか考えてみてください。それは試しSIGTERMSIGKILLみます。なぜそうだと思いますか?そして、shutdownコマンド自体がこれら2つだけを使用するのに、なぜ他の信号が必要なのですか?


さて、長い答えに戻って、これは素晴らしいワンライナーです:

for SIG in 15 2 3 6 9 ; do echo $SIG ; echo kill -$SIG $PID || break ; sleep 30 ; done

信号の合間に30秒間スリープします。なぜ他にワンライナーが必要なのですか?;)

また、推奨:妥当な回答15 2 9からのシグナルのみで試してください。

安全性echo行く準備ができたら秒を削除します。私はそれdry-runオンラインユーザーのために私のと呼んでいます。常にテストに使用してください。


巧みにスクリプト

実際、私はこの質問に非常に興味をそそられたので、それを行うための小さなスクリプトを作成することにしました。こちらからダウンロード(クローン)してください:

KillgracefullyリポジトリへのGitHubリンク


8

通常SIGTERMは、デフォルトのkillを送信します。それは理由のためのデフォルトです。プログラムが妥当な時間内にシャットダウンしない場合にのみ、に頼るべきですSIGKILL。ただし、SIGKILLこのプログラムでは、データをクリーンアップする可能性がなく、データが破損する可能性があることに注意してください。

「ハングアップ」の略で、歴史的にモデムが切断されていることを意味しました。本質的にはと同等です。デーモンが時々使用する理由SIGHUPHUPSIGTERMSIGHUPが構成の再起動または再ロードにするは、デーモンが制御端末からデタッチするためです。デーモンはそれらを必要としないためSIGHUP、受信しないため、信号は一般的な使用のために「解放された」と見なされました。すべてのデーモンがこれをリロードに使用するわけではありません!SIGHUPのデフォルトのアクションは終了することであり、多くのデーモンはそのように動作します!したがってSIGHUP、デーモンに盲目的にsを送信し、デーモンが存続することを期待することはできません。

編集: SIGINTプロセスは通常^C、プログラムを中断するための端末設定に関連付けられているため、プロセスを終了するにはおそらく不適切です。多くのプログラムは独自の目的でこれをキャプチャするため、機能しないのは十分に一般的です。SIGQUIT通常、デフォルトでコアダンプが作成されます。コアファイルを配置する必要がない限り、コアダンプも適切な候補ではありません。

要約:送信SIGTERMしてもプログラムが時間枠内に終了しない場合は、送信してくださいSIGKILL


4
SIGKILLによるフォローアップは、データの損失/データの破損を防ぐよりも、即座にシャットダウンすることが優先される状況でのみ実行する必要があることに注意してください。
thomasrutter 2013

@dwcあなたの答えの次の点がわかりませんでした。「デーモンがSIGHUPを使用して構成を再起動または再ロードすることがある理由は、デーモンが制御端末から切り離されるため、SIGTERMを受信しないため、シグナルは一般的な使用のために「解放された」と見なされたためです。」
ジャック

3
@Jack試してみましょう:SIGHUPは、端末が切断されたことをプロセスに通知する「ハングアップ」信号です。デーモンはバックグラウンドで実行されるため、端末は必要ありません。つまり、「ハングアップ」信号はデーモンには関係ありません。そもそも端末が接続されていないため、端末の切断から受信することはありません。また、シグナルはとにかく定義されているため、元の目的では必要ありませんが、多くのデーモンは、構成ファイルの再読み取りなど、別の目的でシグナルを使用します。
システム一時停止2013

システムPAUSEに感謝します。これは役に立ちます。
ジャック

6

SIGTERM実際には、アプリケーションにメッセージを送信することを意味します:「あなたはとても親切で自殺しますか」。クリーンアップおよびシャットダウンコードを実行するために、アプリケーションによってトラップおよび処理できます。

SIGKILLアプリケーションによってトラップすることはできません。アプリケーションは、クリーンアップの機会なしにOSによって強制終了されます。

SIGTERM最初に送信し、しばらくスリープしてから送信するのが一般的SIGKILLです。


ポーリングは(SIGKILLの前に)寝るよりも少し効率的だと思います
Ohad Schneider

@OhadSchneiderですが、単純なbashコマンド以上のものが必要になります。
vartec 2017年

ええ、次のようなものを使用して、プロセスがまだ生きている間にループする必要があると思います:stackoverflow.com/a/15774758/67824
オハドシュナイダー2017

5
  • SIGTERMは、ウィンドウで「「X」をクリックする」ことと同じです。
  • SIGTERMは、Linuxがシャットダウンするときに最初に使用するものです。

それが私が知りたかったことです。+1。ありがとう。
luc

6
「SIGTERMは、ウィンドウ内の「X」をクリックすることと同じです」いいえ、そうではありません。ダイアログはもちろん、1つのアプリケーションで任意の数の(ドキュメントやツールなどの)ウィンドウを簡単に開くことができるためです。終了コマンドと同じように、最後のウィンドウを閉じるコマンドにも応答します(明白な例は考えられませんが、自明ではありませんが、そのように実行できない理由はありません)。SIGTERMは、アプリケーションに終了を適切に要求することと同等です(またはそうである必要があります)が、その特定のアプリケーションで実行される可能性があります
ユーザー

3

ここですべての議論が行われているため、コードは提供されていません。これが私の見解です:

#!/bin/bash

$pid = 1234

echo "Killing process $pid..."
kill $pid

waitAttempts=30 
for i in $(seq 1 $waitAttempts)
do
    echo "Checking if process is alive (attempt #$i / $waitAttempts)..."
    sleep 1

    if ps -p $pid > /dev/null
    then
        echo "Process $pid is still running"
    else
        echo "Process $pid has shut down successfully"
        break
    fi
done

if ps -p $pid > /dev/null
then
    echo "Could not shut down process $pid gracefully - killing it forcibly..."
    kill -SIGKILL $pid
fi

0

HUPは私にはゴミのように聞こえます。デーモンにその構成を再読み取りさせるために送信します。

SIGTERMは傍受される可能性があります。デーモンには、そのシグナルを受信したときに実行するクリーンアップコードがある場合があります。SIGKILLではそれを行うことはできません。したがって、SIGKILLを使用すると、デーモンの作成者にオプションを与えることはありません。

ウィキペディアで詳細をご覧ください

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