Quando Jobs do Cron Nao Executam - Checklist de Troubleshooting

Quando Jobs do Cron Nao Executam - Checklist de Troubleshooting

O que voce vai aprender

  • Por que um script que funciona manualmente falha no cron
  • Como confirmar falhas do cron pelos logs
  • Como resolver as armadilhas comuns: PATH, ambiente, sintaxe de agendamento e permissoes

Resumo rapido (ordem de triagem)

Quase todo caso de "cron nao executa" se reduz a um destes cinco. Verifique de cima para baixo.

  1. O daemon do cron nao esta rodando
  2. Sem entrada de execucao nos logs (nunca foi iniciado)
  3. PATH errado (cron e um ambiente diferente do seu shell interativo)
  4. Variaveis de ambiente ausentes (.bashrc nao e lido)
  5. Sintaxe de agendamento, permissoes ou erros de final de linha

Premissas (ambiente alvo)

  • SO: Ubuntu / Debian (pacote cron, log em /var/log/syslog)
  • RHEL / CentOS usam servico crond e log em /var/log/cron
  • Foco no crontab do usuario (crontab -e)

Por que funciona manualmente mas nao no cron?

Conclusao: Diferente de um login interativo, o cron executa um shell nao-interativo que nunca le .bashrc / .profile e mantem um PATH minimo. Essa diferenca de ambiente explica a maioria dos casos de "funciona manualmente, falha no cron".

Uma execucao manual (shell de login) e uma execucao no cron iniciam o shell por caminhos fundamentalmente diferentes.

Item Shell de login interativo Job do cron
Arquivos de inicializacao lidos .bash_profile / .bashrc, etc. nenhum
PATH completo (inclui /usr/local/bin, etc.) minimo (frequentemente /usr/bin:/bin)
HOME / LOGNAME definidos parcialmente definidos
Diretorio de trabalho onde voce esta $HOME do usuario
Saida padrao terminal enviada por email (ou descartada)

Uma vez que voce internalize essa diferenca, cada verificacao abaixo se torna "preencher o que falta no ambiente minimo do cron", um item por vez.

O daemon do cron esta rodando?

Conclusao: Primeiro confirme o daemon com systemctl status cron. Se esta parado, nenhum job executa. Esta e a pre-condicao a descartar antes de qualquer outra coisa.

# Ubuntu / Debian
$ systemctl status cron

# RHEL / CentOS
$ systemctl status crond

Se nao esta active (running), habilite e inicie.

$ sudo systemctl enable --now cron

O nome do servico difere por distribuicao: Ubuntu usa cron, familia RHEL usa crond. Se status diz Unit cron.service could not be found, tente o outro nome.

Como confirmar se executou pelos logs?

Conclusao: O cron registra no syslog toda vez que dispara. Se grep CRON /var/log/syslog nao mostra entrada, o job nunca foi iniciado.

A existencia ou nao de uma linha de log muda a direcao da sua triagem.

# Ubuntu / Debian
$ grep CRON /var/log/syslog | tail -20

# Via journal do systemd
$ journalctl -u cron --since "1 hour ago"

# RHEL / CentOS
$ sudo grep CRON /var/log/cron | tail -20

Um disparo bem-sucedido deixa uma linha como esta.

Jun  5 10:00:01 host CRON[12345]: (alice) CMD (/home/alice/backup.sh)

Como ler:

  • Existe uma entrada -> o cron disparou. O problema esta no script (PATH / permissoes / ambiente). Prossiga para as proximas secoes.
  • Sem entrada -> nunca foi iniciado. Suspeite de erro na sintaxe de agendamento, localizacao errada do crontab ou daemon parado.

Se nenhum log aparece no Ubuntu, rsyslog pode estar ausente ou parado (systemctl status rsyslog). Nesse caso use journalctl -u cron como fonte primaria.

Por que o PATH causa falha?

Conclusao: O PATH do cron e minimo (frequentemente /usr/bin:/bin). Escreva comandos em /usr/local/bin e similares com caminhos absolutos, ou defina PATH no topo do crontab.

"Funciona manualmente mas command not found no cron" quase sempre vem disso. Ha tres correcoes.

# 1) Usar caminho absoluto (encontrar com which)
$ which node
/usr/local/bin/node

# No crontab, especificar o caminho absoluto
* * * * * /usr/local/bin/node /home/alice/job.js
# 2) Definir PATH no topo do crontab
PATH=/usr/local/bin:/usr/bin:/bin
0 * * * * node /home/alice/job.js
# 3) Exportar PATH dentro do script antes de executar
#!/bin/bash
export PATH=/usr/local/bin:/usr/bin:/bin
node /home/alice/job.js

Capturar o ambiente real do cron e o metodo mais seguro. Adicione temporariamente a linha abaixo, depois faca diff do cronenv resultante contra seu shell.

* * * * * env > /tmp/cronenv 2>&1
$ diff <(env) /tmp/cronenv

Uma variavel de ambiente ausente e a causa?

Conclusao: O cron nao le .bashrc / .profile. Jobs frequentemente falham porque LANG ou variaveis de runtime (NODE_ENV, JAVA_HOME, etc.) nao estao definidas.

Variaveis que seu shell interativo definiu implicitamente estao vazias no cron. Defini-las explicitamente no script e a correcao mais confiavel.

#!/bin/bash
# Variaveis que tendem a nao estar definidas no ambiente do cron
export LANG=en_US.UTF-8
export HOME=/home/alice
export NODE_ENV=production

cd "$HOME/app" || exit 1
/usr/local/bin/node index.js

Fazer source de ~/.bashrc dentro de um script do cron como workaround e fragil. A guarda "retornar imediatamente se nao-interativo" no topo do .bashrc (padrao do Ubuntu) pode impedir que qualquer coisa carregue. Exporte as variaveis que voce precisa individualmente.

Como encontrar erros de agendamento e sintaxe?

Conclusao: Sao cinco campos: minuto, hora, dia-do-mes, mes, dia-da-semana. O comportamento OR de dia/dia-da-semana e o % sem escape sao as armadilhas classicas. Se nenhuma entrada de execucao aparece no log, suspeite da sintaxe primeiro.

+-- minuto (0-59)
| +-- hora (0-23)
| | +-- dia do mes (1-31)
| | | +-- mes (1-12)
| | | | +-- dia da semana (0-7, 0 e 7 sao domingo)
| | | | |
* * * * *  comando a executar

Tropecos comuns:

  • % nao e literal: o cron transforma % em um comando em nova linha. Faca escape com barra invertida, ex. escreva date +%Y-%m-%d como date +\%Y-\%m-\%d.
  • Dia e dia-da-semana ambos definidos: 0 0 1 * 1 executa no "dia 1 ou segunda-feira" (um OR), nao no "dia 1 e segunda-feira". Isso facilmente diverge da intencao.
  • Sem comentarios no final da linha: * * * * * cmd # nota e invalido. Comentarios devem estar em sua propria linha com #.

crontab.guru e uma forma rapida de verificar o que um agendamento significa. Apos salvar, sempre re-verifique com crontab -l que foi armazenado como pretendido.

Verificar permissoes e localizacao do crontab

Conclusao: Um script sem permissao de execucao ou com caminho de shebang errado falha logo apos disparar. Ao colocar arquivos em /etc/cron.d/, e facil esquecer que a linha precisa de um campo de usuario.

Permissao de execucao do script e shebang

$ chmod +x /home/alice/backup.sh
$ head -1 /home/alice/backup.sh
#!/bin/bash

Um script editado no Windows pode pegar finais de linha CRLF e falhar com bad interpreter. Veja Corrigindo "bad interpreter" para detalhes.

A sintaxe difere por tipo de crontab

Localizacao Campo de usuario Uso
crontab -e (usuario) nenhum jobs pessoais
/etc/crontab obrigatorio sistema inteiro
/etc/cron.d/<file> obrigatorio pacotes / jobs extras
# /etc/cron.d/ e /etc/crontab exigem um campo de usuario
# +min +hr +dia +mes +dsem +usuario   +comando
  0    3   *    *    *     alice      /home/alice/backup.sh

Errar o campo de usuario e o log mostra um erro como bad username, ou o job silenciosamente nunca executa.

Como redirecionar saida para depuracao?

Conclusao: O cron envia saida padrao e erro padrao por email. Em hosts sem MTA, essa saida desaparece, entao redirecionar para arquivo torna os erros visiveis.

# Enviar stdout e stderr para um arquivo de log
* * * * * /home/alice/backup.sh >> /tmp/backup.log 2>&1

2>&1 combina erro padrao no mesmo arquivo. Apos executar, /tmp/backup.log mantem as mensagens brutas de command not found ou Permission denied.

Reproducao minima

Quando voce nao consegue isolar a causa, primeiro confirme que o cron funciona com um job que apenas escreve a data a cada minuto.

* * * * * date >> /tmp/cron-test.log 2>&1

Se este log cresce, o cron esta saudavel e voce isolou o problema no script.

Resumo do checklist

Conclusao: Trabalhe de cima para baixo -- daemon, logs, PATH, ambiente, sintaxe, permissoes, saida -- e voce consegue identificar quase qualquer causa de "cron nao executa".

Verifique cada item na ordem.

  • [ ] systemctl status cron (RHEL: crond) mostra active (running)
  • [ ] grep CRON /var/log/syslog tem uma entrada de execucao
  • [ ] Comandos usam caminhos absolutos, ou PATH= esta definido no topo do crontab
  • [ ] Variaveis de ambiente necessarias (LANG, de runtime) sao exportadas no script
  • [ ] Cinco campos de tempo, % com escape, OR de dia/dia-da-semana entendido
  • [ ] Script e executavel, shebang esta correto, finais de linha sao LF
  • [ ] >> /tmp/job.log 2>&1 torna erros visiveis

Proximas leituras: