はじめに
「あのバッチ、昨夜ちゃんと動いたっけ?」——朝一番にSSHでサーバーに入り、crontab -lで設定を確認し、ログファイルをgrepで漁る。cronで定時ジョブを運用していると、こんな朝を何度も経験しますよね。
ジョブが増えるほど管理は煩雑になり、サーバーが複数台になれば「どのジョブがどのサーバーで動いているのか」を把握するだけでも一苦労です。しかも肝心のサーバーが落ちていたら、ジョブは黙って実行されないままです。
そんなcron運用の悩みを、Web UIとマルチサーバー対応でまるごと解決してくれるのが、今回ご紹介する**Cronicle(クロニクル)**です。
Cronicleとは
Cronicleは、Node.js製のマルチサーバー対応タスクスケジューラ&ランナーです。開発者のJoseph Huckaby氏によってMITライセンスで公開されており、「cronの強力な代替」として、スケジュール実行・繰り返し実行・オンデマンド実行のすべてをWeb UIから管理できます。
一言でいえば「ブラウザで操作できる、分散対応のcron」です。
主な特徴
- Web UIですべて完結 - ジョブの登録・編集・手動実行・ログ閲覧・パフォーマンスグラフの確認まで、ブラウザだけで操作できます
- マルチサーバー&自動フェイルオーバー - 複数のワーカーサーバーにジョブを振り分けられ、プライマリサーバーがダウンしてもバックアップが自動で引き継ぎます
- リアルタイム監視 - 実行中のジョブの進捗バーやライブログをその場で確認できます
- 言語を問わないプラグイン機構 - シェルスクリプトはもちろん、Node.js・Python・PerlなどSTDIN/STDOUTを扱える言語なら何でもジョブ化できます
- REST APIとWebhook - 外部システムからのジョブ起動や、完了通知の連携も標準でサポートしています
- タイムゾーン対応 - イベントごとにタイムゾーンを指定できるため、グローバルなサービス運用でも安心です
インストール
CronicleはNode.jsのLTS版が入っていれば、ワンライナーでインストールできます。
# Node.js LTSがインストール済みであることを確認
node -v
# Cronicleを /opt/cronicle にインストール
curl -s https://raw.githubusercontent.com/jhuckaby/Cronicle/master/bin/install.js | node
インストールが終わったら、初期セットアップと起動を行います。
# 初期セットアップ(プライマリサーバーで1回だけ実行)
/opt/cronicle/bin/control.sh setup
# 起動
/opt/cronicle/bin/control.sh start
これでデフォルトのポート3012でWeb UIが立ち上がります。
http://YOUR_SERVER_HOSTNAME:3012/
初期アカウントはユーザー名・パスワードともにadminです。ログインしたら、真っ先にパスワードを変更しておきましょう。
基本的な使い方
Web UIでジョブを登録する
Cronicleでは、実行するジョブを「イベント」と呼びます。Web UIの「Schedule」タブから「Add Event」をクリックし、次の3点を設定するだけで最初のジョブが動き出します。
- Event Name - ジョブの名前(例:
daily-backup) - Plugin - 実行方法。まずは組み込みの「Shell Script」を選択
- Timing - 実行タイミング。cron式ではなくGUIのチェックボックスで「毎日3時」のように直感的に選べます
Shell Scriptプラグインには、そのままスクリプトを書き込めます。
#!/bin/bash
# データベースのバックアップ例
pg_dump mydb > /backup/mydb_$(date +%Y%m%d).sql || exit 1
echo "50%"
# 古いバックアップの削除
find /backup -name "*.sql" -mtime +7 -delete || exit 1
echo "100%"
注目してほしいのはecho "50%"の行です。パーセント表記を標準出力に流すだけで、Web UI上のプログレスバーがリアルタイムに進みます。残り時間の推定まで自動で表示してくれるので、長時間バッチの「今どこまで進んだ?」問題から解放されます。
REST APIからジョブを起動する
登録したイベントは、APIキーを発行すれば外部から起動できます。デプロイ完了後にキャッシュ更新ジョブを蹴る、といった連携が簡単に実現できます。
curl -s "http://localhost:3012/api/app/run_event/v1" \
-H "Content-Type: application/json" \
-X POST \
-d '{"id": "YOUR_EVENT_ID", "api_key": "YOUR_API_KEY"}'
実践的なユースケース
カスタムプラグインで進捗と結果を細かく報告する
Cronicleの真骨頂はプラグイン機構です。仕組みはシンプルで、STDINからJSONでジョブ情報を受け取り、STDOUTにJSONで状態を返すだけです。Node.jsで書いた例を見てみましょう。
#!/usr/bin/env node
// /opt/cronicle/plugins/report-job.js
const rl = require('readline').createInterface({ input: process.stdin });
rl.on('line', (line) => {
const job = JSON.parse(line);
rl.close();
// Web UIで設定したパラメータを受け取れます
console.log(`対象テーブル: ${job.params.table_name}`);
// 進捗を報告(0.0〜1.0)
process.stdout.write(JSON.stringify({ progress: 0.5 }) + "\n");
// 処理が終わったら完了を報告
// code: 0 が成功、0以外はエラーとして扱われます
process.stdout.write(JSON.stringify({
complete: 1,
code: 0,
perf: { fetch: 12.5, aggregate: 3.2, write: 1.8 }
}) + "\n");
});
このファイルに実行権限を付け、Web UIの「Plugins」タブでパスとパラメータ(例: table_name)を登録すれば、イベント作成時にフォーム入力できる独自プラグインの完成です。
最後のperfにも注目してください。処理ごとの所要時間を渡しておくと、Cronicleが円グラフでボトルネックを可視化してくれます。「このバッチ、どこが遅いんだろう」という調査が、グラフを眺めるだけで済むようになります。
ジョブのチェーン実行でパイプラインを組む
イベントには「成功したら次のイベントを実行する」チェーン設定があります。たとえば次のような夜間パイプラインが、コードを1行も書かずに組めます。
export-data- DBからデータをエクスポート- 成功したら
transform-data- データを集計・変換 - 成功したら
notify-report- HTTP Request Pluginでレポート生成APIを呼び出し
途中で失敗すればチェーンは止まり、Webhookやメールで通知が飛びます。cronで同じことをやろうとすると、実行時刻をずらして祈るか、巨大なラッパースクリプトを書くことになりがちです。その管理から解放されるのは大きなメリットです。
複数サーバーへのスケールとフェイルオーバー
ワーカーサーバーを追加すると、サーバーグループ単位でジョブの実行先を制御できます。「重いバッチはバッチ専用グループで」「全サーバーで一斉にログローテーションを」といった振り分けがWeb UIから設定でき、プライマリサーバーが落ちてもバックアップサーバーが自動でスケジューラの役割を引き継ぎます。
「cronを動かしていたサーバーごと落ちていて、ジョブが数日間実行されていなかった」という悪夢とは、これでお別れです。
まとめ
Cronicleについて、cronの課題を解決する次の観点から紹介しました。
- ワンライナーでインストールでき、Web UIからジョブの登録・監視・ログ閲覧まで完結すること
echo "50%"だけでプログレスバーが動く、開発者にやさしい進捗報告の仕組み- STDIN/STDOUTのJSONだけで書ける、言語を問わないプラグイン機構
- チェーン実行・マルチサーバー・自動フェイルオーバーといった運用向けの堅牢な機能
「とりあえずcrontabに書いておく」で始まった定時ジョブが増え、管理しきれなくなってきたなら、Cronicleへの移行を検討する絶好のタイミングです。まずは開発サーバーにインストールして、普段のバッチをひとつ移してみてください。ライブログが流れるWeb UIを見れば、もう黒い画面でcrontab -eを打つ生活には戻れなくなるはずです。
