Cronなどで定期的にスクリプトを実行していると、前回の処理が終わらないうちに次が起動してスクリプト等が2重起動してそれが原因でリソースが多く使いサーバーが不安定になったりするケースがあります
このようにCronでスクリプトを実行する場合に、2重起動を防止する機能を追加したシェルスクリプトにする方法を紹介します
今回は、Linuxで標準的に使える flock を使って、簡単に2重起動を防止する方法をご紹介します。
flock とは?
flock は ファイル単位で排他制御(ロック)を行うためのコマンドです。主にスクリプトやプロセスの同時実行制御に使われます。
- 既にロックされていれば、次のプロセスは起動できない(もしくは待機する)
- スクリプト終了時には自動でロックが解除される
flock のインストール
多くのLinuxディストリビューション(CentOS, Rocky Linux, Ubuntuなど)には標準で flock が含まれています。flockがない場合は以下でインストールできます:
・RHEL系(CentOS / Rocky Linux)
$ sudo yum install util-linux
・Debian系(Ubuntuなど)
$ sudo apt install util-linux
スクリプトの2重起動を防ぐ
以下は、/tmp/test.lock
というロックファイルを使って、同じスクリプトが複数同時に実行されるのを防ぐサンプルです
#!/bin/bash LOCKFILE="/tmp/test.lock" # ファイルディスクリプタ200を使ってロックを取得 exec 200>"$LOCKFILE" flock -n 200 || { echo "[$(date '+%F %T')] Another instance is already running. Exiting." exit 1 } echo "[$(date '+%F %T')] Script started." # ★ここに本処理を書く sleep 60 # テスト用に1分だけ待機 echo "[$(date '+%F %T')] Script finished."
サンプルのシェルスクリプトの詳細
exec 200>”$LOCKFILE” | ファイルディスクリプタ200でロックファイルをオープン |
flock -n 200 | ロックを試みる(-n は「待機しない」) |
exit 1 | 他プロセスが実行中なら即終了 |
sleep 60 | 実際の処理の代わりに1分待機(例) |
ロックの解除は不要?
スクリプト終了時にファイルディスクリプタ200が自動的に閉じられるため、ロックも自動で解除されます。
明示的に flock -u などを記述する必要はありません。
ログファイルに記録する
シェルスクリプトの処理内容をログに残したい場合は、以下のようにしてログを記録するようにします
#!/bin/bash LOGFILE="/var/log/test_script.log" exec 200>/tmp/test.lock flock -n 200 || { echo "$(date '+%F %T') - Already running." >> "$LOGFILE" exit 1 } echo "$(date '+%F %T') - Started." >> "$LOGFILE" # 実処理… echo "$(date '+%F %T') - Finished." >> "$LOGFILE"
まとめ
flock
を使えば簡単にスクリプトの2重起動を防止できます。- ロックファイルは一時ディレクトリ(例:
/tmp/
)に作成すればOK。 - スクリプト終了時には自動でロック解除されるため、運用も安心。
コメント