はじめに
商用システムの運用では、LinuxサーバのCPU使用率が急上昇するトラブルは珍しくありません。CPU負荷は一時的なスパイクで終わることもあれば、アプリケーションのレスポンス遅延やタイムアウト、バッチ処理の遅延、さらにはサービス停止へ発展することもあります。
重要なのは、CPU使用率が高いという事実だけを見て原因を決めつけないことです。まずシステム全体の状態を確認し、CPU時間の内訳を見て、どのProcess・ThreadがCPUを使用しているのかを段階的に絞り込んでいきます。
本記事では、LinuxサーバにおけるCPU高負荷を検知してから、原因を特定し、暫定対処・恒久対処へつなげるまでの流れを実践的に解説します。まず全体フローを確認し、実際の状況に応じて必要な章から読み進めても問題ありません。
CPU高負荷とは
CPU使用率は、一定時間のうちCPUがどのような処理に時間を使っていたかを示す指標です。CPU使用率が高いこと自体が、直ちに障害を意味するわけではありません。高いCPU使用率でも処理性能やレスポンスが要求を満たしている場合は、必ずしも問題ではありません。
一方で、高負荷状態が継続しCPUの余力がなくなると、次のような影響が発生する可能性があります。
- アプリケーションのレスポンス遅延・タイムアウト
- バッチ処理の遅延・タイムアウト
- SSHや運用コマンドの応答悪化
- Run Queueの増加による処理待ち
- 他Processへの性能影響
CPU高負荷のトラブルシューティング全体像
CPU高負荷を検知したら、いきなり原因Processを探すのではなく、次の順番で調査すると効率よく切り分けできます。

特に商用システムでは、障害発生中に調査できるとは限りません。現在の状態を見るコマンドと、過去の状態を振り返るコマンドを使い分けることが重要です。
| 状況 | 主なコマンド | 用途 |
|---|---|---|
| 現在発生中 | top / vmstat / pidstat | リアルタイムに状況を確認 |
| 発生後の事後調査 | sar | 障害発生時刻のCPU状態を振り返る |
CPU全体の状態を確認する
topで現在のCPU状態を確認する
障害が現在進行中であれば、まずtopでシステム全体を確認します。
# top実際のtop実行例:

CPU調査では、主に次の2点を確認します。
- Load Average
- %Cpu(s) の内訳
Load Averageを確認する
Load Averageは、過去1分・5分・15分におけるシステム負荷の平均値です。Linuxでは、CPUを実行中または実行待ちのTaskだけでなく、割り込み不可スリープ(D state)にあるTaskもLoad Averageに含まれます。
重要:Load Averageが高い = CPU使用率が高いとは限りません。
たとえば、Load Averageが高いにもかかわらずCPUのidleが十分に残っている場合は、CPU不足ではなく、Block I/O待ちなどでD stateのTaskが増えていないか確認する必要があります。

CPU論理コア数はnprocやlscpuで確認できます。
また、top実行中に「1」を押すと、CPUコアごとの使用状況を確認できます。
CPU全体の使用率には余裕があっても、Single Thread処理やCPU Affinityなどの影響で、特定の論理CPUだけが100%近く使用されている場合があります。そのため、CPU全体の平均値だけでなく、CPUコアごとの偏りも確認します。
CPUコアごとの表示例:

CPU時間の内訳を確認する
topの%Cpu(s)には、CPUがどの種類の処理に時間を使っていたかが表示されます。
| 項目 | 意味 | 高い場合に疑うもの |
|---|---|---|
us | User Modeで通常Processを実行した時間 | Application処理、計算処理、SQL処理など |
sy | Kernel Modeで処理した時間 | System Call、Kernel処理など |
ni | nice値が変更されたUser Processの実行時間 | nice設定されたProcess |
id | CPUがidleだった時間 | 値が小さいほどCPUの余力が少ない |
wa | I/O完了待ちに関連してidleとして計上された時間 | Block I/Oの遅延を疑う。ただし単独で断定しない |
hi | Hardware Interrupt処理時間 | Device / Interrupt負荷 |
si | SoftIRQ処理時間 | Network受信などのSoftIRQ負荷 |
st | Virtual MachineがHypervisor側の都合でCPUを使えなかった時間 | Host側CPU競合・Overcommitなど |
idがほぼ0でCPU使用率が高い場合でも、まずus、sy、si、stなどのどこが増えているかを見ます。原因によって次に調査する対象が変わるためです。
vmstatでRun Queueも確認する
vmstatを使うと、CPUだけでなくMemoryやI/Oを横断的に確認できます。
# vmstat 1vmstatの実行結果:

CPU高負荷時は、特にr、us、sy、id、waを確認します。
| 項目 | 見るポイント |
|---|---|
r | 実行可能状態のTask数。継続的に論理CPU数を大きく上回る場合はCPU待ちを疑う |
us | User ModeのCPU時間 |
sy | Kernel ModeのCPU時間 |
id | idle時間 |
wa | I/O待ちに関連する時間。I/O Bottleneckの手掛かりとして確認 |
sarで障害発生時のCPU状態を振り返る
商用システムでは、「22時頃にCPUアラートが発生したが、現在は正常」というケースがよくあります。この場合、現在のtopを確認しても障害発生時の状況は分かりません。
sysstatが有効化されていれば、sarを使って過去のCPU状態を確認できます。
sar -u実際の sar -u の実行結果:

過去の日付のsysstatファイルを指定する場合は、環境に応じて次のように確認します。
sar -u -f /var/log/sa/sa0X実際の sar -u -f の実行結果:

CPUコアごとに確認したい場合は次のように実行します。
sar -P ALL実際の sar -P ALL の実行結果:

sarでは、障害発生時刻の%user、%system、%iowait、%steal、%idleなどを確認し、「CPUの何が上昇していたのか」を切り分けます。
sar・Application Log・Batch実行時刻などを突き合わせると、原因を特定しやすくなります。CPU時間の内訳から原因を切り分ける
| 観測結果 | 疑う対象 | 次の調査例 |
|---|---|---|
usが高い | Application / DBなどのUser Process | top、pidstatでProcess特定 |
syが高い | System Call / Kernel処理 | pidstat、必要に応じてperfなど |
waが高い | Block I/O遅延の可能性 | iostat -xなどでI/O状態を確認 |
siが高い | SoftIRQ負荷 | /proc/softirqs、Network負荷などを確認 |
stが高い | Virtualization Host側のCPU競合 | Hypervisor / Cloud側のMetricsを確認 |
CPUを使用しているProcessを特定する
topでCPU使用率の高いProcessを確認する
topでは、ProcessごとのCPU使用率をリアルタイムに確認できます。CPUを多く消費しているProcessを特定し、Application名や実行ユーザー、起動コマンドなどを確認します。
Process一覧では、特にPID、USER、PR、NI、S、%CPU、TIME+、COMMANDを確認します。
pidstatでProcessのCPU使用率を時系列で確認する
pidstatを使うと、Process単位のCPU使用率を一定間隔で確認できます。
pidstat 1実際の pidstat の実行結果:

特定Processだけに絞る場合は-pを指定します。
pidstat -p 707126 1
%usr、%system、%wait、%CPUを見ることで、そのProcessがどのようにCPUを消費しているかを確認できます。
psでCPU使用率の高いProcessを一覧化する
コマンド実行時点のProcess一覧をCPU使用率順に取得したい場合は、psも便利です。
ps aux --sort=-%cpu | head実際の ps aux の実行結果:

Thread単位まで原因を深掘りする
Java ApplicationやマルチスレッドProgramでは、Process単位でCPU使用率が高いことが分かっても、どの処理が原因なのかまでは分かりません。その場合はThread単位まで掘り下げます。
top -HでThreadを確認する
top -H -p <PID>実際の top -H の表示例:

対象Processに属するThreadごとのCPU使用率が表示されます。
pidstat -tでThreadを確認する
pidstat -t -p <PID> 1実際のThread単位のpidstat実行結果:

TID(Thread ID)単位でCPU使用率を確認し、特にCPUを消費しているThreadを特定します。
(補足)Java Applicationの場合
TomcatなどのJava Applicationでは、次のように調査を進めると原因を絞り込みやすくなります。
- top / pidstat
- Java Processが高CPU
- top -H / pidstat -t
- 高CPU Threadを特定
- Thread Dumpなどと照合
- Applicationの処理を特定
CPU使用率の高いThreadを特定した後は、Thread DumpやApplication固有のProfiling情報などを用いて、どの処理がCPUを消費しているのかを確認します。
Application / OS / DBまで原因を追う
ProcessやThreadを特定したら、そのProcessがなぜCPUを使用しているのかを調査します。この段階では、OS全体のMetricsだけでなく、ApplicationやMiddleware、Database側の情報が重要になります。
OS / Kernel Log
RHEL系では、環境に応じてjournalctlや/var/log/messagesを確認します。
# journalctl -k
# journalctl --since "2026-09-09 05:00" --until "2026-09-09 06:00"
# tail /var/log/messagesSoft Lockup、Hard Lockup、Taskの長時間Blockなど、CPU高負荷と関連するKernel Messageがないかを確認します。
Web / AP Server
ApacheやNginxではAccess Logを確認し、CPU高負荷が発生した時間帯にRequest数が急増していないか、特定URLへ集中していないかを確認します。
TomcatなどのJava Applicationでは、Application Logに加えてGC Logも確認します。GC回数やGC時間が通常時より大きく増えている場合は、GC負荷がCPU使用率上昇に関係している可能性があります。
GC Logの例:

Database
Database ProcessがCPUを大量に使用している場合は、SQLやSessionの状態をDatabase側で確認します。
PostgreSQLではSlow Query Logやpg_stat_activity、pg_stat_statementsなど、Oracle DatabaseではAWRやASHなどを利用し、CPU消費の大きいSQLや処理を特定します。
PostgreSQL Slow Query Logの例:

必要に応じてperfなどで深掘りする
topやpidstatでは「どのProcess / ThreadがCPUを使っているか」は確認できますが、「どのFunctionやCode PathでCPU時間を消費しているか」までは分かりません。
より深い分析が必要な場合は、perfなどのProfiling Toolを使ってCPU Hotspotを調査します。
# perf top
# perf record -p <PID> -g -- sleep 30
# perf reportCPU高負荷時の暫定対処
以下では、実際にCPU高負荷状態を再現して取得した画面・コマンド結果も使いながら説明します。

原因調査と並行してサービス影響が拡大している場合は、システムを安定させるための暫定対処を検討します。ただし、原因を十分に確認せずにProcess停止やCPU制限を行うと、別の障害を引き起こす可能性があります。
Service / Processを停止する
原因Serviceが特定でき、停止しても業務影響を許容できる場合は、Serviceとして管理されているProcessであればsystemctl stopなどの正規の停止手順を優先します。
systemctl stop <service>個別ProcessにSignalを送る場合、通常はまずSIGTERMで正常終了を要求します。
kill <PID>SIGTERMによる停止例:

SIGTERMで停止できず、影響を確認したうえで緊急停止が必要な場合に限り、SIGKILLを最終手段として検討します。
kill -9 <PID>SIGKILLの実行例:

kill -9を実行しないでください。優先度を下げる
停止できないProcessについて、他Processへの影響を抑えるためにnice値を変更する方法があります。
renice 10 -p <PID>renice の実行例:

ただし、nice値を下げてもCPU負荷そのものが解消するわけではありません。あくまでCPU競合時のScheduling優先度を調整する対処です。
CPU使用量を制御する
Service単位でCPU使用量を制御する必要がある場合は、まずsystemdやcgroupsによるCPU Resource Controlを検討します。商用システムでは、Service管理方式や運用標準に合わせて制御方法を選択することが重要です。
cpulimitを利用して個別ProcessのCPU使用率を制限する方法もありますが、systemdやcgroupsで管理できない場合の補足的な選択肢として考えます。
cpulimit -p <PID> -l <使用率制限値> &cpulimit の実行例:

上記の例では、PID 887537のProcessのCPU使用率を50%に制限し、cpulimitをBackgroundで実行しています。
CPUリソースを増強する
Virtual MachineやCloud環境では、vCPUを追加することで一時的に余力を確保できる場合があります。
ただし、Single Thread処理、Lock競合、I/O待ち、Application設計が原因の場合は、CPU数を増やしても改善しないことがあります。CPU増強は原因を切り分けたうえで実施します。
CPU高負荷の恒久対処
恒久対処では、CPU使用率が上昇した根本原因を解消します。代表的な対処は次の通りです。
- Applicationの改善:無限Loop、高負荷な計算処理、無駄なPollingなどを修正する
- SQLの最適化:CPU消費の大きいSQLを見直し、IndexやSQLを改善する
- Batch設計の改善:実行時間帯の変更、分割、並列度の調整を行う
- Traffic制御:Rate Limitや流量制御を導入し、突発的なRequest増加に備える
- Capacity見直し:CPU数、Instance Size、Scale Out構成などを見直す
- 監視強化:CPU使用率だけでなくLoad Average、Run Queue、Process単位のCPU、Application Metricsを継続監視する
まとめ
LinuxサーバでCPU使用率が上昇した場合、重要なのはCPU使用率という1つのMetricだけを見て原因を決めつけないことです。
- まずCPU全体を見る:top、sar、vmstatで現在または障害発生時の状態を確認する。
- CPU時間の内訳を見る:us、sy、wa、si、stなどから調査対象を切り分ける。
- Processを特定する:top、pidstat、psを利用する。
- Threadまで深掘りする:top -Hやpidstat -tで高負荷Threadを特定する。
- 根本原因まで追う:Application Log、GC、Database、必要に応じてperfなどで原因を分析する。
- 暫定対処と恒久対処を分ける:Service停止、優先度調整、Resource制御などで影響を抑えつつApplication・SQL・Capacityなどの根本原因を改善する。
CPU調査はシステム全体 → CPU時間の内訳 → Process → Thread → Applicationの順に段階的に絞り込むことが重要です。
参考資料
- Linux man-pages: proc_loadavg(5)
- Linux Kernel Documentation: The /proc Filesystem
- Linux man-pages: pidstat(1)
※コマンド出力やLog保存先はDistribution、Version、設定により異なります。実環境の設計・運用ルールに合わせて確認してください。



コメント