System::ProcWatch はちょっとしたクラスを集めたもので、 システムのプロセスを容易に監視できるようにします。これは、 Unix のプログラム procps (ps) に基づいています。
System::ProcWatch を使用するには、System::ProcWatch の操作に基づいたルールセットを定義しなければなりません。 ルール (あるいはジョブ、ウォッチ) とは、ある条件が true と評価された際にどんなアクションが起こるのかを決めるものです。
これ以降は後で書きます……。
System::ProcWatch を、PHP スクリプト以外から使用することもでき、 そのために利用するシェルスクリプト procwatch および procwatch-lint が同梱されています。
procwatch コマンドは、システムの調査のために使用します。 デーモンとして実行するか、あるいは cron で実行します。
使用法は procwatch -h の出力を参照ください。
procwatch-lint は、XML で書かれた procwatch の設定ファイルの妥当性を検証するためのものです。 XML::DTD::XmlValidator を利用しています。
こちらも同様に、使用法については procwatch-lint -h の出力を参照ください。
System::ProcWatch アプリケーションの設定は、以下の三通りの方法で行えます。
System::ProcWatch の設定は、XML で行うことを推奨します。 この方式は、シンプルであると同時に高機能でもあります。
XML 設定ファイル/設定文字列のルート要素となるのが procwatch 要素です。この要素には省略可能な属性 version があり、暗黙的に "1.0" と設定されます。
procwatch 要素は、ルールセットを表すものです。 その子要素がルール群を表します。
ルート要素 procwatch の直接の子要素となるのが watch 要素です。これは一回あるいは複数回登場します。
watch 要素には必須属性がひとつあります。それが name 属性で、ウォッチ (あるいはジョブ、ルール) の名前を "httpd-count" のように指定します。
個々の watch 要素が、それぞれひとつのルールを表します。 検索に使用する正規表現や評価条件、そして実行するアクションといった内容が その中に含まれます。
ルールは、以下の三種類の子要素から構成されています。
pattern 要素の内容は perl 互換の正規表現で、 ps の出力の特定のカラムを評価するために使用します。
必須属性は match です。 ps の出力のカラム名を小文字にしたもの、例えば "command" や "vsz" を指定します。
このおかげで、System::ProcWatch は非常に多目的に使用できるようになっています。 また、procps プログラムが存在するあらゆるプラットフォームで使用できます。
pattern 要素の内容は perl 互換の正規表現で、 match 属性で定義したカラムに対して マッチを行います。正規表現には、開始と終了のデリミタを 必ず含めなければなりません。また、中では任意の PCRE 修飾子を使用することができます。
例: <pattern match="command">/sbin\/httpd/</pattern>
condition 要素は、条件を指定します。 これが TRUE と評価されたときに、後で定義するアクションが実行されます。
condition 要素には、必須属性と任意属性がひとつずつあります。 必須属性は type でこれは "presence" あるいは "attr" のいずれかでなければなりません。 任意属性は attr です。しかし、 type 属性の値が "attr" である場合は attr 属性も必須となります。
attr 属性は、 "user" や "%mem" など procps の出力のカラムを表します。
type 属性の内容によって、 condition 要素の構文や振る舞いは異なります。
condition の type が "presence" の場合、中身は空となることもあります。 この場合、常に true と評価されます。
condition の子要素として、以下の要素が存在します。
これらを組み合わせ、例えば min と max で範囲を指定することなどができます。
execute 要素では、 condition にあてはまった場合に行われるアクションを定義します。
必須属性は type で、これは "shell" あるいは "php" のいずれかでなければなりません。
一目瞭然でしょうが、execute 要素の中身が シェル (shell_exec() を用いて) あるいは PHP (eval() を用いて) のいずれかで実行されるわけです。
execute 要素は、複数指定することができます。
execute の文の中では、以下のような特殊変数が使用可能です。
XML 設定ファイル
<?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE procwatch SYSTEM "/usr/share/pear/data/System_ProcWatch/procwatch-1_0.dtd"> <procwatch> <!-- いくつかの設定の例 ================== このジョブは、実行中の httpd プロセスの数を調べます。 ps の COMMAND カラムに対して、正規表現 "/httpd/" でマッチングを行います。 見つかったプロセス数が 10 より少なかったり 30 より多かったりした場合は 指定した文字列がシェルで実行されます。 --> <watch name="httpd-count"> <pattern match="command">/httpd/</pattern> <condition type="presence"> <min>10</min> <max>30</max> </condition> <execute type="shell">echo $msg $pids >> /var/log/procwatch</execute> </watch> <!-- このジョブは、すべての httpd プロセスが使用している物理メモリの合計を調べます。 ps の COMMAND カラムに対して、正規表現 "/httpd/" でマッチングを行います。 これは、パターンにマッチした ps の %MEM カラムの値を合計し、その値を 指定した sum と比較します。もし結果が sum を超えていた場合に、 指定した文字列がシェルで実行されます。 --> <watch name="httpd-usage"> <pattern match="command">/httpd/</pattern> <condition type="attr" attr="%mem"> <sum>5</sum> </condition> <execute type="shell">echo $msg $pids >> /var/log/procwatch</execute> </watch> <!-- このジョブは、ゾンビプロセスを探します。 ps の STAT カラムに対して正規表現 "/Z/" でマッチングを行い、 0 個より多くのゾンビが見つかった場合に、指定した文字列がシェルで実行されます。 --> <watch name="ZOMBIES"> <pattern match="stat">/Z/</pattern> <condition type="presence"> <max>0</max> </condition> <execute type="shell">echo $msg $pids >> /var/log/procwatch</execute> </watch> <!-- このジョブは、実行中のプロセスを探します。 ps の STAT カラムに対して正規表現 "/R/" でマッチングを行い、 実行中のプロセスが見つかった場合に、指定した文字列がシェルで実行されます。 --> <watch name="running"> <pattern match="stat">/R/</pattern> <condition type="presence" /> <execute type="shell">echo $msg $pids >> /var/log/procwatch</execute> </watch> </procwatch>
INI ファイルによる設定も事実上同じようなものですが、例外として execute の type には "shell" しか使用できません。
INI 設定ファイル
配列で System::ProcWatch を設定する方法は、次の例のようになります。
PHP 設定配列
<?php
$watches = array();
$watches['job1'] = array();
$watches['job1']['pattern'] = array();
$watches['job1']['condition'] = array();
$watches['job1']['execute'] = array();
$watches['job1']['pattern']['command'] = '/httpd/';
$watches['job1']['condition']['presence'] = array('min' => 10, 'max' => 100);
$watches['job1']['execute']['shell'] = array('/usr/bin/mail2admin $msg');
$watches['job2'] = array();
// ...
?>