MENU

CPU使用率が急騰したときに原因プロセスを特定・対処する実務手順

サーバーの応答が遅い、監視アラートが鳴った——そういう場面でまず確認したいのがCPU使用率と、それを引き起こしているプロセスです。本記事では、リアルタイムで原因プロセスを特定し、優先度変更や停止で対処するまでの手順をまとめます。

目次

まずリアルタイムでCPU全体像を把握する

top コマンドを引数なしで実行します。デフォルトで %CPU 降順に並ぶため、画面上部に表示されるプロセスが最もCPUを消費しています。

top

出力例(Ubuntu 24.04 / RHEL 9 環境):

top - 14:22:05 up 3 days,  2:11,  2 users,  load average: 3.42, 2.87, 2.15
Tasks: 212 total,   3 running, 209 sleeping,   0 stopped,   0 zombie
%Cpu(s): 78.4 us,  8.1 sy,  0.0 ni, 10.2 id,  3.1 wa,  0.0 hi,  0.2 si,  0.0 st
MiB Mem :   7838.2 total,    512.4 free,   5124.8 used,   2201.0 buff/cache
MiB Swap:   2048.0 total,   1900.2 free,    147.8 used.   2713.0 avail Mem

    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
  14823 www-data  20   0  512348  98412  14328 R  95.3   1.3   3:21.44 php-fpm8.3
   8801 mysql     20   0 1831200 423880  32768 S  14.7   5.4  12:04.12 mysqld
   1024 root      20   0       0      0      0 I   1.0   0.0   0:14.33 kworker/u4:2

ヘッダー3行目の %Cpu(s) 行が全体像です。us(ユーザー空間)が高ければアプリ側、sy(カーネル空間)が高ければシステムコール多発、wa(I/O待ち)が高ければディスクやネットワークがボトルネックである可能性があります。更新間隔を1秒に変えるには、起動後に d を押して 1 Enter と入力します。終了は q です。

top 出力で必ず読む列——状態(S列)に特に注目

プロセス一覧の主要列の意味は以下の通りです。実務でとくに重要なのは S列(プロセス状態)%CPU です。

意味
PIDプロセスID
USER実行ユーザー
PR / NIスケジューリング優先度 / nice値(NI が大きいほど優先度低)
VIRT / RES仮想メモリ / 実メモリ使用量
Sプロセス状態(下記参照)
%CPU直近の更新間隔中のCPU使用率
%MEM実メモリ使用率
TIME+起動からの累積CPU時間(1/100秒単位)
COMMANDコマンド名(c キーでフルパス表示に切替可)

S列の値が示すプロセス状態:

  • R: 実行中またはキューで待機中(CPUを積極消費)
  • S: スリープ中(イベント待ちで休眠。通常の待機状態)
  • D: 割り込み不可スリープ(I/O待ち。この状態のプロセスが多い場合は、CPUよりディスクやNFSが本当の原因である可能性が高い)
  • Z: ゾンビ(終了済みだが親プロセスが回収していない。大量発生は親プロセスに問題あり)
  • T: 一時停止中

PID を特定したあとの追加調査

問題のプロセスの PID がわかったら、そのプロセスが何をしているか深掘りします。

# 起動コマンドの全文を確認(引数まで含めて表示)
cat /proc/14823/cmdline | tr '\0' ' '; echo

# プロセスが開いているファイル・ソケットを確認
lsof -p 14823

# スレッド単位のCPU使用率を1秒おきに表示(sysstatパッケージ)
pidstat -t -p 14823 1

pidstat が入っていない場合はパッケージをインストールしてください。

# Debian / Ubuntu
sudo apt install sysstat

# RHEL / AlmaLinux / Rocky Linux
sudo dnf install sysstat

ある運用現場では、%CPU が 100% を超えるプロセスがあり調査したところ、マルチスレッドプロセスがスレッド単位で複数コア分を消費していました。pidstat -t でスレッドレベルまで確認することで原因を絞り込めた事例です。

対象プロセスが systemd のサービスとして管理されている場合は、systemd-cgtop でサービス単位のリソース消費を確認できます。

systemd-cgtop

プロセスへの対処——優先度変更と終了

原因プロセスが判明したら、状況に応じて対処します。本番サービスにすぐ手を出せない場面では、まず優先度を下げてCPU割当を抑制するのが安全な第一手です。

優先度を下げて様子を見る

# nice値を +10 に変更(値が大きいほど優先度が低くなる。最大 +19)
sudo renice +10 -p 14823

これにより他のプロセスへのCPU影響を軽減しつつ、プロセス自体は動かし続けられます。サービスへの影響を最小限にしながら時間を稼ぎたいときに有効です。

プロセスを停止する

停止して問題ないと判断したら、まず SIGTERM(終了要求)を送ります。プロセスに後処理(ファイルクローズ、一時ファイル削除など)の機会を与えられます。

# まず SIGTERM で終了を要求
kill 14823

# 数秒待っても止まらない場合のみ SIGKILL(強制終了)
kill -9 14823

注意: kill -9 はプロセスを即時強制終了するため、ファイルの不整合やロックファイルが残存するリスクがあります。systemd が管理するサービスは直接 kill するより systemctl stop が推奨です。直接 kill すると Restart=on-failure 設定によって自動再起動が走る場合もあります。

# systemd 管理サービスを正しく停止する
sudo systemctl stop php-fpm

# 再起動させたい場合
sudo systemctl restart php-fpm

証跡としてスナップショットを記録する

障害対応中はそのときの状態をファイルに残しておくと、後の原因分析や報告書に役立ちます。

# CPU使用率上位10プロセスをタイムスタンプ付きで保存
ps aux --sort=-%cpu | head -11 | tee /tmp/cpu_spike_$(date +%Y%m%d_%H%M%S).txt

# 10秒おきに5回取得して追記(合計50秒分の記録)
pidstat -u 10 5 >> /tmp/pidstat_log_$(date +%Y%m%d).txt

# top をバッチモードで1回だけ実行してファイルに保存
top -b -n 1 | head -30 > /tmp/top_snapshot_$(date +%Y%m%d_%H%M%S).txt

ある情シス担当者が夜間バッチ後のCPU挙動を cron で定期収集するようにしたところ、特定の週次バッチが毎週火曜深夜にCPUを独占している傾向が可視化でき、バッチの実行タイミングを分散させることで問題を解消できました。リアルタイムの確認だけでなく、継続的な記録が再発防止につながります。

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

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

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

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

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

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

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

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

この記事を書いた人

目次