Esecuzione di operazioni di scrittura atomica in un file in bash


13

Dopo aver esaminato la documentazione di Bash , questa domanda e questa non mi sono ancora chiare come posso eseguire operazioni di scrittura atomica (append) su un file in Bash. Ho uno script che viene eseguito in più istanze e ad un certo punto deve scrivere i dati in un file:

echo "$RESULT" >> `pwd`/$TEMP_DIR/$OUT_FILE

Come è possibile rendere atomiche tutte le operazioni di scrittura da tutti gli script contemporaneamente in esecuzione su quel file (in modo che i dati di un'istanza non si sovrappongano a quelli di un'altra)?


1
Cordiali saluti non è necessario `pwd`; puoi semplicemente usare un punto ( .). Inoltre dovresti citare l'intero nome del file poiché include variabili .
Wildcard il

1
Potresti anche voler esaminare la possibilità di utilizzare FIFO .
Wildcard il

@Wildcard Grazie. Stavo usando in pwdprecedenza nello script per informare l'utente sulla directory di lavoro corrente e anche scrivere voci in un file di registro. guardando oltre FIFOs ora.
Sebi,

1
In realtà c'è una migliore introduzione agli FIFO proprio su questo sito; il link che ho fornito qualche minuto fa sono le specifiche POSIX mkfifoe non esattamente il livello introduttivo.
Wildcard il

Che si tratti di un FIFO o di un file, corri comunque il rischio che due istanze scrivano contemporaneamente e si scambino reciprocamente gli output.
clacke il

Risposte:


10

Sembra che tu debba usare flockcome nell'esempio di man ( http://linux.die.net/man/1/flock )

(
flock -x 200

# Put here your commands that must do some writes atomically

) 200>/var/lock/mylockfile 

E metti tutti i tuoi comandi che devono essere atomici in ().


L'operazione di scrittura sarà atomica anche se (flock -s 200 # Metti qui i tuoi comandi che devono fare alcune scritture atomicamente) 200> / var / lock / mylockfile è distribuito su più script in esecuzione contemporaneamente? O, al contrario, il blocco è relativo solo a / var / lock / mylockfile?
Sebi,

1
Lo script blocca / var / lock / mylockfile, ma solo un'istanza dello script può ottenere un blocco di scrittura su di esso. Altre istanze aspetteranno fino a quando non /var/lock/mylockfilesarà disponibile il blocco.

-s è un blocco condiviso - adatto per le letture, per un blocco in scrittura devi usare -x / -e. È nella pagina man che hai collegato.
Evan Benn,

A che punto si verifica lo sblocco in questo codice? Non appena qualcosa viene scritto /var/lock/mylockfilenel processo che ha chiamato flock -x?
Chris Stryczynski,

@ChrisStryczynski È possibile eseguire questo esempio (flock -x 200; date; sleep 10; date;) 200>/var/lock/mylockfilein due shell e vedere che gli sblocchi avvengono solo dopo l'esecuzione di tutti i comandi in () (ovvero in una subshell)

4

flockè uno dei modi di interbloccare le operazioni. L'utilità fa parte del set di strumenti util-linux ed è disponibile solo per Linux. Altre utilità, disponibili su una più ampia gamma di piattaforme, sono basate setlocksull'utilità di Daniel J. Bernstein dal suo pacchetto daemontools:

  • setlock da daontoontools
  • setlock dall'encore dei daemontools di Bruce Guenter
  • s6-setlock dalla s6 di Laurent Bercot
  • chpst dalla runit di Gerrit Pape
  • runlock dall'autore di Wayne Marshall
  • setlock dal mio set di strumenti nosh

Questi strumenti operano con un paradigma leggermente diverso da quello usato nella risposta di M. Kurenkov (uno che flockpuò anche impiegare, ma non in quella risposta). Uno invoca il setlockprogramma per caricare a catena il comando che deve essere interbloccato. setlocksi apre e blocca il file di blocco e lascia un descrittore di file per esso aperto nel suo processo. Il blocco persiste per tutto il processo (a meno che il comando successivo concatenato rilasci esplicitamente il blocco trovando e chiudendo il descrittore di file aperto).

Per il caso nella domanda, è necessario interbloccare il comando che produce la linea di output, tenendo presente che ciò invoca un comando esterno echo al posto di un echocomando incorporato della shell :

setlock mylockfile echo "$ RESULT" >> ./$TEMP_DIR/$OUT_FILE

In questo caso non è necessario interbloccare l'apertura del file di output in modalità append. Se lo fosse, si dovrebbe aprire quel file all'interno del blocco, il che richiede l'utilizzo di programmi come fdredir/ redirfd:

setlock mylockfile fdredir --append 1 "./$TEMP_DIR/$OUT_FILE" echo "$ RESULT"
quale si può trasformare in una funzione shell se si desidera:

outfile () {setlock mylockfile fdredir --append 1 "./$TEMP_DIR/$OUT_FILE" "$ @"; } 
[…]
Eco del file "$ RESULT"
o attenersi alla sintassi della shell e farla interpretare da una seconda shell in esecuzione sotto l'interblocco, che richiede alcune quotazioni non banali se le variabili della propria shell non vengono esportate come variabili di ambiente:

setlock mylockfile sh -c 'echo' "$ RESULT" '>> "./'$TEMP_DIR'/'$OUT_FILE'" '

Questo ovviamente generalizza a cose diverse dalla scrittura nei file di output:

setlock mylockfile sh -c '... interbloccato; cose …'

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.