Ottieni un blocco di lettura / scrittura esclusivo su un file per gli aggiornamenti atomici


10

Voglio avere un file che viene utilizzato come contatore. L'utente A scriverà e incrementerà questo numero, mentre l'utente B richiede di leggere il file. È possibile che l'utente A possa bloccare questo file in modo che nessuno possa leggerlo o scriverlo fino al termine della scrittura dell'utente A?

Ho esaminato flockma non riesco a farlo funzionare come mi aspetto.

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

Se c'è un modo più appropriato per ottenere questo file incrementale di tipo atomico, sarebbe fantastico sentirlo anche tu!

Il mio obiettivo è:

LOCK counter.txt; write to counter.txt;

allo stesso tempo

Read counter.txt; realize it's locked so wait until that lock is finished.

1
"non riesco a farlo funzionare come mi aspetto." Cosa significa specificamente ?
Giovanni 1024,

Sono sicuro che lo sto usando in modo errato, ma mentre uso il codice sopra posso usare due shell e farli modificare entrambi il file del contatore mentre pensavo che uno lo stesse bloccando. Quindi, se eseguo quella linea due volte su due shell separate, (ciascuna con il proprio numero da echo), vedo ancora il secondo numero in fase di scrittura
d -_- b

1
Quando il primo completa e rilascia il blocco, il secondo viene eseguito. Non è così che dovrebbe funzionare? (Nel codice sopra, && sleep 5viene eseguito dopo che il gregge rilascia il blocco.)
John1024

Hmm intersting ... Quindi in quel caso sarebbe stato troppo veloce per catturare il mio occhio umano. Grande! La mia prossima sfida è come inserire più comandi flock, ma lo inserirò come una domanda separata. Grazie Giovanni!
d -_- b

3
@d -_- b Adoro il tuo nome utente. Questo è il nome utente più intelligente che abbia mai visto.
Devyn Collier Johnson,

Risposte:


10

L'elaborazione di Bash del comando seguente potrebbe essere sorprendente:

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

Bash viene eseguito prima flock -x -w 5 /dev/shm/counter.txt echo "4" > /dev/shm/counter.txte, se ciò si completa correttamente (rilasciando il blocco), quindi viene eseguito sleep 5. Pertanto, il blocco non viene mantenuto per i 5 secondi previsti.

A parte &contro&&

Se uno ha due comandi, Ae B, poi:

  1. A & Binizia Ain background e quindi inizia Bsenza attendere Ache finisca.

  2. A && Bsi avvia A, attende il completamento, quindi, se si completa correttamente (codice di uscita 0), si avvia B. Se Afallisce (codice di uscita diverso da zero), Bnon viene mai eseguito.

In breve, &e &&sono due operatori di lista completamente diversi.


3
mi sorprenderebbe se entrasse A && B, Aaspetterebbe Bdi finire.
Andras Gyomrey,

1
in A &&B, A viene eseguito per primo. B viene eseguito solo se A eseguito ed è uscito correttamente. Usare un; B per eseguire sempre B indipendentemente dallo stato di esecuzione di A.
kapad il

15

I blocchi di file non sono obbligatori 1 , ovvero non è possibile bloccare un file in modo che un altro processo non possa accedervi. Bloccare un file significa che se un processo (nother) verifica se è stato bloccato, lo saprà.

Lo scopo flockè quello di fare cose come ciò che vuoi, ma devi quindi utilizzare flockper ogni tentativo di accesso . Tieni presente che stanno bloccando le chiamate; da man flock:

se il blocco non può essere acquisito immediatamente, il gregge attende fino a quando il blocco non è disponibile


1. Il che rende la funzione inutile se la si utilizza per, ad esempio, la sicurezza, ma questo non è lo scopo dei blocchi dei file: sono per la sincronizzazione, che è ciò che si sta facendo. L'utente Leo ha sottolineato che potrebbe esserci un'implementazione non standardizzata del blocco obbligatorio dei file nel kernel di Linux ( vedere questa discussione ), basato su paralleli storici di altri sistemi operativi * nix. Tuttavia, questa sembra essere solo un'interfaccia di livello C.


Grazie! Questo aiuta a dare un senso all'aspetto "consultivo" e al modo in cui devo usarlo flockogni volta. molto utile!
d -_- b

2

È possibile utilizzare "sh -c command ..." per eseguire l'intero comando shell, incluso il reindirizzamento dei file, con il blocco premuto. Inoltre, poiché stai utilizzando il file come contatore, devi tenere il blocco continuamente mentre esegui la lettura e la riscrittura. Quindi vorresti fare qualcosa del genere per incrementare il contatore e restituire il suo nuovo valore:

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

La modifica dei segni più in segni meno dovrebbe ridurre il contatore:

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

Mi aspetto che inizializzi il contatore prima che possa verificarsi qualsiasi contesa, quindi non dovresti preoccuparti di bloccare così presto:

echo 0 > /dev/shm/counter.txt

Non penso che avresti mai bisogno di ostruire il valore del contatore mentre potrebbe verificarsi una contesa, ma, se mai lo facessi, dovresti farlo in questo modo:

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

Penso che tu capisca come fare la lettura, ma la includo per completezza:

flock --shared /dev/shm/counter.txt cat /dev/shm/counter.txt

Questa sembra essere l'unica risposta che nota correttamente che nella domanda, il file viene aperto dalla shell prima ancora che il gregge
venga
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.