Linux上でプロセス毎のI/Oを調査するツール piotop.pl をさらに改造

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件のフィードバック

コメントは受け付けていません。