ps-watcherによるプロセスモニタリング

 コンピュータのモニタリングには、多種多様な方法がある。大規模なシステムには、プロプライエタリの大がかりなアプリケーションを適用してもよいだろう。ソフトウェアや、システムの微調整を行うコンサルタントに費用をかけられるからだ。NagiosやOpenNMSなどのオープンソースのモニタリングツールは、入手はタダだが、計画や微調整はやはり必要になる。システム上のプロセスデータに関するやや小さな問題に対処したい場合には、プロセスモニタリングツールである ps-watcher が便利だ。

 ps-watcherは、ある1つの作業に特化して、それをうまく処理してくれるUnixツールの1例である。システム上のすべてのプロセス情報にアクセスし、その情報に基づいた選択を行うことを可能とする。ps-watcherは、異なるUnixおよびLinuxマシン上のさまざまなプロセス情報に対し、一貫したインターフェースを提供する(ただし、注意を要する部分あり)。

 ps-watcherは、最初からシステムに含まれてはいないかもしれないが、これをインストールするのは簡単である。ソースコードをダウンロードし、「configure; make; make install」というお決まりのコマンドを実行する。ps-watcherをroot権限でインストールまたは実行する必要はないが、実行したい処理によってはrootで起動するか、sudoコマンドを使用する必要があるかもしれない。簡単なモニタリングや警告のためだけならば、任意のユーザでps-watcherを実行することができる。システム要件は特にないため、任意のUnix系システムにインストールし、稼働させることができるはずだ。

 インストールを終えたら、構成ファイルを作成する。構成ファイルには、psコマンドの出力に基づくps-watcherのレポート内容に対する、モニタリングや操作のための規則を記述する。構成ファイルの他にも、ps-watcherの動作を微調整したり、デバッグを支援したりするためのコマンドラインオプションを指定することができる。

簡単な例

 ps-watcherは、メモリ溢れによるマシンのクラッシュを防ぐことができる。つまり、バグによって同一プログラムのコピーが多数実行される現象を回避する。基本的な使用例の1つは、あるプログラムが稼働していることを保証するというものである。たとえば、正確な時刻を維持するためのNetwork Time Protocolデーモンntpdのコピーが、CentOS Linuxサーバ上に1つだけ存在するようにしたい場合を考える。ntpdを継続的に稼働させるのは、それほど容易というわけでもない。たとえば、システム時間と基準時間が大きく異なる場合は、起動直後に停止してしまう。ntpdを継続的に稼働させるための方法の1つは、任意の時点において少なくとも1つのntpdが稼働していることをps-watcherによって保証することである。以下の内容からなるps-watcher.cfgファイルを作成する。

[ntpd]
occurs = none
action = /etc/init.d/ntpd restart

 角括弧に囲まれた1行目は、psの出力におけるcmdフィールドとマッチングさせるための正規表現である。特定のプロセスが稼働していることをモニタリングし、かつ、そのプロセスがある条件を満たす場合には何らかの操作を行う、という記述をしたい場合には、同一のプロセス名で2度マッチングさせたいと思うかもしれないが、ps-watcherでは、1つの構成ファイル内で同一のプロセス名に複数回マッチさせることはできないようになっている(このための方法については、後ほど説明する)。この場合の回避策としては、"ntpd"と"ntp"など、少し異なる正規表現にマッチさせるという手段をとるしかない。2行目(occurs=none)は、マッチするプロセス名がなければaction行を実行するようにps-watcherに指示している。occurs行は、アクション行の実行頻度を制御する。noneの場合は、マッチするものがなければアクションを実行し、everyの場合は、マッチしたすべてに対してアクションを実行する。指定可能なその他の値については、ps-watcherのmanページを参照してほしい。

 この構成ファイルを使用するには、(rootで)ps-watcherを起動し、「ps-watcher --config ps-watcher.cfg」というコマンドによってこの構成ファイルを指定する。ps-watcherは自動的に自分自身をデーモン化し、定期的に再実行する(デフォルトでは5分おき)。ps-watcherが常に稼働されるようにするには、/etc/rc.localに1行追加して、ブートの度にこれが起動されるようにする。

より複雑な例

 ps-watcherの強みはその柔軟性にある。任意のマッチング条件を定義し、マッチした場合(またはしなかった場合)に任意のアクションを実行することができるため、優れた汎用のシステムモニタリングツールであるといえる。たとえば私は最近、FreeBSDのコンピュータにおいてプログラムの子プロセスが時々停止しないという問題に遭遇した。そのために時間が経つにつれてシステム負荷が徐々に増大し、最後にはシステムが応答しなくなるという現象が生じていた。完全に修復するにはおそらく、バグのあるソフトウェアを修正するためのアップグレードがいくつか必要なのだが、実稼働サーバであったため、ソフトウェアアップグレードのためのダウンタイムを設けるまでは、システムが停止しないように一時的な応急措置を講じなければならなかった。

 最初に思いついたのは、親と分離した子プロセスが消費するCPU時間をモニタリングし、たとえば1時間という上限を超えたらkillするという方法である。残念ながら親プロセスと子プロセスの名前が同一であるため、この方法はうまくいかなかった。親プロセスは常に稼働しているため、すぐにそのCPU時間は1時間を超過し、ps-watcherにkillされてしまうのだ。

 そこでプロセスID(PID)と親のプロセスID(PPID)の両方でマッチングさせることを思いついた。マスタープロセスはバックグラウンドデーモンであるため、その親は必ずinit(PPIDは1)である。子プロセスのPPIDは、マスタープロセスのプロセスIDである。これを利用して、ps-watcherの構成ファイルを以下のように作成した(マスタープロセスと子プロセスの名前を「foo」とする)。

[foo]
 occurs = every
 trigger = elapsed2secs('$time') > 1*HOURS && $ppid != 1
 action = <<EOT
 echo "$command accumulated too much CPU time" | /bin/mail user\@host
 kill -TERM $pid
EOT

[foo?]
 occurs = none
 action = /usr/local/etc/foo restart

 この構成ファイルでは、ps-watcherの高度な機能をいくつか使用している。まず、ps-watcherのビルトイン関数elapsed2secsを含む、2つのトリガ条件を組み合わせている。アクション行では、複数のアクションを実行するために、シェルスクリプトのヒアドキュメント(here-document)を使用している。最後に、少なくとも1つのマスタープロセスが稼働していることを確認し、稼働していなければ再起動するという処理を加えた。

その他の注意点

 しかしps-watcherは、柔軟であるがゆえに、面倒な部分もある。たとえばアクション行はPerlで解釈されるため、特殊文字は正しくエスケープしなければならない。上記の例では、メールアドレスの中の’@’の前にバックスラッシュを入れた。そうしなければPerlで解釈することができない。ps-watcherを使用する前にはドキュメント(manページ)を注意深く読み、前述のように同一コマンドで複数回マッチングさせることができない点など、その他の制約も理解しておく必要がある。

 幸い、ps-watcherにおけるほとんどの問題は、デバッグ機能をオンにすることで解決することができる。ps-watcherをデバッグモードで起動するには、以下のようにコマンドを実行する。

ps-watcher --debug 1 --nodaemon --log --config ps-watcher.cfg

 この場合ps-watcherは、起動時にバックグラウンドにはならず、デバッグメッセージを直接コンソールに出力する。これで構成ファイルの問題を特定し修正することができるはずだ。構成ファイルにおけるクォーティングの誤りなどは、デバッグ出力においてwarningとして指摘される場合が多い。

 ps-watcherは、ps出力をそのまま表示するということを覚えておいてほしい。ps出力は、FreeBSDやLinuxなどOSによってかなり違いがある。「ps-watcher --help」というコマンドを用いれば、使用中のプラットフォームにおいて有効な変数のリストが表示される。私が最初混同しそうになったのは、プロセスの累積CPU時間がFreeBSDでは$timeであるのに対し、Linuxでは$bsdtimeだということである。一見するとLinuxの$etimeが、FreeBSDの$timeに相当するのかと誤解しがちだ。$etimeは、プロセス起動からの経過実行時間である。

まとめ

 小さな問題を1つか2つ修正したいだけのために、包括的なシステムモニタリングツールを使うのはかえって面倒だ。ps-watcherは、マシンのプロセス情報をモニタリングし、それに対する処理を行いたい場合にまず使用するツールとして最適だといえる。

Linux.com 原文(2008年9月25日)