この記事は何?
この記事はインフラエンジニアが身につけるべき負荷計測コマンドについて解説しています。サーバーやアプリケーションの応答が遅延するなど本来のパフォーマンスを発揮できない時にインフラエンジニアに調査が依頼されることは多いでしょう。
大前提として日常的な負荷計測は手動コマンドで行うべきではありません。Mackerel / Zabbix / CloudWatchなどの監視ツールに委ねるべきです。しかし様々な状況や目的から手動で負荷計測したいケースも出てくるでしょう。そのような時に役立つコマンドを解説していきます。
なお、当記事はLinuxに関して初歩的なオペレーションを行ったことがある層を前提にしています。そのためtop / ps / uptime / free / df / netstatなどのコマンドは解説しません。初歩的なオペレーションからワンランクアップしたいエンジニアにお薦めです。
vmstat
このコマンドは何?
vmstatはシステム全体の負荷を出力するコマンドです。CentOSやDebian / UbuntuやopenSUSEなど多くの環境では標準でvmstatコマンドがインストールされています。細かなプロセス単位のボトルネック特定までは使えませんが、システム全体でどのような負荷が掛かっているかを簡単に知ることができます。
vmstatのインストール方法
CentOSやDebian / UbuntuやopenSUSEではvmstatコマンドは標準でインストールされています。
vmstaの出力
vmstatを実行してみましょう。vmstat 5
で5秒間隔のリソースの使用状況を確認できます。
$ vmstat 5
第1引数は何秒間隔で行うかの数値設定ですが、第2引数で実行回数を指定できます。vmstat 5 10
で5秒間隔で10回実行します。第2引数を指定しない場合は永続的に実行されます。何もオプションを指定しない場合は1回のみ実行されます。
各項目の意味
それぞれの項目の意味は以下の通りです。
項目 | 意味 |
---|---|
r | 実行待ち状態にあるプロセス数の合計 |
b | ディスクI/Oやページングなどリソース確保のためにブロックされている状態のプロセス数の合計 |
swpd | 使用中の仮想メモリ(スワップ)量 |
free | 空きメモリ量 |
buff | バッファメモリ量 |
cache | キャッシュメモリ量 |
si | スワップメモリからメモリに展開したデータ量(スワップ・イン) |
so | メモリからスワップメモリに書き込んだデータ量(スワップ・アウト) |
bi | ディスクなどブロックデバイスから読み込んだブロック数 |
bo | ディスクなどブロックデバイスに書き込んだブロック数 |
in | 割り込み回数 |
cs | コンテキスト・スイッチの回数 |
us | CPUのカーネルコード以外の実行に費やした時間の割合 |
sy | CPUのカーネルコードの実行に費やした時間の割合 |
id | CPUのアイドル状態の時間の割合 |
wa | CPUのデータの入出力待ちに費やした時間の割合 |
st | 仮想マシン(ゲストOS)がホストOSに割り当て要求をしたがしたが割り当てられなかったCPU使用率 |
メモリ量の表示単位を変更したい
デフォルトではメモリ量がキロバイト単位になっていますので、メガバイトに表示修正したい場合は、vmstat -SM
オプションを使うと良いでしょう。
$ vmstat -SM
-S
は単位を指定するオプションであり、m
は1,000,000、M
は1,048,576、k
は1,000、K
は1,024バイト単位となります。オプション指定なしの場合は-SK
と同値です。
メモリの使用量の情報が見たい
vmstat -m
でメモリの詳細情報を見ることができます。
$ vmstat -m
各ディスク別の統計情報を見たい
vmstat -d
でディスク別の統計情報を表示します。
$ vmstat -d
ディスク全体の統計情報を見たい
ディスク全体の統計情報を見たい場合はvmstat -D
オプションを使うと良いでしょう。
$ vmstat -D
タイムスタンプ情報を付与したい
vmstatの出力結果には標準ではタイムスタンプ情報は付与されません。後からいつ出力したかを辿れるようにタイムスタンプ情報を付与したい場合もあるでしょう。タイムスタンプ情報を付与するには以下の2つ方法があります。
1番目の方法はvmstat -t
オプションを付与する方法です。一番右側にタイムスタンプが表示されます。
あるいはvmstatにパイプで| awk '{print strftime("%F %T ") $0}'
を付与すると良いでしょう。
$ vmstat 10 | awk '{print strftime("%F %T ") $0}'
sar
このコマンドは何?
sarコマンドはvmstatコマンドと似ていますが、このコマンドをインストールするだけで自動的に過去の統計情報を保存してくれます。例えば2日前にどんな負荷がシステムに掛かっていたのかを調査したい場合などsarコマンドはとても役に立ちます。
導入方法
sarコマンドの導入にあたってはsysstatというパッケージが必要です。sysstatはOS標準では付属していない場合が多くインストールが必要です。
導入方法:CentOSの場合
CentOSの場合は以下のコマンドでインストールできます。
$ sudo sudo yum install sysstat
導入方法:Debian / Ubuntuの場合
Debian / Ubuntuの場合は以下のコマンドでインストールできます。
$ sudo sudo apt install sysstat
Debian / Ubuntuの場合はインストール直後はsysstatは無効になっています。/etc/default/sysstatファイルを開き、ENABLED="false"になっている箇所をtrueに変えましょう。
$ sudo vi /etc/default/sysstat ENABLED="true"
導入方法:openSUSEの場合(※注意が必要)
openSUSEの場合は以下のコマンドでインストールできます。
$ sudo sudo zypper in sysstat
ただ残念なことにopenSUSE15.0や15.1ではsysstatが必要としているgettextパッケージの依存関係に問題があるようです。
解決方法1を選択して標準でインストールされているgettext-runtime-miniのパッケージを削除すればsysstatをインストールすることができます。
インストール直後
インストールした直後は統計ログが蓄積されておらず、コマンドを実行しても以下のようなエラーになります。コーヒーでも飲みながログが溜まるまで待ちましょう。
$ sar /var/log/sa/sa03 を開けません: そのようなファイルやディレクトリはありません
10分間以上待っても統計データが出力されない場合は、導入に問題があった可能性があります。設定を確認しましょう。
ちなみにこのsa03というのは日付に対応しています。7月3日ならば/var/log/sa/sa03というファイルに統計情報が蓄積されます。このようにしてデフォルトで28日前までの統計データを辿ることができます。
オプションなしでsarを実行した場合、あるいはsar -u
を実行した場合は過去のCPU使用率を出力することができます。
各項目の意味
項目 | 意味 |
---|---|
%user | CPUのうちカーネル以外の処理に使われた時間の割合 |
%nice | CPUのうちnice値を変更したプロセスに使われた時間の割合 |
%system | CPUのうちカーネル処理に使われた時間の割合 |
%iowait | CPUのうちI/O待ちに使われた時間の割合 |
%steal | CPUのうちゲストOSがホストOSに割り当て要求をしたが割り当てられなかった時間の割合 |
%idle | CPUのうちアイドル状態かつI/Oリクエスト待ちではなかった時間の割合 |
ロードアベレージを表示したい
ロードアベレージの推移を出力したい場合は、
$ sar -q
項目 | 意味 |
---|---|
runq-sz | 実行待ちのキューに入っているプロセス数 |
plist-sz | プロセスリストの中のプロセス数とスレッド数 |
ldavg-1 | 過去1分間のロードアベレージ |
ldavg-5 | 過去5分間のロードアベレージ |
ldavg-15 | 過去15分間のロードアベレージ |
メモリの状態を表示したい
メモリの推移を出力したい場合は、sar -r
オプションを使うと良いでしょう。
$ sar -r
項目 | 意味 |
---|---|
kbmemfree | 物理メモリ空き容量 |
kbmemused | 物理メモリ使用量 |
%memused | 物理メモリ使用率 |
kbbuffers | バッファに使用されている物理メモリ使用量 |
kbcached | キャッシュに使用されている物理メモリ使用量 |
kbcommit | 現在のワークロードに必要なメモリ容量 |
%commit | 総メモリ容量(RAM+スワップ)に対する現在のワークロードに必要なメモリ容量の比率 |
ディスクI/Oを表示したい
ディスクI/Oの推移を出力したい場合は、sar -b
オプションを使うと良いでしょう。
$ sar -b
項目 | 意味 |
---|---|
tps | 1秒あたりのI/Oリクエスト数 |
rtps | 1秒あたりの読み込みI/Oリクエスト数 |
wtps | 1秒あたりの書き込みI/Oリクエスト数 |
bread/s | 1秒あたりの読み込みデータ量(ブロック単位) |
bwrtn/s | 1秒あたりの書き込みデータ量(ブロック単位) |
ネットワークの通信状態を表示したい
ネットワークの通信状態を表示したい場合は、sar -n DEV
オプションを使うと良いでしょう。
$ sar -n DEV
項目 | 意味 |
---|---|
IFACE | ネットワークインターフェース名 |
rxpck/s | 1秒あたりの総受信パケット数 |
txpck/s | 1秒あたりの総送信パケット数 |
rxkB/s | 1秒あたりの総受信キロバイト数 |
txkB/s | 1秒あたりの総送信キロバイト数 |
rxcmp/s | 1秒あたりの総受信圧縮パケット数 |
txcmp/s | 1秒あたりの総送信圧縮パケット数 |
rxmcst/s | 1秒あたりの総受信マルチキャストパケット数 |
ネットワークの通信エラー状態を表示したい
先ほどのコマンドのDEVオプションをEDEVに変えると通信エラーの統計を出力できます。
$ sar -n EDEV
項目 | 意味 |
---|---|
IFACE | ネットワークインターフェース名 |
rxerr/s | 1秒あたりの総受信エラーパケット数 |
txerr/s | 1秒あたりのパケット送信エラー数 |
coll/s | 1秒あたりのパケット送信衝突数 |
rxdrop/s | 1秒あたりのバッファ領域不足で発生した受信パケットのドロップ数 |
txdrop/s | 1秒あたりのバッファ領域不足で発生した送信パケットのドロップ数 |
txcarr/s | 1秒あたりのパケット送信キャリアエラー数 |
rxfram/s | 1秒あたりのフレーム・アライメント・エラー数 |
rxfifo/s | 1秒あたりの受信パケットのFIFOオーバーランエラー数 |
txfifo/s | 1秒あたりの送信パケットのFIFOオーバーランエラー数 |
過去の情報を取得したい
過去の日付の統計結果を得たい場合は、sar -f
オプションでログファイルを指定すると過去の日付のデータが確認できます。
$ sar -f /var/log/sa/sa05
トラブルシューティング:ファイルが開けない
サーバーの大きな構成変更をした場合に過去のログファイルが以下のエラーで開けないことがあります。
$ sar -f /var/log/sa/sa05 システム動作情報ファイルの形式が正しくありません
このような場合は以下のコマンドで過去のファイルを開くことができます。
$ sar -f /var/log/sa/sa05 --legacy
過去のデータの蓄積期間を延長したい
sarコマンドでデフォルトで記録される期間は28日間ですが、これを延長することもできます。/etc/sysconfig/sysstatに以下のデフォルト値が保存されています。
# Run system activity accounting tool every 10 minutes */10 * * * * root /usr/lib64/sa/sa1 1 1 # 0 * * * * root /usr/lib64/sa/sa1 600 6 & # Generate a daily summary of process accounting at 23:53 53 23 * * * root /usr/lib64/sa/sa2 -A faust@ip-172-31-29-53:~% sudo cat /etc/sysconfig/sysstat # sysstat-9.0.4 configuration file. # How long to keep log files (in days). # If value is greater than 28, then log files are kept in # multiple directories, one for each month. HISTORY=28 # Compress (using gzip or bzip2) sa and sar files older than (in days): COMPRESSAFTER=31 # Parameters for the system activity data collector (see sadc manual page) # which are used for the generation of log files. SADC_OPTIONS="-S DISK" # Compression program to use. ZIP="bzip2"
HISTORY=28
となっているのがログの保存期間です。1年間取り続けたいならばこれをHISTORY=365
に変えると良いでしょう。
なお、HISTORYを28より大きい数字にした場合、データ保存ファイル名が/var/log/sa/sa{DD}であったのが、/var/log/sa/{YYYYMM}/{DD}に自動的に変わります。ディレクトリは自動的に作成されます。
COMPRESSAFTER=31
はログを圧縮するデータ経過日数です。ここで指定した日数を経過したログはgzipまたはbzip2で圧縮されます。この圧縮形式を決めているのがZIP="bzip2"
オプションです。
実行間隔を短くしたい
sysstatの記録間隔は/etc/cron.d/sysstatで設定されています。デフォルトでは10分間隔です。また23時53分に前日のログとしてアーカイブされます。
*/10 * * * * root /usr/lib64/sa/sa1 1 1 # 0 * * * * root /usr/lib64/sa/sa1 600 6 & # Generate a daily summary of process accounting at 23:53 53 23 * * * root /usr/lib64/sa/sa2 -A
もしこの間隔を5分おきのように短く設定したい場合は、/10
となっている部分を/5
に変更すると良いでしょう。ただしその分、ログのファイルサイズと負荷は少し上がります。
時間帯を指定して統計データを取得したい
sarコマンドで時間帯を指定したい場合は、sar -s hh:mm:ss -e hh:mm:ss
で指定すると良いでしょう。過去の日付ファイルから時間帯を絞り込むこともできます。
$ sar -s 15:00:00 -e 20:00:00
iostat
このコマンドは何?
iostatはディスクI/Oの負荷を計測するのに便利なコマンドです。
導入方法
sarコマンドで紹介したsysstatパッケージを導入すると使えるようになります。
iostatコマンドの出力結果
iostatをオプション無しで初回実行した場合、出力結果は以下のようになります。
iostat -x
で表示項目を増やすことができます。
iostat -x 5
で5秒間隔のI/O負荷が表示されます。
$ iostat -x 5
iostatの注意点として初回実行時はディスクデバイスが有効になってから現在までの累積値が表示されます。リアルタイムなデータを得たいならば2回目以降の結果を元に計測するのが良いでしょう。
各項目の意味
項目 | 意味 |
---|---|
rrqm/s | 1秒間あたりのデバイスへマージされた読み込みリクエスト数 |
wrqm/s | 1秒あたりのデバイスへマージされた書き込みリクエスト数 |
r/s | 1秒あたりの読み込みリクエスト数 |
w/s | 1秒あたりの書き込みリクエスト数 |
rsec/s | 1秒あたりの読み込みセクタ数 |
wsec/s | 1秒あたりの書き込みセクタ数 |
avgrq-sz | デバイスへのI/Oリクエストの平均ヘクタサイズ |
avgpu-sz | デバイスへのI/Oリクエストのキューの平均ヘクタサイズ |
await | デバイスへのI/Oリクエストの平均待ち時間(ミリ秒) |
svctm | デバイスへのI/Oリクエストの平均処理時間(ミリ秒) |
%util | デバイスへのI/Oリクエスト時のCPUの使用率 |
mpstat
このコマンドは何?
mpstatコマンドはCPU別の処理負荷を調べるのに便利なコマンドです。
導入方法
sarコマンドで紹介したsysstatパッケージを導入すると使えるようになります。
CPU処理の偏りを調べたい
mpstatをオプション無しで実行した場合はCPU全体の情報が出力されますが、mpstat -P ALL
を指定することでCPU別の処理状況を表示できます。どこかのCPUに処理が偏っていないかを調査できます。以下は1秒間隔でCPUの偏りを調査する例です。
$ mpstat -P ALL 1
dstat
このコマンドは何?
dstatはvmstatより詳細に負荷要因になっているプロセスを特定することができます。
導入方法:CentOSの場合(※注意が必要)
CentOS系の場合は以下のコマンドでインストールできますが、CentOS6の場合は注意が必要です。
$ sudo yum install dstat
CentOS6のYumでインストールしたdstatでは、ディスクI/Oが最も多いプロセスをプロセスIDつきで表示する--top-io-advや、ブロックベースで最もディスクI/Oが多いプロセスをプロセスIDつきで表示する--top-bio-advなどのオプションが標準で無効になっています。CentOS7では標準で有効になっていますので問題ありません。
$ sudo dstat -ta --top-io-adv --top-bio-adv dstat: option --top-bio-adv not recognized, try dstat -h for a list of all the options
CentOS6の場合の対応策として、ソースコードからインストールした場合はこのオプションが標準で有効になります。
$ git clone https://github.com/dagwieers/dstat $ cd dstat $ make $ sudo make install
まあ、--top-io-advや--top-bio-advが使えなくても、そのミニマム版である--top-ioや--top-bioなどで近い結果は得られるのですが、--top-io-advや--top-bio-advが使えた方がプロセスIDが取得できるなど何かと便利です。
導入方法:Debian / Ubuntuの場合
Debian / Ubuntuの場合は以下のコマンドでインストールできます。
$ sudo apt install dstat
導入方法:openSUSEの場合
openSUSEの場合は以下のコマンドでインストールできます。
$ sudo zypper in dstat
dstatの実行結果
オプション無しでdstatを実行した結果は以下の通りです。
$ dstat
vmstatとかなり似ていますがカラフルになっていますね。ネットワーク通信やページングに関する情報も表示されています。なお、オプション無しで実行した場合はdstat -cdngy
というオプションを指定したのと同値になります。仮にdstat -t
(タイムスタンプ情報付与)などでオプションを追加したい場合は、dstat -ta
などと-aオプションを付けると、-cdngyをつけるのと同じ意味になります。
最もCPU使用率が高いプロセスを特定したい
dstat --top-cpu-adv
を使うと最もCPU使用率が高いプロセスをPIDつきで表示させることができます。なお、この特定結果は一般ユーザー権限では出てこない場合が多くsudoをつけて実行すると良いでしょう。
$ sudo dstat -t --top-cpu-adv
最もメモリ使用量が多いプロセスを表示したい
dstat --top-mem
を使うと最もCPU使用率が高いプロセスを表示させることができます。
$ sudo dstat -t --top-mem
最もディスクI/Oを行っているプロセスを特定したい
dstat --top-io-adv
やdstat --top-bio-adv
オプションを使うと最もディスクIOを行っているプロセスをPIDつきで表示させることができます。
$ sudo dstat -t --top-io-adv --top-bio-adv
最もOOM Killerの発動要因となりそうなプロセスを特定したい
-dstat --top-oom
を実行すると最もOOM Killer発動要因となりそうなプロセスが表示されます。
$ sudo dstat -t --top-oom
dstatのプラグイン導入方法
dstatのオプションはプラグイン形式で拡張できます。プラグインはPythonで書くことができ、/usr/share/dstat/のディレクトリにdtsta_hogehoge.pyのような名前で入れればオプションで指定できるようになります。多くの場合、標準で以下のプラグインが同梱されています。
lsof
このコマンドは何?
ある程度原因となるプロセスが絞られてきたらlsofコマンドを実行するのもお薦めです。lsofによって現在プロセスがオープンしているファイル(ファイルディスクリプタ)を調査できます。
導入方法:CentOSの場合
CentOSの場合は以下のコマンドでインストールできます。
$ sudo sudo yum install lsof
導入方法:Debian / Ubuntuの場合
Debian / Ubuntuの場合は以下のコマンドでインストールできます。
$ sudo sudo apt install lsof
lsofは多くのディストリビューションに標準でインストールされています。
プロセスがオープンしているファイル一覧を調べたい
lsofはオプションをつけずに実行すると全プロセスの全てのオープンしているファイル一覧を出力してしまいますので、lsof -p ****
でプロセスIDを指定するか、プロセス名でgrepするようにしましょう。
$ sudo lsof -p MySQLのプロセスID
stress
このコマンドは何?
stressコマンドはシステムに対して意図的に負荷を与えることができます。
導入方法:CentOSの場合
CentOSの場合は以下のコマンドでインストールできます。
$ sudo sudo yum install stress
導入方法:Debian / Ubuntuの場合
Debian / Ubuntuの場合は以下のコマンドでインストールできます。
$ sudo sudo apt install stress
導入方法:openSUSEの場合
残念なことにopenSUSEの標準のリポジトリにはstressパッケージは保管されていません。
以下のリンクを参考に環境に合わせたRPMをインストールする必要があります。
CPUに負荷を掛けたい
stressを使ってCPUに負荷を掛けてみましょう。CPU負荷はstress -c 2 -t 10
などのオプションで掛けることができます。-cで指定するのはワーカーの数、-tは実行時間(秒)です。manによると内部的にはsqrt()
を実行しています。2コアのサーバーで動かす場合はワーカーは2つに設定すると良いでしょう。
$ stress -c 2 -t 10
dstatでCPU負荷を見てみましょう。CPU使用率が100%になっています。
mpstatで見ても各コアに均等に負荷が掛かっています。
メモリに負荷を掛けたい
stressでメモリに負荷を掛ける場合はstress --vm
オプションを使います。--vmはmalloc()
とfree()
を繰り返すワーカーの数です。-vm-bytesでメモリ量を指定することができます。デフォルトではメモリの確保と解放を繰り返しますが、--vm-keepオプションでメモリの確保を継続させることができます。
今回は1GBのメモリを確保し続けるワーカーを2つ動かしてみましょう。
$ stress --vm 2 --vm-bytes 1G --vm-keep -t 30
それではdstatの結果を見てみましょう。stressによってメモリ負荷が掛かったのが確認できます。
トラブルシューティング
以下のエラーが出たらメモリが少なってアロケートできず新たにmalloc()
を実行するワーカーが追加できません。ほどほどにしましょう。
stress: info: [25009] dispatching hogs: 0 cpu, 0 io, 2 vm, 0 hdd stress: FAIL: [25011] (494) hogvm malloc failed: Cannot allocate memory stress: FAIL: [25009] (394) <-- worker 25011 returned error 1 stress: WARN: [25009] (396) now reaping child worker processes stress: FAIL: [25009] (400) kill error: No such process stress: FAIL: [25010] (494) hogvm malloc failed: Cannot allocate memory stress: FAIL: [25009] (394) <-- worker 25010 returned error 1 stress: WARN: [25009] (396) now reaping child worker processes stress: FAIL: [25009] (400) kill error: No such process stress: FAIL: [25009] (451) failed run completed in 0s
応用編へ向けて
今回紹介しきれなかったコマンドは応用編にて書いていきます。