cronジョブなどで定期的に何かを実行する際、 なにか起こったらすぐ対応するために休みの日などには行わないようにしたいことがあります。
もしくは逆にCPUリソースを食う様なものを休みの日にだけ実行したいこともあるかもしれません。
そういった場合には holiday_jp-go を使うと便利です。
cronジョブで平日だけ実行したい
cronジョブでは曜日の設定ができるため、設定ファイルで
0 1 * * 1-5 /path/to/cron_script.sh
とかしておくと月曜から金曜の毎日1時にこのスクリプトが実行されます。
パラメーターは左から
- 秒 (0 - 59)
- 時 (0 - 23)
- 日 (1 - 31)
- 月 (1 - 12)
- 曜日 (0 - 6)
です。 最後の曜日は0が日曜、6が土曜になっているので1-5で指定すると月曜から金曜、の指定になります。
ぱっとやりたいだけならこれでも十分。
祝日も止めたい
cronは祝日を知らないのでcronの機能だけではできません。
そこで外部から情報を取ってこなくてはいけませんが、 日本の祝日情報としてはholiday_jpというレポジトリにある情報が便利です。
holiday-jp/holiday_jp
このレポジトリでは内閣府のホームページから情報を取ってきています。
情報はyaml形式でまとめられていて、 holidays.yml は日付と祝日の名前、 holidays_detailed.yml にはさらに曜日や英語名なども含まれています。
リストとしては1970年から2050年までの情報があり、 今でも新しく変更があればきちんとアップデートされていてメンテナンスされています。
holiday-jpにはJavaやRubyなどでこの情報を使うライブラリが用意されています。
また、 Holidays JP API (日本の祝日API) に行くとJSONやCSVなど様々な形式で取得するためのAPIが公開されています。
もともと@komagataさんがRubyで作っていた祝日取得ライブラリがあって @k1LoWさんが外でも使えるように情報をデータセットとして作り、 その後 holiday-jp/holiday_jp というユーザーとレポジトリを作成して管理する様になった様です。
最初のブログは2009年なので10年選手ですね。
今後もよろしくおねがいします。
休み判定ツール
holiday-jpにもいくつかの言語用のライブラリがありますが、 コマンドラインツールとしては emasaka/jpholidayp が使われている感じでした。 Python製で当日が土日祝日の場合は0、そうでない場合は1を終了ステータスとして返すツールです。 (エラーの場合には2。) このツールを使う場合にはYAMLを扱うためにPyYAMLをインストールする必要があります。 pipとかでは配布されてないのでその辺り自分で最初に行う必要があります。
cronで祝日判定しようと思ったら、emasaka/jpholidaypが素晴らしかった blog: takahiro okumura
もうちょっと別なのを探していたところ、 Go製で作られたツールがあり、 Goのバイナリならどの環境用のものもできますしそのバイナリだけで動きますし、 さらにはLinux環境だとrpmやadpkgでもインストールできるようになっていて便利です。
こちらも終了ステータスで当日が 土日祝日の場合は0、そうでない場合は1、エラーの場合には2を返します。
これを探していたときには Linux環境で自動でセットアップするような環境で使いたかったのでこの knqyf263/holiday_jp-go を使っています。
一応注意として、これらのツールは祝日に加えて土日も休みとして判定しまとめて休みかどうかの結果を出します。 祝日かどうかだけ知りたい場合にはちょっと手を加えるか別のツールを使う必要があります。
あと、cronジョブ用に作られてる、ということもあってその当日だけの結果を返しますが、 引数で日付を与えるとその日の判定を返してくれたりすると別の用途でも使えるかも。
土日祝日以外でcronジョブを実行する
祝日の情報が手に入るようになったのであとはこれを使えばよいだけ
土日も判定に入るのでcronでは曜日部分は*
にしてしまって
スクリプト実行前にholiday_jp-go
を入れて実行するかどうか判定します。
0 1 * * * holiday_jp-go || /path/to/cron_script.sh
土日祝日だと0(成功)ステータスを返すので そうでないときだけスクリプトを実行する形です。
cron専用のスクリプトであれば(特にシェルスクリプトであれば)、スクリプトの中でholiday_jp-goを使っても良いですし、 スクリプトの中で土日祝日とそうでない日で別のことをする、といったことも簡単に出来るようになります。
一つだけ注意点としては、holiday_jp-go
がエラーを起こした場合にも失敗ステータスになってこのスクリプトが実行されてしまいます。
それを避けたければ終了ステータスが1であることを確認する様にきっちりとやります。
0 1 * * * holiday_jp-go || /bin/test $? -eq 1 && /path/to/cron_script.sh
逆に度に祝日だけで実行したい場合には
0 1 * * * holiday_jp-go && /path/to/cron_script.sh
とすれば良いだけですね。
その他のツール/情報源
日本以外の祝日も使いたい、という場合にはdate-holidaysというツールがあります。
全部で140カ国以上、400地域近くの祝日を網羅しているとういことですが、 それだけあると数年分のデータでもデータがすごい量になりそうなものですが、決まりに従って計算を行うことで 元のデータを軽量化しています。
日本のデータはこれですが、成人の日とかを見ると
- 1999年までは1月15日
- ただし1974年以降は日曜の場合には次の月曜に振替
- 2000年以降は1月第2月曜
という設定になっています。
こちらも精力的にメンテナンスが行われているので最新の祝日もきちんと反映されています。
他の祝日情報源としてはGoogleカレンダーがあります。 Googleカレンダーで左側にある他のカレンダーという表示の右側の+ボタンを押して 関心のあるカレンダーを探すへ行き、 出てきた休日の中の地域限定の祝日を開いて 日本の祝日にチェックを入れれば自分のGoogleカレンダーに祝日を表示させることができます。
この情報をAPIとかで取ってきて使う、という方法が結構昔はやられていたようですが、 APIの仕様が変わって認証を求められるようになったとかで、 holidaypとかでも2014年ころにGoogleカレンダーからholiday_jpに移ったようです。
まとめ
cronジョブを平日だけ動かしたい、 さらには祝日もちゃんと休ませたい、 ということで祝日を見る方法を探したところ holiday_jpという便利なデータセットがありました。
これを使ったコマンドで簡単に土日祝日がチェック出来る holiday_jp-go というツールを使うと簡単にcronジョブを勤労日だけに走らせることが出来ます。
あと、ついでに見つけた date-holidayss も世界中の祝日がわかるということと、 データ量を抑えるためにルールを指定して計算する様になっていて それがかなり細かく設定できるのでツールとして面白いかな、と。