crontabをテストする
cronはサービスの一部であり,
テスト項目には次のようなものが挙げられます。
- a.crontabにシンタックスエラーがないか
- b.意図しない危険な指定がされていないか
(うっかり毎分指定, 日付と曜日の重複指定など) - c.ログを捨てていないか
- d.規約に従って記述をしているか
- e.コマンドに実行パーミッションが付いているか
- f.指定コマンドやファイル名をtypoしていないか
- g.実行時間のチェック
(意図した時間に実行されるか, 実行されたくない時間に誤って実行されないか)
これだけのテスト要求項目があり,
Parse::Crontabを使ったcrontabのテスト
crontabのテストには拙作のParse::Crontabが便利です。先ほど取り上げたテスト項目を,
use strict;
use warnings;
use Test::More;
use File::Which qw/which/;
use Parse::Crontab;
# 11 2 * * * $MYPROJ_RUN script/batch.pl \
# DailyPartition 2>&1 | $LOGGER cron.daily_partition -
# 上記のように指定されているか確認する
my $crontab = Parse::Crontab->new(
file => 'data/crontab.txt'
);
# a crontab のシンタックスに誤りがないか
ok $crontab->is_valid
or diag $crontab->error_messages;
# b 危険な指定の確認
ok !$crontab->warning_messages
or diag $crontab->warning_messages;
# ジョブ一覧を取得する
for my $job ($crontab->jobs) {
my $command = $job->command;
# c $LOGGER でログを出力しているか
like $command, qr!2>&1\s+\|\s+\$LOGGER!, 'logger ok';
# d $MYPROJ_RUN を使う規約を守っているか
ok $command =~ m!^\$MYPROJ_RUN!;
my ($opt, $rest_command) =
$command =~
m!^\$MYPROJ_RUN\s*(*?)?\s*--\s*(.*)!;
my $cmd = +(split /\s+/, $rest_command)[0];
# e 実行権がちゃんと付与されているか
ok -e $cmd or $cmd = which($cmd);
ok -x $cmd;
if (my ($module) =
$rest_command =~
m!^script/batch\.pl\s+([A-Za-z0-9]+)!
) {
# f batch.pl への指定モジュールが存在するか
my $module_file = "lib/MyApp/Batch/$module.pm";
ok -e $module_file;
}
# g スケジュールオブジェクトを取り出して
# 必要に応じて実行時間のテストをする
my $schedule = $job->schedule;
ok $schedule->match(hour => 2, minutes => 15 ...);
}
done_testing;
aでcrontabのシンタックス確認,
crontabの本番環境
本番反映の方法
crontabコマンドは引数にファイルを指定すると,
次のようにしてcrontabを反映すればよいでしょう。筆者のプロジェクトではcronやワーカ類を動かす専用のサーバを立てているので,
% ssh myproj-batch01
# 差分確認
% diff -u <(crontab -l) data/crontab.txt
# 反映
% crontab data/crontab.txt
上記はデプロイ時に自動反映してもよいとは思いますが,
crontabの本番反映漏れを防ぐTips
さて,
そういうミスを防ぐために,
<続きの