
サーバーの反応が遅い、という連絡を受けてSSHでログインしたところを想像してください。画面にはプロンプトだけがあり、どこから見ればいいのかを決めるのは自分です。監視ツールが入っていない環境なら、まずコマンドを入力して確認するのが唯一の手がかりになります。
このとき困るのは、コマンドを知らないことよりも出力のどこを見ればいいのかです。free の free が少ないのを見てメモリ不足だと判断したり、ロードアベレージの数字だけで混雑を決めつけたりする間違いは、経験を積んだ運用者でも行いがちです。この記事では、最初に打つ4つのコマンドと、その出力で読み間違えやすい項目を整理します。
順番に実行して、どこが詰まっているかの当たりを付けます。
uptime # 負荷の全体感
vmstat 1 5 # CPU、メモリ、I/O を1秒間隔で5回
free -h # メモリの残り
df -h # ディスクの空きvmstat の出力で、次のように見る場所を決めます。
| 目立つ数字 | 疑うところ | 次に見るコマンド |
|---|---|---|
| us が高い | アプリケーションの処理 | top、ps --sort=-%cpu |
| sy が高い | システムコール、コンテキストスイッチ | top、pidstat -w |
| wa が高い | ディスクI/O待ち | iostat -x 1、df -h |
| st が高い | 仮想化環境で他のゲストにCPUを取られている | ホスト側、クラウド事業者の指標 |
| si、so が動く | メモリ不足によるスワップ | free -h、ps --sort=-%mem |
| b が多い | 中断できない待ち | iostat -x 1 |
最初の行は起動時からの平均値なので読み飛ばし、2行目以降を見ます。vmstat 1 5 と回数を指定しておくと、5回で自動的に止まります。
/images/blog/linux-cpu-memory-disk-check-commands/mid-01.png
uptime はロードアベレージを3つ返します。左から1分、5分、15分の平均です。
$ uptime
14:32:01 up 42 days, 3:11, 2 users, load average: 4.21, 3.88, 2.40ロードアベレージはCPU使用率ではありません。 実行待ちのプロセスと、中断できない待ち状態のプロセスを合わせた数です。判断にはコア数との比較が要ります。nproc でコア数を確認し、それを超えていれば処理が追いついていない状態を疑います。4コアで4.21なら、ちょうど埋まっているあたりです。
3つの数字の並びも情報です。1分が15分より大きければ負荷は今まさに上がっているところで、逆なら山を越えたところです。
内訳は top で見ます。
%Cpu(s): 62.3 us, 8.1 sy, 0.0 ni, 21.4 id, 7.9 wa, 0.0 hi, 0.3 si, 0.0 st| 項目 | 意味 | 高いときに見るところ |
|---|---|---|
| us | ユーザー空間、つまりアプリケーションのコード | どのプロセスが食っているか |
| sy | カーネル空間、システムコール処理 | システムコールの回数、コンテキストスイッチ |
| wa | I/O完了待ちでCPUが空いた時間 | ディスク、ネットワークストレージ |
| st | 仮想化環境でハイパーバイザに取られた時間 | ホスト側の混雑 |
wa について補足します。この値はCPUが空いている間にI/O待ちのタスクがあった時間です。CPUが常に他の仕事を持っていれば、ディスクがキャパオーバーしていてもwaはほとんど上がりません。waが低いことはディスクが正常であるとは言えません。
st は仮想マシンでのみ意味を持ちます。物理サーバーでは0のままです。クラウドで st が継続的に上がるなら、同じ物理ホスト上の他のゲストにCPU時間を取られている状態を疑います。
対象のプロセスを特定します。
ps -eo pid,comm,%cpu,%mem --sort=-%cpu | head
top -Hp <PID> # そのプロセスのスレッド単位Javaのようにスレッドを多く持つプロセスでは、top -Hp でスレッドまで下りてからスレッドダンプと突き合わせると、どのコードで止まっているかまで追えます。
free -h の出力で最も誤解されるのがfree列です。
$ free -h
total used free shared buff/cache available
Mem: 15Gi 6.2Gi 412Mi 128Mi 8.6Gi 8.4Gi
Swap: 2.0Gi 128Mi 1.9Gifree が412MiBしかないのを見て、メモリが枯渇していると判断するのは誤りです。見るべきは available の8.4GiBです。
Linuxは空いているメモリをディスクキャッシュ(buff/cache)に展開します。使わずに空けておくより、キャッシュとして使ったほうが速いからです。このキャッシュはアプリケーションがメモリを要求すれば解放されるので、実質的には空きです。available はその解放できる分を含めた、これから使える量の目安になります。
本当に足りているかはスワップの動きで判断します。
$ vmstat 1 5
procs -----------memory---------- ---swap-- -----io----
r b swpd free buff cache si so bi bo
2 0 131072 421888 262144 8912896 0 0 24 88si(スワップイン)とso(スワップアウト)が継続的に動いていれば、メモリが足りずにディスクへの退避が起きています。swpd に値が残っていても si、so が0のままなら、過去に退避されたページが残っているだけで今は問題ありません。
対象のプロセスは ps で見ます。
ps -eo pid,comm,%mem,rss --sort=-%mem | headRSS(常駐セットサイズ)は実際に物理メモリ上にあるサイズです。共有ライブラリの分が複数プロセスで重複して数えられるため、全プロセスのRSSを足すとキャパシティーを超えることがあります。合計ではなく、突出しているプロセスを見つける目的で使います。
$ df -h
Filesystem Size Used Avail Use% Mounted on
/dev/nvme0n1p1 100G 94G 1.2G 99% /Use% が100%に近ければ容量不足です。 どの部分で費やしているのかdu で確認します。
du -h --max-depth=1 / 2>/dev/null | sort -rh | head見つからないときは、次の2つを確認します。
inodeの枯渇。 容量に余裕があるのに書き込めない場合です。小さなファイルが大量にあるとinodeだけが先に終了します。
$ df -i
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/nvme0n1p1 6553600 6553600 0 100% /削除済みなのに開かれたままのファイル。 ログファイルを消したのに空き容量が戻らないケースです。プロセスがファイルハンドルを持っている間、領域は解放されません。df と du の数字が食い違うのがこの状態のアラートです。
lsof +L1該当プロセスを再起動するか、ログローテーションの設定を見直します。
I/Oが遅いかどうかは iostat -x 1 で見ます。
Device r/s w/s rkB/s wkB/s r_await w_await aqu-sz %util
nvme0n1 12.0 340.0 480.0 21760.0 0.32 8.44 2.87 62.1%util の読み方には注意が要ります。この値はデバイスに1つ以上の要求があった時間の割合です。要求を1つずつ処理する装置ならキャパオーバーの目安になりますが、NVMeやSSD、RAIDのように並列で処理する装置では100%に近くても余裕が残っていることがあります。キャパオーバーを疑うのは r_await、w_await(1要求あたりの待ち時間)と aqu-sz(キューの長さ)が一緒に伸びているときです。
ロードアベレージには、CPUの実行待ちだけでなく中断できない待ち状態のプロセスも含まれるためです。ディスクやネットワークストレージの応答が遅いと、CPUは空いているのにロードアベレージだけが上がります。vmstat の b 列と wa を合わせて確認してください。
読める情報は同じです。htop は色分けとスクロールがあって見やすい一方、多くのディストリビューションで標準インストールではありません。障害対応中に入っていない可能性があるので、top の読み方は押さえておくほうが安全です。
使用率だけでは決まりません。availableが十分にあれば、usedが高くてもキャッシュとして使われているだけです。危険の判断はスワップの動き(si、so)と、OOM Killerがプロセスを終了させた記録で行います。記録は dmesg -T | grep -i oom で確認できます。
古いカーネルや設定では、コンテナ内の top や free がホスト全体の値を返すことがあります。cgroup v2環境なら /sys/fs/cgroup/memory.max と memory.current、CPUは cpu.stat の nr_throttled を直接見るほうが確実です。スロットリングが起きていれば nr_throttled が増えます。
サーバーの処理時間に要する際の切り分けは、uptime で全体感をつかみ、vmstat でCPU、メモリ、I/Oのどこがボトルネックかを決め、そこから top、free、df に流れていく順番が基本です。
特に間違えやすい箇所はこちらになります。①freeではなくavailableを見ること、②ロードアベレージはコア数と比べること、③waが低くてもディスクが健全とは限らないことです。
ただし、コマンド入力で対処するのはその瞬間の値だけです。夜間に一度だけ跳ねた負荷や、週に数回しか起きない遅延は、後からログインしても再現できません。継続的にリソースを記録しておくと、障害が起きた時刻にさかのぼって当時の状態を確認できます。WhaTapのサーバーモニタリングは無料で試せます。15日間の無料トライアルを始める