flock は、同じ処理が同時に走らないように排他ロックをかける Linux の仕組みです。 定期ジョブやデプロイスクリプトの二重起動を防ぐ用途でよく使われます。
なぜ必要になるのか
典型的なのは cron です。5分おきに実行する設定にしても、処理が5分以内に終わらなければ次が重なって走ります。
そして重なった時にだけ問題が起きます。
- 同じデータを二重に処理する
- 一時ファイルを取り合って壊す
- メモリを2倍使って OOM で落ちる
- 積み重なって、サーバー全体が反応しなくなる
普段は正常で、処理が遅くなった日だけ壊れるため、原因の特定が遅れがちな種類の障害です。
基本の書き方
cron の行を flock で包むのが定石です。
* * * * * /usr/bin/flock -n /tmp/job.lock /path/to/job.sh
-n が重要です。ロックを取れなければ即座に諦めて終了します。 これを付けないと、後続のプロセスがロックを待って溜まり続け、防ぎたかった状況をかえって悪化させます。
「実行できなかった」は多くの場合エラーではなく正常動作です。次の実行機会に回ればよいので、通知を出すかどうかは処理の性質で決めます。
押さえておきたい注意点
ロックファイルの置き場所に注意してください。/tmp は再起動時に消える環境があり、NFS など共有ファイルシステム上では期待どおりに動かないことがあります。同一サーバー内の永続的な場所を使うのが無難です。
また flock が守るのは同じロックファイルを使うプロセス同士だけです。ロックを取らずに直接スクリプトを叩けば普通に二重実行できます。手動実行の手順も同じロックを通すようにしてください。
実務で見るポイント
- 分散環境(複数サーバー)では flock では守れない。DBやKVSによるロックが必要
- ロックを取れずに終了したことをログへ残すと、頻発時に気づける
- 「重い処理は cron の間隔を延ばす」より、まずロックで多重起動を止める