É um problema comum em muitos sistemas: você programou tarefas definidas no cronjobs e, por alguma razão, elas levam mais tempo para serem executadas do que o previsto. Isso significa que eventualmente elas começam a se sobrepor e a serem executadas ao mesmo tempo. Se esses são cronjobs que estão atuando sobre os mesmos dados de um banco de dados↳Banco de dados134 conteúdosSQL ou NoSQL: eis a questão!!Data · mar 2020Banco de dados: como organizar e dar segurança para milhões de dados de loteriasData · mai 20215 serviços gratuitos na cloud para bancos de dados PostgresData · fev 2025Ver tudo em Data →, isso pode significar corrupção de dados. Se eles estão fazendo um grande processamento de dados, isso poderia significar a carga do servidor está subindo muito. Por causa dessa alta carga, esses cronjobs estão levando mais tempo do que o habitual e, antes que você perceba, há um círculo vicioso em que cronjobs mantêm o lançamento e se sobrepõem uns aos outros.
Obviamente, você não quer isso. A boa notícia é que isso é bem fácil de evitar.
Utilizando flock
O flock é uma ferramenta muito interessante para o gerenciamento de arquivos de bloqueio. Esses arquivos de bloqueio são usados para determinar se um script ou um aplicativo já está em execução (comparável a um arquivo PID que contém a identificação do processo do script sendo executado). Se o bloqueio existe, o cronjob não será iniciado. Se o bloqueio não existe, é seguro lançar o cron.
Veja o seguinte exemplo comum, onde um cron é executado a cada minuto no servidor.
$ crontab -l * * * * * /usr/bin/php /path/to/cron.php
Se o script leva mais de um minuto para executar, eles começam a se sobrepor. Para evitar isso, você pode mudar com o exemplo flock abaixo.
$ crontab -l * * * * * /usr/bin/flock -w 0 /path/to/cron.lock /usr/bin/php /path/to/cron.php
O exemplo acima requer que o flock gerencie esses arquivos de bloqueio. Se isso ainda não existe no seu sistema, a instalação deve ser tão simples como um yum install flock ou apt-getinstall flock, dependendo de sua distribuição Linux↳Linux34 conteúdosKali Linux em um Servidor VPS: como, quando e por que usar?DevSecOps · dez 2024Construindo um Windows Service ou Linux Daemon com Worker Service & .NET Core – Parte 2Dev (Back & Front) · jul 2020Criando uma WebApi utilizando .NET, Linux e VSCodeDev (Back & Front) · ago 2019Ver tudo em DevSecOps → (mais sobre isso aqui).
No momento em que o flock começa, ele bloqueia o arquivo de bloqueio que você especificar no comando. Você pode ver isso ao solicitar o usuário/script que está tendo o bloqueio sobre esse arquivo.
$ fuser -v /path/to/cron.lock
USER PID ACCESS COMMAND
cron.lock: root 7836 f.... flock
root 7837 f.... php
Ele vai mostrar o processo de IDs (PIDs) do script que está mantendo o bloqueio. Se nenhum script estiver mantendo o bloqueio, o comando fuser retornará simplesmente nada.
$ fuser -v /path/to/cron.lock
Então, o flock é uma boa maneira de evitar a sobreposição de cronjobs usando uma ferramenta de linha de comando adicional.
Utilizando pgrep
Outro método, sem o uso de arquivos de bloqueio, é utilizar um liner bash-one bem simples que verifica o arquivo de execução atual e o executa se ele não estiver funcionando. O truque é envolver seu crontask em um nome exclusivo do bash-script, assim:
$ cat /path/to/cron.sh #!/bin/bash /usr/bin/php /path/to/cron.php $ chmod +x /path/to/cron.sh
No seu crontab, ele deve ser listado assim:
$ crontab -l * * * * * /path/to/cron.sh
O comando acima irá, assim como o primeiro exemplo, executar o nosso script PHP↳PHP44 conteúdosPadronizando seu código com PHP CS FixerDev (Back & Front) · mai 2019Docker de imagem. Para rodar projetos PHP em menos de 30 segundosDev (Back & Front) · jan 2026PHP 7.3: conheça as novidades desta versãoDev (Back & Front) · abr 2019Ver tudo em Dev (Back & Front) → a cada minuto através de um script. Para evitar a sobreposição, ele pode também ser alterado para isto:
$ crontab -l * * * * * /usr/bin/pgrep -f /path/to/cron.sh > /dev/null 2> /dev/null || /path/to/cron.sh
O comando pgrep irá retornar falso se não encontrar um processo de execução correspondente ao primeiro argumento, /path/to/cron.sh. Se ele retornar falso, vai processar a segunda parte da comparação OR (a linha vertical dupla, ||). Se o processo de execução foi encontrado, pgrep irá retornar o ID do processo (PID) e Bash não vai continuar para a segunda parte do argumento OR, já que o primeiro já retornou verdadeiro.
O truque aqui é usar nomes de script muito originais. Se o nome é muito genérico (como “cron.sh”), pgrep pode retornar IDs de processo a partir de outras tarefas cron em execução e não executar o cron que você queria.
Utilizando bloqueio de arquivos dentro do script
Se os exemplos acima não estão disponíveis para você, você ainda pode usar o conceito de arquivos de bloqueio em seu aplicativo. Um dos primeiros comandos em seu script poderia ser verificar a existência de um arquivo de bloqueio. Se ele existir, o script poderia simplesmente sair (1) do aplicativo e parar de rodar. Se o bloqueio de arquivo não existir, o script poderia criá-lo e evitar que o próximo trabalho seja executado.
Como último passo no seu script, você remove o arquivo de bloqueio para indicar que o script terminou e permitir que a próxima execução continue.
***
Texto original disponível em http://mattiasgeniar.be/2012/07/24/prevent-cronjobs-from-overlapping-in-linux/







