Skip to main content

Practical Examples

Learning Focus

This page contains 27 complete examples, each with the .timer unit, the .service unit, activation commands, and expected output. Every example is copy-paste-ready.

How To Use This Page
  • Examples are grouped by schedule frequency — jump to the pattern you need.
  • Each example includes systemd-analyze calendar validation where applicable.
  • Adapt User=, paths, and scripts to your environment.

Every Minute

1. Health Check (Every Minute)

/etc/systemd/system/health-check.service
[Unit]
Description=Lightweight health check

[Service]
Type=oneshot
ExecStart=/usr/local/bin/health-check.sh
StandardOutput=append:/var/log/health-check.log
StandardError=append:/var/log/health-check.log
/etc/systemd/system/health-check.timer
[Unit]
Description=Run health check every minute

[Timer]
OnCalendar=minutely
Persistent=true

[Install]
WantedBy=timers.target
activate.sh
sudo systemctl daemon-reload
sudo systemctl enable --now health-check.timer
systemctl list-timers health-check.timer --no-pager
expected-output.txt
NEXT LEFT LAST PASSED UNIT ACTIVATES
Mon 2026-03-02 00:01:00 UTC 38s left Mon 2026-03-02 00:00:01 UTC 21s ago health-check.timer health-check.service

Every 5–30 Minutes

2. Disk Monitoring (Every 5 Minutes)

/etc/systemd/system/disk-check.service
[Unit]
Description=Disk usage alert

[Service]
Type=oneshot
ExecStart=/usr/local/bin/disk-alert.sh
StandardOutput=append:/var/log/disk-alert.log
StandardError=append:/var/log/disk-alert.log
/etc/systemd/system/disk-check.timer
[Unit]
Description=Check disk usage every 5 minutes

[Timer]
OnCalendar=*:0/5
Persistent=true

[Install]
WantedBy=timers.target
validate.sh
systemd-analyze calendar --iterations=3 '*:0/5'
expected-output.txt
Next elapse: Mon 2026-03-02 00:05:00 UTC
Iter. #2: Mon 2026-03-02 00:10:00 UTC
Iter. #3: Mon 2026-03-02 00:15:00 UTC

3. WordPress Cron Runner (Every 15 Minutes)

Replaces the default wp-cron.php page-visit trigger. Requires define('DISABLE_WP_CRON', true); in wp-config.php.

/etc/systemd/system/wp-cron-runner.service
[Unit]
Description=Run due WordPress cron events

[Service]
Type=oneshot
User=www-data
WorkingDirectory=/var/www/html
ExecStart=/usr/local/bin/wp cron event run --due-now --path=/var/www/html
StandardOutput=append:/var/log/wp-cron.log
StandardError=append:/var/log/wp-cron.log
/etc/systemd/system/wp-cron-runner.timer
[Unit]
Description=Trigger WordPress cron events every 15 minutes

[Timer]
OnCalendar=*:0/15
Persistent=true

[Install]
WantedBy=timers.target

4. CDN Sync (Every 30 Minutes)

/etc/systemd/system/cdn-sync.service
[Unit]
Description=Sync static assets to CDN

[Service]
Type=oneshot
User=www-data
ExecStart=/usr/local/bin/sync-cdn.sh
StandardOutput=append:/var/log/cdn-sync.log
/etc/systemd/system/cdn-sync.timer
[Unit]
Description=Sync CDN every 30 minutes

[Timer]
OnCalendar=*:0/30
Persistent=true

[Install]
WantedBy=timers.target

Hourly

5. Hourly Server Report

/etc/systemd/system/hourly-report.service
[Unit]
Description=Generate hourly server summary

[Service]
Type=oneshot
ExecStart=/usr/local/bin/hourly-report.sh
/etc/systemd/system/hourly-report.timer
[Unit]
Description=Hourly report

[Timer]
OnCalendar=hourly
Persistent=true

[Install]
WantedBy=timers.target

6. Media Sync to Object Storage (Every 2 Hours)

/etc/systemd/system/media-sync.service
[Unit]
Description=Sync uploads to object storage

[Service]
Type=oneshot
User=www-data
ExecStart=/usr/local/bin/rclone sync /var/www/html/wp-content/uploads remote:wp-uploads
StandardOutput=append:/var/log/media-sync.log
/etc/systemd/system/media-sync.timer
[Unit]
Description=Sync media to object storage every 2 hours

[Timer]
OnCalendar=*-*-* 0/2:00:00
Persistent=true

[Install]
WantedBy=timers.target

7. Cache Flush (Every 6 Hours)

/etc/systemd/system/wp-cache-flush.service
[Unit]
Description=Flush WordPress object cache

[Service]
Type=oneshot
User=www-data
WorkingDirectory=/var/www/html
ExecStart=/usr/local/bin/wp cache flush --path=/var/www/html
StandardOutput=append:/var/log/wp-cache-flush.log
/etc/systemd/system/wp-cache-flush.timer
[Unit]
Description=Flush WordPress object cache every 6 hours

[Timer]
OnCalendar=*-*-* 00/6:00:00
Persistent=true

[Install]
WantedBy=timers.target

Daily

8. WordPress Nightly Backup (2:15 AM)

/etc/systemd/system/wp-backup.service
[Unit]
Description=WordPress nightly backup
After=network-online.target
Wants=network-online.target

[Service]
Type=oneshot
User=www-data
Group=www-data
WorkingDirectory=/var/www/html
ExecStart=/usr/bin/flock -n /var/lock/wp-backup.lock /usr/local/bin/wp-backup.sh
StandardOutput=append:/var/log/wp-backup.log
StandardError=append:/var/log/wp-backup.log
RuntimeMaxSec=2h
/etc/systemd/system/wp-backup.timer
[Unit]
Description=Run WordPress backup nightly at 02:15

[Timer]
OnCalendar=02:15
Persistent=true
RandomizedDelaySec=5m
AccuracySec=1m

[Install]
WantedBy=timers.target
activate.sh
sudo systemctl daemon-reload
sudo systemctl enable --now wp-backup.timer
sudo systemctl start wp-backup.service # Test run immediately
journalctl -u wp-backup.service -n 20 --no-pager
expected-output.txt
Mar 02 02:15:07 vps wp-backup.sh[1201]: [2026-03-02T02:15:07] Backup started
Mar 02 02:15:42 vps wp-backup.sh[1201]: [2026-03-02T02:15:42] Database exported: 145M
Mar 02 02:16:10 vps wp-backup.sh[1201]: [2026-03-02T02:16:10] Archive created: wp-backup-2026-03-02.tar.gz
Mar 02 02:16:10 vps wp-backup.sh[1201]: [2026-03-02T02:16:10] Done.

9. Log Rotation (Midnight)

/etc/systemd/system/force-logrotate.service
[Unit]
Description=Force logrotate run

[Service]
Type=oneshot
ExecStart=/usr/sbin/logrotate /etc/logrotate.conf
/etc/systemd/system/force-logrotate.timer
[Unit]
Description=Force logrotate daily at midnight

[Timer]
OnCalendar=daily
Persistent=true

[Install]
WantedBy=timers.target

10. Uptime Check (Twice Daily — 9 AM and 9 PM)

/etc/systemd/system/uptime-check.timer
[Unit]
Description=Uptime check twice daily

[Timer]
OnCalendar=09,21:00
Persistent=true

[Install]
WantedBy=timers.target
validate.sh
systemd-analyze calendar --iterations=4 '09,21:00'
expected-output.txt
Next elapse: Mon 2026-03-02 09:00:00 UTC
Iter. #2: Mon 2026-03-02 21:00:00 UTC
Iter. #3: Tue 2026-03-03 09:00:00 UTC
Iter. #4: Tue 2026-03-03 21:00:00 UTC

11. Database Export (Daily at 2:30 AM with Lock)

/etc/systemd/system/wp-db-backup.service
[Unit]
Description=WordPress database export

[Service]
Type=oneshot
User=www-data
ExecStart=/usr/bin/flock -n /var/lock/wp-db-backup.lock /usr/local/bin/wp db export /mnt/backups/wp-db.sql --path=/var/www/html
RuntimeMaxSec=1h
StandardOutput=append:/var/log/wp-db-backup.log
StandardError=append:/var/log/wp-db-backup.log
/etc/systemd/system/wp-db-backup.timer
[Unit]
Description=WordPress DB export daily at 02:30

[Timer]
OnCalendar=02:30
Persistent=true
RandomizedDelaySec=5m

[Install]
WantedBy=timers.target

12. Backup Retention Purge (Daily at 4 AM)

/etc/systemd/system/backup-prune.service
[Unit]
Description=Prune backup files older than 14 days

[Service]
Type=oneshot
ExecStart=/usr/bin/find /mnt/backups -name "*.sql" -mtime +14 -delete
StandardOutput=append:/var/log/backup-prune.log
/etc/systemd/system/backup-prune.timer
[Unit]
Description=Prune old backups daily at 04:00

[Timer]
OnCalendar=04:00
Persistent=true

[Install]
WantedBy=timers.target

13. Peak-Hours Cache Warming (8 AM – 8 PM, Every 10 Minutes)

/etc/systemd/system/cache-warm.service
[Unit]
Description=Warm WordPress page cache

[Service]
Type=oneshot
User=www-data
ExecStart=/usr/local/bin/cache-warm.sh
/etc/systemd/system/cache-warm.timer
[Unit]
Description=Warm cache every 10 minutes during peak hours

[Timer]
OnCalendar=*-*-* 08..20:0/10
Persistent=false

[Install]
WantedBy=timers.target
validate.sh
systemd-analyze calendar --iterations=5 '*-*-* 08..20:0/10'
expected-output.txt
Next elapse: Mon 2026-03-02 08:00:00 UTC
Iter. #2: Mon 2026-03-02 08:10:00 UTC
Iter. #3: Mon 2026-03-02 08:20:00 UTC
Iter. #4: Mon 2026-03-02 08:30:00 UTC
Iter. #5: Mon 2026-03-02 08:40:00 UTC

14. SSL Certificate Renewal (Daily 3 AM with Fleet Jitter)

/etc/systemd/system/certbot-renew.service
[Unit]
Description=Renew TLS certificates with Certbot

[Service]
Type=oneshot
ExecStart=/usr/bin/certbot renew --quiet --deploy-hook "systemctl reload nginx"
StandardOutput=append:/var/log/certbot.log
StandardError=append:/var/log/certbot.log
/etc/systemd/system/certbot-renew.timer
[Unit]
Description=Daily certbot renewal with stable fleet jitter

[Timer]
OnCalendar=03:00
Persistent=true
RandomizedDelaySec=30m
FixedRandomDelay=true
AccuracySec=1m

[Install]
WantedBy=timers.target

Certbot only renews if expiry is within 30 days. The --deploy-hook reloads Nginx only when a renewal happens.


Weekly

15. Business Digest (Weekdays at 6 AM)

/etc/systemd/system/daily-digest.service
[Unit]
Description=Send daily business digest

[Service]
Type=oneshot
ExecStart=/usr/local/bin/send-digest.sh
/etc/systemd/system/daily-digest.timer
[Unit]
Description=Business digest on weekdays at 6 AM

[Timer]
OnCalendar=Mon..Fri 06:00
Persistent=true

[Install]
WantedBy=timers.target

16. Weekly WordPress Cleanup (Monday 3 AM)

/etc/systemd/system/weekly-cleanup.service
[Unit]
Description=Weekly WordPress cleanup and optimization

[Service]
Type=oneshot
User=www-data
ExecStart=/usr/local/bin/wp-weekly-cleanup.sh
StandardOutput=append:/var/log/weekly-cleanup.log
/etc/systemd/system/weekly-cleanup.timer
[Unit]
Description=Weekly cleanup every Monday at 03:00

[Timer]
OnCalendar=Mon 03:00
Persistent=true
RandomizedDelaySec=10m

[Install]
WantedBy=timers.target

Use case: wp db optimize, delete old revisions, clear transients.


17. Saturday Maintenance Window (2 AM)

/etc/systemd/system/maintenance.service
[Unit]
Description=Weekly maintenance (heavier tasks)

[Service]
Type=oneshot
ExecStart=/usr/local/bin/maintenance.sh
RuntimeMaxSec=3h
StandardOutput=append:/var/log/maintenance.log
/etc/systemd/system/maintenance.timer
[Unit]
Description=Run heavy maintenance on Saturday at 02:00

[Timer]
OnCalendar=Sat 02:00
Persistent=true
RandomizedDelaySec=15m

[Install]
WantedBy=timers.target

Use case: Full backup, database vacuum, PHP-FPM restart, plugin update dry-run.


Monthly and Beyond

18. Bimonthly Report (1st and 15th at 4 AM)

/etc/systemd/system/bimonthly-report.timer
[Unit]
Description=Bimonthly report on 1st and 15th

[Timer]
OnCalendar=*-*-01,15 04:00:00
Persistent=true

[Install]
WantedBy=timers.target
validate.sh
systemd-analyze calendar --iterations=4 '*-*-01,15 04:00:00'
expected-output.txt
Next elapse: Sun 2026-03-15 04:00:00 UTC
Iter. #2: Wed 2026-04-01 04:00:00 UTC
Iter. #3: Wed 2026-04-15 04:00:00 UTC
Iter. #4: Fri 2026-05-01 04:00:00 UTC

19. Monthly Report (1st of Month)

/etc/systemd/system/monthly-report.timer
[Unit]
Description=Monthly server report

[Timer]
OnCalendar=monthly
Persistent=true

[Install]
WantedBy=timers.target

20. Quarterly Billing Export

/etc/systemd/system/quarterly-export.timer
[Unit]
Description=Quarterly billing data export

[Timer]
OnCalendar=quarterly
Persistent=true

[Install]
WantedBy=timers.target
validate.sh
systemd-analyze calendar --iterations=4 'quarterly'
expected-output.txt
Next elapse: Wed 2026-04-01 00:00:00 UTC
Iter. #2: Wed 2026-07-01 00:00:00 UTC
Iter. #3: Thu 2026-10-01 00:00:00 UTC
Iter. #4: Fri 2027-01-01 00:00:00 UTC

21. Last Day of Every Month

/etc/systemd/system/month-end-rollup.timer
[Unit]
Description=Month-end data rollup

[Timer]
OnCalendar=*-*~1 00:00:00
Persistent=true

[Install]
WantedBy=timers.target
validate.sh
systemd-analyze calendar --iterations=3 '*-*~1 00:00:00'
expected-output.txt
Next elapse: Tue 2026-03-31 00:00:00 UTC
Iter. #2: Thu 2026-04-30 00:00:00 UTC
Iter. #3: Sun 2026-05-31 00:00:00 UTC

22. First Monday of Each Month

/etc/systemd/system/monthly-first-monday.timer
[Unit]
Description=First Monday of each month at 03:00

[Timer]
OnCalendar=Mon *-*-1..7 03:00:00
Persistent=true

[Install]
WantedBy=timers.target

23. Annual Cleanup (January 1)

/etc/systemd/system/annual-cleanup.timer
[Unit]
Description=Annual cleanup on January 1

[Timer]
OnCalendar=yearly
Persistent=true

[Install]
WantedBy=timers.target

Boot and Monotonic

24. Post-Boot Startup Task (2 Minutes After Boot)

/etc/systemd/system/startup-task.service
[Unit]
Description=One-time startup initialization task

[Service]
Type=oneshot
ExecStart=/usr/local/bin/post-boot-setup.sh
RemainAfterExit=yes
/etc/systemd/system/startup-task.timer
[Unit]
Description=Run startup task 2 minutes after boot

[Timer]
OnBootSec=2min

[Install]
WantedBy=timers.target

25. Boot Then Recurring Hourly (Heartbeat)

/etc/systemd/system/heartbeat.timer
[Unit]
Description=Run heartbeat 30s after boot, then every hour

[Timer]
OnBootSec=30s
OnUnitActiveSec=1h

[Install]
WantedBy=timers.target

26. Cooldown Retry (20 Minutes After Completion)

/etc/systemd/system/retry-worker.timer
[Unit]
Description=Retry worker 20 minutes after each run completes

[Timer]
OnUnitInactiveSec=20m

[Install]
WantedBy=timers.target

"Next run starts 20 minutes after the previous run finished, not 20 minutes after it started."


Advanced

27. User-Level Timer (No Root Required)

~/.config/systemd/user/personal-backup.service
[Unit]
Description=Personal file backup

[Service]
Type=oneshot
ExecStart=%h/bin/backup-home.sh
StandardOutput=append:%h/logs/backup.log
~/.config/systemd/user/personal-backup.timer
[Unit]
Description=Personal backup every 6 hours

[Timer]
OnCalendar=*-*-* 00/6:00:00
Persistent=true

[Install]
WantedBy=default.target
activate-user-timer.sh
systemctl --user daemon-reload
systemctl --user enable --now personal-backup.timer
sudo loginctl enable-linger "$USER"
systemctl --user list-timers --no-pager

Example Quick Reference

#PatternScheduleKey Feature
1Health checkminutelyHigh-frequency polling
2Disk alert*:0/5Step-based interval
3WP cron*:0/15Replaces wp-cron.php
4CDN sync*:0/30Periodic sync
5Hourly reporthourlyKeyword shortcut
6Media sync0/2:00:00Multi-hour interval
7Cache flush00/6:00:004x daily
8WP backup02:15flock + RuntimeMaxSec
9Log rotationdailyKeyword shortcut
10Uptime check09,21:00List operator
11DB export02:30flock + jitter
12Backup purge04:00find + delete retention
13Cache warming08..20:0/10Range + step
14Certbot03:00FixedRandomDelay fleet
15Business digestMon..Fri 06:00Range operator
16Weekly cleanupMon 03:00WP optimize
17MaintenanceSat 02:00Heavy weekend window
18Bimonthly*-*-01,15 04:00Day list
19Monthly reportmonthlyKeyword
20QuarterlyquarterlyKeyword
21Month-end*-*~1 00:00Tilde (last day)
22First MondayMon *-*-1..7 03:00Range + day-of-week
23AnnualyearlyKeyword
24Post-bootOnBootSec=2minOne-shot startup
25Boot+recurringOnBootSec=30s + OnUnitActiveSec=1hCombined
26Cooldown retryOnUnitInactiveSec=20mGap after completion
27User timer00/6:00:00 + lingerNo root, %h specifier

What's Next

  • Production Patterns — hardening, flock overlap prevention, Persistent, jitter, and fleet safety.