Cronで回してるスクリプトでエラーが出た時に/dev/nullにエラーを捨てるなどの暴挙をしていなければ、メールでエラーを教えてくれます。

とても便利なのですが、外部からのfeedをパースする処理を多用していると、やむを得ない理由でエラーが定期的に出続けてしまうことがあります。

基本的にはメールの内容見て判断していくしかないのですが、常に見ていられるわけではないので、あとでたまった分をザーっと見ていくことになるんですが、コレが結構大変だったり、実は深刻なバグがあって、大量にエラーが出ていたりしても半日ぐらい気がつかない、なんて事が希にあります。

そうならないためにも、普段からエラー数をグラフにして可視化しておくと便利そうなのでやってみました。

やっていることは、Cronから送られるメールをMAILTOで自分自身に送信するように

$ crontab -e
MAILTO=cron-error@cron.error.example.com
*/5 * * * * /path/to/something.sh

ここではcron.error.example.comにしてますが実際は自分の管轄するドメインならなんでも良いので、/etc/hostsで自サーバに向けてしまいます

/etc/hosts
127.0.0.1  cron.error.example.com

これで同一サーバのSMTPにメールが配送されます。

今回はSMTPにPostfix使っているので、Postfix側でメールを受けたらスクリプトを起動するように設定していきます。

/etc/postfix/main.cf
virtual_alias_maps = hash:/etc/postfix/virtual
alias_maps = hash:/etc/aliases

/etc/postfix/virtual
@cron.error.example.com cron_error

/etc/aliases
cron_error: "|/path/to/count-cron-error.pl"

postfixのmain.cfでvirtual_alias_mapsとalias_mapsを読み込み指定しておいて、/etc/postfix/virtualの方でcron.error.example.comにメールがきたら、ローカルユーザーのcron_errorに配送するように指定、/etc/aliasesのほうでcron_errorにきたメールをスクリプトに渡してあげます。


あとはスクリプトの方で好きにカウントすればいいです。ちなみにこのケースでは

#!/usr/local/bin/perl
use strict;
use warnings;
use Cache::Memcached::Fast;

my $cache = new Cache::Memcached::Fast({servers => ['192.168.254.2:11211']});
my $key = 'cron:error:count';
my $count = $cache->get( $key ) || 0;
$count++;
$cache->set( $key, $count,  60 * 60);

こんな感じでキャッシュに溜めておいて

#!/usr/local/bin/perl
use strict;
use warnings;
use Cache::Memcached::Fast;
use LWP::UserAgent;

my $cache = new Cache::Memcached::Fast({servers => ['192.168.254.2:11211']});
my $key = 'cron:error:count';
my $count = $cache->get( $key ) || 0;

my $ua = LWP::UserAgent->new;
$ua->post('http://gf.example.com/api/cron/error/count', {number => $count});

$cache->remove( $key );

こっちをCronで起動GrowthForecastに投げています。すると・・

52

こんな感じで良い感じにグラフ化してくれます。

上の例は最低限のレベルだけですが、頑張ればメールの内容にしたがって分類してグラフ作る事も可能なので、外的要因でどうしてもCronのエラーが出てしまうような環境の場合は便利です。

※外的要因が無い場合はさっさとエラー解消した方がいいでしょう

ちなみに、今回はPostfixつかいましたが、qmail使う場合は、vpopmailのほうでダミードメインを設定して読ませることが可能です。