導入
cron に登録したら終わり、ではありません。「ちゃんと動いたのか」「失敗していないか」を後から確認できて、はじめて運用できる状態です。ここは実務で差が出るところです。
説明
まず、必ずログを残します。cron の実行結果は画面に出ないので、残さなければ何も分かりません。
#!/bin/bash
set -eu
LOG_FILE=/home/user/batch.log
log() {
echo "[$(date +%Y-%m-%d) $(date +%H:%M:%S)] $1" >> "$LOG_FILE"
}
log "処理を開始しました"
COUNT=$(grep ERROR /home/user/logs/app.log | wc -l)
log "エラー件数: $COUNT"
log "処理を終了しました"
# 確認用に中身を表示
cat "$LOG_FILE"
ログに入れるべき情報は3つです。
- いつ(日時。あとで「昨日は動いたのか」を調べられる)
- 何をしたか(開始・終了・件数)
- 失敗したか(エラーメッセージ。
2>&1で標準エラー出力も同じログへ)
crontab 側では、こう書きます。
0 3 * * * /home/user/scripts/backup.sh >> /home/user/backup.log 2>&1
次に 多重起動 の問題です。5分おきの処理が、あるとき6分かかったら——前の処理が終わる前に次が始まり、2つが同時にファイルを触ります。データが壊れる典型パターンです。
flowchart TD
A["10:00 実行開始"] --> B["10:05 まだ終わっていない"]
B --> C["10:05 cron が2つ目を起動"]
C --> D["同じファイルを2つが同時に更新<br/>→ 壊れる"]
A2["flock で排他"] --> E["2つ目は起動せずスキップ<br/>→ 安全"]
対策は flock(ファイルロック)です。実行中は鍵をかけ、鍵が取れなければ何もせず終わります。
*/5 * * * * flock -n /tmp/mybatch.lock /home/user/scripts/check.sh
-n は「鍵が取れなければ待たずに諦める」という指定です。これ1つで多重起動が防げます。
ログは放っておくと際限なく育ちます。実務では
logrotateという仕組みで「7日分だけ残して古いものは圧縮・削除」と設定するのが定番です。自分で書くなら、find /var/log/mybatch -mtime +7 -deleteのような掃除を、これまた cron に登録します。
やってみよう
スクリプトを実行して、batch.log に時刻つきのログが3行たまることを確かめましょう。次にもう一度実行すると、追記されて6行になることを確認してください(> ではなく >> を使っている理由がここにあります)。
演習
ログ関数を使って バックアップ完了 というメッセージを batch.log に記録し、cat で表示してください。
ヒント1を見る
log "バックアップ完了" を追加します。
ヒント2を見る
最後の cat "$LOG_FILE" で中身が表示されます。