Perl Hackers Hub

第25回 cron周りのベストプラクティス(2)

この記事を読むのに必要な時間:およそ 4 分

前回の(1)はこちらから。

プロジェクトでcronを利用する

筆者は普段ゲーム開発のサーバサイドを担当していますが,プロジェクトによってはバッチサーバのcrontabが100行を超えることもあります。イベント,ランキング処理,監視,集計,バックアップ,リカバリ処理などをしっかりやろうとすると,どうしてもそれくらいになってしまいます。

100行とはいかなくても,プロジェクトで使うcrontabの行数が膨らんでくると,サーバで直接crontabを編集することは管理上現実的ではありません。

crontabの記述とリポジトリ管理

では実際のプロジェクトでcrontabをどのように管理していけばよいのでしょうか。筆者は次の方針を立てています。

  • crontabの記述にゆるやかな規約を設け,リポジトリ管理する
  • crontabの自動テストを行う
  • crontabの反映方法をなるべく自動化する
  • crontabの反映漏れを検知する

crontabの記述にはRubyのwheneverのようなDSLDomain Specific Languageドメイン特化言語)を使うアプローチもあります。これはちょっとした用途には便利かもしれませんが,かっちりとcron運用する中ではあまりお勧めできません。DSLレイヤが増える分,結果的に管理が煩雑になり,crontabのテストも書きづらくなるからです。それよりもcrontabを記述するうえでのゆるやかな規約を設け,わかりやすく記述できるように工夫することが大事です。

crontabの例

では実際にはどのようなcrontabを書けばよいのでしょうか? リスト1リスト2に悪い例と良い例を示します。

リスト1 悪いcrontabの例

37 2 * * * /opt/perl-5.18/bin/perl /home/app/proj/script/daily_partitition.pl > /dev/null 2>&1
7 2 * * * /opt/perl-5.18/bin/perl /home/app/proj/script/event_partition.pl > /dev/null 2>&1

リスト1には次の問題点があります。

  • レイアウトがバラバラで読みづらい
  • 重複した記述が多い
  • 出力を/dev/nullに捨ててしまっている

リスト2 良いcrontabの例

PATH=/usr/local/bin:/usr/bin:/bin
MYPROJ_RUN="/home/app/myproj/env-exec runcron"
LOGGER="/path/to/fluent-agent-lite"

### db partitioning
37 2 * * * $MYPROJ_RUN -- script/batch.pl DailyPartition 2>&1 | $LOGGER cron.daily_partition -
7 2 * * * $MYPROJ_RUN -- script/batch.pl EventPartition 2>&1 | $LOGGER cron.event_partition -

筆者が担当しているプロジェクトではリスト2のようにcrontabを記述し,リポジトリにコミットしています。これには次のような工夫が見られます。

  • レイアウトの工夫
  • 環境変数の活用
  • env-execとruncronを指定した起動方法の統一
  • perlの場合はbatch.plランチャをさらに経由
  • 出力先の統一とfluent-agent-liteの活用

それぞれに関して以降で説明していきます。

レイアウトの工夫

当たり前ですが,見やすく書くことは大事です。次のことに気をつけています。

  • ジョブの内容などで分類してコメントを入れ,セクション分けする
  • セクションごとでよいので縦の位置をそろえて書く
環境変数の活用

環境変数は/usr/local/bin$PATHが通っていないと不便なこともあるので,通すようにしています。

また,crontab内では同じような記述が重複することも多いので,そういったものはcrontab内で環境変数を設定してまとめるとよいでしょう。リスト2では,$MYPROJ_RUN$LOGGERという変数を定義しています。

env-execとruncronを指定した起動方法の統一

$MYPROJ_RUNを前置して各種バッチを起動するように統一しています。$MYPROJ_RUNの中にはenv-execruncronが指定されています。

env-execはプロジェクト用にカスタマイズされたラッパ用のシェルスクリプトです。

env-execの内容

#!/bin/sh
set -e
export USER=app
export HOME=/home/$USER
cd $(dirname $0)
export PATH="local/bin:/opt/perl-5.18/bin:$PATH"
export PERL5LIB="lib:local/lib/perl5"
export PLACK_ENV=production
exec "$@"

このシェルスクリプトでは次のことを行っています。

  • appというアプリケーション実行ユーザの指定
  • プロジェクトディレクトリへcd
  • perl-buildでビルドしたPerlへの$PATHを通す
  • 各種環境変数の設定
  • 引数で指定したコマンドをexecで実行

このラッパシェルは,cronに限らずアプリケーションサーバを含めた各種デーモンの起動においても利用しています。これはPerlプロジェクトの例ですが,同じようなアプローチはほかの言語でも可能でしょう。

runcronについては次回(3)で詳しく取り上げます。

perlの場合はbatch.plランチャをさらに経由

上記の例ではさらに,script/batch.plというファイルを指定しています。内容は以下のとおりです。

batch.plの内容

#!/usr/bin/env perl
use strict;
use warnings;
use Module::Load;
my $name = shift @ARGV;
my $module = "MyApp::Batch::$name";
load $module;
$module->new_with_options->run;

リスト2ではDailyPartitionという引数を受け取っていますが,この場合はMyApp::Batch::DailyPartitionというモジュールが読み込まれ,そのコンストラクタとrunメソッドが呼ばれるようになっています。MouseX::Getoptを統一的に使っているため,コンストラクタはnew_with_optionsになっています。

このようにバッチ処理の実体をモジュール形式で書くことで,プロジェクトリポジトリ内にplファイルが氾濫せず,バッチ処理のテストが書きやすくなるというメリットもあります。

出力先の統一とfluent-agent-liteの活用

cronにおいてジョブの出力をどのように扱うかは重要です。 /dev/nullに捨ててしまう例を時折見かけますが,これは完全なる悪手です。$MAILTOの適切な設定を行う,loggerコマンドでsyslogに投げる,ファイルに追記保存するなどいろいろやり方はありますが,筆者の最近のお気に入りはfluent-agent-liteを使う方法です。リスト2でも,$LOGGERという出力コマンド格納用の変数にfluent-agent-liteを代入しています。

fluent-agent-liteは田籠聡さんが作成したFluentdプロトコル互換のツールです。Perlで書かれており,送信に特化しているため軽量です。

fluent-agent-liteは標準入力を受け取り,その内容を{"message":"hello"}といったJSONJavaScript Object Notation形式に自動変換して,指定したタグとともにFluentdに送信してくれます。ログファイルなどをtailした出力と連携して使われることが多いですが,このように単発の出力を扱う際にも利用できます。

loggerコマンドの代替としてFluentdがカジュアルに使え,Fluentdに投げてしまえば,あとはさまざまな処理を行うことができる点が魅力です。


このような規約を設けることで,crontabをわかりやすく記述できます。ほかに,crontab自体のテストを書きやすくできるというメリットもあります。次項でcrontabのテストについて解説します。

著者プロフィール

松木雅幸(まつきまさゆき)

好きな言語はPerlと中国語。持ちネタは中国語LT。Songmuの由来は「松木」の中国語発音表記である。

大学で中国語と機械翻訳の研究に注力した勢いで卒業後,中国に渡る。中国でITベンチャーの立ち上げに携わった後に帰国。語学学校のシス担,印刷系SIerでの何でも屋業を経て,2011年1月より(株)カヤック所属。

前職までの多言語ぶりとは打って変わり,現職ではソーシャルゲーム開発のリードエンジニアとしてひたすらPerlを書く日々を過ごしている。CPANに上げたモジュール数は50近いが,無駄にたくさんあげているとの噂も。

最近はRijiというBlogツールをゴリ押しで普及させようとしている。

Blog:http://www.songmu.jp/riji/

コメント

コメントの記入