topコマンドのように、実行中のプロセスとプロセスのreadとwriteのI/OをBpsでリアルタイムで表示するツールpiotop.plをPerlの復習がてら作ってみました。さらに、それをOpenVZやVirtuozzo+Plesk+Apacheの環境で、どのコンテナのどのドメインのどのCGIやPHPがどの程度I/Oを使っているのか、まで調べることができるようにしました。
はじめに
vmstatやiostat等が個人的にはあまり見やすくないのと、Webサーバ上でトラフィックだけでなく、実際にHDDとのI/Oがどの程度なのかをプロセス単位で調べたい、というのがもともとの動機です。トラフィックが少なくても、サーバ内部で猛烈にI/Oするようなプログラムもあって、それがサーバや共有ストレージに負荷を与える事が多々ありました。また、サーバを共有している場合では、以前にも述べましたが、リソースを食っているユーザとそのプロセスのみをきちんと調査して制限し、優良なユーザには迷惑をかけないようにするのが運用者のたしなみだと言えます。
さらに、それをOpenVZやVirtuozzoのコンテナ環境でも、複数のコンテナをまたいでプロセスのI/Oや高負荷対象の調査をしたいと思うのが普通の流れだと思います。
追記(2012/04/15):元々iotopというコマンドがPythonであったようですね。今見てびっくりしました。piotop.plとしてスクラッチで書いたのと、これを元々書いたのが2、3年前だったので、当時はiotopの存在に気づいていませんでした。とりあえずは、それのPerl版と思ってもらうと良いと思います。名前もかぶってたので変えました。さらに、それをVirtuozzoに対応させた所に新規性があると思って頂けると嬉しいです。(強引ですが・・・)
導入
では、前置きはこれくらいにしておいて、先に一旦piotop.plの使い方を説明します。piotop.plを動かすには、まず、プロセス毎にI/Oを計測する機能をkernelで有効にしておかないといけません。といっても、最近のCentOS等はデフォルトで有効になっているので、すぐに使えると思います。使えるかどうかの確認は、proc以下に以下のファイルがあるかを確認してください。
[program lang=’bash’ escaped=’true’]
ls /proc/self/io
[/program]
これがあれば、piotop.plが使えます。では、実際にソースをダウンロードして叩いてみましょう。
[program lang=’bash’ escaped=’true’]
git clone git://github.com/matsumoto-r/piotop.git
[/program]
「LinuxでIPやポート単位で簡単にトラフィックをコントロールしよう」の時と同様に、ここでも独自PerlモジュールであるSystem::BaseとSystem::Procを使っているので必要なPerlモジュールをインストールしておきます。(rpmforgeを見れるようにしておくこと)
もしくは、普通に実行してみた足りないPerlモジュールを適当に入れると良いとおもいます。下のは何も考えずに入れる用です。
[program lang=’bash’ escaped=’true’]
yum --enablerepo=rpmforge install perl-Class-Accessor perl-Jcode perl-DBI perl-JSON perl-Data-Dump perl-LWP-UserAgent-Determined
[/program]
使い方
では実際に使ってみましょう。まずは、以下のようにコマンドを叩くとヘルプが出力されます。
[program lang=’bash’ escaped=’true’]
./piotop.pl --help
[/program]
以下の出力が得られます。
[program lang=’bash’ escaped=’true’]
usage: ./piotop.pl [--line|-l LINE] [--interval|-i INTERVAL] [--sortorder|-s SORT] [--count|-c COUNT] [--zero|-z]
-l, --line output lines (default 20)
-i, --interval check interval (default 3)
-s, --sort sort order: read, write (default write)
-c, --count count (default no limit)
-z, --nozero don't print zero value
-h, --help display this help and exit
-v, --version display version and exit
[/program]
基本的には、オプションは何もつけずに実行してやれば良いです。その場合は、3秒毎に各プロセスのI/OをMbpsの単位でwriteの多い順にソートして出力する。また、出力のインターバルを変えたい場合や、sortをreadの多い順にしたい場合、また、出力の行数を変更したり、I/Oが0Mbpsの場合は表示しない、表示回数を10回にする等のオプションを用意しています。
例えば、1秒間隔でreadのsortで、10行だけ表示したい場合は、以下のようにオプションを渡します。
[program lang=’bash’ escaped=’true’]
./piotop.pl --line=10 --interval=1 --sort=read
[/program]
表示回数を5回、I/Oが0の場合は表示しない、5秒間隔で表示したい場合は、以下のようにオプションを渡します。
[program lang=’bash’ escaped=’true’]
./piotop.pl --nozero --count=5 --interval=5
[/program]
rsyncコマンド実行中にpiotopを試してみた
では、実際にどういう出力がされるか、rsyncコマンドを叩いている最中に実行してみました。
まずは、何もオプションを渡さず実行した場合(3秒間隔、writeの多い順、20行表示、0bpsも表示)です。
[program lang=’bash’ escaped=’true’]
./piotop.pl
[/program]
実行結果は以下のようになります。topのように画面がclearされながら出力されます。
[program lang=’bash’ escaped=’true’]
-- Every 3 sec --
13:59:10 up 13 days, 15:28, 11 users, load average: 0.22, 0.05, 0.01
pid state read write command cwd_path
1818 S (sleeping) 0bps 1Mbps kjournald /
13314 S (sleeping) 21Kbps 32Kbps rsync /backup
13312 D (disk sleep) 21Mbps 0bps rsync /
13313 D (disk sleep) 20Mbps 0bps rsync /backup
21561 S (sleeping) 0bps 0bps bash /root
1788 S (sleeping) 0bps 0bps kmpathd/0 /
2174 S (sleeping) 0bps 0bps ntpd /
7 S (sleeping) 0bps 0bps watchdog/1 /
1793 S (sleeping) 0bps 0bps kmpath_handlerd /
26 S (sleeping) 0bps 0bps kblockd/1 /
227 S (sleeping) 0bps 0bps khungtaskd /
460 S (sleeping) 0bps 0bps ata/0 /
453 S (sleeping) 0bps 0bps scsi_eh_0 /
18 S (sleeping) 0bps 0bps khelper /
25086 S (sleeping) 0bps 0bps sshd /
16 S (sleeping) 0bps 0bps events/2 /
15312 S (sleeping) 0bps 0bps bash /root/DEV/develop-code
27 S (sleeping) 0bps 0bps kblockd/2 /
233 S (sleeping) 0bps 0bps aio/2 /
25087 S (sleeping) 0bps 0bps bash /home/matsumoto_r
463 S (sleeping) 0bps 0bps ata/3 /
230 S (sleeping) 0bps 0bps kswapd0 /
13028 S (sleeping) 0bps 0bps sshd /
21124 S (sleeping) 0bps 0bps tiarra /usr/local/tiarra
454 S (sleeping) 0bps 0bps aacraid /
1789 S (sleeping) 0bps 0bps kmpathd/1 /
231 S (sleeping) 0bps 0bps aio/0 /
151 S (sleeping) 0bps 0bps kseriod /
232 S (sleeping) 0bps 0bps aio/1 /
462 S (sleeping) 0bps 0bps ata/2 /
10 S (sleeping) 0bps 0bps watchdog/2 /
11 S (sleeping) 0bps 0bps migration/3 /
13311 S (sleeping) 0bps 0bps sh /root
13029 S (sleeping) 0bps 0bps bash /home/matsumoto_r
25107 S (sleeping) 0bps 0bps ssh /home/matsumoto_r
1184 S (sleeping) 0bps 0bps kedac /
29 S (sleeping) 0bps 0bps kacpid /
149 S (sleeping) 0bps 0bps khubd /
6049 S (sleeping) 0bps 0bps screen /root
25151 S (sleeping) 0bps 0bps screen /root
[/program]
rsyncでファイルリストを作っている最中で、readが多く発生しているようですね。これだとwriteソートでは見難いです。なので、readソートで出力してみます。コマンドは以下です。
[program lang=’bash’ escaped=’true’]
./piotop.pl -s read
[/program]
すると、以下のように出力が得られます。(topコマンドのようにターミナルがclearされるように実装しています)
[program lang=’bash’ escaped=’true’]
-- Every 3 sec --
13:59:19 up 13 days, 15:28, 11 users, load average: 0.42, 0.10, 0.03
pid state read write command cwd_path
13312 D (disk sleep) 22Mbps 0bps rsync /
13313 D (disk sleep) 21Mbps 0bps rsync /backup
503 S (sleeping) 10Kbps 6Mbps kjournald /
1818 S (sleeping) 0bps 2Mbps kjournald /
21561 S (sleeping) 0bps 0bps bash /root
1788 S (sleeping) 0bps 0bps kmpathd/0 /
2174 S (sleeping) 0bps 0bps ntpd /
7 S (sleeping) 0bps 0bps watchdog/1 /
1793 S (sleeping) 0bps 0bps kmpath_handlerd /
26 S (sleeping) 0bps 0bps kblockd/1 /
227 S (sleeping) 0bps 0bps khungtaskd /
460 S (sleeping) 0bps 0bps ata/0 /
453 S (sleeping) 0bps 0bps scsi_eh_0 /
18 S (sleeping) 0bps 0bps khelper /
25086 S (sleeping) 0bps 0bps sshd /
16 S (sleeping) 0bps 0bps events/2 /
13314 S (sleeping) 0bps 0bps rsync /backup
15312 S (sleeping) 0bps 0bps bash /root/DEV/develop-code
27 S (sleeping) 0bps 0bps kblockd/2 /
233 S (sleeping) 0bps 0bps aio/2 /
25087 S (sleeping) 0bps 0bps bash /home/matsumoto_r
463 S (sleeping) 0bps 0bps ata/3 /
230 S (sleeping) 0bps 0bps kswapd0 /
13028 S (sleeping) 0bps 0bps sshd /
21124 S (sleeping) 0bps 0bps tiarra /usr/local/tiarra
454 S (sleeping) 0bps 0bps aacraid /
1789 S (sleeping) 0bps 0bps kmpathd/1 /
231 S (sleeping) 0bps 0bps aio/0 /
151 S (sleeping) 0bps 0bps kseriod /
232 S (sleeping) 0bps 0bps aio/1 /
462 S (sleeping) 0bps 0bps ata/2 /
10 S (sleeping) 0bps 0bps watchdog/2 /
11 S (sleeping) 0bps 0bps migration/3 /
13311 S (sleeping) 0bps 0bps sh /root
13029 S (sleeping) 0bps 0bps bash /home/matsumoto_r
25107 S (sleeping) 0bps 0bps ssh /home/matsumoto_r
1184 S (sleeping) 0bps 0bps kedac /
29 S (sleeping) 0bps 0bps kacpid /
149 S (sleeping) 0bps 0bps khubd /
6049 S (sleeping) 0bps 0bps screen /root
[/program]
readでソートされました。Mbpsで出力されていて、直感的にI/Oとそれに紐づくプロセスが分かりやすいと思います。これで、リソースを使いすぎてるユーザを発見して、cgroup等で制限してやりましょう。そういうツールも鋭意作成中です。
おまけというか本番(piotop.plをVirtuozzo+Plesk+Apache環境に対応)
おまけというかこっちが本番です。わりと本気で作ったものなので紹介しておきます。こっちのツールはpiotop.plをさらに改良したpiotop_for_virtuozzo.plです。
これは、OpenVZやVirtuozzoでコンテナを複数収容しているときに、ハードウェアノード上からこのpiotop_for_virtuozzo.plを叩くことで、全コンテナのプロセスでのI/Oのランキングを出力することができます。また、そのプロセスがどのコンテナにあるのかもctidという項目欄で出力するので、どのコンテナのどのプロセスがリソースを消費しているのかを調べることができます。
また、Plesk+Virtuozzoを使っている場合では、恐らく/var/www/vhosts/以下に各PleskクライアントのApacheを使ったWebホスティング領域がデフォルトであると思います。そのディレクトリ構造を利用して、コンテナ内のプロセスがWebサーバ経由のプロセス(例えばCGI)で、実行されているユーザが特定できる場合は、そのユーザと紐づくドメインを出力するようにしています。
これによって、どのコンテナのどのドメインのCGIがどの程度I/Oを使っているのか、まで調べることが可能です。かなり便利だと思うので、是非Plesk+Virtuozzoなハードウェアノードの管理者でApacheを動かしている場合は使ってみてください。使い方は、piotop.plと同じで、出力例としては以下のようになります。Plesk+Virtuozzo環境を今試せないので適当に想像して出力してみました。
[program lang=’bash’ escaped=’true’]
./piotop_for_virtuozzo.pl
[/program]
出力結果は以下です。
[program lang=’bash’ escaped=’true’]
-- Every 3 sec --
14:24:41 up 13 days, 15:53, 11 users, load average: 0.86, 1.56, 1.34
pid state read write ctid domain command cwd_path
21561 S (sleeping) 0bps 82Mbps 201 hoge.matsumoto-r.jp hoge.cgi /path/to/vz/201/var/www/vhosts/hoge.matsumoto-r.jp/httpdocs
21562 S (sleeping) 99Mbps 10Mbps 202 fuga.matsumoto-r.com fuga.cgi /path/to/vz/202/var/www/vhosts/fuga.matsumoto-r.com/httpdocs
1788 S (sleeping) 0bps 0bps nothing nothing kmpathd/0 /
2174 S (sleeping) 0bps 0bps nothing nothing ntpd /
7 S (sleeping) 0bps 0bps nothing nothing watchdog/1 /
1793 S (sleeping) 0bps 0bps nothing nothing kmpath_handlerd /
26 S (sleeping) 0bps 0bps nothing nothing kblockd/1 /
227 S (sleeping) 0bps 0bps nothing nothing khungtaskd /
460 S (sleeping) 0bps 0bps nothing nothing ata/0 /
453 S (sleeping) 0bps 0bps nothing nothing scsi_eh_0 /
18 S (sleeping) 0bps 0bps nothing nothing khelper /
25086 S (sleeping) 0bps 0bps nothing nothing sshd /
16 S (sleeping) 0bps 0bps nothing nothing events/2 /
15312 S (sleeping) 0bps 0bps nothing nothing bash /root/DEV/develop-code
27 S (sleeping) 0bps 0bps nothing nothing kblockd/2 /
233 S (sleeping) 0bps 0bps nothing nothing aio/2 /
25087 S (sleeping) 0bps 0bps nothing nothing bash /home/matsumoto_r
463 S (sleeping) 0bps 0bps nothing nothing ata/3 /
230 S (sleeping) 0bps 0bps nothing nothing kswapd0 /
13028 S (sleeping) 0bps 0bps nothing nothing sshd /
21124 S (sleeping) 0bps 0bps nothing nothing tiarra /usr/local/tiarra
454 S (sleeping) 0bps 0bps nothing nothing aacraid /
1789 S (sleeping) 0bps 0bps nothing nothing kmpathd/1 /
231 S (sleeping) 0bps 0bps nothing nothing aio/0 /
151 S (sleeping) 0bps 0bps nothing nothing kseriod /
232 S (sleeping) 0bps 0bps nothing nothing aio/1 /
462 S (sleeping) 0bps 0bps nothing nothing ata/2 /
10 S (sleeping) 0bps 0bps nothing nothing watchdog/2 /
13586 R (running) 0bps 0bps nothing nothing piotop_for_virtu /usr/local/sbin
11 S (sleeping) 0bps 0bps nothing nothing migration/3 /
13029 S (sleeping) 0bps 0bps nothing nothing bash /home/matsumoto_r
25107 S (sleeping) 0bps 0bps nothing nothing ssh /home/matsumoto_r
1184 S (sleeping) 0bps 0bps nothing nothing kedac /
29 S (sleeping) 0bps 0bps nothing nothing kacpid /
149 S (sleeping) 0bps 0bps nothing nothing khubd /
6049 S (sleeping) 0bps 0bps nothing nothing screen /root
25151 S (sleeping) 0bps 0bps nothing nothing screen /root
563 S (sleeping) 0bps 0bps nothing nothing udevd /
15635 S (sleeping) 0bps 0bps nothing nothing bash /usr/local/tiarra
13258 S (sleeping) 0bps 0bps nothing nothing bash /usr/local/sbin
12 S (sleeping) 0bps 0bps nothing nothing ksoftirqd/3 /
[/program]
ドメインがある行を見れば、一発でどこのだれが悪い事をしているのかわかると思います。ドメインが出力されている行は赤色で表示されるので見やすいと思います。そのほかにも、複数のコンテナ全体でのCPUやメモリの使用量、ハードウェアノードのプロセスとコンテナ上のプロセスの紐づけ等を出力するコマンドを作りましたが、また機会があれば紹介したいと思います。
是非、こういうツールを駆使して安定したWebサーバを運用していきましょう。もちろん、こういうツールを使って、運用管理の時間を短縮し、コードを書く時間を増やすのが目的です。
「Linux上でプロセス毎のI/Oを調査するツール piotop.pl をさらに改造」への2件のフィードバック
コメントは受け付けていません。