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


9

カウンターとして使用するファイルが欲しいのですが。ユーザー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.

1
「期待どおりに動作しないようです。」どのような具体的にそれが意味するのでしょうか?
John1024 2013

私はそれを間違って使用していると確信していますが、上記のコードを使用している間、2つのシェルを使用して、1つがロックしていると思っている間に両方にカウンターファイルを編集させることができます。したがって、その行を2つの別々のシェルで2回実行すると(それぞれに固有の番号がエコーされます)、2番目の番号が書き込まれていることがわかります
d -_- b

1
最初のプロセスが完了してロックを解放すると、2番目のプロセスが実行されます。それはそれがうまくいくべき方法ではありませんか?(上記のコードで&& sleep 5は、flockがロックを解除したに実行されます。)
John1024

うーん面白いです...その場合、人間の目が追いつくには速すぎました。すごい!次の課題はflock、複数のコマンドをに配置する方法ですが、これは別の質問として説明します。ジョンありがとう!
d -_- b

3
@d -_- b私はあなたのユーザー名が大好きです。それは私が今まで見た中で最も賢いユーザー名です。
Devyn Collier Johnson

回答:


10

以下のコマンドの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れ、Bashが正常に完了すると(ロックを解除して)、実行されsleep 5ます。したがって、ロックは予想される5秒間保持されません。

脇に&&&

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

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

  2. A && Bが開始しA、完了するまで待機し、完了した場合(終了コード0)、開始しBます。場合A(ゼロ以外の終了コード)が失敗し、その後、B実行されることはありません。

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


3
A && B、終了Aするのを待つと、私は驚きますB
Andras Gyomrey

1
A && Bでは、Aが最初に実行されます。Bは、Aが実行されて正常に終了した場合にのみ実行されます。使う; 関係なく、常にAの実行状態のBを実行するB
kapad

15

ファイルのロックは必須ではありません1-つまり、ファイルをロックして別のプロセスアクセスできないようにすることはできません。ファイルをロックするということは、(他の)プロセスがファイルがロックされているかどうかを確認する場合、プロセスがそれを知ることを意味します。

の目的はflock、希望どおりのことを行うことですが、試行されたすべてのアクセスに使用flockする必要があります。これらは通話をブロックしていることに注意してください。からman flock

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


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


ありがとう!これは、「助言」の側面と、flock毎回どのように使用する必要があるかを理解するのに役立ちます。非常に役立ちます!
d -_- b

2

"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

これは、質問では、flock が実行される前にファイルがシェルによって開かれることを正しく
認識する
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.