To verify that a custom systemd timer loads and executes correctly on Debian 10, you must first ensure the associated service unit is valid and enabled. Use
systemctl list-timers to check if the timer appears in the active schedule, and run
systemctl status <timer-name> for detailed runtime logs. If the timer does not trigger, inspect the journal with
journalctl -u <service-name> to identify permission errors or missing dependencies that prevent execution.
Creating the Service and Timer Units
Before troubleshooting, it is essential to have properly configured unit files. A systemd timer relies on a companion service file to define what action to perform. Create a service file, such as
<name>.service, in
/etc/systemd/system/. This file should specify the executable script or command under the
[Service] section. For example:
[Unit]
Description=My Custom Task
[Service]
Type=oneshot
ExecStart=/usr/local/bin/my-script.sh
Next, create the corresponding timer file,
<name>.timer, in the same directory. The timer defines when the service runs. You can use
OnCalendar= for specific times or
OnUnitActiveSec= for relative intervals. Ensure the
WantedBy=timers.target line is present in the
[Install] section to enable the timer.
[Unit]
Description=Run My Custom Task Daily
[Timer]
OnCalendar=*-*-* 02:00:00
Persistent=true
[Install]
WantedBy=timers.target
After creating these files, reload the systemd daemon using
sudo systemctl daemon-reload. Then, enable both the service and the timer:
sudo systemctl enable my-script.service
sudo systemctl enable my-script.timer
Enabling the timer starts it immediately. You can confirm it is running by checking its status. If you need to manage dependencies between services, consider reviewing how to restart systemd service dependencies effectively.
Verifying Timer Activation
The most direct way to check if your timer is loaded is to list all active timers. Run the following command:
systemctl list-timers --all
This output shows the next activation time, last activation time, and unit name for each timer. Look for your custom timer in this list. If it is missing, the timer was not enabled correctly, or there is a syntax error in the unit file. The
--all flag ensures you see disabled timers as well, which helps diagnose configuration issues.
You can also get detailed information about a specific timer:
systemctl status my-script.timer
This command displays whether the timer is active (running) or inactive (dead). It also shows recent log entries related to the timer unit. If the timer is active but not triggering, proceed to check the service logs.
Checking Service Execution Logs
Even if the timer is active, the service might fail to execute due to script errors or permission issues. Use the journal to view logs for the service:
journalctl -u my-script.service -f
The
-f flag follows the log in real-time. Trigger the timer manually by running:
systemctl start my-script.service
Then observe the journal output. If the script fails, the error messages will appear here. Common issues include incorrect paths in
ExecStart, lack of execute permissions on the script, or environment variables not being set. For more complex setups involving variables, refer to guides on expanding the use of variables in systemd service files.
If the service depends on other system resources, ensure those dependencies are met. Failure to start due to unmet dependencies is a frequent cause of silent failures.
Testing Manual Triggers
To isolate timing issues, disable the timer temporarily and run the service manually:
sudo systemctl stop my-script.timer
sudo systemctl start my-script.service
Check the exit status with
echo $?. A zero indicates success. If the script runs manually but not via the timer, the issue may be related to the environment context. Systemd timers run in a limited environment compared to user shells. Ensure absolute paths are used for all commands and scripts.
Also, verify that the timer is not masked. A masked unit cannot be started even if enabled. Check with:
systemctl is-enabled my-script.timer
It should return "enabled". If it returns "masked", unmask it with
sudo systemctl unmask my-script.timer.
Common Pitfalls and Fixes
Several common mistakes prevent timers from working. First, ensure the timer file has correct syntax. A single typo in
OnCalendar can disable the timer silently. Second, check file permissions. The service file should be readable by root, and the script should be executable. Third, avoid using
~ or
$HOME in unit files unless explicitly expanded, as systemd does not interpret shell expansions by default.
If you suspect conflicts with other system processes, review related system tasks. For instance, if your timer interacts with mounted drives, ensure shares are automatically mounted before the service runs. Refer to documentation on automatically mounting shares in Linux to resolve such dependency issues.
Finally, remember that systemd timers are precise. If you miss a scheduled run due to the system being off, the
Persistent=true option ensures the missed run occurs at the next boot. Always test changes in a staging environment before applying them to production systems.
Frequently Asked Questions
Why does my timer show as inactive in systemctl list-timers?
An inactive timer usually means it is not enabled or failed to start during boot. Verify that you ran
systemctl enable <timer-name> and that the unit file contains no syntax errors. Check
systemctl status <timer-name> for specific failure reasons.
How can I debug why my service script fails only when run by a timer?
Timers run in a restricted environment without user shell variables. Use absolute paths for all executables and scripts in the
ExecStart directive. Check
journalctl -u <service-name> for error messages that indicate missing files or permissions.
What does Persistent=true do in a timer unit?
The
Persistent=true setting ensures that if the system is powered off during a scheduled run, the timer will trigger the service immediately upon the next boot. This guarantees that periodic tasks are not skipped due to downtime.
Can I use relative time intervals like OnUnitActiveSec=5min?
Yes, you can use relative intervals such as
OnUnitActiveSec=5min or
OnBootSec=1min. These intervals reset after each successful activation or boot, respectively. They are useful for recurring tasks that do not need to align with clock time.
How do I force a timer to run immediately for testing?
You can manually trigger the associated service by running
systemctl start <service-name>. This bypasses the timer schedule and allows you to test the service logic directly. Remember to restart the timer afterward if you want normal scheduling to resume.