Linuxでの古いファイルロックの処理とクラスタの強力な使用

Linuxでの古いファイルロックの処理とクラスタの強力な使用

cronを介して定期的に(数分ごとに)実行されるスクリプトがあります。しかし、スクリプトは何度も並列に実行されず、時には少し時間がかかるので、いくつかのロックを実装したいと思います。つまり、以前のインスタンスがすでに実行されている場合は、スクリプトが早く終了していることを確認してください。

さまざまな提案に基づいて、次のロックが作成されました。

lock="/run/$(basename "$0").lock"
exec {fd}<>"$lock"
flock -n $fd || exit 1

スクリプトの他のインスタンスがまだ実行されている場合は、終了1を呼び出す必要があります。

これで問題は、スクリプトが終了した後も古いロックが残っていることがあることです。これは事実上、cronが再度実行されないことを意味します(次の再起動まで、またはロックされたファイルが削除されるまで)。これは確かに私が望むものではありません。

lslocksコマンドが既存のファイルロックを一覧表示できることがわかりました。これは次のことを示しています。

(unknown)        2732 FLOCK        WRITE 0     0   0 /run...                                                                 

プロセス(この場合は2732)はもう存在しません(例:ps aux)。完全なファイル名(例:/ run ...)が表示されない理由もわかりません。 lslocksには--notrucate引数がありますが、これはファイル名が切り捨てられるのを避けることができるように聞こえますが、出力は変更されず、まだ/ run ...です。

だから、いくつかの質問があります。

  • これらのロックがあるのはなぜですか、クラスタのロックがプロセスのライフサイクルの外側に存在するのはなぜですか?
  • lslocksがフルパス/ファイル名を表示しないのはなぜですか?
  • これを防ぎ、スクリプトロックをより強力にするための良い方法はありますか?
  • 再起動せずに古いロックをクリーンアップする方法はありますか?

ベストアンサー1

ロックはflockファイル記述オブジェクトに関連付けられており、ファイル記述を参照するすべてのファイル記述子が閉じられると消えます。foll.2 マンページ)。

ファイルがまだロックされている場合、ファイルディスクリプタは元のプロセスまたはサブプロセスでまだ参照されることがほとんどあります(元のプロセス層の外に参照を伝播するために渡すファイルディスクリプタなどを使用しないと仮定します)。

私はそれを確認することをお勧めしますsudo fuser $lock_path

この問題を解決するために、私は2つの方法を知っています。つまり、シェルが子プロセスがファイルディスクリプタを継承しないようにするか、ファイルディスクリプタを参照しているすべてのプロセスをまだ終了することですfuser -k ...

表示されるパスは情報を収集するlslocksために使用されるため、不完全です/proc/locks。ファイルにはマウントポイントの識別子とロックを取得したプロセスに関する情報が含まれていますが、ロックファイルへのパスは含まれていません。プロセスの確認時にロックを保持するファイル記述子が見つからない場合は、lslocksマウントポイントの印刷に戻ります。

おすすめ記事