Executando operações de gravação atômica em um arquivo no bash

9

Depois de passar pela documentação do bash, esta pergunta e isso ainda não está claro para mim como posso executar operações de gravação atômica (anexar) em um arquivo no bash. Eu tenho um script que é executado em várias instâncias e em algum momento deve gravar dados em um arquivo:

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

Como é possível fazer todas as operações de gravação de todos os scripts em execução simultânea para esse arquivo atômico (para que os dados de uma instância não se sobreponham aos dados de outra)?

    
por Sebi 05.04.2016 / 19:17

2 respostas

9

Parece que você precisa usar flock como no exemplo do man ( link )

(
flock -x 200

# Put here your commands that must do some writes atomically

) 200>/var/lock/mylockfile 

E coloque todos os seus comandos que devem ser atômicos em ().

    
por 05.04.2016 / 19:22
3

flock é uma das formas de operações de intertravamento. O utilitário faz parte do conjunto de ferramentas util-linux e está disponível apenas para Linux. Outros utilitários, disponíveis em uma ampla variedade de plataformas, baseiam-se no utilitário setlock de Daniel J. Bernstein em seu pacote daemontools:

Essas ferramentas operam com um paradigma ligeiramente diferente do usado na resposta de M. Kurenkov (uma que flock também pode empregar, mas não nessa resposta). Um invoca o programa setlock para carregamento em cadeia para o comando que deve ser intertravado. O setlock abre e bloqueia o arquivo de bloqueio e deixa um descritor de arquivo aberto em seu processo. O bloqueio persiste por tanto tempo quanto esse processo (a menos que o comando subsequente encadeado para liberar explicitamente o bloqueio localizando e fechando o descritor de arquivo aberto).

Para o caso na questão, é necessário interligar o comando que produz a linha de saída, sabendo que isso invoca um external echo no lugar de um comando echo embutido no shell:

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

Neste caso, não é necessário interbloquear a abertura do arquivo de saída no modo de anexação. Se fosse, seria necessário abrir esse arquivo dentro do bloqueio, o que exigia o uso de programas como fdredir / redirfd :

setlock mylockfile fdredir --append 1 "./$TEMP_DIR/$OUT_FILE" echo "$RESULT"
, que pode se transformar em uma função de shell se você quiser:
outfile() { setlock mylockfile fdredir --append 1 "./$TEMP_DIR/$OUT_FILE" "$@" ; }
[…]
outfile echo "$RESULT"
ou ficar com a sintaxe do shell e interpretá-la por um segundo shell executando o interlock, exigindo algumas cotações não triviais se as variáveis do shell não forem exportadas como variáveis de ambiente:
setlock mylockfile sh -c 'echo '"$RESULT"' >> "./'$TEMP_DIR'/'$OUT_FILE'"'

Isso, é claro, se generaliza para outras coisas além de escrever para arquivos de saída:

setlock mylockfile sh -c '… interlocked ; stuff …'
    
por 15.10.2018 / 15:26