Quando Jobs do Cron Não Executam - Checklist de Troubleshooting
O que você 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 permissões
Resumo rápido (ordem de triagem)
Quase todo caso de "cron não executa" se reduz a um destes cinco. Verifique de cima para baixo.
- O daemon do cron não está rodando
- Sem entrada de execução nos logs (nunca foi iniciado)
- PATH errado (cron é um ambiente diferente do seu shell interativo)
- Variáveis de ambiente ausentes (
.bashrcnão é lido) - Sintaxe de agendamento, permissões ou erros de final de linha
Premissas (ambiente alvo)
- SO: Ubuntu / Debian (pacote
cron, log em/var/log/syslog) - RHEL / CentOS usam serviço
cronde log em/var/log/cron - Foco no crontab do usuário (
crontab -e)
Por que funciona manualmente mas não no cron?
Conclusão: Diferente de um login interativo, o cron executa um shell não-interativo que nunca lê
.bashrc/.profilee mantém um PATH mínimo. Essa diferença de ambiente explica a maioria dos casos de "funciona manualmente, falha no cron".
Uma execução manual (shell de login) e uma execução no cron iniciam o shell por caminhos fundamentalmente diferentes.
| Item | Shell de login interativo | Job do cron |
|---|---|---|
| Arquivos de inicialização lidos | .bash_profile / .bashrc, etc. |
nenhum |
PATH |
completo (inclui /usr/local/bin, etc.) |
mínimo (frequentemente /usr/bin:/bin) |
HOME / LOGNAME |
definidos | parcialmente definidos |
| Diretório de trabalho | onde você está | $HOME do usuário |
| Saída padrão | terminal | enviada por email (ou descartada) |
Uma vez que você internalize essa diferença, cada verificação abaixo se torna "preencher o que falta no ambiente mínimo do cron", um item por vez.
O daemon do cron está rodando?
Conclusão: Primeiro confirme o daemon com
systemctl status cron. Se está parado, nenhum job executa. Esta é a pré-condição a descartar antes de qualquer outra coisa.
# Ubuntu / Debian $ systemctl status cron # RHEL / CentOS $ systemctl status crond
Se não está active (running), habilite e inicie.
$ sudo systemctl enable --now cron
O nome do serviço difere por distribuição: Ubuntu usa cron, família RHEL usa crond. Se status diz Unit cron.service could not be found, tente o outro nome.
Como confirmar se executou pelos logs?
Conclusão: O cron registra no syslog toda vez que dispara. Se
grep CRON /var/log/syslognão mostra entrada, o job nunca foi iniciado.
A existência ou não de uma linha de log muda a direção 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 está no script (PATH / permissões / ambiente). Prossiga para as próximas seções.
- Sem entrada -> nunca foi iniciado. Suspeite de erro na sintaxe de agendamento, localização 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 primária.
Por que o PATH causa falha?
Conclusão: O PATH do cron é mínimo (frequentemente
/usr/bin:/bin). Escreva comandos em/usr/local/bine similares com caminhos absolutos, ou defina PATH no topo do crontab.
"Funciona manualmente mas command not found no cron" quase sempre vem disso. Há três correções.
# 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 é o método mais seguro. Adicione temporariamente a linha abaixo, depois faça diff do cronenv resultante contra seu shell.
* * * * * env > /tmp/cronenv 2>&1
$ diff <(env) /tmp/cronenv
Uma variável de ambiente ausente é a causa?
Conclusão: O cron não lê
.bashrc/.profile. Jobs frequentemente falham porqueLANGou variáveis de runtime (NODE_ENV,JAVA_HOME, etc.) não estão definidas.
Variáveis que seu shell interativo definiu implicitamente estão vazias no cron. Defini-las explicitamente no script é a correção mais confiável.
#!/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 é fragil. A guarda "retornar imediatamente se não-interativo" no topo do .bashrc (padrão do Ubuntu) pode impedir que qualquer coisa carregue. Exporte as variáveis que você precisa individualmente.
Como encontrar erros de agendamento e sintaxe?
Conclusão: São cinco campos: minuto, hora, dia-do-mês, mês, dia-da-semana. O comportamento OR de dia/dia-da-semana e o
%sem escape são as armadilhas clássicas. Se nenhuma entrada de execução 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
Tropeços comuns:
%não é literal: o cron transforma%em um comando em nova linha. Faça escape com barra invertida, ex. escrevadate +%Y-%m-%dcomodate +\%Y-\%m-\%d.- Dia e dia-da-semana ambos definidos:
0 0 1 * 1executa no "dia 1 ou segunda-feira" (um OR), não no "dia 1 e segunda-feira". Isso facilmente diverge da intenção. - Sem comentários no final da linha:
* * * * * cmd # notaé inválido. Comentários devem estar em sua própria linha com#.
crontab.guru é uma forma rápida de verificar o que um agendamento significa. Após salvar, sempre re-verifique com crontab -l que foi armazenado como pretendido.
Verificar permissões e localização do crontab
Conclusão: Um script sem permissão de execução ou com caminho de shebang errado falha logo após disparar. Ao colocar arquivos em
/etc/cron.d/, é fácil esquecer que a linha precisa de um campo de usuário.
Permissão de execução 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
| Localização | Campo de usuário | Uso |
|---|---|---|
crontab -e (usuário) |
nenhum | jobs pessoais |
/etc/crontab |
obrigatório | sistema inteiro |
/etc/cron.d/<file> |
obrigatório | 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 usuário e o log mostra um erro como bad username, ou o job silenciosamente nunca executa.
Como redirecionar saída para depuração?
Conclusão: O cron envia saída padrão e erro padrão por email. Em hosts sem MTA, essa saída desaparece, então redirecionar para arquivo torna os erros visíveis.
# Enviar stdout e stderr para um arquivo de log * * * * * /home/alice/backup.sh >> /tmp/backup.log 2>&1
2>&1 combina erro padrão no mesmo arquivo. Após executar, /tmp/backup.log mantém as mensagens brutas de command not found ou Permission denied.
Reprodução mínima
Quando você não 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 está saudável e você isolou o problema no script.