Cron jobs no Linux: agendar tarefas na VPS

Cron é o agendador de tarefas padrão do Linux, essencial em qualquer VPS para automatizar backups de banco de dados, renovação de certificados SSL, limpeza de logs, verificação de saúde dos serviços e outras tarefas recorrentes. A sintaxe é simples e o serviço roda independente de qualquer app.

Sintaxe do crontab

Cada linha do crontab define quando e o que executar. Os 5 campos de tempo controlam o agendamento:

bash
# Estrutura:
# ┌─────────── minuto (0-59)
# │ ┌───────── hora (0-23)
# │ │ ┌─────── dia do mês (1-31)
# │ │ │ ┌───── mês (1-12 ou jan-dec)
# │ │ │ │ ┌─── dia da semana (0-7, domingo=0 ou 7, ou sun-sat)
# │ │ │ │ │
# * * * * *  comando

# Exemplos práticos:
0 2 * * *   /opt/backup.sh           # todo dia às 2h da manhã
*/5 * * * * /opt/check-health.sh     # a cada 5 minutos
0 3 * * 0   /opt/backup-semanal.sh  # domingo às 3h
0 */6 * * * /opt/sync.sh             # a cada 6 horas
30 8 1 * *  /opt/relatorio-mensal.sh # dia 1 de cada mês às 8h30

Gerenciar crontab por usuário

Cada usuário do sistema tem seu próprio crontab. Tarefas administrativas devem usar o crontab do root:

bash
# Editar crontab do usuário atual
crontab -e

# Listar crontab atual (sem editar)
crontab -l

# Editar crontab de outro usuário (como root)
sudo crontab -u deploy -e

# Remover todo o crontab do usuário atual
crontab -r

# Ver todos os crontabs do sistema (root pode ver todos)
sudo crontab -u root -l
cat /etc/crontab
ls /etc/cron.d/
ls /etc/cron.daily/ /etc/cron.weekly/ /etc/cron.monthly/

Logs e captura de erros

Cron não mostra output por padrão, redirecione para arquivo ou receba por e-mail:

bash
# Redirecionar output para arquivo de log
0 2 * * * /opt/backup.sh >> /var/log/backup.log 2>&1
# ">> arquivo" = append (não sobrescreve)
# "2>&1" = stderr junto com stdout

# Timestamp no log
0 2 * * * echo "=== $(date) ===" >> /var/log/backup.log && /opt/backup.sh >> /var/log/backup.log 2>&1

# Suprimir output (para tarefas silenciosas)
0 * * * * /opt/check.sh > /dev/null 2>&1

# Verificar se o cron executou (logs do sistema)
sudo grep CRON /var/log/syslog | tail -20
sudo journalctl -u cron | tail -20

# Configurar logrotate para o arquivo de log do cron
sudo nano /etc/logrotate.d/meu-cron
# Conteúdo:
# /var/log/backup.log {
#   daily
#   rotate 7
#   compress
#   missingok
# }

Exemplos práticos para VPS

Tarefas mais comuns para automatizar em qualquer VPS com Docker:

bash
# Backup diário do PostgreSQL às 2h
0 2 * * * docker exec postgres pg_dump -U postgres meu_banco | gzip > /opt/backups/pg-$(date +\%Y\%m\%d).sql.gz

# Limpar backups com mais de 7 dias
0 3 * * * find /opt/backups -mtime +7 -delete

# Renovar certificado SSL (verificação diária, renova se < 30 dias para expirar)
0 4 * * * docker run --rm -v ssl_certs:/etc/letsencrypt -v ssl_www:/var/www/certbot certbot/certbot renew --quiet && docker exec nginx nginx -s reload

# Verificar se containers essenciais estão rodando e reiniciar se necessário
*/10 * * * * docker ps --filter "name=n8n" --filter "status=running" | grep -q n8n || docker start n8n

# Limpeza semanal do Docker (domingo às 3h)
0 3 * * 0 docker system prune -f >> /var/log/docker-prune.log 2>&1

# Checar uso de disco e enviar alerta
0 */6 * * * df / | awk 'NR==2{if(+$5>80)system("curl -s -X POST WEBHOOK_URL -d \"{\"text\":\"Disco VPS: "$5"\"}\"")}'

Systemd timers: alternativa moderna ao cron

Systemd timers são mais robustos que cron, têm logs integrados, suporte a dependências e podem executar após um delay se a VPS estava desligada no horário agendado:

bash
# Criar um timer systemd para backup
# 1. Criar o service que executa a tarefa
sudo nano /etc/systemd/system/backup-postgres.service
# [Unit]
# Description=Backup PostgreSQL
# [Service]
# Type=oneshot
# ExecStart=/opt/backup-postgres.sh

# 2. Criar o timer
sudo nano /etc/systemd/system/backup-postgres.timer
# [Unit]
# Description=Backup PostgreSQL diário
# [Timer]
# OnCalendar=*-*-* 02:00:00
# Persistent=true    # executa se VPS estava desligada no horário
# [Install]
# WantedBy=timers.target

# 3. Habilitar e iniciar
sudo systemctl daemon-reload
sudo systemctl enable backup-postgres.timer
sudo systemctl start backup-postgres.timer

# Verificar próxima execução
systemctl list-timers backup-postgres.timer

Não quer configurar manualmente?

Implante o VPS em menos de 5 minutos com a Runstack. Infraestrutura da OPEN Datacenter, com servidores em São Paulo.

Perguntas frequentes

Causas mais comuns: (1) PATH diferente, use caminhos absolutos no script (ex: /usr/bin/docker, não docker); (2) permissão de execução ausente, chmod +x /opt/meu-script.sh; (3) sintaxe errada no crontab, verifique com crontab -l; (4) cron não está rodando, systemctl status cron.

Execute o comando diretamente no terminal com o mesmo usuário que o cron usaria: sudo -u root /opt/meu-script.sh. Para simular exatamente o ambiente do cron (sem variáveis de ambiente do shell): env -i HOME=/root /bin/bash --noprofile --norc -c "/opt/meu-script.sh".

Cron: tarefas simples de sistema (backup, limpeza, scripts shell). Sem dependências externas, sem interface visual. n8n: workflows complexos com múltiplos steps, condições, chamadas de API, notificações. Se o agendamento precisa de lógica de negócio (ex: "backup SE disco > 70%"), use n8n. Para tarefas de infraestrutura simples, cron é mais adequado.

Cron tem resolução mínima de 1 minuto. Para tarefas mais frequentes: (1) no script, execute em loop com sleep: while true; do tarefa; sleep 30; done &; (2) use o systemd timer com OnBootSec=30s e OnUnitActiveSec=30s; (3) use um processo supervisor como supervisord.

crontab -e edita o crontab do usuário atual (armazenado em /var/spool/cron). /etc/crontab é o crontab do sistema com um campo extra: o usuário que executa o comando. Arquivos em /etc/cron.d/ têm o mesmo formato do /etc/crontab. Para tarefas de sistema (root): use sudo crontab -e ou /etc/cron.d/. Para tarefas do usuário deploy: use crontab -e como esse usuário.