systemd Timer vs cron: Escolhendo o Agendador Certo

systemd Timer vs cron: Escolhendo o Agendador Certo

Qual você deve usar?

Use systemd timer como padrão para novas cargas de trabalho. Os logs se integram com journalctl, dependências entre serviços podem ser aplicadas, e execuções perdidas são capturadas na próxima inicialização. Mantenha o cron ao manter tarefas existentes ou quando um agendamento de uma linha é tudo que você precisa.

Tabela de Decisão Rápida

Cenário Recomendado
Nova tarefa periódica systemd timer
Logs centralizados via journalctl systemd timer
Depende de outro serviço systemd timer
Gatilho relativo a inicialização systemd timer
Mantendo tarefas cron existentes Manter cron
Uma linha simples em um agendamento cron

O que é cron?

cron é o agendador de tarefas tradicional do UNIX. Uma única linha no crontab define quando e o que executar, usando cinco campos: minuto, hora, dia-do-mês, mês e dia-da-semana.

Sintaxe do crontab

min hora dom mes dsm comando
# Todo dia as 3:00 da manha
0 3 * * * /home/user/scripts/backup.sh

# A cada 5 minutos
*/5 * * * * /usr/local/bin/collect-logs.sh

# Toda segunda-feira as 9:00 da manha
0 9 * * 1 /usr/local/bin/send-report.sh

Comandos do crontab

# Abrir o editor para o usuario atual
crontab -e

# Listar tarefas atuais
crontab -l

# Remover todas as tarefas (use com cautela)
crontab -r

cron envia a saída por email para o usuário local por padrão. Em ambientes sem um daemon de email, a saída acumula em /var/spool/mail. Adicione MAILTO="" no topo do seu crontab para suprimir isso.

O que é systemd timer?

Um systemd timer consiste em dois arquivos de unidade: um arquivo .timer (o agendamento) e um arquivo .service (o comando a executar). Ambos são gerenciados pelo systemd, então logs, dependências e verificações de status passam pela mesma interface.

Exemplo Mínimo: Executar a Cada 5 Minutos

/etc/systemd/system/collect-logs.service

[Unit]
Description=Collect system logs

[Service]
Type=oneshot
ExecStart=/usr/local/bin/collect-logs.sh

/etc/systemd/system/collect-logs.timer

[Unit]
Description=Run collect-logs every 5 minutes

[Timer]
OnCalendar=*:0/5
Persistent=true

[Install]
WantedBy=timers.target

Habilitando e Monitorando um Timer

# Recarregar arquivos de unidade apos qualquer alteracao
sudo systemctl daemon-reload

# Habilitar e iniciar o timer imediatamente
sudo systemctl enable --now collect-logs.timer

# Listar todos os timers ativos com proximos horarios de execucao
systemctl list-timers

# Verificar logs de execucao
journalctl -u collect-logs.service

Por que o systemd Timer é melhor?

As duas vantagens principais sobre o cron são logging centralizado e controle granular.

Logs vão para o journalctl

# Ultimas 50 entradas de log
journalctl -u collect-logs.service -n 50

# Logs apenas de hoje
journalctl -u collect-logs.service --since today

# Apenas erros
journalctl -u collect-logs.service -p err

A saída do cron vai para email ou um arquivo separado. A saída do systemd timer vai para o journal junto com todos os outros eventos do sistema, tornando a investigação de incidentes muito mais rápida.

Dependências de Serviços

[Unit]
Description=Database backup
Requires=postgresql.service
After=postgresql.service

A tarefa só executa se o PostgreSQL estiver ativo. O cron não tem mecanismo equivalente - você precisaria verificar dentro do script.

Gatilhos Relativos a Inicialização

[Timer]
# 10 minutos apos a inicializacao
OnBootSec=10min
# Depois a cada hora
OnUnitActiveSec=1h

systemd timer suporta tanto agendamentos baseados em calendário (OnCalendar) quanto relativos (OnBootSec/OnUnitActiveSec). O cron não suporta nenhum dos dois.

Capturando Execuções Perdidas com Persistent=true

[Timer]
OnCalendar=daily
Persistent=true

Se a máquina estiver desligada no horário agendado, a tarefa executa na próxima inicialização em vez de ser ignorada silenciosamente. O cron não faz isso sem o anacron.

Como escrever OnCalendar?

OnCalendar usa o formato de timestamp próprio do systemd. Sempre valide com systemd-analyze calendar antes de habilitar um novo timer.

# Validar um agendamento e mostrar os proximos horarios de disparo
systemd-analyze calendar "Mon *-*-* 03:00:00"

# Padroes comuns
OnCalendar=daily          # 00:00 todo dia
OnCalendar=hourly         # 00:00 toda hora
OnCalendar=weekly         # Seg 00:00 toda semana
OnCalendar=*:0/5          # a cada 5 minutos
OnCalendar=Mon 03:00      # Seg 03:00 toda semana
OnCalendar=*-*-* 03:00:00 # todo dia as 03:00 (mesmo que acima)

Execute systemd-analyze calendar antes de habilitar qualquer novo timer. Ele imprime os próximos dois horários agendados, capturando erros de digitação antes que causem falhas silenciosas.

Como migrar do cron para o systemd Timer?

Passo 1: Revisar tarefas existentes

crontab -l
# 0 3 * * * /home/user/scripts/backup.sh

Passo 2: Criar o arquivo de serviço

sudo nano /etc/systemd/system/backup.service
[Unit]
Description=Daily backup

[Service]
Type=oneshot
User=user
ExecStart=/home/user/scripts/backup.sh

Passo 3: Criar o arquivo de timer

sudo nano /etc/systemd/system/backup.timer
[Unit]
Description=Run backup daily at 3:00 AM

[Timer]
OnCalendar=*-*-* 03:00:00
Persistent=true

[Install]
WantedBy=timers.target

Passo 4: Habilitar e verificar

sudo systemctl daemon-reload
sudo systemctl enable --now backup.timer

# Confirmar que o timer esta registrado
systemctl list-timers --all | grep backup

# Verificar logs apos a primeira execucao
journalctl -u backup.service --since today

Passo 5: Remover a tarefa do cron

crontab -e
# Delete or comment out the migrated line

Confirme que o timer está funcionando via systemctl list-timers e journalctl -u backup.service antes de remover a tarefa original do cron. Deixar ambos ativos causa execução dupla.

Resumo da comparação

Recurso cron systemd timer
Complexidade de setup Uma linha Dois arquivos de unidade
Logging Email ou arquivo journalctl
Dependências de serviços Não Sim
Gatilho relativo a boot Não Sim (OnBootSec)
Capturar exec. perdidas Não (precisa anacron) Sim (Persistent=true)
Tarefas por usuário crontab por usuário Unidades de serviço do usuário
Comando de inspeção crontab -l systemctl list-timers

Próximas leituras