本文へスキップ
BecomeCoder

シェルスクリプトコース · 第8章 cron で定期実行 · レッスン38

ログと多重起動 ― 運用に耐えるバッチにする

ブラウザで完結

導入

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" で中身が表示されます。

実際に動かしてみよう

本文のサンプルや演習のコードは、コードブロック右上の「コピー」ボタンでコピーして、下のエディタに貼り付ければそのまま実行できます。

シェルスクリプト(シミュレート)

スクリプトを書くエディタと、それを動かす仮想シェルを読み込みます(本物のbashではなく、動きを再現した学習用の環境です)。
スクロールして表示された時点でも自動で読み込まれます。