UnderHost
Knowledgebase Docs

Scheduled Tasks: Cron and systemd Timers

Schedule tasks with cron and systemd timers. Crontab syntax, common patterns, logging, debugging scheduled jobs.

On this page

Cron is the Linux task scheduler that runs commands at specific times. Every backup, every cleanup script, every report generation runs on cron. Master cron and you automate your entire infrastructure. Crontab syntax is intimidating at first, but becomes intuitive.

Cron Overview

  • Cron daemon (crond) runs in background
  • Checks crontab files every minute
  • Executes matching scheduled tasks
  • Each user has separate crontab
  • Root crontab has highest privilege

Crontab Syntax

MIN HOUR DOM MON DOW COMMAND
 0   0   1   1   *  /usr/bin/backup.sh    # Run at 12:00am on Jan 1
FieldRangeMeaning
MIN0-59Minute (0=00, 30=30th minute)
HOUR0-23Hour (0=midnight, 12=noon)
DOM1-31Day of month
MON1-12Month (1=Jan, 12=Dec)
DOW0-6Day of week (0=Sun, 6=Sat)

Create and Edit Crontabs

# View current crontab
crontab -l

# Edit crontab (opens editor)
crontab -e

# Edit another user's crontab (as root)
crontab -u www-data -e

# Remove all cron jobs
crontab -r

# View system crontabs
ls -la /etc/cron.d/

Common Patterns

# Every minute
* * * * * /usr/bin/script.sh

# Every hour at :00
0 * * * * /usr/bin/hourly.sh

# Every day at 2:30 AM
30 2 * * * /usr/bin/daily.sh

# Every Monday at 6 PM
0 18 * * 1 /usr/bin/weekly.sh

# Every 1st of month at midnight
0 0 1 * * /usr/bin/monthly.sh

# Every 15 minutes
*/15 * * * * /usr/bin/frequent.sh

Practical Examples

# Backup database daily at 3 AM
0 3 * * * /usr/local/bin/backup-db.sh >> /var/log/backup.log 2>&1

# Clean old logs weekly (Sunday at 4 AM)
0 4 * * 0 find /var/log -name "*.log" -mtime +30 -delete

# Renewal SSL certificates (2 AM daily)
0 2 * * * certbot renew --quiet

# Check disk space every 6 hours
0 */6 * * * /usr/bin/check-disk.sh | mail -s "Disk Report" admin@example.com

systemd Timers

Modern alternative to cron (better for complex tasks):

# Create timer unit: /etc/systemd/system/backup.timer
[Unit]
Description=Daily backup timer
Requires=backup.service

[Timer]
OnCalendar=daily
OnCalendar=*-*-* 03:00:00
Persistent=true

[Install]
WantedBy=timers.target

# Create service unit: /etc/systemd/system/backup.service
[Unit]
Description=Backup script
After=network.target

[Service]
ExecStart=/usr/local/bin/backup.sh
Type=oneshot

# Enable and start
systemctl enable backup.timer
systemctl start backup.timer

Debug Cron Jobs

# Cron logs are in syslog
tail -100 /var/log/syslog | grep CRON

# Check if cron ran (shows output)
grep CRON /var/log/syslog | tail -20

# Debug: test script manually first
/usr/bin/script.sh

# Add logging to script
#!/bin/bash
echo "$(date) - Starting backup" >> /var/log/backup.log
# ... commands ...
echo "$(date) - Backup complete" >> /var/log/backup.log

Best Practices

  • Use absolute paths: Don't rely on $PATH in cron. Use /usr/bin/python3 not python3
  • Redirect output: Send stdout/stderr to log files. Use >> /var/log/task.log 2>&1
  • Set timeout: Long-running tasks should have timeout (use timeout command)
  • Email alerts: Pipe output to mail if task fails. MAILTO=admin@example.com at top of crontab
  • Avoid peak times: Don't schedule backups during business hours
  • Test first: Always test script manually before adding to cron
Cron is unforgiving—test scripts manually first

Cron runs without a terminal. No $PATH, no HOME directory context, no environment variables. What works in your shell may fail in cron. Always use absolute paths and log output.

Related: systemd basics | Bash scripting | Process management | Log rotation

Was this article helpful?

Need a developer-friendly server?

Use an UnderHost Cloud VPS for SSH, Git, Node.js, Python, Laravel, Docker, cron, and custom development workflows.

Related articles

Back to Developer Tools