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.