Erhalten Sie eine exklusive Lese- / Schreibsperre für eine Datei für atomare Updates

9

Ich möchte eine Datei haben, die als Zähler verwendet wird. Benutzer A schreibt und erhöht diese Nummer, während Benutzer B das Lesen der Datei anfordert. Ist es möglich, dass Benutzer A diese Datei sperren kann, sodass niemand sie lesen oder schreiben kann, bis der Schreibvorgang von Benutzer A abgeschlossen ist?

Ich habe nachgesehen flock, kann es aber nicht so zum Laufen bringen, wie ich es erwartet habe.

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

Wenn es einen angemesseneren Weg gibt, um diese atomähnliche Inkrementierungsdatei zu erhalten, wäre es auch toll, sie zu hören!

Mein Ziel ist:

LOCK counter.txt; write to counter.txt;

während zur gleichen Zeit

Read counter.txt; realize it's locked so wait until that lock is finished.
d -_- b
quelle
1
"Ich kann es nicht so zum Laufen bringen, wie ich es erwartet habe." Was bedeutet das konkret ?
John1024
Ich bin sicher, dass ich es falsch verwende, aber während ich den obigen Code verwende, kann ich zwei Shells verwenden und beide die Zählerdatei bearbeiten lassen, während ich dachte, eine sperrt sie. Wenn ich diese Zeile also zweimal auf zwei separaten Shells laufen
lasse
1
Wenn der erste seine Sperre abschließt und aufhebt, wird der zweite ausgeführt. Sollte das nicht so funktionieren? (Im obigen Code && sleep 5wird ausgeführt, nachdem die Herde die Sperre
aufgehoben hat
Hmm interessant ... In diesem Fall wäre es für mein menschliches Auge zu schnell gewesen, um es zu fangen. Toll! Meine nächste Herausforderung besteht darin, mehrere Befehle einzugeben flock, aber das werde ich als separate Frage stellen. Danke John!
d -_- b
3
@d -_- b Ich liebe deinen Benutzernamen. Das ist DER klügste Benutzername, den ich je gesehen habe.
Devyn Collier Johnson

Antworten:

10

Bashs Verarbeitung des folgenden Befehls kann überraschend sein:

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

Bash wird zuerst ausgeführt flock -x -w 5 /dev/shm/counter.txt echo "4" > /dev/shm/counter.txt. Wenn dies erfolgreich abgeschlossen wurde (Aufheben der Sperre), wird es ausgeführt sleep 5. Somit wird die Sperre nicht für die 5 Sekunden gehalten, die man erwarten kann.

John1024
quelle
3
es würde mich überraschen , wenn in A && B, Awürde warten Bbis Ende.
Andras Gyomrey
15

Dateisperren sind nicht obligatorisch 1 - dh Sie können eine Datei nicht sperren, damit ein anderer Prozess nicht darauf zugreifen kann. Das Sperren einer Datei bedeutet, dass ein (anderer) Prozess, der prüft , ob sie gesperrt wurde, dies weiß.

Der Zweck flockist Sachen zu tun , wie das, was Sie wollen, aber Sie müssen dann verwenden flockfür jede und jeden versuchten Zugriff . Denken Sie daran, dass diese Anrufe blockieren. von man flock:

Wenn das Schloss nicht sofort erworben werden kann, wartet die Herde, bis das Schloss verfügbar ist


1. Was die Funktion nutzlos erscheinen lässt, wenn Sie sie beispielsweise für Sicherheitszwecke verwenden, aber dies ist nicht der Zweck von Dateisperren - sie dienen der Synchronisierung, was Sie auch tun. Benutzer Leo wies darauf hin, dass es möglicherweise eine nicht standardisierte Implementierung der obligatorischen Dateisperrung im Linux-Kernel gibt ( siehe diese Diskussion ), die auf historischen Parallelen von anderen * nix-Betriebssystemen basiert. Dies scheint jedoch nur eine C-Level-Schnittstelle zu sein.

Goldlöckchen
quelle
Vielen Dank! Dies hilft dabei, den Beratungsaspekt zu verstehen und zu verstehen, wie ich ihn flockjedes Mal verwenden muss. sehr hilfreich!
d -_- b
2

Sie können den Befehl "sh -c ..." verwenden, um den gesamten Shell-Befehl einschließlich der Dateiumleitung mit gehaltener Sperre auszuführen. Da Sie die Datei als Zähler verwenden, müssen Sie die Sperre kontinuierlich halten, während Sie lesen und zurückschreiben. Sie möchten also so etwas tun, um den Zähler zu erhöhen und seinen neuen Wert zurückzugeben:

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))'

Das Ändern der Pluszeichen in Minuszeichen sollte den Zähler verringern:

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))'

Ich gehe davon aus, dass Sie den Zähler initialisieren, bevor es zu Konflikten kommen kann. Sie sollten sich also keine Sorgen machen müssen, dass Sie so früh sperren:

echo 0 > /dev/shm/counter.txt

Ich glaube nicht, dass Sie jemals den Zählerwert einschränken müssten, während es zu Konflikten kommen könnte, aber wenn Sie dies jemals getan haben, sollten Sie dies folgendermaßen tun:

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

Ich denke, Sie verstehen, wie man liest, aber ich füge es der Vollständigkeit halber hinzu:

flock --shared /dev/shm/counter.txt cat /dev/shm/counter.txt
Adam Richter
quelle
Dies scheint die einzige Antwort zu sein, die richtig bemerkt, dass in der Frage die Datei von der Shell geöffnet wird, bevor die Herde überhaupt läuft ...
eichin