cron の代替を作りました。
経緯
cron(自動実行プログラム)の管理が煩雑でした。
増え続けるcrontab。ここ数年管理が崩壊していました。systemd.timer や google app scripts なども増えるし、ラムダ系で実行してたりいろいろな所で、タイマー(カレンダー)による実行が溢れかえる。手軽に作れる一方でエラーログを確認したりがめんどくさいので放置してて実行してるけど動いてないスクリプトとかもあり全容把握が困難でした。
散らばる cron / systemd.timer
crontab による管理は、3つの箇所に別れます。
システム(/etc/cron.d/
) root ( /var/spool/cron/crontabs/root
) そして個人ユーザー ( /var/spool/cron/crontabs/$USER
) の3つに別れます。この時点でいい加減に管理していると大変。
最近は、systemd.timer が増えてきました。 systemd.timer は systemd.service とペアになっているので、ファイルが複数に分かれます。さらに、ユーザー空間の systemd ( systemd --user )もあります。ログ管理や任意実行は平易化したが、ファイル管理は煩雑になりました。
ここに、lxd/docker/vbox などの仮想環境のcronが加わると管理は不可能になります。
散らばる通知・ログ
大変なのはログと通知の管理です。スケジューラーがコケたときに通知くるけどcron などは > /dev/null
とか > /var/log/my-job.log
みたいにログファイルに書くしかなくて困る。エラー時の実行ログと正常ログを見たいのに、実行ログと実行時間から推察してログをたどるのが面倒だった。
crontab 書くのめんどくさい
ちょっとした分岐が書きたい
crontab で実行しようとすると、スクリプトいったん実行可能なファイルにして書き出す必要があって、条件分岐をかくのが大変だし、実行ファイルを一箇所に集めて管理とか大変だ。crontab 見ても何が実行されるのかパット見わからないことが多くて困る。
一時停止が大変
ジョブがエラーになってるときなど、一時停止したいときコメントアウトで対応してるとコメントアウトだらけになって、何がなんだかわからなくなった。
crontab の実行予定がわからない。
大量にあるとスクロールしながらひと目見て、cron 書式から次回実行はいつなんだというのがわかりにくい。ソートしたい。
ssh経由でリモート実行したい
cron を一箇所に集めて、sshでリモート実行ちゃえばある程度解決する。SSHで実行するとなると環境変数やssh-agentを書いて環境変数をうまく扱う必要がある。するとスクリプトファイルを使って実行するがcrontabファイルで完結しなくなる。
cron 限界じゃね?
というわけで、cronは5~10件が限界じゃね?別の何かが必要じゃないかと思いました。
webで管理したい。
webでcronの実行予定とスクリプト本文を編集できたらいいじゃん。
web管理機能を探したけど
いいものが見つからなかった。ジョブスケジューラは高機能すぎる気がするしjenkinsとかはCI/CDツールだし。どうも用途に合わないので、laravelでcron書式をつかったスケジュール実行ができるのでそれを応用して作りました。
ソフトウェア仕組み
root で スケジュール実行用のワーカーを常駐させて、毎分単位で実行するべき処理を探しては実行する。
このソフトウェアの限界
毎分単位で処理を探して、プロセスをforkしてジョブを実行するので、1000件くらいが上限だと思われる。
このソフトの特長
WEBから編集ができます。
一時停止状況がわかるように
コメントアウトの代わりに一時停止状況がわかるように
次回実行の予定がわかるように
cron表記を日本語表記にして次回実行がわかるようにしておいた。
実行ごとに結果がわかるように
実行ごとにSTDOUT/STDERRを保存するように。また実行時間も測定し、スケジュール全体の見直しに活用できるようにしました。
スクリプト本文の直接記述
crontab が1コマンド(1行)で記述しなくちゃいけなくて改行を入れてるとおかしくなるのでとても不便なので、
改行やコメントを書けるようにして、直接記述できるようにしして、実行シェルをbash以外から選べるようにしておいた。現在はbash/phpを選べます。sh/rubyは行けそうなのでそのうち対応しようと思います。pythonはちょっと難しいかも。
インストールと取得はgithub
Github に公開しておきます。
とりあえず試す用のdockerも用意しました。
docker pull ghcr.io/takuya/cronjob-alternative:latest docker run --rm -p 5000:80 ghcr.io/takuya/cronjob-alternative:latest
cronといってますが、cron表記を使うだけで、crontabの編集を一切やりません。実行するワーカーはcronとは別にじぶんで起動して使います。