web-dev-qa-db-ja.com

アトミック更新のためにファイルの排他的な読み取り/書き込みロックを取得する

カウンターとして使用するファイルが欲しいのですが。ユーザーAはこの番号を書き込んでインクリメントし、ユーザーBはファイルの読み取りを要求します。ユーザーAがこのファイルをロックして、ユーザーAの書き込みが完了するまで誰もファイルを読み書きできないようにすることは可能ですか?

flockを調査しましたが、期待どおりに動作しないようです。

flock -x -w 5 /dev/shm/counter.txt echo "4" >  /dev/shm/counter.txt && sleep 5

このアトミックなインクリメントファイルを取得するためのより適切な方法があるとしたら、それも聞いてみたいと思います。

私の目標は:

LOCK counter.txt; write to counter.txt;

同時に

Read counter.txt; realize it's locked so wait until that lock is finished.
9
d-_-b

以下のコマンドのBashの処理は意外かもしれません。

flock -x -w 5 /dev/shm/counter.txt echo "4" >  /dev/shm/counter.txt && sleep 5

Bashは最初にflock -x -w 5 /dev/shm/counter.txt echo "4" > /dev/shm/counter.txtを実行し、それが正常に完了すると(ロックを解除して)、sleep 5を実行します。したがって、ロックは予想される5秒間保持されません。

&&&は別として

ABの2つのコマンドがある場合、次のようになります。

  1. A & BAをバックグラウンドで開始し、Bが完了するのを待たずにAを開始します。

  2. A && BAを開始し、それが完了するのを待って、正常に完了した場合(終了コード0)、Bを開始します。 Aが失敗した場合(ゼロ以外の終了コード)、Bは実行されません。

つまり、&&&は、2つの完全に異なるリスト演算子です。

10
John1024

ファイルのロックは必須ではありません1 -つまり、別のプロセスがファイルにアクセスできないようにファイルをロックすることはできません。ファイルをロックするということは、a(nother) processchecksif if it has been locked?.

flockの目的は好きなことをすることですが、その場合は試行されたすべてのアクセスに対してflockを使用する必要があります。これらは通話をブロックしていることに注意してください。 man flockから:

ロックをすぐに取得できない場合、flockはロックが使用可能になるまで待機します


1.たとえば、セキュリティなどで機能を使用している場合、機能が役に立たないように見えますが、それはファイルロックの目的ではありません。これは同期のためのものであり、これが実行していることです。ユーザーLeoは、他の* nixオペレーティングシステムからの歴史的な類似点に基づいて、Linuxカーネルに必須のファイルロックの標準化されていない実装があるかもしれないと指摘しました( この議論を参照 )。ただし、これはCレベルのインターフェースのみのようです。

15
goldilocks

"sh -c command ..."を使用して、ロックを保持したまま、ファイルリダイレクトを含むシェルコマンド全体を実行できます。また、ファイルをカウンターとして使用しているため、読み取りと書き込みを行う間、継続的にロックを保持する必要があります。したがって、カウンタをインクリメントしてその新しい値を返すには、次のようなことを行います。

flock --exclusive --wait 5 /dev/shm/counter.txt sh -c 'read count < /dev/shm/counter.txt ; echo $((count + 1)) > /dev/shm/counter.txt ; echo $((count + 1))'

プラス記号をマイナス記号に変更すると、カウンターが減少します。

flock --exclusive --wait 5 /dev/shm/counter.txt sh -c 'read count < /dev/shm/counter.txt ; echo $((count - 1)) > /dev/shm/counter.txt ; echo $((count - 1))'

競合が発生する前にカウンターを初期化するので、早くロックすることを心配する必要はありません。

echo 0 > /dev/shm/counter.txt

競合が発生する可能性があるときにカウンター値を上書きする必要はないと思いますが、これを行った場合は、こうする必要があります。

flock --exclusive --wait 5 /dev/shm/counter.txt sh -c 'echo 0 > /dev/shm/counter.txt'

読み方は理解していると思いますが、完全を期すために含めています。

flock --shared /dev/shm/counter.txt cat /dev/shm/counter.txt
2
Adam Richter