cron で exponential backoff するツール作った
はじめに
cron を使うと繰り返しコマンドを実行するのが便利です。
* * * * * /path/to/the/command
crontab でこの様に指定すると1分毎に実行されます。
*/3 * * * * /path/to/the/command
この様に指定すると3分毎に実行されます。
とても便利ではあるのですがコマンドの実行が失敗すると、冗長なコマンド実行となり得ます。cron ではコマンドの実行が失敗し続けるとメールが運営者に繰り返し送信され続けます。
crontab にコマンドが1分毎に実行される様に投入してひとまず正常起動を確認、仕事を終えて家に返ってビールでも飲んで、さぁ寝ようかなと思った頃にコマンドが失敗し始めると、朝までメールが飛び続けます。
またウェブサービスの API を呼び出す cron ジョブを投入していたらそのウェブサービスがメンテナンスに入った、なんて事もあると思います。メンテナンス中にも関わらず無限に失敗し続ける API 呼び出しはもしかしたら BAN の対象になってしまうかもしれません。
全ては cron に exponential backoff する機能がないのが問題です。
systemd timer で解決する
systemd の timer を使うとそれに近い exponential backoff を実現できます。
moriwaka さんありがとうございます。ただ、今まで crontab で運用してきたものは、なかなか簡単に移行できる物ではありません。(少なくとも僕は)
backoff コマンドを作った
使い方は簡単。crontab でコマンドの前に backoff と書くだけです。
* * * * * backoff /path/to/the/command
こう書くだけで前回の失敗から連続で失敗した場合の、次回起動間隔が長くなってくれます。
経過 | 結果 | backoff |
---|---|---|
0分後 | 成功 | |
1分後 | 成功 | |
2分後 | 失敗 | 1分 |
3分後 | 失敗 | 2分 |
4分後 | 実行なし | |
5分後 | 失敗 | 4分 |
7分後 | 実行なし | |
8分後 | 実行なし | |
9分後 | 実行なし | |
10分後 | 成功 | 0分 |
11分後 | 成功 | 0分 |
仕組みは簡単で、この backoff コマンドがカレントディレクトリに .backoff という leveldb のデータベースを保存し、失敗のたびに backoff を増やしていくというものです。
Usage of ./backoff:
-V verbose
-f string
storage file (default ".backoff")
-k string
key (default is command-line)
-max duration
max wait (default 1h0m0s)
-off duration
offset (default 1m0s)
-v show version
.backoff ディレクトリのディレクトリは変更できる様にしてあります。また上記の例では1分毎ですが
*/3 * * * * /path/to/the/command
この例の様に3分毎の実行であれば、3分,6分,9分 と増えて欲しいものです。そういう場合には -off 3m
と指定できる様にしてあります。
*/3 * * * * backoff -off 3m /path/to/the/command
また backoff はどんどん増えますがその最大値も指定できる様になっています。最大は 1 時間ですが -max 0
を指定すると無制限に増え続けます。
おわりに
cron をなかなか捨てられない人の為の backoff コマンドを作りました。まだ出来たてですしバグもあるかもしれません。何か問題を見付けたらコントリビュートして下さい。
Discussion