How to Use systemd Timers Instead of Cron in Debian 12 Bookworm
Categories:
5 minute read
In traditional Unix-like systems, the cron utility has long been the standard way to schedule recurring tasks. While cron
is simple and effective, systemd timers provide a more modern, flexible, and powerful alternative, especially in systems where systemd
is the default init system — such as Debian 12 Bookworm.
In this article, we’ll explore how to replace cron jobs with systemd
timers, understand how they work, and provide practical examples to help you adopt this method confidently on your Debian 12 system.
Why Use systemd
Timers Over Cron?
Before diving into configuration, let’s look at some advantages of using systemd
timers over traditional cron:
- Better logging:
systemd
integrates withjournald
, providing centralized and detailed logs. - Dependency management: Timers can be linked to other
systemd
services, allowing complex orchestration. - Accurate scheduling:
systemd
timers allow monotonic time-based execution and calendar-based events. - Job tracking: You can check when a job last ran, when it will run again, and if it failed.
- User-based timers: Like
cron
, users can set up timers without needing superuser privileges.
Step-by-Step Guide: Replacing Cron with systemd
Timers
Let’s walk through replacing a cron job with a systemd timer. We’ll start from scratch.
Example Task: Log the Current Date Every Hour
We’ll simulate a cron job that logs the current date and time to a file every hour.
Step 1: Create a systemd
Service Unit
Unlike cron jobs, systemd
separates the action (what to do) and the schedule (when to do it). First, we’ll define a service that executes the command.
Create a new service file, e.g., /etc/systemd/system/log-date.service
.
[Unit]
Description=Log current date and time to /var/log/date.log
[Service]
Type=oneshot
ExecStart=/usr/bin/date >> /var/log/date.log
Explanation:
Type=oneshot
: This tellssystemd
that the command runs once and exits.ExecStart
: Specifies the command to run. In this case, we append the current date to a log file.
Step 2: Create the Timer Unit
Now let’s create the timer file: /etc/systemd/system/log-date.timer
.
[Unit]
Description=Run log-date.service every hour
[Timer]
OnCalendar=hourly
Persistent=true
[Install]
WantedBy=timers.target
Explanation:
OnCalendar=hourly
: This schedules the job to run at the start of every hour. You can customize this to your needs (more on that later).Persistent=true
: Ensures that the job runs immediately on boot if it was missed while the system was off.WantedBy=timers.target
: Ensures the timer starts automatically on boot when enabled.
Step 3: Enable and Start the Timer
To activate the timer, run the following:
sudo systemctl daemon-reload
sudo systemctl enable --now log-date.timer
Check if the timer is active:
systemctl list-timers
This will display all active timers, their last and next runtime, and associated service units.
Step 4: View Logs
One major advantage of systemd
timers is access to detailed logs:
journalctl -u log-date.service
This shows output and errors from the last runs of the service.
Using User-Level Timers
Just like crontab -e
allows individual users to set up cron jobs, users can also manage their own timers.
Here’s how a non-root user can create a timer:
- Create directories (if they don’t exist):
mkdir -p ~/.config/systemd/user
- Create a service file, e.g.,
~/.config/systemd/user/mytask.service
:
[Unit]
Description=User task example
[Service]
Type=oneshot
ExecStart=/usr/bin/notify-send "Time to take a break!"
- Create a timer file, e.g.,
~/.config/systemd/user/mytask.timer
:
[Unit]
Description=Notify break time every 2 hours
[Timer]
OnUnitActiveSec=2h
Unit=mytask.service
[Install]
WantedBy=default.target
- Reload user systemd daemon and enable the timer:
systemctl --user daemon-reexec
systemctl --user enable --now mytask.timer
- View user timers:
systemctl --user list-timers
Note: Ensure your user session is enabled for lingering if you want timers to persist outside login sessions:
sudo loginctl enable-linger yourusername
Customizing Timer Schedules
systemd
timers provide powerful scheduling options beyond cron:
Examples of OnCalendar
Values
Timer Expression | Description |
---|---|
OnCalendar=daily | Every day at midnight |
OnCalendar=weekly | Every week on Monday at 00:00 |
OnCalendar=monthly | First day of the month at 00:00 |
OnCalendar=*-*-01 12:00 | Every month on the 1st at noon |
OnCalendar=Mon *-*-* 09:00 | Every Monday at 9am |
OnCalendar=2025-05-01 10:00:00 | One-time run on May 1, 2025 at 10am |
You can even specify multiple schedules:
OnCalendar=Mon,Fri 12:00
Comparing Cron vs systemd Timers
Feature | cron | systemd timers |
---|---|---|
Logging | Limited, needs manual setup | Built-in with journald |
Syntax | Crontab-specific syntax | Human-readable OnCalendar |
Dependencies | None | Can depend on services or other units |
Missed Jobs | Skipped | Can run missed jobs on boot |
User Access | Yes (with crontab ) | Yes (with --user ) |
Timer Types | Time-based only | Time-based and monotonic |
Job Status | No built-in status tracking | systemctl list-timers shows all |
Tips and Best Practices
- Test your service manually before enabling the timer:
sudo systemctl start log-date.service
Use
Persistent=true
for important tasks that must run even if the system was off during the scheduled time.Use monotonic timers (
OnBootSec
,OnActiveSec
) for tasks relative to system uptime (e.g., post-boot actions).Use descriptive unit names and place them in
/etc/systemd/system/
or~/.config/systemd/user/
depending on system or user context.
Disabling and Removing Timers
To disable and stop a timer:
sudo systemctl disable --now log-date.timer
To completely remove it:
sudo rm /etc/systemd/system/log-date.timer
sudo rm /etc/systemd/system/log-date.service
sudo systemctl daemon-reload
Conclusion
While cron remains a simple and widely-used tool for scheduling, systemd
timers offer a modern, integrated, and highly configurable approach, especially for Debian 12 Bookworm users. They provide better logging, more readable time expressions, and native integration with the rest of the systemd
ecosystem.
Once you get comfortable with the structure of .service
and .timer
files, you’ll find that systemd
timers are not only powerful but often easier to manage and troubleshoot than traditional cron jobs.
So the next time you’re writing a script to run on a schedule — whether every 10 minutes or every Monday — consider giving systemd
timers a try.
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.