What are cron and crontab?
cron is a time-based job scheduler in Unix-like operating systems. It runs as a daemon (crond) in the background and executes scheduled commands at specified dates and times.
crontab (cron table) is both the name of the configuration file containing the schedule of cron entries, and the command used to edit that file. Each user can have their own crontab, and there's a system-wide crontab as well.
Key Difference from 'at': While 'at' schedules one-time tasks, cron schedules recurring tasks that run repeatedly on a schedule.
Example 1View Your Crontab
Example 2Edit Your Crontab
Example 3Run Script Every Day at 2:30 AM
30 2 * * * /home/user/scripts/daily_backup.sh
Example 4Run Every Hour
0 * * * * /usr/local/bin/hourly_check.sh
Example 5Run Every 15 Minutes
*/15 * * * * /home/user/monitor.sh
Example 6Run on Specific Days of the Week
0 9 * * 1-5 /home/user/weekday_task.sh
Example 7Run on the First Day of Every Month
0 0 1 * * /home/user/monthly_report.sh
Example 8Run Multiple Times Per Day
0 8,12,16,20 * * * /home/user/check_status.sh
Example 9Redirect Output to Log File
30 2 * * * /home/user/backup.sh >> /var/log/backup.log 2>&1
Example 10Run at System Reboot
@reboot /home/user/startup_script.sh
Example 11Special Time Shortcuts
@hourly /home/user/hourly.sh @daily /home/user/daily.sh @weekly /home/user/weekly.sh @monthly /home/user/monthly.sh @yearly /home/user/yearly.sh @reboot /home/user/startup.sh
| Shortcut | Equivalent To |
|---|---|
| @hourly | 0 * * * * |
| @daily | 0 0 * * * |
| @weekly | 0 0 * * 0 |
| @monthly | 0 0 1 * * |
| @yearly | 0 0 1 1 * |
Example 12Run Every 5 Hours
0 */5 * * * /home/user/five_hour_task.sh
Example 13Remove Your Crontab
Example 14Edit Another User's Crontab (as root)
Example 15Set Environment Variables
SHELL=/bin/bash PATH=/usr/local/bin:/usr/bin:/bin MAILTO=admin@example.com 30 2 * * * /home/user/backup.sh
Example 16Run on Business Days Only
0 9 * * 1-5 /home/user/business_hours_task.sh
Example 17Run Every 2 Hours Between 9 AM and 5 PM
0 9-17/2 * * * /home/user/office_hours_check.sh
Example 18Install Crontab from File
Example 19Run on Specific Dates
0 0 1,15 * * /home/user/twice_monthly.sh
Example 20Check Cron Daemon Status
📚 Additional Information
Crontab Field Values
| Field | Values | Special Characters |
|---|---|---|
| Minute | 0-59 | * , - / |
| Hour | 0-23 | * , - / |
| Day of Month | 1-31 | * , - / |
| Month | 1-12 or JAN-DEC | * , - / |
| Day of Week | 0-7 or SUN-SAT (0=7=Sunday) | * , - / |
Special Characters Explained
| Character | Meaning | Example |
|---|---|---|
| * | Any value | * in hour = every hour |
| , | Value list separator | 1,15 = 1st and 15th |
| - | Range of values | 1-5 = 1 through 5 |
| / | Step values | */15 = every 15 units |
Common Crontab Patterns
# Every minute * * * * * command # Every 5 minutes */5 * * * * command # Every hour at minute 30 30 * * * * command # Every day at 2:30 AM 30 2 * * * command # Every Sunday at midnight 0 0 * * 0 command # Every weekday at 6:30 AM 30 6 * * 1-5 command # Every month on the 1st at midnight 0 0 1 * * command # Every quarter (Jan, Apr, Jul, Oct) on the 1st 0 0 1 1,4,7,10 * command # Twice a day (6 AM and 6 PM) 0 6,18 * * * command # Every 6 hours 0 */6 * * * command # Every Monday at 9 AM 0 9 * * 1 command # Last day of month (using a trick with conditional) 0 0 28-31 * * [ "$(date +\%d -d tomorrow)" = "01" ] && command
System-Wide Crontabs
In addition to user crontabs, there are system-wide crontab locations:
- /etc/crontab - System-wide crontab file
- /etc/cron.d/ - Directory for system cron jobs
- /etc/cron.hourly/ - Scripts run every hour
- /etc/cron.daily/ - Scripts run daily
- /etc/cron.weekly/ - Scripts run weekly
- /etc/cron.monthly/ - Scripts run monthly
Format: minute hour day month dow user command
System Crontab Example
# /etc/crontab format (note the extra 'user' field) SHELL=/bin/bash PATH=/sbin:/bin:/usr/sbin:/usr/bin # m h dom mon dow user command 17 * * * * root cd / && run-parts --report /etc/cron.hourly 25 6 * * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily ) 47 6 * * 7 root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly ) 52 6 1 * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
Crontab Commands Summary
| Command | Description |
|---|---|
| crontab -e | Edit your crontab |
| crontab -l | List your crontab |
| crontab -r | Remove your crontab |
| crontab -u user -e | Edit another user's crontab (requires root) |
| crontab file | Install crontab from file |
| crontab -l > file | Backup your crontab to file |
Debugging Cron Jobs
- Check cron logs: tail -f /var/log/syslog | grep CRON
- Test with frequent schedule: Set to */1 (every minute) for testing
- Redirect to log file: Add >> /tmp/crontest.log 2>&1 to see output
- Use full paths: Always use absolute paths for commands and files
- Check permissions: Ensure scripts are executable (chmod +x)
- Set PATH: Add PATH=/usr/local/bin:/usr/bin:/bin to your crontab
- Test script manually: Run your script directly to verify it works
Common Cron Issues and Solutions
Solution: Use absolute paths and set PATH variable in crontab
Solution: Check MAILTO variable and ensure mail system is configured
Solution: Verify cron syntax with a cron validator tool online, check /var/log/syslog for errors
Solution: Run crontab -e to create your first crontab
Best Practices
- Always use absolute paths: /usr/bin/python3 instead of python3
- Add comments: Use # to document what each job does
- Log everything: Redirect output to log files for troubleshooting
- Test scripts first: Run manually before scheduling in cron
- Be timezone aware: Cron uses system timezone, not user timezone
- Avoid overlapping jobs: Ensure previous job completes before next starts
- Use locking: Implement file locks to prevent multiple instances
- Keep scripts simple: Use shell scripts to organize complex tasks
- Monitor cron jobs: Check logs regularly for failures
- Backup your crontab: Run crontab -l > crontab_backup.txt regularly
Environment Variables in Cron
Cron jobs run with a minimal environment. You can set variables at the top of your crontab:
SHELL=/bin/bash PATH=/usr/local/bin:/usr/bin:/bin MAILTO=admin@example.com HOME=/home/user LANG=en_US.UTF-8 # Your cron jobs below...
Preventing Overlapping Jobs
# Using flock to prevent overlaps * * * * * /usr/bin/flock -n /tmp/myjob.lock /home/user/script.sh # Using a PID file * * * * * [ ! -f /tmp/script.pid ] && echo $$ > /tmp/script.pid && /home/user/script.sh ; rm -f /tmp/script.pid
Real-World Sysadmin Examples
# Daily backup at 2 AM
0 2 * * * /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1
# Clear temp files every hour
0 * * * * find /tmp -type f -mtime +7 -delete
# Monitor disk space every 15 minutes
*/15 * * * * df -h | awk '$5 > 90 {print}' | mail -s "Disk Alert" admin@example.com
# Restart service daily at 3 AM
0 3 * * * systemctl restart myservice
# Update Let's Encrypt certificates weekly
0 3 * * 0 certbot renew --quiet
# Database backup every 6 hours
0 */6 * * * mysqldump -u root mydb | gzip > /backup/mydb_$(date +\%Y\%m\%d_\%H\%M).sql.gz
# Log rotation monthly
0 0 1 * * /usr/sbin/logrotate /etc/logrotate.conf
# System update check daily
0 4 * * * apt update && apt list --upgradable | mail -s "Updates Available" admin@example.com
# Clear old logs weekly
0 2 * * 0 find /var/log -name "*.log" -mtime +30 -delete
# Monitor website uptime every 5 minutes
*/5 * * * * /usr/local/bin/check_website.sh
Advanced Cron Patterns
# Run every weekday at 9:30 AM 30 9 * * 1-5 /home/user/weekday_task.sh # Run every 2 hours between 8 AM and 6 PM 0 8-18/2 * * * /home/user/business_hours.sh # Run on the first Monday of every month 0 9 1-7 * 1 /home/user/first_monday.sh # Run every 90 minutes (use at for this, or creative cron) 0 0,1,3,4,6,7,9,10,12,13,15,16,18,19,21,22 * * * /home/user/90min.sh # Run at random time between 2-3 AM (prevents thundering herd) 0 2 * * * sleep $((RANDOM \% 3600)) && /home/user/script.sh
Cron vs. Systemd Timers
Modern Linux systems offer systemd timers as an alternative to cron:
| Feature | Cron | Systemd Timers |
|---|---|---|
| Learning Curve | Easy, standard syntax | Steeper, more complex |
| Logging | Via syslog/email | Integrated with journalctl |
| Dependencies | None | Can depend on services |
| Missed Jobs | Skipped if system off | Can catch up missed runs |
| User Jobs | Easy (crontab -e) | Possible but less common |
| Portability | Universal on Unix/Linux | systemd systems only |
Security Considerations
- Restrict cron access: Use /etc/cron.allow and /etc/cron.deny
- Protect credentials: Don't hardcode passwords in crontab; use credential files
- Set proper permissions: Ensure scripts aren't world-writable
- Limit email output: Avoid sending sensitive data via email
- Use sudo carefully: Minimize scripts run as root
- Audit crontabs: Regularly review all user and system crontabs
- Log job execution: Keep audit trail of what runs and when
Access Control Files
- /etc/cron.allow - If exists, only listed users can use crontab
- /etc/cron.deny - If cron.allow doesn't exist, listed users cannot use crontab
- If neither exists, only root can use crontab (default on some systems)
- If only cron.deny exists and is empty, all users can use crontab
Useful Cron Generators
Online tools can help generate cron syntax:
- crontab.guru - Human-readable cron schedule expressions
- crontab-generator.org - Visual cron expression builder
- cronitor.io/cron-job-monitoring - Cron generator with monitoring
Testing Cron Jobs
# Create a test crontab entry that runs every minute * * * * * echo "Test at $(date)" >> /tmp/crontest.log # Watch the log file tail -f /tmp/crontest.log # After confirming it works, remove the test entry crontab -e
Backing Up and Restoring Crontabs
# Backup your crontab
crontab -l > ~/crontab_backup_$(date +%Y%m%d).txt
# Backup all user crontabs (as root)
for user in $(cut -f1 -d: /etc/passwd); do
crontab -u $user -l > /backup/crontab_$user 2>/dev/null
done
# Restore from backup
crontab ~/crontab_backup_20251102.txt
# Restore specific user's crontab (as root)
crontab -u username ~/crontab_backup_username.txt
Fun Facts
- The name "cron" comes from the Greek word "chronos" meaning time
- cron was first implemented in Unix Version 7 by Ken Thompson in 1979
- The anacron command can run jobs on systems that aren't always on (like laptops)
- You can use month and day names: JAN-DEC and SUN-SAT instead of numbers
- Some systems support a 6th field for seconds, but this is non-standard