シェルでスクリプトの多重起動を制御する方法とサンプルコードを紹介します。cronでスクリプトを実行して処理が終わらないまま、次の実行時刻になってしまうことのないように。

サンプルコード

  • スクリプト
#!/bin/bash

# ロックファイル/ログファイル
LOG_FILE=/path/`date +\%Y\%m\%d`.log
LOCK_FILE=/path/file.lock

# ロックファイルの確認と作成
if ! ln -s $$ ${LOCK_FILE}; then
  echo "LOCKED"
  exit
fi

# 実行開始時間をログに残す
echo "実行開始 : "`date` >>${LOG_FILE} 2>&1

########################################
# Main実行 
########################################
/bin/bash /path/main.sh >>${LOG_FILE} 2>&1

# エラーチェック
if [ $? -ne 0 ]; then
  echo "実行コマンドエラー" >>${LOG_FILE} 2>&1
fi

# 実行終了時間をログに残す
echo "実行終了 : "`date` >>${LOG_FILE} 2>&1

# ロックファイルの削除
rm ${LOCK_FILE}

exit
  • ログ
実行開始 : Thu May 2 17:31:01 JST 2019
実行終了 : Thu May 2 17:39:47 JST 2019
実行開始 : Thu May 2 17:46:01 JST 2019
実行終了 : Thu May 2 17:54:44 JST 2019
実行開始 : Thu May 2 18:01:01 JST 2019
実行終了 : Thu May 2 18:09:48 JST 2019
実行開始 : Thu May 2 18:16:01 JST 2019
実行終了 : Thu May 2 18:24:46 JST 2019
実行開始 : Thu May 2 18:31:01 JST 2019
スポンサードサーチ

備忘録

6分で終わるスクリプトを15分間隔で動かしてます。もしデータ量が急に増えてスクリプト実行時間が15分を超えてしまっても次の15分後に実行されます。

ロックファイルの生成はシンボリックリンクで

「ロックファイル確認」→「ロックファイル作成」という処理だと、ロックファイル「確認」と「作成」の間に処理が走ってしまう可能性があり、完全にロックされている状態ではありません。下記はNGです。

# ファイルの存在チェック
if [ -e ファイル ]; then
  # ロック!
  exit
fi
# ロックファイル作成
touch ${LOCK_FILE}

「ロックファイル確認」と「ロックファイル作成」は同時に行う必要があります。シンボリックリンクでロックファイルを生成すると、既にファイルが存在するとエラーになり処理が中断され、ファイルがなかった場合はロックファイルが生成されます。

# ロックファイルの確認と作成
if ! ln -s $$ ${LOCK_FILE}; then
  echo "LOCKED"
  exit
fi

補足

# ログのローテートも忘れずに!
0 1 * * * /logrotate.sh
#!/bin/bash

# log roteta everyday
# ログファイルのある場所へ移動
cd /log/path/
# ログが30日以上あるものを抽出して削除
find ./ -name '*.log' -mtime +30 -exec rm -f {} \;
スポンサードサーチ