How to Replace Cron Jobs with systemd Timers on Linux
Learning how to replace cron jobs with systemd timers on Linux gives you a more powerful and reliable way to schedule tasks on your server. Cron has been the go-to scheduler for decades. It works fine for simple tasks. But systemd timers offer better logging, dependency management, and integration with the rest of your system. In this tutorial, you’ll learn how to create a service unit, write a timer unit, enable it, and verify it’s running correctly. By the end, you’ll be confident migrating your existing cron jobs to systemd timers. This guide is aimed at Linux server administrators who want more control over scheduled tasks. Whether you’re managing a WordPress server, a VPS, or a bare-metal machine, systemd timers can replace cron jobs cleanly and effectively.
Prerequisites for Replacing Cron Jobs with systemd Timers
Before you start, make sure you meet the following requirements.
Required access and software:
- A Linux system running systemd (Ubuntu 16.04+, Debian 8+, CentOS 7+, or similar)
- Root or sudo access to the server
- Basic familiarity with the terminal and text editors like
nanoorvim - An existing cron job you want to migrate (or a script you want to schedule)
Assumed knowledge:
You should know how to navigate the Linux filesystem. You should also understand what a cron job does. No prior systemd experience is required.
Estimated time: 20–30 minutes.
You can check whether systemd is running on your system with this command:
systemctl --version
If you see a version number, you’re ready to go. For deeper background on systemd, the official systemd project page is a great reference.
Step-by-Step Guide to Replacing Cron Jobs with systemd Timers
For a related walkthrough, see: How to Create a Wordpress Block Theme From Scratch Using the Create Block Theme Plugin
This section walks you through the full migration process. We’ll use a simple example: a backup script that runs every day at 2 AM.
Step 1: Identify your existing cron job
Open your crontab to find the job you want to migrate.
crontab -l
You might see something like this:
0 2 /usr/local/bin/backup.sh
Note the schedule and the script path. You’ll need both.
Step 2: Create the systemd service unit file
A systemd timer needs a matching service file. The service file defines what to run. Create it with your editor:
sudo nano /etc/systemd/system/backup.service
Add the following
[Unit]
Description=Daily Backup Script
[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh
User=root
The Type=oneshot setting tells systemd this is a task that runs and exits. It’s the right type for scripts that don’t run as daemons. Save and close the file.
Step 3: Create the systemd timer unit file
Now create the timer file. It must share the same base name as the service file.
sudo nano /etc/systemd/system/backup.timer
Add this
[Unit]
Description=Run Daily Backup at 2 AM
[Timer]
OnCalendar=-- 02:00:00
Persistent=true
[Install]
WantedBy=timers.target
The OnCalendar directive replaces your cron schedule. The Persistent=true option means the timer will run the missed job if the system was off at the scheduled time. This is a big advantage over cron.
Step 4: Reload the systemd daemon
After creating new unit files, you must reload systemd so it picks them up.
sudo systemctl daemon-reload
Always run this after adding or editing unit files.
Step 5: Enable and start the timer
Enable the timer so it starts automatically on boot. Then start it immediately.
sudo systemctl enable backup.timer
sudo systemctl start backup.timer
Note: you enable and start the timer, not the service. The timer triggers the service on schedule.
Step 6: Verify the timer is active
Check that your timer is running correctly.
sudo systemctl status backup.timer
You should see Active: active (waiting) in the output. To see all active timers on your system, run:
systemctl list-timers --all
This shows the next scheduled run time for every timer. It’s much more informative than crontab -l.
Step 7: Test the service manually
Before removing your old cron job, test the service directly.
sudo systemctl start backup.service
Then check the logs to confirm it ran successfully:
sudo journalctl -u backup.service
The journalctl man page explains all the filtering options available to you. This logging is one of the strongest reasons to replace cron jobs with systemd timers on Linux.
Step 8: Remove the old cron job
Once you’ve confirmed everything works, remove the original cron entry.
crontab -e
Delete the line for the job you migrated. Save and close. Your systemd timer is now fully in charge.
Troubleshooting Common systemd Timer Issues
Even straightforward setups can hit snags. Here are the most common problems and how to fix them.
Timer not triggering the service
Check that the timer and service filenames match exactly. A timer named backup.timer will only trigger backup.service. Any mismatch and nothing will run. Double-check with:
ls /etc/systemd/system/backup.
Service fails silently
Run the service manually and read the logs carefully.
sudo systemctl start backup.service
sudo journalctl -u backup.service -n 50
Look for permission errors or missing script paths. Make sure your script is executable:
sudo chmod +x /usr/local/bin/backup.sh
Timer shows wrong next run time
Your system timezone affects OnCalendar schedules. Check your current timezone:
timedatectl
If it’s wrong, set it correctly:
sudo timedatectl set-timezone America/New_York
Replace America/New_York with your actual timezone.
Daemon not reloaded after changes
If you edit a unit file and the changes don’t take effect, you probably forgot to reload. Always run sudo systemctl daemon-reload after any edit.
Tip: Use systemd-analyze calendar "-- 02:00:00" to validate your OnCalendar syntax before saving the timer file.
Conclusion
You now know how to replace cron jobs with systemd timers on Linux from start to finish. You created a service unit, wrote a timer unit, enabled it, tested it, and cleaned up the old cron entry. Systemd timers give you better logging through journald, catch missed runs with Persistent=true, and integrate cleanly with other system services. These advantages make the switch well worth the small extra effort. Your next step is to audit all your existing cron jobs and migrate them one by one. Start with simple, low-risk tasks to build confidence. Once you’re comfortable, you can explore advanced timer features like OnBootSec for post-boot delays and RandomizedDelaySec to spread load across your server. Systemd timers are a solid upgrade for any Linux administrator.
