Dicas para configurar cron com logging e notificação de falhas
1. Fundamentos do cron e redirecionamento de saída
O cron é um dos utilitários mais antigos e confiáveis do Unix, mas sua simplicidade pode enganar. Por padrão, a saída de um job cron é enviada por email ao proprietário do crontab — algo que raramente funciona em ambientes modernos sem um MTA configurado. A primeira lição é: nunca confie no comportamento padrão do cron para logging.
A sintaxe básica do crontab segue o formato minuto hora dia mês semana comando. Para redirecionar a saída corretamente, use:
# Exemplo básico com redirecionamento
0 2 * * * /opt/scripts/backup.sh >> /var/log/cron/backup.log 2>&1
O operador >> anexa a saída padrão ao arquivo, enquanto 2>&1 redireciona a saída de erro para o mesmo destino. Para integrar com syslog, utilize o comando logger:
0 3 * * * /opt/scripts/verifica_disco.sh 2>&1 | logger -t verifica_disco -p cron.info
Isso envia as mensagens para o syslog local com a tag "verifica_disco", permitindo consulta centralizada via journalctl ou arquivos em /var/log/.
2. Estrutura de logging robusta para jobs cron
Uma estratégia de logging bem planejada inclui três elementos: nomenclatura padronizada, rotação automática e timestamps. Crie diretórios específicos por job:
/var/log/cron/
├── backup/
│ ├── backup-2025-01-15.log
│ └── backup-2025-01-16.log
├── monitoria/
│ └── monitoria-2025-01-15.log
└── sincronizacao/
└── sincronizacao-2025-01-15.log
Configure o logrotate para evitar que os logs cresçam indefinidamente. Exemplo em /etc/logrotate.d/cron-jobs:
/var/log/cron/*.log {
daily
rotate 30
compress
delaycompress
missingok
notifempty
create 0640 root adm
postrotate
systemctl restart rsyslog > /dev/null 2>&1 || true
endscript
}
Cada linha de log deve conter timestamp e identificação do job. No script, implemente:
#!/bin/bash
LOG_FILE="/var/log/cron/backup/backup-$(date +%Y-%m-%d).log"
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [INFO] Iniciando backup..." >> "$LOG_FILE"
3. Captura e tratamento de erros dentro do script
Scripts robustos precisam de tratamento explícito de erros. Use set -e para abortar em qualquer falha e trap para capturar sinais e garantir limpeza:
#!/bin/bash
set -e
LOG_FILE="/var/log/cron/backup.log"
ERROR_FLAG=0
trap 'echo "[$(date)] [ERRO] Job finalizado com falha" >> "$LOG_FILE"; ERROR_FLAG=1' ERR
funcao_log() {
local level="$1"
local message="$2"
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [${level}] ${message}" >> "$LOG_FILE"
}
funcao_log "INFO" "Iniciando processo de backup"
rsync -avz /dados /backup/ || funcao_log "ERRO" "Falha na sincronização"
Diferencie saída normal de erros críticos usando níveis de severidade (INFO, WARN, ERROR). Crie funções padronizadas para reuso em múltiplos scripts.
4. Notificação por email com mailx e mutt
Para ambientes que ainda dependem de email, configure o mailx (ou heirloom-mailx) com um relay SMTP. Edite /etc/mail.rc:
set smtp=smtp://smtp.exemplo.com:587
set smtp-auth=login
set smtp-auth-user=seuemail@exemplo.com
set smtp-auth-password=suasenha
set from="cron@exemplo.com"
No script, envie logs de erro automaticamente:
#!/bin/bash
LOG_FILE="/var/log/cron/backup.log"
SUBJECT="[CRON] Falha no backup - $(hostname) - $(date '+%Y-%m-%d %H:%M')"
if [ $? -ne 0 ]; then
tail -50 "$LOG_FILE" | mailx -s "$SUBJECT" admin@exemplo.com
fi
Para formatação mais rica, use mutt:
mutt -s "$SUBJECT" -a "$LOG_FILE" -- admin@exemplo.com < /dev/null
5. Notificação via sistemas modernos (Slack, Telegram, Webhook)
Sistemas modernos preferem notificações instantâneas via API. Para Slack, crie um webhook e use curl:
#!/bin/bash
WEBHOOK_URL="https://hooks.slack.com/services/T0000/B0000/xxxxx"
MESSAGE="{\"text\": \"Falha no job de backup em $(hostname) - $(date)\"}"
curl -X POST -H 'Content-type: application/json' --data "$MESSAGE" "$WEBHOOK_URL"
Para Telegram, utilize a API de bots:
#!/bin/bash
BOT_TOKEN="seu_token"
CHAT_ID="seu_chat_id"
MESSAGE="Falha no job de backup em $(hostname)"
curl -s "https://api.telegram.org/bot${BOT_TOKEN}/sendMessage" \
-d "chat_id=${CHAT_ID}" \
-d "text=${MESSAGE}"
Para serviços de monitoramento como Healthchecks.io, envie um ping simples:
curl -fsS --retry 3 https://hc-ping.com/seu-uuid > /dev/null
6. Monitoramento proativo com scripts wrapper
Crie um wrapper que registre início, fim e status de cada execução. Isso permite detectar jobs que não executaram ou falharam silenciosamente:
#!/bin/bash
# wrapper_cron.sh
JOB_NAME="$1"
shift
LOG_DIR="/var/log/cron/${JOB_NAME}"
mkdir -p "$LOG_DIR"
LOG_FILE="${LOG_DIR}/${JOB_NAME}-$(date +%Y%m%d-%H%M%S).log"
echo "[$(date)] [INICIO] Job: ${JOB_NAME}" > "$LOG_FILE"
START_TIME=$(date +%s)
# Executa o comando real
"$@" >> "$LOG_FILE" 2>&1
EXIT_CODE=$?
END_TIME=$(date +%s)
DURATION=$((END_TIME - START_TIME))
echo "[$(date)] [FIM] Job: ${JOB_NAME} - Codigo: ${EXIT_CODE} - Duracao: ${DURATION}s" >> "$LOG_FILE"
if [ $EXIT_CODE -ne 0 ]; then
# Envia alerta
curl -s "https://api.telegram.org/bot${BOT_TOKEN}/sendMessage" \
-d "chat_id=${CHAT_ID}" \
-d "text=Job ${JOB_NAME} falhou com codigo ${EXIT_CODE} em $(hostname)"
fi
Use no crontab:
0 2 * * * /opt/scripts/wrapper_cron.sh backup /opt/scripts/backup.sh
Implemente heartbeat: se o wrapper não gerar log por mais de 24h, dispare alerta externo.
7. Centralização de logs e alertas com ferramentas externas
Para ambientes maiores, centralize logs. Envie para syslog remoto configurando o rsyslog:
# No cliente (script)
logger -n logserver.exemplo.com -P 514 -t backup "Iniciando backup"
# No servidor (/etc/rsyslog.conf)
:syslogtag, contains, "backup" /var/log/cron/backup.log
Use systemd-cat para integrar com journald:
#!/bin/bash
exec > >(systemd-cat -t backup -p info) 2>&1
echo "Iniciando backup"
Para métricas no Prometheus, crie um exporter simples que leia os logs e exponha contadores de falhas. Ou configure alertas no Zabbix com monitoramento de arquivos de log via log[] item.
8. Boas práticas e troubleshooting
Teste notificações manualmente antes de confiar nelas:
# Simula falha
/opt/scripts/backup.sh; echo "Exit code: $?"
# Testa envio de email
echo "Teste" | mailx -s "Teste notificacao cron" admin@exemplo.com
# Testa webhook
curl -X POST -H 'Content-type: application/json' \
--data '{"text":"Teste webhook cron"}' "$WEBHOOK_URL"
Verifique permissões e caminhos absolutos em todos os scripts. O cron executa com ambiente mínimo — use PATH explícito:
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
0 2 * * * /opt/scripts/backup.sh
Audite jobs não notificados: crie um job diário que verifica se todos os wrappers registraram execução nas últimas 24h. Se faltar algum, dispare alerta.
#!/bin/bash
# verifica_heartbeat.sh
for job in backup monitoria sincronizacao; do
LAST_LOG=$(ls -t /var/log/cron/${job}/*.log 2>/dev/null | head -1)
if [ -z "$LAST_LOG" ] || [ $(stat -c %Y "$LAST_LOG") -lt $(date -d '24 hours ago' +%s) ]; then
echo "Job ${job} sem execucao nas ultimas 24h" | mailx -s "Heartbeat perdido" admin@exemplo.com
fi
done
Referências
- Documentação oficial do cron (man crontab) — Referência completa sobre sintaxe do crontab, variáveis de ambiente e redirecionamento de saída.
- Guia de logging para scripts shell no Linux — Tutorial prático sobre implementação de logging estruturado em scripts bash com rotação e syslog.
- Documentação do logrotate — Manual oficial do logrotate com exemplos de configuração para rotação automática de logs.
- API de Bots do Telegram — Documentação oficial para envio de mensagens via bot Telegram, usada em notificações de falhas.
- Healthchecks.io - Monitoramento de jobs cron — Serviço de heartbeat e monitoramento para jobs cron, com integração via ping HTTP.
- Guia de envio de email com mailx no Linux — Tutorial detalhado sobre configuração de mailx com relay SMTP para notificações por email.
- Slack Webhook API — Documentação oficial do Slack para criação e uso de webhooks de mensagens.
- Integração de logs com systemd-journald — Manual do systemd-cat para envio de logs de scripts shell ao journald.