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 ().
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)?
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 ().
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:
setlock
do daemontools setlock
do daemontools-encore de Bruce Guenter s6-setlock
do s6 de Laurent Bercot chpst
do episódio de Gerrit Pape runlock
do perpetrador de Wayne Marshall setlock
do meu conjunto de ferramentas 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" "$@" ; }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:
[…]
outfile echo "$RESULT"
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 …'
Tags command-line bash linux semaphore