kill-9とkill-15の違い


多くのプログラマーはLinuxシステムに慣れていないと信じています.自分の日常開発機器がLinuxでなくても、オンラインサーバの大部分はそうです.だから、よく使われるLinuxコマンドを身につけるのもプログラマーに必要なスキルです.
しかし、一部の命令については一知半解で、不適切な使用でオンライン障害を引き起こす人が多いのではないかと心配しています.
この間、私たちのオンラインアプリケーションは警報を適用して、頻繁にFGCして、緊急に問題を処理する必要があって、そこで同僚がオンラインに行って機械を再起動します(正常なプログラムはまずスタックdumpを採集して、それから再起動して、メモリの漏洩などの問題があるかどうかを調べるのに便利です).
しかし、再起動中、同僚は正常な再起動コマンドが反応していないことを発見し、killコマンドを使用してJavaプロセスを「殺す」ことを試みたが、依然として無効だった.そこで彼は私的に「kill-9」を使ってプロセスの生命を終わらせることにした.
アプリケーションプロセスは実行されましたが、それに伴って多くの問題が発生しました.まず、上流システムで突然大量のアラームが発生し、開発に対応してRPCサービスを呼び出すと応答がなく、頻繁にタイムアウトします.
その後、システムには汚いデータが一部存在し、同じトランザクションで完全に更新する必要があるデータが半分しか更新されていないことがわかりました.
なぜ正常なkillはプロセスを「殺す」ことができず、kill -9でよいのか.なぜkill -9がこの一連の連鎖反応を引き起こしたのか.通常のkill実行時、JVMはどのように処理しますか?
これらの問題を明らかにするには、まずkillコマンドから話します.
killコマンド
Linuxで1つのプロセスを終了するには2つの方法があり、フロントプロセスであればCtrl+Cキーを使用して終了することができます.バックグラウンドプロセスの場合はkillコマンドを使用して終了する必要があります.(実はCtrl+Cもkillコマンド)
killコマンドのフォーマットは次のとおりです.
kill[  ][   ]

 :

kill 21121

kill -9 21121

ここで[パラメータ]はオプションで、jps/ps/pidof/pstree/topなどのツールでプロセス番号を取得できます.
killのコマンドパラメータは次のとおりです.
-l信号です.信号の番号付けパラメータを付けない場合は、「-l」パラメータを使用してすべての信号名がリストされます.
-a現在のプロセスを処理する場合、コマンド名とプロセス番号の対応関係は制限されません.
-p killコマンドは、関連するプロセスのプロセス番号のみを印刷し、信号を送信しないことを指定します.
-s指定送信信号
-uユーザーの指定
通常、-l(信号)を使用する場合が多く、前述したkill -99が信号である.
信号が指定されていない場合、デフォルトでは終了信号(15)が発行されます.一般的な信号は次のとおりです.
HUP 1終端断線
INT 2割り込み(Ctrl+Cと同じ)
QUIT 3脱退(Ctrl+)
TERM 15終端
KILL 9強制終了
CONT 18続行(STOPとは逆にfg/bgコマンド)
STOP 19一時停止(Ctrl+Zと同じ)
よく使われるのは :9 :15です.また、 :2は、前述したCtrl+Cがフロントプロセスを終了することです.
では、kill -9kill -15はいったいどんな違いがあるのでしょうか.どうすればいいですか?
kill-9とkill-15の違い
killコマンドのデフォルトの信号は15で、まずこのデフォルトのkill -15信号について説明します.kill -15が使用されると、システムはSIGTERMの信号を対応するプログラムに送信する.プログラムがこの信号を受信した後、具体的にどのように処理するかは自分で決めることができる.
この場合、アプリケーションは次のように選択できます.
  • 1、即時停止プログラム
  • 2、応答リソースを解放する後にプログラム
  • を停止する.
  • 3、この信号を無視して、プログラム
  • の実行を継続する.kill -15信号は、対応するプロセスに「安全でクリーンな終了」を通知するだけであるため、プログラムが信号を受信した後、終了前にリソース解放、一時ファイルクリーンアップなどの「準備作業」を行い、準備作業が完了したら、プログラムの終了を行うのが一般的である.ただし、「準備作業」の進行中にブロックやその他の問題が発生して成功しなかった場合、アプリケーションは終了信号を無視することを選択できます.これは、デフォルトのkill信号がSIGTERM(15)であり、SIGTERM(15)の信号がブロックされ、無視されるため、killコマンドを使用することがある理由です.kill -15と比較して、kill -9は相対的に強硬で、システムはSIGKILL信号を出して、彼はこの信号を受信したプログラムがすぐに運行を終了すべきで、ブロックされたり無視されたりしてはいけないと要求します.したがって、kill-15コマンドに比べて、kill-9は実行時にアプリケーションが「準備作業」を行う時間がないため、通常、データが失われたり、端末が正常な状態に戻らないなどの副作用をもたらす.JavaがSIGTERM(15)をどのように処理するかはよく知られていますが、LinuxではJavaアプリケーションは独立したプロセスとして実行され、Javaプログラムの終了実行はJVMの閉鎖に基づいて実現され、JVMの閉鎖方式は3種類に分けられています.
    正常に閉じる:最後の非デーモンスレッドが終了するか、Systemが呼び出される.exitまたは他の特定のプラットフォームの方法でシャットダウン(SIGINT(2)、SIGTERM(15)信号を受信など)強制シャットダウン:Runtimeを呼び出す.haltメソッドまたはオペレーティングシステムにおいてkill(SIGKILL(9)信号を受信)異常クローズを強制する:運転中にRuntimeException異常に遭遇するなど.
    JVMプロセスは、kill -15の信号通知を受信したときに、一時ファイルの削除などのクリーンアップ動作を行うことができます.もちろん、開発者もtomcatコンテナを停止させ、dubboサービスをラインオフさせるなど、追加のことをカスタマイズすることができます.このようなカスタムJVMクリーンアップ動作は、JDKで提供されるshutdown hookによって実現される.JDKはJavaを提供しています.Runtime.addShutdownHook(Thread hook)メソッドでは、JVMが閉じたフックを登録できます.例は次のとおりです.
    public class ShutdownHookTest {
    
    
        public static void main(String[] args) {
    
            boolean flag = true;
    
            Runtime.getRuntime().addShutdownHook(new Thread(() -> {
    
                System.out.println("hook execute...");
    
            }));
    
    
            while (flag) {
    
                // app is runing
    
            }
    
    
            System.out.println("main thread execute end...");
    
        }
    
    }

    コマンドの実行:
    ➜ jps 6520 ShutdownHookTest 6521 Jps ➜ kill 6520
    コンソール出力:
    hook execute... Process finished with exit code 143 (interrupted by signal 15: SIGTERM)
    kill(デフォルトkill-15)を使用してプロセスを閉じると、プログラムは私が登録したshutdownHookを実行してから終了し、interrupted by signal 15: SIGTERMコマンドkill -9を実行すると、ヒントが与えられます.
    ➜ kill -9 6520

    コンソール出力:
    Process finished with exit code 137 (interrupted by signal 9: SIGKILL)

    kill-9を使用してプロセスを強制的に閉じると、プログラムはshutdownHookを実行せずに直接終了し、interrupted by signal 9: SIGKILLのまとめ:killコマンドはLinuxプロセスを終了するために使用され、デフォルトでは、信号を指定しない場合、killはkill -15に等価であることがわかります.kill -15が実行されると、システムは対応するプログラムにSIGTERM(15)信号を送信し、この信号は実行、ブロック、無視することができるので、アプリケーションは信号を受信した後、いくつかの準備をしてプログラムの終了を行うことができる.場合によっては、kill -15はプログラムを終了することができません.彼は無視される可能性があるため、kill -9を使用することができます.システムはSIGKILL(9)信号を発行します.この信号は無視とブロックを許可しないので、アプリケーションはすぐに終了します.これにより、データ損失などの副作用も多くなるため、必要でない場合はkill -9コマンドを使用しないでください.特に、ウェブアプリケーション、RPCサービスの提供、タイミングタスクの実行、長いトランザクションを含むアプリケーションでは、kill -9はspringコンテナ、tomcatサービス、dubboサービス、プロセスエンジン、ステータスマシンなどに十分な時間を与えていないためです.