Navegando na rede nacional me deparei com um artigo interessante (que trago aqui textualmente porque é explicado com maestria), onde seu autor nos mostra como tornar nossos scripts Bash mais robustos usando Armadilhas.
Torne seus scripts bash mais robustos com armadilhas
Imagine que você tenha um script bash que é executado todos os dias a cada seis horas e que em algum ponto ele falha ou o mesmo script é executado duas vezes simultaneamente. Essas duas situações são bastante incômodas, pois requerem intervenção humana para serem corrigidas ou, em determinados momentos, não podem ser tratadas, deixando o sistema em um estado inconsistente. A solução para isso, entre outras, é usar armadilhas.
Traps é uma maneira simples e eficaz de controlar a saída de scripts bash. Voltemos à mesma situação inicial, se o script for parado manualmente, por exemplo com ctrl-c, ele é interrompido retornando o sinal de saída
INT
e se terminar com
kill
então a saída seria
TERM
.
Todos os códigos de saída possíveis podem ser vistos com
kill -l
no entanto os mais usados são precisamente
INT, TERM, SAIR
Se o script consiste, por exemplo, em sincronização de arquivos com
rsync
O mais sensato é contar com um arquivo de bloqueio que não permite que o script seja executado simultaneamente:
LOCK = "/ var / run / rsync.lock" if [! -e $ LOCK]; em seguida, toque em $ LOCK rsync -avz foo bar rm $ LOCK senão echo "rsync já está em execução" fi
Em espanhol simples, o script anterior verifica se o arquivo de bloqueio existe e, se não existir, ele o cria e depois executa o comando correspondente, finalmente excluindo o arquivo de bloqueio. Se o arquivo existir, o script simplesmente envia uma mensagem ao usuário indicando que o comando já está em execução.
Porém, quando há uma situação problemática, pode acontecer que o arquivo de bloqueio não seja eliminado, arruinando os efeitos indesejados. A solução é muito simples:
LOCK = "/ var / run / rsync.lock" if [! -e $ LOCK]; então trap "rm -f $ LOCK; sair" INT TERM SAIR toque $ LOCK rsync -avz foo bar rm $ LOCK trap - INT TERM SAIR senão echo "rsync já está rodando" fi
A particularidade desta solução é que o comando fica encerrado em uma armadilha, de modo que quando um sinal é recebido
INT, TERM, SAIR
o script para e limpa o arquivo de bloqueio.
Vale dizer que pode haver uma situação de competição no script acima entre o momento em que o arquivo de bloqueio é verificado e o momento em que é criado. Uma possível solução seria usar um modo de redirecionamento e noclobber do bash que não redireciona para um arquivo existente:
LOCK = "/ var / run / rsync.lock" if (set -o noclobber; echo $$> "$ LOCK") 2> / dev / null; então trap 'rm -f "$ LOCK"; sair $? ' INT TERM EXIT rsync -avz foo bar rm -f $ LOCK trap - INT TERM EXIT else echo "rsync já está em execução: $ (cat $ LCK)" fi
A peculiaridade deste último é que se utiliza como já havia falado, o modo noclobber e que o arquivo de bloqueio contém o PID do processo que está sendo executado.
Vale ressaltar ainda que existem outras soluções como
flock
o
solo
no entanto, neste post eu queria compartilhar as soluções com recursos próprios do bash. Você pode aprender um pouco mais sobre Traps com este excelente guia.
Ótimo! Obrigado por compartilhar.
Bom artigo, basta mudar 'echo "rsync já está em execução: $ (cat $ LCK)"' para 'echo "rsync já está em execução: $ (cat $ LOCK)"'
lembranças
Um artigo muito interessante, sim senhor! Isso eu mantenho.
É um comando muito útil para se ter em mente. Usei em um script que publiquei em um post, para deletar alguns arquivos que o script criou quando foi interrompido.
Muito interessante, sim senhor.