🐈
cronで任意の分単位で実行する・エスケープを回避する
動機
cronで16分ごとに実行したい機会があったので方法を調べました。その際、cronの記法のエスケープ周りでハマっていたのですが、回避法も見つけたので書きます。
やったこと
cronの時間設定を自由にする
こちらを参考にしました。
60の約数であれば、例えば 0/3 * * * *
などで設定できますが、そうでない場合はできません。
↑で紹介されている方法として、毎分実行して、その時刻をエポック分に変換してインターバルの倍数かどうかを判定します。
以下の場合、eposhを秒にして(%s)、分にして(/60)から 16で割ってあまりが 0 なら echo "hello"
を実行します。
cron
* * * * * test $[($(date +\%s))/60\%16] -eq 0 && echo "hello"
エスケープするが・・・ハマる
上記では、%
の部分が \%
と書いてありますが、これはcronでのエスケープです。しかし、私の環境(Ubuntu)では動作しませんでした。cronの記述は何かとハマりますね・・・。
こちらの方法を参考にして、シェルスクリプト内で判定することにしました。気づいたらああそうか、という感じですがハマっている間は思いつかないですよねー。
mycron.sh
interval=16
mod=$[($(date +%s)) / 60 % $interval]
if [ $mod -eq 0 ]; then
echo "hello"
fi
最終的にcrontab -e にはこう書きます。
cron
* * * * * bash path/to/mycron.sh
まとめ
- cronで自由にインターバル時間を決めて実行することができた
- shellで呼び出すようにして、cronの記述でハマるのを避けられた
(余談:Amazon EventBridgeなら楽なはずだが)
EventBridgeを使うとrate()
で自由にインターバル時間を決められるのですが、今回はpythonを実行してboto3の最新版を使いたいけどそれもLambdaの設定が面倒なのでローカルでcronしようという状況でした。
Discussion