MENU

暴走・フリーズしたプロセスを確実に停止する実務手順

Linuxサーバーでプロセスが応答しなくなったとき、まずやることは2ステップです。①対象のPIDを調べる、②そのPIDにシグナルを送る。この2ステップで大半のケースは片付きます。

目次

最短2ステップ:PIDを調べてシグナルを送る

対象プロセス名が myapp の場合を例に、最短手順を示します。

# PIDを調べる
pgrep myapp

# 得られたPIDにSIGTERM(終了要求)を送る
kill -15 12345

kill -15(SIGTERM)を送ると、プロセスは自身でクリーンアップ処理をしてから終了します。数秒待っても消えない場合は kill -9(SIGKILL)に切り替えます。SIGKILLはカーネルが強制的にプロセスを破棄するため必ず止まりますが、後処理は一切走りません。

# どうしても止まらないときの最終手段
kill -9 12345

注意:kill -9 はログのフラッシュやロックファイルの解放が省略されます。DBプロセスを強制終了するとデータファイルが破損するリスクがあるため、SIGTERMが効かないときにのみ使用してください。

プロセスIDを調べる3つの方法

PIDを取得する方法はいくつかあります。目的に応じて使い分けると確実です。

pgrep:プロセス名でPIDだけ取得

pgrep -l nginx
# 出力例:
# 1234 nginx
# 1235 nginx

-l オプションを付けるとプロセス名もあわせて表示されるため、本当に目的のプロセスかどうかを一目で確認できます。

ps aux:詳細な一覧から目視確認

ps aux | grep myapp

CPU使用率・メモリ使用率・コマンドライン全体が表示されるため、引数まで含めて「正しいプロセスか」を確認できます。状態欄が Z のゾンビプロセスはシグナルで消せません。親プロセスが wait() するか、親ごと終了させる必要があります。

pidof:コマンド名が完全一致する場合

pidof sshd

コマンド名と完全一致するプロセスのPIDをスペース区切りで返します。マスター+ワーカー構成のサービスでは複数のPIDが返るため、正しい対象を選んで操作します。

systemdサービスは systemctl 経由で止める

systemdで管理されているサービス(nginx、sshd、MySQLなど)を直接 kill で止めるのは推奨されません。systemctl を使うと、ユニットの依存関係も考慮した上でクリーンに停止できます。

# サービスの停止
sudo systemctl stop nginx

# 停止後の状態確認
systemctl status nginx

ある運用現場では、systemd管理下の nginx を直接 kill -9 で落としたところ、systemdが即座に再起動を試みるループに入り、意図した停止ができなかった事例があります。systemctl stop を使えばこの問題は起きません。

どのサービスがsystemdで管理されているかを確認するには次のコマンドを使います。

systemctl list-units --type=service --state=running

誤操作を防ぐ:PIDを必ず確認してから実行する

PIDはプロセスが終了すると別のプロセスに再利用されます。PIDをメモしてから時間をおいて kill を実行すると、別のプロセスを止めるリスクがあります。取得したPIDをその場ですぐ確認し、即実行するのが基本です。

# 確認と実行をワンライナーで
kill -15 $(pgrep -x myapp)

-x オプションはコマンド名の完全一致を強制するため、myapp2old_myapp などへ誤ってシグナルを送るリスクを下げられます。本番環境では実行前に pgrep -l -x myapp で対象を目視確認する運用ルールを設けることを強くお勧めします。

名前で一括停止する方法と注意点

複数の同名プロセスをまとめて止めたい場合は pkill が便利です。ただし本番サーバーでは「意図せず複数のプロセスを巻き込む」リスクがあるため、事前に対象の数を確認してから使います。

# 止める前に対象プロセス数を確認
pgrep -l -x myapp

# 確認後、一括でSIGTERMを送る
pkill -15 -x myapp

# 数秒後も残っていればSIGKILLで強制終了
pkill -9 -x myapp

killall はコマンド名の完全一致で動作しますが、ディストリビューションによって挙動が微妙に異なる場合があります。Linux専用サーバーでも pkill -x を使う方が意図が明確です。

停止後の確認と後処理

シグナルを送った後、プロセスが実際に消えたかどうかを確認します。

# PIDが消えていれば何も出力されない
pgrep -x myapp

# プロセステーブル全体で確認したい場合
ps aux | grep myapp

SIGKILL後もプロセスが残っている(ps の状態欄が D:割り込み不能スリープ)場合は、カーネルレベルのI/O待ちに入っています。この状態はシグナルで止められません。NFSなどネットワークファイルシステムのタイムアウト待ちや壊れたストレージドライバが原因であることが多く、最終的にはサーバー再起動が必要になるケースがあります。

プロセスが終了したら、ロックファイルやPIDファイル(/var/run/*.pid)が残っていないかも確認してください。古いPIDファイルが残ったままだと、サービスを再起動する際に「すでに起動している」と誤判定される原因になります。

<PR>この記事に関連するおすすめ書籍

[改訂第3版]シェルスクリプト基本リファレンス

移植性の高いシェルスクリプトを書くための逆引きリファレンス。運用スクリプトの信頼性を高めたい方に。

「コマンドは打てる。次は”現場で通用する型”を最短で身につけたい」——そんなあなたへ。

ネットの断片的なTipsをコピペするだけでは、体系的な運用スキルはなかなか積み上がりません。リナックスマスター.JPの無料メルマガ「リナマガ」では、現場で実際に使うLinuxサーバー運用の考え方を、順を追って実務目線でお届けしています。いま登録された方には、安全なサーバー構築の「型」をまとめた『Linuxサーバー構築入門マニュアル(図解60P)』を完全無料でプレゼント中です。

>> 図解60P『Linux入門マニュアル』を無料で受け取る
(メルマガ登録は10秒・いつでも解除OK)

※ 「独学の時間がもったいない」「プロから現場の技術を最短で学びたい」という本気の方には、2日で実務レベルが身につく初心者向けハンズオンセミナーもご用意しています。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

目次