LinuxサーバーのCPUが突然100%になった日の話|現役講師が語る原因特定とtopコマンドへの向き合い方

HOMEリナックスマスター.JP 公式ブログLinux学習ガイド > LinuxサーバーのCPUが突然100%になった日の話|現役講師が語る原因特定とtopコマンドへの向き合い方
宮崎智広 この記事の監修:宮崎智広(Linux実務・教育歴20年以上・受講者3,100名超)
「サーバーが急に重くなったんですが、何かサーバーに問題がありますか?」

SE時代にある日の夕方16時過ぎ、お客さんから掛かってきた電話の第一声がこれでした。その日は久しぶりに定時で帰れると思っていたのに、この一本でそんな計画はあっさり崩れました。

この記事では、20年以上Linuxサーバーを運用してきた経験から、SE時代(2001年~2006年)に実際に経験したCPU使用率100%の障害対応を振り返ります。その時に学んだことと、今も3,100名のセミナー受講生に伝え続けている「CPU障害発生時の原因特定の考え方」をお話しします。

この記事のポイント

・ CPU 100%が出たらtopコマンドで「どのプロセスが原因か」を最初に確認する
・ コマンド名だけでなくps auxfでプロセスツリーを追うと全体像が見えやすくなる
・ 「即kill」より「観察→記録→対処」の型が現場での鉄則
・ SE時代の実体験:PerlCGIの無限ループがApacheの子プロセスを詰まらせていた


LinuxサーバーのCPUが突然100%になった日の話|現役講師が語る原因特定とtopコマンドへの向き合い方

LinuxサーバーのCPUが突然100%になった日の話|現役講師が語る原因特定とtopコマンドへの向き合い方
「このままじゃマズい」と感じていませんか?
参考書を開く気力もない、同年代に取り残される不安——
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

「サーバーが重い」という電話から始まった1時間

お客さんから電話が来た時、最初は何が起きているのか全く分かりませんでした。VPNで客先のLinuxサーバーに接続しようとすると、SSHのセッションが繋がるまでに妙に時間がかかる。繋がった後も、ls と打つだけで数秒待たされる。

「これは確実にサーバー側で何かが起きている」と直感しました。こういう時に私が最初にやることは一つです。topコマンドを叩く。それだけです。

# topコマンドでCPU使用状況を確認する $ top top - 16:23:45 up 142 days, 4:12, 2 users, load average: 3.95, 3.87, 3.72 Tasks: 187 total, 4 running, 183 sleeping, 0 stopped, 0 zombie %Cpu(s): 99.2 us, 0.5 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.3 si MiB Mem : 2048.0 total, 123.4 free, 1845.2 used, 79.4 buff/cache PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 18472 apache 20 0 82456 41234 3200 R 98.3 2.0 12:34.56 perl 18473 apache 20 0 82448 41120 3200 R 98.1 2.0 12:33.21 perl 547 apache 20 0 42764 18432 4096 S 0.3 0.9 0:02.14 httpd 1 root 20 0 8192 3456 2816 S 0.0 0.2 0:01.23 init

topの出力を見た瞬間、「ああ、これは重いわけだ」と思いました。CPU使用率が99%を超えている。しかも一番上に表示されているのはhttpdではなく「perl」でした。しかも2プロセス。

私がこのサーバーでPerlを常時起動するような設定はしていなかったはずです。何が起きているのか、すぐには分かりませんでした。

topを見た後に行った3つの確認

1. PIDからプロセスの詳細を確認する

topでCPUを食い荒らしているプロセスが分かったら、次はそのPIDを使って詳細を調べます。psコマンドでフルパスを確認しました。

# PIDを指定してプロセスの詳細(フルパス)を確認する $ ps aux --pid 18472 USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND apache 18472 98.3 2.0 82456 41234 ? R 16:11 12:34 /usr/bin/perl /var/www/cgi-bin/order/process.cgi

コマンド名は「perl」でしたが、その後ろにフルパスが続いていました。`/var/www/cgi-bin/order/process.cgi`。「あれ、これはお客さんが作ったCGIスクリプトだ」とすぐに分かりました。

2. ps auxfでプロセスツリー全体を確認する

プロセスの詳細が分かったら、次はプロセスツリーを確認します。親プロセスが何かを理解することで「誰がこのプロセスを起動したか」が明確になります。

# プロセスツリーを表示してApacheの子プロセスを確認する $ ps auxf | grep -A 5 httpd root 547 0.3 0.9 42764 18432 ? Ss 09:15 0:02 /usr/sbin/httpd apache 18470 0.0 0.4 42764 9008 ? S 16:11 0:00 \_ /usr/sbin/httpd apache 18471 0.0 0.4 42764 9012 ? S 16:11 0:00 \_ /usr/sbin/httpd apache 18472 98.3 2.0 82456 41234 ? R 16:11 12:34 \_ perl /var/www/cgi-bin/order/process.cgi apache 18473 98.1 2.0 82448 41120 ? R 16:11 12:33 \_ perl /var/www/cgi-bin/order/process.cgi

Apacheの子プロセスとして、PerlのCGIスクリプトが2つ動き続けていました。通常、CGIスクリプトはリクエストを受けたら処理して終了するはずです。それが終了せず、CPU98%を使い続けているということは、スクリプトの中で無限ループが発生していると考えるのが自然です。

最初にhttpdを疑ってApacheを再起動しようとしていたら、同じスクリプトが別のリクエストで再び起動され、状況は何も変わらなかったはずです。プロセスツリーで「Apacheの子プロセスとしてperlが動いている」と確認したから、正しく原因を特定できました。

3. killする前に「今の状態」を記録する

プロセスを特定した時点で「さあkillしよう」という衝動に駆られます。しかし、SE時代に先輩から言われていた言葉を思い出して、少しだけ手を止めました。

「対処する前に、今見えている状態を必ずメモしておけ。再発した時に証拠がないと同じ苦労を繰り返すことになる」

私はtopとpsの出力をファイルに保存してから対処しました。

# 対処前に現在の状態をファイルに保存する(日時を含むファイル名で) $ top -b -n 1 > /tmp/top_snapshot_$(date +%Y%m%d_%H%M%S).txt $ ps auxf > /tmp/ps_snapshot_$(date +%Y%m%d_%H%M%S).txt # 状態を保存したらプロセスを強制停止する $ kill -9 18472 $ kill -9 18473

2つのプロセスを止めると、topのCPU使用率はみるみるうちに下がっていきました。SSHの応答速度も体感できるほど改善されました。
プロセスツリーを追う|観察・記録・対処の型

原因はお客さんが昼間に修正したCGIスクリプトだった

プロセスを止めてからお客さんに連絡を入れました。「今日、サーバー上のファイルを変更しましたか?」と確認すると、「実は昼休みにprocess.cgiのループ処理を少し直しました」という返答が来ました。

お客さんが「少し修正した」ループ処理が、終了条件のない無限ループになっていたのです。ループ内の終了フラグを更新するコード1行を、誤って削除してしまっていました。

私の現場でよく見かけるのが、「CGIスクリプトを修正したけど動作確認が十分でなく、本番で初めて問題が発覚する」というパターンです。この時もまさにそれでした。サイトへのアクセスがCGIスクリプトを呼び出し、そのスクリプトが無限ループに入り、Apacheの子プロセスが増殖してCPUを使い果たした——という流れです。

CPU 100%が起きやすい場面とトラブルシュートの考え方

この経験をきっかけに、CPU使用率が異常になる場面についてより意識するようになりました。20年以上サーバーを運用してきた経験から言うと、CPU 100%が起きやすい状況にはいくつかのパターンがあります。

スクリプトの無限ループ:今回のケースがまさにこれ。CGI・シェルスクリプト・Pythonなどで終了条件を誤ると発生する。
フォーク爆弾:プロセスが自分自身を際限なく生成し続けるケース。シェルスクリプトのバグで起きることがある。
外部からのスクレイピングや大量アクセス:Webサーバーへの過負荷でApacheのプロセスが積み上がる。
バッチ処理の重複起動:cronで定期実行するバッチが前のジョブが終わる前に次のジョブが起動され続ける。

これらを切り分ける鉄則は「プロセスの名前・親プロセス・起動時刻を確認する」ことです。topだけでは情報が足りない時は、psコマンドでSTART(起動時刻)も確認します。同じプロセスが短い間隔で何度も起動されているなら、cronや外部リクエストが原因の可能性が高い。1つのプロセスが長時間実行されているなら、無限ループや重い処理が疑われます。

セミナーで3,100名以上に伝えているCPU障害対応の型

この経験以来、私がCPU使用率異常の対応で守るようにしている手順があります。セミナーで3,100名以上を指導してきた中で、この型を持っていない受講生がトラブル発生時に焦ってしまうケースを数多く見てきました。

観察:topを開いてどのプロセスがCPUを使っているかを確認する
記録:topとpsの出力をファイルに保存する(日時を含めたファイル名で)
対処:kill、サービス再起動、設定変更など、目的に合った対処を行う

この順番を守ることで、対処後に「あの時どういう状態だったか」を振り返ることができます。再発時の原因特定が格段に速くなります。20年以上の現場経験で気づいたのは、「即対処」で問題が解決した場合でも、その記録が次の障害を防ぐ財産になるということです。

また、特にCPU使用率の問題で強調したいのは「コマンド名だけで判断しない」ということです。topに表示されるCOMMAND列は、長いパスが切り詰められることがあります。プロセスの名前だけ見てapacheだperlだと判断するのではなく、psコマンドでフルパスまで確認する習慣が、誤った対処を防いでくれます。

CPU使用率の確認で使うコマンド早見表

やりたいこと コマンド
CPU使用率の高いプロセスをリアルタイムで確認する top
特定PIDのプロセス詳細(フルパス含む)を確認する ps aux --pid PID番号
プロセスツリー(親子関係)を確認する ps auxf
topの現在状態をファイルに1回分保存する top -b -n 1 > ファイル名
プロセスを強制停止する kill -9 PID番号

まとめ

CPU使用率100%の障害は、Linuxサーバーを運用していれば必ず一度は経験します。私のSE時代の体験から言えることは、「慌てずにtopを開いて、プロセスツリーを追う」という基本の型が、最終的に最速の解決につながるということです。

「即kill」の衝動を抑えて、まず観察し、記録する。この順番を体に染み込ませておくと、どんな現場でも焦らずに対処できるエンジニアになれます。

CPU使用率の異常に気づいた時、ぜひこの記事で紹介した確認の型を思い出してください。

次に読む記事
ポート確認・ss・lsofコマンドでプロセスとポートを確認する方法
Apacheのタイムアウト設定|本番Webサーバー運用で確認すべき設定

CPU障害対応の型を身につける|現役講師が語る原因特定の方法

「CPU 100%」の原因を素早く特定できる、現場で通用するLinuxスキルを身につけませんか?

障害発生時に焦らず「観察→記録→対処」の型を実行できる力は、コマンドを知っているだけでは身につきません。
ネットの切れ端の情報をコピペするだけでなく、現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、『Linuxサーバー構築入門マニュアル(図解60P)』を完全無料でプレゼントしています。

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

無料メルマガで学習を続ける

Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。

登録無料・いつでも解除できます

暗記不要・1時間後にはサーバーが動く

3,100名以上が実践した「型」を無料で公開中

プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。

姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

Linux無料マニュアル(図解60P) 名前とメールで30秒登録
宮崎 智広

この記事を書いた人

宮崎 智広(みやざき ともひろ)

株式会社イーネットマーキュリー代表。現役のLinuxサーバー管理者として20年以上の実務経験を持ち、これまでに累計3,100名以上のエンジニアを指導してきたLinux教育のプロフェッショナル。「現場で本当に使える技術」を体系的に伝えることをモットーに、実践型のLinuxセミナーの開催や無料マニュアルの配布を通じてLinux人材の育成に取り組んでいる。

趣味は、キャンプにカメラ、トラウト釣り。好きな食べ物は、ラーメンにお酒。休肝日が作れない、酒量を減らせないのが悩み。最近、ドラマ「フライトエンジェル」を観て涙腺が崩壊しました。