web-dev-qa-db-ja.com

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

comment on this answer of another question で、コメンターは言います:

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

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

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

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

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

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

83
system PAUSE

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

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

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

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

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

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

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

アプリケーションがSIGKILLを終了する必要がある理由は、クリーンアップシーケンス中に何かがバグアウトした場合だけです。その場合、ターミナルを開いて手動でSIGKILLできます。それとは別に、SIGKILLをするもう1つの理由は、[〜#〜] [-#〜]それを防ぐためです自分自身をきれいにすることから。

世界の半分は5秒後にSIGKILLを盲目的に送信しますが、それでもやるべきことは恐ろしく間違っています。

108
lhunath

ショートアンサーSIGTERM、30秒後、SIGKILLを送信します。つまり、SIGTERMを送信し、少し待機します(プログラムごとに異なる場合がありますが、システムをよく知っているかもしれませんが、5〜30秒で十分です。マシンをシャットダウンすると、自動的に待機します。急いでいるのはなぜですか?)、SIGKILLを送信します。

合理的な回答SIGTERMSIGINTSIGKILLこれで十分です。プロセスはおそらくSIGKILLの前に終了しますvery

ロングアンサーSIGTERMSIGINTSIGQUITSIGABRTSIGKILL

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

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

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

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

ほとんど愚かな長い答え

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

あなたが本当にすべてを試してみる必要がある場合(それはここではなく、合理的な答えを使用することをお勧めします)テーブルが引き起こす破壊に関して順序付けられていると言うのは楽しいでしょうが、それは完全ではありませんtrue)。

アスタリスク(*)の付いたシグナルは、[〜#〜] not [〜#〜]を推奨します。これらについての重要なことは、それが何をするようにプログラムされているかを決して知らないかもしれないということです。特にSIGUSR!それは黙示録を開始するかもしれません(それはプログラマが望むことを何でもするための無料のシグナルです!)。しかし、処理されない場合[〜#〜] or [〜#〜]、まれに終了するように処理された場合、プログラムは終了します。

表では、終了してコアダンプを生成するデフォルトオプションの信号は、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の前に試行する必要があります。これは、プログラムが信号を処理しない場合のほうが良いからです。そして、それらのうちの1つだけを処理する場合、SIGUSR1を処理する可能性がはるかに高くなります。

ところで、KILL:他の答えが述べているように、SIGKILLをプロセスに送信することは間違っていません。さて、shutdownコマンドを送信するとどうなりますか? SIGTERMおよびSIGKILLのみを試行します。なぜそうだと思いますか?そして、非常にshutdownコマンドがこれら2つだけを使用する場合、なぜ他の信号が必要なのですか?


さて、長い答えに戻って、これはニースのワンライナーです:

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

信号間で30秒間スリープします。他にonelinerが必要なのはなぜですか? ;)

また、推奨:合理的な回答からの信号15 2 9のみで試してください。

safety:準備ができたら2番目のechoを削除します。 onlinersdry-runと呼びます。常にテストに使用してください。


kill killfullyfully

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

Killgracefully repository へのGitHubリンク

16
Dr Beco

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

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

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

6
vartec
  • SIGTERMは、ウィンドウで「 'X'をクリックする」ことと同等です。
  • SIGTERMは、シャットダウン時にLinuxが最初に使用するものです。
4
gbarry

ここでのすべての議論では、コードは提供されていません。私の見解は次のとおりです。

#!/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
2
Ohad Schneider

HUPは私にとってはごみのように聞こえます。デーモンに設定を再読み込みさせるために送信します。

SIGTERMは傍受できます。デーモンは、そのシグナルを受け取ったときに実行するクリーンアップコードを持っているだけです。 SIGKILLに対してはできません。したがって、SIGKILLを使用すると、デーモンの作成者にオプションを与えることはできません。

詳細については Wikipedia

0
innaM