こんにちは、さるまりんです🐒
8月11日は山の日。山に登ったり、ちょっと一息ついたり――そんな祝日ですが、サーバー上のcron
ジョブたちは今日も変わらず動いています。
でも、ちょっと待ってください。「そのcron
ジョブ、祝日も必要ですか?」
今回は、cron
でこれまでハマったことと、祝日には実行をスキップする簡単な方法を考えてみます。
関数として共通化できる形で、再利用して便利に使えるようにしていきますね。
⚠️ cronのありがちなハマりどころ
PATHが通ってない問題
cron
で動かしたら、command not found
で失敗していた…なんて経験ありませんか?
cron
はログインシェルとは違って環境変数が限られているため、php
やnode
などのコマンドが見つからなくて使えないことがあります。
対策:フルパス指定 or PATHの明示
PATH
をちゃんと書いておく
PATH=/usr/local/bin:/usr/bin:/bin
またはコマンドなどを絶対パスで指定します
/usr/bin/php /home/user/script.php
[[ ]]
や source
が動かない?
cron
はデフォルトで /bin/sh
を使ってジョブを実行します(実際は環境によって異なりますが)。
そのため、[[ ]]
や source
などbash専用の構文はエラーになります。
対策:crontab -e
で SHELL=/bin/bash
を明示
SHELL=/bin/bash
この一行を crontab
の先頭に書くだけで、bash構文が使えるようになります。
set -euo pipefail
も忘れずに
過去の記事でも紹介したとおり、シェルスクリプトでは安全性の高い設定として次の1行を入れておきましょう:
set -euo pipefail
過去記事の「setとオプションを使って安全にシェルスクリプトを書こう」も参考にしてもらえると嬉しいです。
祝日はスキップしたい?
冒頭でも触れたように「祝日は実行しない」ようにするには、スクリプト内で判定して終了するのが簡単で安全と思います。
さらに、判定処理を関数化して共通化することで、複数のバッチ処理で再利用できて便利ですね。
祝日判定関数を共通化
ディレクトリ構成の例
/home/user/scripts/
├── common.sh ← 祝日判定関数など共通ロジック
├── holiday-aware.sh ← cronで呼び出す本体
└── holidays.txt ← 祝日リスト
common.sh
(共通関数ファイル)
#!/bin/bash
HOLIDAYS_FILE="${HOLIDAYS_FILE:-$(dirname "$0")/holidays.txt}"
is_holiday_today() {
local today
today=$(date +%Y-%m-%d)
grep -q "$today" "$HOLIDAYS_FILE"
}
holiday-aware.sh
(cron
用スクリプト本体)
#!/bin/bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
source "$SCRIPT_DIR/common.sh"
if is_holiday_today; then
echo "今日は祝日なのでスキップします。"
exit 0
fi
echo "通常処理を実行中..."
# ここに本来の処理を書く
holidays.txt
の例
2025-01-01
2025-02-11
2025-08-11
2025-12-23
このファイルは祝日を yyyy-MM-dd
形式で持っています。
cronの設定例(crontab -e)
SHELL=/bin/bash
PATH=/usr/local/bin:/usr/bin:/bin
0 5 * * * /home/user/scripts/holiday-aware.sh >> /var/log/batch.log 2>&1
これで毎朝5時にバッチを実行しつつ、祝日ならスキップできます!
holidays.txt を自動更新したい?
せっかくなので祝日も自動で管理したいですよね?
こんなワンライナーで、内閣府が提供している祝日CSVからholidays.txt
を生成できます。
curl -s https://www8.cao.go.jp/chosei/shukujitsu/syukujitsu.csv \
| iconv -f Shift_JIS -t UTF-8 \
| tail -n +2 \
| cut -d, -f1 \
| awk -F'[/-]' '{printf("%04d-%02d-%02d\n", $1, $2, $3)}' \
> ~/scripts/holidays.txt
やっていることは、祝日CSVから、ゼロパディング付き yyyy-MM-dd
形式で holidays.txt
を生成です。
これを週1回などでcron
に登録すれば、祝日リストも常に最新に保てます!
cron
でハマった経験はこれまでも何度もあるので同じことで困らないようにここにメモして回避していきたいと思います。
そして、祝日はスキップというものにはお休みをとってもらうようにしてみます。
実際に平日だけでお休みの日ならスキップって処理結構あると思います。
お休みじゃなくて祝日の前後の営業日にずらすと言う場合もあるかな。それはまた改めて発展系を考えてみたいと思います。
cron
にも“山の日”のようなお休みを。
サーバーさんに優しいプログラマーになれるかな。
読んでくださってありがとうございました。
それではまた!