Protegendo linhas do crontab com FLOCK

Em algumas situações queremos colocar uma linha no crontab que rode de tempos em tempos, mas queremos garantir de algum modo, que esta não ira rodar em paralelo caso a execução anterior não tenha sido finalizada, por exemplo:

*/1 * * * * root /sbin/exemplo/processa_relatorios.asp -t diario

Se as 18:23 o comando processa_relatorios.asp começar e as 18:24 não tiver terminado, teremos 2 execuções em paralelo deste, que pode gerar resultados monstruosos.

Várias pessoas (inclusive eu) acabam implementando algum mecanismo de lock na aplicação (ou no comando) para que ele consiga saber que já existe outra instância rodando e que não poderá rodar novamente caso o crontab dispare, mas descobri que existe o comando FLOCK, disponivel no Debian e em algumas outras versões de linux, que pode resolver isso com mais facilidade!

A linha de cron para esse exemplo ficaria assim:

*/1 * * * * root flock -w 0 /tmp/lock_relatorios  -c "/sbin/exemplo/processa_relatorios.asp -t diario"

onde:
"-w 0" indica que deve esperar 0 segundos caso o comando esteja em execução (isto é, vai desistir de rodar o comando pois não há tempo de espera)
"-c" é o comando a ser executado
"/tmp/lock_relatorios" é o arquivo que será lockado para a execução desse comando

Outro exemplo:

- arquivo /etc/cron.d/teste

*/1 * * * * root flock -w 0 /tmp/test -c "date && sleep 70" >> /tmp/log.txt

- a saida do log será:


Mon Dec 19 09:36:01 BRST 2011
Mon Dec 19 09:38:01 BRST 2011
Mon Dec 19 09:40:01 BRST 2011

Nesse caso podemos ver que não rodou a cada minuto pois havia um "sleep 70" que estava segurando a execução do comando.

0 comments: