人間とウェブの未来

「ウェブの歴史は人類の歴史の繰り返し」という観点から色々勉強しています。

mruby-cliを使ってプロセスのfdをリソース使用率を元に解析するワンバイナリなツールpfdsを作った

タイトルのままなのですが、pidから対象プロセスがopenしてるファイルとそのownerを解析し、CPU使用率やMemory使用率と合わせてレポートするワンバイナリなツールを作りました。

というのも、ホスティングにおいては負荷をかけているプロセスについて、リソース使用量を元にopenしているファイルパスやファイルのownerを迅速に知りたい場合が多いからです。

既にあるコマンド、lsof/proctopとかその辺を組み合わせるともちろんできるんですが、mruby-cliを使ってone-binaryで作ってみたかったのと、openしているファイルとCPU使用率やMemory使用量同時にサクっと素早く表示してくれるツールがパッと調べた所なかったので実装してみました。

  • pfds - report a snapshot of the current processes fd

github.com

使い方

使い方はほぼREADMEのままなのですが、CPU使用量とかがいらない場合は、shortオプションで実行すると以下のように表示されます。

shortバージョン

$ sudo pfds short `pgrep nginx` | head
   19939 daemon /usr/local/nginx-1.9.5/logs/error.log
   19939 daemon /usr/local/nginx-1.9.5/logs/access.log
   19939 daemon /usr/local/nginx-1.9.5/logs/deflate.log
   19940 daemon /usr/local/nginx-1.9.5/logs/error.log
   19940 daemon /usr/local/apache-2.4.16/htdocs/blog/wp-content/plugins/wp-social-bookmarking-light/images/hatena.gif
   19940 daemon /usr/local/nginx-1.9.5/logs/access.log

左から、pid、openしているファイルのowner、openしているファイル、の順です。また、高速に動作するように、デフォルでは4並列で解析しており、並列数はMRUBY_MULTI環境変数から変更できます。

sudo MRUBY_MULTI=24 pfds short `pgrep httpd`

とかですね。

リソース使用量も表示するバージョン

CPUやMemoryの使用量でsortなどをしたい場合は、

$ sudo pfds `pgrep nginx` | head
   19939  0.0  0.1 daemon /usr/local/nginx-1.9.5/logs/error.log
   19939  0.0  0.1 daemon /usr/local/nginx-1.9.5/logs/access.log
   19939  0.0  0.1 daemon /usr/local/nginx-1.9.5/logs/deflate.log
   19940  0.0  0.3 daemon /usr/local/nginx-1.9.5/logs/error.log
   19940  0.0  0.3 daemon /usr/local/apache-2.4.16/htdocs/blog/wp-content/plugins/wp-social-bookmarking-light/images/hatena.gif
   14057 37.3  2.1 matsumoto_r /usr/local/apache-2.4.16/htdocs/blog/index.php

とすると、pid、cpu使用率、memory使用率、というように表示されます。

例えば、

sudo ./pfds `pgrep httpd` | sort -nk2

でCPU順にsortしたりすると良いでしょう。

無視リストを作っておく

普通に全部のopenファイルを見ると、たくさんですぎるので、例えばopenしているのがわかっているようなファイルを最初から無視リストにいれておくとよいでしょう。

そのためには、ビルド前に以下の mrblib/pfds/config.rb を変更してからビルドすると良いです。

module Pfds
  module Config

    MULTI_PROCESS = (ENV["MRUBY_MULTI"] || 4).to_i

    IGNORE_FILES = %w(

    /dev/null
    /var/log/httpd/access_log
    /var/log/httpd/ssl_access_log
    /var/log/httpd/error_log
    /var/log/httpd/ssl_error_log

    )

    IGNORE_PATTERN = %w(

    ^pipe:
    ^anon_inode:
    ^socket:
    ^/dev/pts/

    )
  end
end

デフォルトの並列数も変更できますね。

まとめ

ということで、ワンバイナリなのでバイナリ一つサーバに送り込めば使えて、わりと色々便利なのでぜひ使ってみてください。