linux

systemd timer no lugar do cron: agendar script com log e sem execução dupla

Um systemd timer substitui uma linha do crontab com dois arquivos: um .service que diz o que rodar e um .timer que diz quando. Em troca, você ganha a saída no journalctl, a execução perdida recuperada quando o servidor volta (Persistent=true) e a garantia de que o systemd não abre uma segunda cópia enquanto a anterior roda.

Quais são os dois arquivos?

# /etc/systemd/system/backup-banco.service
[Unit]
Description=Backup do banco

[Service]
Type=oneshot
User=backup
ExecStart=/usr/local/bin/backup-banco.sh
# /etc/systemd/system/backup-banco.timer
[Unit]
Description=Backup do banco todo dia 03:15

[Timer]
OnCalendar=*-*-* 03:15:00
Persistent=true
RandomizedDelaySec=5min

[Install]
WantedBy=timers.target

O timer ativa o service de mesmo nome, sem precisar de Unit=. O Persistent=true grava em disco a última execução: se a máquina estava desligada às 03:15, o backup roda assim que o timer subir de novo. O RandomizedDelaySec espalha o disparo em até 5 minutos, útil quando vários servidores têm a mesma tarefa.

Como ligar e conferir se vai rodar?

sudo systemctl daemon-reload
sudo systemctl enable --now backup-banco.timer
systemctl list-timers backup-banco.timer
systemd-analyze calendar 'Mon..Fri *-*-* 03:15:00' --iterations=3
sudo systemctl start backup-banco.service
journalctl -u backup-banco.service --since today

Quem leva o enable é o .timer, não o .service. O systemd-analyze calendar mostra as próximas datas da expressão no fuso do servidor antes de você confiar nela. E rodar o .service na mão é o teste que o cron nunca deu: mesmo usuário, mesmo ambiente, e o erro aparece no journal com hora e código de saída.

Quando eu continuo no cron?

Quando não tenho root ou a tarefa é de um usuário só. O systemd tem timer de usuário (systemctl --user), mas o gerenciador do usuário só fica de pé com a sessão aberta, a menos que o root rode loginctl enable-linger para essa conta; sem isso, o timer para quando você sai do SSH.

Post Recentes

Custom post type dando 404: flush_rewrite_rules na ativação do plugin

A listagem do custom post type abre e o single dá 404 no WordPress 6.9. Entenda o cache das rewrite…

4 horas atrás

Descrição em massa no WooCommerce: wp eval-file lendo a lista de SKUs

400 produtos importados do fornecedor com a aba Descrição vazia. Um wp eval-file percorre os SKUs sem texto, grava pelo…

20 horas atrás

Frete grátis no WooCommerce: esconder as outras opções de entrega

Some com PAC e SEDEX da lista quando o frete grátis está disponível, usando woocommerce_package_rates, e limpe o cache de…

1 dia atrás

Erro HTTP no WordPress ao enviar imagem para a biblioteca de mídia

A barra de upload chega no fim e o WordPress devolve só "Erro HTTP". Separe as três causas: Imagick barrado…

2 dias atrás

style amp-custom acima de 75KB: como cortar o CSS inline do AMP

The author stylesheet specified in tag 'style amp-custom' is too long? Meça o bloco com curl e tire da fila…

2 dias atrás

Creation of dynamic property: deprecated no PHP 8.3 com WordPress 6.9

debug.log crescendo em gigabytes com avisos de propriedade dinâmica. Veja como isolar o plugin culpado, corrigir a classe e silenciar…

3 dias atrás