Cron job falhou em silêncio? Como detectar isso antes do cliente
Uma tarefa agendada que deixa de correr não dá erro — só deixa de acontecer. Porque é que a monitorização normal não a apanha, e o que fazer.
O cliente escreve a perguntar porque é que não recebeu o resumo semanal de encomendas. Vais ver e percebes que o último saiu há cinco semanas. O site está de pé, o site sempre esteve de pé, e a tarefa que gerava o resumo parou num domingo qualquer sem dar um único sinal.
É a categoria de falha mais desagradável que existe, e a razão é simples: o silêncio de uma tarefa que falhou é exactamente igual ao silêncio de uma tarefa que correu bem.
Porque é que a monitorização normal não apanha isto.
A monitorização de sites funciona por interrogação: nós batemos à porta, o servidor responde, e a resposta diz-nos o estado. Funciona porque há sempre um endereço para consultar.
Uma tarefa agendada não tem porta. Não escuta, não responde, não tem endpoint. A mesma ferramenta que vigia o site com sucesso está estruturalmente cega a ela — não é uma limitação de configuração, é uma consequência de como a coisa funciona.
O que agrava é o tipo de trabalho que costuma viver num cron. Não é código crítico com testes: é a cópia de segurança nocturna, a sincronização do stock, a renovação do certificado, a limpeza da base de dados, o email de resumo. Coisas que ninguém vê enquanto correm bem — o que é o mesmo que dizer que ninguém vê quando param.
As formas de morrer em silêncio.
Vale conhecê-las, porque cada uma tem um remédio diferente.
- O cron foi-se com a migração. Mudou-se de alojamento, o site veio todo, e a crontab do servidor antigo ficou lá. É a causa número um e continua a ser.
- O caminho mudou. O interpretador de PHP passou de
/usr/bin/phppara outro sítio numa actualização. O cron continua a disparar todos os dias e a falhar em silêncio todos os dias. - O output vai para lado nenhum. Muita gente acrescenta
> /dev/null 2>&1para não encher a caixa de correio — e ao fazê-lo desliga o único mecanismo de aviso que o cron tem de origem. - Corre e não faz nada. O script arranca, apanha uma excepção logo no princípio, e sai com código zero. Do ponto de vista do sistema, correu bem.
- O WP-Cron do WordPress. Este merece parágrafo próprio.
O caso do WordPress.
O WP-Cron não é um cron. É uma fila de tarefas que só é verificada quando alguém visita o site. Num site com tráfego constante, isto é indistinguível de um cron a sério. Num site institucional com trinta visitas por dia, as tarefas correm com horas de atraso — ou não correm de todo durante a noite.
O resultado prático é que actualizações agendadas, cópias de segurança e envios
de email num site com pouco tráfego são fundamentalmente pouco fiáveis. O remédio
é conhecido: desactivar o WP-Cron no wp-config.php e chamar o
wp-cron.php a partir de um cron a sério no painel do alojamento. É uma linha em
cada lado e resolve o problema de vez.
O padrão que resolve: o heartbeat.
A solução é inverter a direcção. Em vez de sermos nós a bater à porta da tarefa, é a tarefa a avisar-nos quando acaba.
Na prática: existe um endereço único por tarefa, e o script chama-o na última linha, depois de tudo ter corrido bem. Do outro lado, alguém sabe que devia receber essa chamada todos os dias entre as 3h00 e as 3h15. Se a chamada não chegar, é porque a tarefa não correu — e aí sim há um alerta.
0 3 * * * /usr/bin/php /home/user/backup.php && curl -fsS https://exemplo/hb/abc
Repara no &&: a chamada só acontece se o comando anterior tiver saído com
sucesso. É o pormenor que separa “a tarefa correu” de “a tarefa foi disparada”.
Isto chama-se dead man’s switch e é um padrão antigo. Há ferramentas dedicadas a fazê-lo, várias com plano gratuito generoso, e é o caminho certo se tens várias tarefas a vigiar.
O que fazer se não quiseres montar isso já.
Há uma versão com fita-cola que apanha o caso mais comum e demora dez minutos.
Faz a tarefa escrever num sítio observável de fora. Um ficheiro de texto servido pelo site com a data e hora da última execução bem sucedida, por exemplo, ou um endpoint que devolve essa data. Depois vigias esse endereço com uma verificação normal.
Não é elegante e tem um limite claro: uma verificação de estado normal só te diz que o endereço responde, não que a data lá dentro é recente. Para isso precisas de verificação por palavra-chave — procurar a data de hoje no corpo da resposta — e isso nem todas as ferramentas gratuitas fazem.
A versão mais bruta ainda, e que mesmo assim é melhor do que nada: põe uma data de fim no calendário. Uma vez por mês, abre a tarefa mais importante de cada cliente e confirma que a última execução foi recente. É trabalho manual, é esquecível, e apanha coisas que estariam paradas há meses.
Onde a De Olho está nisto.
Não temos monitorização de cron jobs, e não entra no lançamento. Está na lista do que queremos fazer — tecnicamente é o inverso do que o motor de verificação já vai fazer e reaproveita quase tudo — mas acrescentar um segundo tipo de vigilância antes de o primeiro estar de pé é a forma habitual de não acabar nenhum. O detalhe está na página da monitorização de cron jobs, com a etiqueta “em breve” à vista para não haver equívoco.
Os limites de qualquer destas abordagens.
Um heartbeat diz-te que a tarefa acabou. Não diz que ela fez o que devia. Uma cópia de segurança que corre em três segundos e grava um ficheiro de zero bytes chama o endereço na mesma, com sucesso, todos os dias.
Se a tarefa é mesmo importante — e as cópias de segurança são —, a verificação tem de incluir alguma coisa sobre o resultado e não só sobre a execução: o tamanho do ficheiro, o número de linhas processadas, a data do registo mais recente. É mais trabalho a escrever o script, e é a diferença entre saber que correu e saber que serviu.
Para o caso geral — o site que responde ou não responde, com que intervalo se verifica e o que conta como falha — a mecânica está em o que é monitorização de uptime.