プロセスの終了 kill

プロセスの終了 kill とは

不要なプロセスを終了させるkillコマンドの使い方をターミナルで実践的に学びます。本レッスンでは、プロセスの終了 kill の基本から実際の使いどころまでを整理し、現場で迷わず使える形に落とし込みます。

なぜ重要か

アプリが応答しない、ポートが解放されない、無限ループしているスクリプトを止めたい、デプロイ前に旧バージョンのプロセスを終了させたい。サーバーや開発機を運用していると「特定のプロセスを止める」場面は数えきれないほど出てきます。そのときに使うのが kill です。名前は物騒ですが、本質は「シグナルを送る」コマンドで、プロセスに対して終了や再読み込みなどの命令を伝える仕組みです。

kill を雑に扱うと、データを書き込み途中のデータベースを強制終了して破損させたり、関係ないプロセスを止めてサービスを巻き込み事故にしたりします。本レッスンではシグナルの種類、正しい使い分け、子プロセスの後始末まで丁寧に押さえます。

基本構文

ターミナル

kill [-シグナル] PID kill -l

-l でシグナルの一覧を表示できます。シグナルは番号または名前で指定し、SIGTERM のように頭の SIG を省略して TERM とも書けます。

シグナル番号用途
TERM15デフォルト。穏便に終了
KILL9強制終了 (捕捉不可)
HUP1設定再読み込み、または切断
INT2Ctrl+C 相当
QUIT3Ctrl+\ 相当、コアダンプ
STOP19一時停止 (捕捉不可)
CONT18停止からの再開

シグナルの流れ

diagram (will load when visible)

kill はカーネルにシグナル送信を依頼するだけで、実際にどう反応するかはプロセス自身が決めます。SIGTERM はキャッチして後始末してから終了できますが、SIGKILL だけはプロセスがキャッチできず、カーネルが強制的に終わらせます。

代表例

穏便に終了する

ターミナル

kill 1234 # 番号省略時は SIGTERM (15) が送られる

これが基本形です。アプリは終了処理を実行できます。データを書き出してからプロセスを抜けるような行儀の良いデーモンであれば、まずこれで止めます。

反応しないので強制終了

ターミナル

kill -9 1234 # または kill -KILL 1234

SIGTERM では止まらないプロセスに対して使う最終手段です。ただしデータ整合性のリスクがあるので、データベースなどは多少待ってでも SIGTERM を優先します。

設定再読み込み

ターミナル

kill -HUP 789 # nginx などは HUP で設定ファイルを再読み込みする

アプリを再起動せずに設定を反映できる代表的な使い方です。再起動だと数秒の停止が発生するので、HUP を使えるなら使うほうが運用上有利です。

名前で kill する pkill, killall

ターミナル

pkill -f "node /app/server.js" killall nginx

PID を毎回調べるのが面倒なときは、pkillkillall で名前マッチで送れます。ただしマッチ条件が広すぎると同名の関係ないプロセスまで巻き込みます。-f を付けるとコマンドライン全体に対してマッチします。

pkill -9 -f . のように曖昧なパターンを使うと、自分のセッションを含むすべてのプロセスを巻き込みます。事前に pgrep -f パターン で対象を確認するクセを付けましょう。

子プロセスを必ず回収する

バックグラウンドで起動した子プロセスは、親プロセスが wait で終了コードを回収するまでゾンビとして残ります。シェルスクリプトでは次のイディオムを覚えておくと役立ちます。

ターミナル

sleep 100 & pid=$! # ... 何か処理 ... kill $pid 2>/dev/null wait $pid 2>/dev/null

$! は直前のバックグラウンドジョブの PID です。kill の後に wait を必ず挟むと、子の終了をきれいに回収できます。本レッスンの演習でもこの形を使います。

SIGTERM と SIGKILL の段階的運用

本番運用では「まず TERM、ダメなら KILL」という段階的アプローチが安全です。

ターミナル

kill 1234 sleep 5 if kill -0 1234 2>/dev/null; then kill -9 1234 fi

kill -0 PID は「シグナルを送らずに、対象が生存しているか確認する」ためのイディオムです。これでまだ生きていれば SIGKILL に切り替えます。systemd の TimeoutStopSec の挙動も内部はこの考え方と同じです。

Docker の docker stop も、内部は SIGTERM を送って 10 秒待ち、終わらなければ SIGKILL という二段構えです。STOPSIGNAL ディレクティブで一段目を変えられます。

演習で確認するポイント

演習では sleep 100 & で長時間プロセスを作り、PID を $! で受け取って kill で終了させます。wait で終了コードを回収し、ゾンビが残らないことを確認しましょう。Cloud Functions のサンドボックス上では他人のプロセスは触れないため、自分で生やした子だけを kill する形になります。

まとめ

  • kill はシグナルを送るコマンドで、デフォルトは SIGTERM (15)
  • SIGKILL (9) はプロセスがキャッチできない強制終了で、最終手段
  • 設定再読み込みなど特殊用途は SIGHUP, SIGUSR1 などを使う
  • pkill, killall は便利だが対象をうっかり広げないように事前確認する
  • バックグラウンド子プロセスは kill の後に wait で回収する

次のレッスン

次は フォアグラウンドとバックグラウンド で、不要なプロセスを終了させるkillコマンドの使い方をターミナルで実践的に学びます を学びます。

事前確認 — 進む前に次の 3 つができることを確認しましょう。

  1. kill コマンド の要点を自分の言葉で説明できる
  2. このレッスンの最小コード (または操作手順) を見ずに書ける
  3. 練習問題やクイズで間違えた箇所を読み直して理解した

理解度チェック (30 秒)

Q. kill コマンド とは何か、1 文で説明してください。

この章のポイント

A. 本文の「このレッスンで分かること」または冒頭の説明文を見直し、自分の言葉で要約できれば OK。詰まったら本レッスンの最初の H2 セクションを読み返してみましょう。

関連レッスン

課題

  1. sleep をバックグラウンドで起動する
  2. kill で確実に終了させる
  3. wait で後始末する

ヒント

script.sh
script.sh
学習モード
script.sh
ターミナル出力