signal(シグナル)とは - SIGTERM / SIGKILL / SIGHUP の違い
この記事で解決できること
SIGTERM/SIGKILL/SIGHUPの 違いと使い分け が分かる- 「
kill -9を最初から使うべきか?」に 根拠を持って答えられる ようになる - プロセスが「終了しない」「設定が反映されない」ときの 切り分けの軸 が手に入る
結論(実務の型)
- まず
kill(=SIGTERM)で 穏便に終了 を試す - 反応しなければ
kill -KILL(=SIGKILL)で 強制終了 kill -9を 反射的に使わない。後始末をスキップさせる最終手段と理解する
signal(シグナル)とは何か?
結論: signal はカーネルがプロセスへ送る非同期の通知。プロセスはそれを受けて終了・停止・再読み込みなどの規定動作を行う。
signal(シグナル)は、カーネルからプロセスへ送られる非同期のソフトウェア割り込み である。「終了してほしい」「停止してほしい」といった短いメッセージを番号で伝える仕組みで、プロセス間通信(IPC)の最も軽量な形のひとつにあたる。
signal が送られる経路は主に 3 つ。
- キーボード操作:
Ctrl+C→SIGINT、Ctrl+Z→SIGTSTP kill/pkillコマンド: 任意のプロセスへ任意の signal を送る- カーネル / 他プロセス: メモリ不足時の
SIGKILL(OOM Killer)、不正メモリアクセス時のSIGSEGVなど
利用可能な signal の一覧は kill -l で確認できる。
$ kill -l
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM ...
signal 番号は すべてが固定ではない。SIGHUP(1) / SIGINT(2) / SIGKILL(9) / SIGTERM(15) など低番号は安定しているが、SIGUSR1 などはアーキテクチャで番号が変わる。スクリプトでは 番号より名前(-TERM / -KILL)で指定するのが安全。
SIGTERM とは?なぜ既定なのか?
結論: SIGTERM(15)は「穏便に終了して」という依頼。プロセスは捕捉して後始末(ファイル保存・接続クローズ)してから終われる。kill の既定値。
SIGTERM(番号 15)は、kill コマンドが signal を指定しなかったときに送る既定の signal である。
# この 2 つは等価 $ kill 12345 $ kill -TERM 12345
SIGTERM の重要な性質は、プロセスが これを捕捉(catch)できる ことだ。受け取ったプロセスは終了する前に、
- 編集中ファイルの保存
- データベース接続やソケットのクローズ
- 一時ファイルの削除
- 子プロセスへの終了通知
といった 後始末(cleanup) を実行してから自分で exit() できる。これが graceful shutdown(穏便な終了) であり、systemd がサービス停止時にまず SIGTERM を送るのもこのためだ。
データを扱うプロセス(DB・エディタ・アプリサーバ)を止めるときは、必ず SIGTERM を先に試す。いきなり強制終了するとデータ破損のリスクがある。
SIGKILL とは?SIGTERM と何が違う?
結論: SIGKILL(9)はカーネルが即座にプロセスを消す強制終了。捕捉・無視・ブロックが一切できず、後始末も走らない最終手段。
SIGKILL(番号 9)は、kill -9 でおなじみの 強制終了 signal である。SIGTERM との決定的な違いは次の 1 点に集約される。
SIGKILL と SIGSTOP だけは、プロセス側で捕捉・無視・ブロックが一切できない。
カーネルがプロセスのハンドラを通さず直接終了させるため、後始末コードは 一切実行されない。
つまり kill -9 は、
- 編集中のデータが 保存されない
- 開いていたファイル・ソケットが 正常にクローズされない
- 一時ファイルや lock ファイルが 残る
- 子プロセスが 孤児(orphan)になる
といった副作用を伴う。これらは OS がある程度回収するが、アプリケーションレベルの整合性は保証されない。
| 観点 | SIGTERM (15) | SIGKILL (9) |
|---|---|---|
| 捕捉できるか | できる | できない |
| 後始末(cleanup) | 走る | 走らない |
| データ保存 | 期待できる | されない |
| 使いどころ | 通常の終了 | TERM が効かないとき |
kill -9 を最初から使うのは避ける。「終わらないからとりあえず -9」は、固まった原因(デッドロック・I/O 待ち)を隠したままデータを失う行為になりがち。まず SIGTERM、数秒待って反応がなければ SIGKILL、という順序を守る。
SIGHUP とは?終了以外の使い道
結論: SIGHUP(1)は元来「端末が切れた」通知だが、デーモンでは「設定ファイルを再読み込みせよ」の合図として再利用される慣習がある。
SIGHUP(番号 1、hang up = 回線切断)は、もともと 制御端末との接続が切れたときに送られる signal だ。ターミナルを閉じると、そこで起動したプロセスには SIGHUP が届き、既定動作では終了する。nohup コマンドが「SIGHUP を無視して実行を継続する」ためのものなのは、この仕様への対処である。
一方、多くの デーモン(常駐プロセス) は SIGHUP を独自に解釈し、「プロセスを再起動せずに設定ファイルを読み直す」合図として使う慣習がある。
# nginx に設定リロードを指示(プロセスは止めない) $ kill -HUP $(cat /var/run/nginx.pid)
この「再読み込み」は signal の仕様ではなく、各デーモンが実装している 慣習 にすぎない。挙動はソフトごとに異なるため、必ず公式ドキュメントで SIGHUP の扱いを確認すること。
SIGINT / SIGSTOP など他の主要 signal
結論: 日常で触れる signal は SIGINT(Ctrl+C)と SIGTSTP(Ctrl+Z)。SIGSTOP / SIGCONT は捕捉不可で、プロセスの一時停止と再開に使う。
ターミナルでよく発生する signal を押さえておく。
SIGINT(2):Ctrl+C。「割り込み」。既定では終了するが捕捉可能(多くの CLI が確認プロンプトを出すのはこのため)。SIGTSTP(20):Ctrl+Z。フォアグラウンドのジョブを一時停止。fg/bgで再開できる。SIGSTOP(19)/SIGCONT(18): プロセスの停止と再開。SIGSTOPはSIGKILL同様 捕捉不可。SIGQUIT(3):Ctrl+\。終了 + コアダンプ生成。
Ctrl+Z で止めたジョブの扱いは ジョブ制御の基本 で詳しく扱っている。
実務での送り方:kill / pkill / killall
結論: PID 指定なら kill、名前指定なら pkill / killall。誤爆を避けるため、まず pgrep で対象を確認してから送るのが安全。
signal を送る代表的なコマンドは 3 つ。
# PID を指定して送る(最も基本) $ kill -TERM 12345 # プロセス名で送る(部分一致) $ pkill -TERM nginx # プロセス名で送る(完全一致、killall) $ killall -TERM nginx
pkill / killall は マッチした全プロセスに送る。意図しないプロセスを巻き込まないよう、送る前に pgrep -a <名前> で対象を必ず確認すること。
$ pgrep -a nginx
「まず TERM、効かなければ KILL」を 1 行で書くなら、間に待機を挟む。
$ kill -TERM 12345; sleep 5; kill -KILL 12345 2>/dev/null
まとめ:signal 使い分けの早見表
結論: 穏便な終了は SIGTERM、最終手段が SIGKILL、設定リロードは SIGHUP。番号より名前で指定し、強制終了は最後に回す。
| やりたいこと | 送る signal | コマンド例 |
|---|---|---|
| 普通に終了させる | SIGTERM | kill <PID> |
| どうしても止まらない | SIGKILL | kill -KILL <PID> |
| 設定を再読み込み | SIGHUP | kill -HUP <PID> |
| 一時停止 / 再開 | SIGSTOP / SIGCONT | kill -STOP / -CONT |