Commands and Management
By the end of this lesson you will be fluent in every command needed to manage timer units — from creation to cleanup, including schedule validation, log inspection, user timers, and bulk operations.
Standard Workflow
Every time you create or modify a timer unit, follow this sequence:
# 1. Create/edit the .timer and .service files
sudo nano /etc/systemd/system/myjob.timer
sudo nano /etc/systemd/system/myjob.service
# 2. Tell systemd to re-read unit files
sudo systemctl daemon-reload
# 3. Enable on boot and start now
sudo systemctl enable --now myjob.timer
# 4. Verify it appears in the timer list
systemctl list-timers myjob.timer --no-pager
# 5. Test the service manually
sudo systemctl start myjob.service
# 6. Check logs
journalctl -u myjob.service -n 20 --no-pager
systemctl — Timer Management
Starting and Stopping
| Command | Description |
|---|---|
sudo systemctl start myjob.timer | Start the timer immediately |
sudo systemctl stop myjob.timer | Stop the timer (won't disable on boot) |
sudo systemctl restart myjob.timer | Stop and restart the timer |
Enabling and Disabling
| Command | Description |
|---|---|
sudo systemctl enable myjob.timer | Enable on boot (does not start) |
sudo systemctl enable --now myjob.timer | Enable on boot AND start now |
sudo systemctl disable myjob.timer | Disable on boot (does not stop) |
sudo systemctl disable --now myjob.timer | Disable AND stop |
.timer, NOT the .serviceAlways enable the .timer, never the .service. Enabling the service directly would run it once at boot — not on a schedule.
# ✅ Correct
sudo systemctl enable --now myjob.timer
# ❌ Wrong — runs once at boot, no scheduling
sudo systemctl enable --now myjob.service
Checking Status
| Command | Description |
|---|---|
systemctl status myjob.timer --no-pager | Timer status: next run, last trigger |
systemctl status myjob.service --no-pager | Service result: exit code, output |
systemctl is-active myjob.timer | Returns active or inactive |
systemctl is-enabled myjob.timer | Returns enabled or disabled |
# Check when it will next fire
systemctl status myjob.timer --no-pager
# Check what happened on the last run
systemctl status myjob.service --no-pager
# Quick check in scripts
if systemctl is-active --quiet myjob.timer; then
echo "Timer is running"
fi
Reloading
| Command | Description |
|---|---|
sudo systemctl daemon-reload | Re-read all unit files from disk |
If you edit a unit file and forget daemon-reload, systemd uses the old version. This is the #1 cause of "I changed the config but nothing happened."
Listing and Discovery
List All Timers
# List all timers with their schedule info
systemctl list-timers --all --no-pager
NEXT LEFT LAST PASSED UNIT ACTIVATES
Mon 2026-03-02 02:15:00 UTC 2h 14min left Sun 2026-03-01 02:15:03 UTC 21h ago wp-backup.timer wp-backup.service
Mon 2026-03-02 00:05:00 UTC 4min left Mon 2026-03-02 00:00:01 UTC 58s ago health-check.timer health-check.service
Mon 2026-03-02 03:00:00 UTC 2h 59min left Sun 2026-03-01 03:01:15 UTC 20h ago certbot-renew.timer certbot-renew.service
Column meanings:
| Column | Meaning |
|---|---|
| NEXT | Next scheduled fire time |
| LEFT | Time remaining until NEXT |
| LAST | Last time the timer fired |
| PASSED | Time since LAST |
| UNIT | The timer unit name |
| ACTIVATES | The service it triggers |
List Enabled Timers
systemctl list-unit-files --type=timer --state=enabled
Show Timer Properties
# Machine-readable properties (for scripting)
systemctl show myjob.timer -p NextElapseUSecRealtime -p LastTriggerUSec -p Unit -p Triggers
# Show the unit file content
systemctl cat myjob.timer
systemctl cat myjob.service
# Show where the unit file is stored
systemctl show -p FragmentPath myjob.timer
Show Dependencies
systemctl list-dependencies myjob.timer
systemctl show -p Triggers myjob.timer
Testing the Service Immediately
# Run the service without waiting for the timer
sudo systemctl start myjob.service
# Check the result
journalctl -u myjob.service -n 20 --no-pager
systemd-analyze — Schedule Validation
Validate OnCalendar Expressions
# Show the next 5 fire times
systemd-analyze calendar --iterations=5 'Mon..Fri 06:00'
# Validate common patterns
systemd-analyze calendar --iterations=3 'daily'
systemd-analyze calendar --iterations=3 '*:0/5'
systemd-analyze calendar --iterations=3 '*-*~1 00:00:00'
systemd-analyze calendar --iterations=5 '09,21:00'
systemd-analyze calendar --iterations=3 '*-*-* 08..20:0/10'
Verify Unit Files
sudo systemd-analyze verify /etc/systemd/system/myjob.timer
sudo systemd-analyze verify /etc/systemd/system/myjob.service
# Verify both at once
sudo systemd-analyze verify /etc/systemd/system/myjob.{timer,service}
No output means no errors. Errors print the exact line and directive:
/etc/systemd/system/myjob.timer:5: Unknown key 'OnCalander' in section 'Timer'
Security Audit
systemd-analyze security myjob.service
Score: 0.0 = fully sandboxed, 10.0 = no sandboxing. Aim for below 3.0.
Boot Impact
systemd-analyze blame | grep timer
systemd-analyze critical-chain timers.target
journalctl — Log Management
Service Logs (Most Important)
The .service produces the real output. The .timer only logs activation events.
| Command | Description |
|---|---|
journalctl -u myjob.service | All logs from the service |
journalctl -u myjob.service -n 50 | Last 50 lines |
journalctl -u myjob.service -f | Follow live output (like tail -f) |
journalctl -u myjob.service --since "1 hour ago" | Logs from the last hour |
journalctl -u myjob.service --since today | Today's logs |
journalctl -u myjob.service --since "2026-03-01" --until "2026-03-02" | Date range |
journalctl -u myjob.service -o json-pretty | JSON format |
journalctl -u myjob.service -p err | Errors only |
Timer Logs
# When the timer fired
journalctl -u myjob.timer --since today --no-pager
Combined View
# Both timer and service logs, interleaved by time
journalctl -u myjob.timer -u myjob.service --since today --no-pager
Log Priority Levels
| Level | Flag | Meaning |
|---|---|---|
| Emergency | -p emerg | System unusable |
| Alert | -p alert | Immediate action required |
| Critical | -p crit | Critical conditions |
| Error | -p err | Error conditions |
| Warning | -p warning | Warning conditions |
| Notice | -p notice | Normal but significant |
| Info | -p info | Informational |
| Debug | -p debug | Debug-level |
User Timer Management
User timers run without root privileges:
| Command | Description |
|---|---|
systemctl --user daemon-reload | Reload user unit files |
systemctl --user enable --now myjob.timer | Enable and start user timer |
systemctl --user disable --now myjob.timer | Disable and stop user timer |
systemctl --user status myjob.timer | Check status |
systemctl --user list-timers --no-pager | List user timers |
journalctl --user -u myjob.service | View user service logs |
mkdir -p ~/.config/systemd/user/
# Place .timer and .service in ~/.config/systemd/user/
systemctl --user daemon-reload
systemctl --user enable --now my-timer.timer
Persistence After Logout
# Keep user timers running after logout
sudo loginctl enable-linger "$USER"
# Check status
loginctl show-user "$USER" | grep Linger
# Disable
sudo loginctl disable-linger "$USER"
Persistent State Management
# Clear stored timer state (reset Persistent catch-up tracking)
sudo systemctl clean --what=state myjob.timer
# Show timer timestamps (last trigger, next elapse)
systemctl show myjob.timer -p LastTriggerUSec -p NextElapseUSecRealtime
Bulk Operations
Enable Multiple Timers
for unit in /etc/systemd/system/*.timer; do
name=$(basename "$unit")
sudo systemctl enable --now "$name"
done
Health Check All Timers
systemctl list-timers --all --no-pager --no-legend | while read -r next left last passed unit activates rest; do
echo "=== $unit ==="
systemctl status "$unit" --no-pager 2>/dev/null | head -5
echo
done
Full Cleanup
sudo systemctl disable --now myjob.timer
sudo rm /etc/systemd/system/myjob.timer
sudo rm /etc/systemd/system/myjob.service
sudo systemctl daemon-reload
sudo systemctl reset-failed
Quick Command Reference
| Task | Command |
|---|---|
| Reload unit files | sudo systemctl daemon-reload |
| Start timer | sudo systemctl start myjob.timer |
| Stop timer | sudo systemctl stop myjob.timer |
| Enable + start | sudo systemctl enable --now myjob.timer |
| Disable + stop | sudo systemctl disable --now myjob.timer |
| Check timer status | systemctl status myjob.timer --no-pager |
| Check service result | systemctl status myjob.service --no-pager |
| List all timers | systemctl list-timers --all --no-pager |
| Follow live logs | journalctl -u myjob.service -f |
| Last N log lines | journalctl -u myjob.service -n 50 |
| Errors only | journalctl -u myjob.service -p err |
| Validate schedule | systemd-analyze calendar --iterations=5 'EXPR' |
| Verify unit syntax | sudo systemd-analyze verify myjob.timer |
| Show unit content | systemctl cat myjob.timer |
| Test service now | sudo systemctl start myjob.service |
| Security audit | systemd-analyze security myjob.service |
| Reset timer state | sudo systemctl clean --what=state myjob.timer |
| Reset failed | sudo systemctl reset-failed |
Key Takeaways
- Always
daemon-reloadafter editing unit files. - Enable the
.timer, not the.service. - Use
systemd-analyze calendarto validate every schedule before deploying. - Use
systemd-analyze verifyto catch syntax errors before runtime. - Check both
.timerstatus (next/last run) and.servicestatus (exit code, logs). - Use
systemctl list-timers --allfor a system-wide overview. - User timers need
loginctl enable-lingerfor persistence after logout.
What's Next
- Practical Examples — 27 complete, copy-paste-ready examples covering every timer pattern.