Cronjobs
WHAT IS CRON ?
Cron is a time-based job scheduler in Unix-like operating systems. Users can schedule jobs (commands or scripts) to run periodically at specific times, dates, or intervals. These scheduled jobs are called Cron jobs, and they are stored in a file called the crontab (cron table).
CHRON SYNTAX EXPLAINED
Each cron job line consists of six fields:
* * * * * command_to_execute
| | | | |
| | | | -- Day of week (0 - 7) (@ or 7 = Sunday)
| | | ---- Month (1 - 12)
| | ------ Day of month (1 - 31)
| -------- Hour (@ - 23)
---------- Minute (0 - 59)
Special Characters
| CHARACTER | MEANING | EXAMPLE |
|---|---|---|
| * | Any value (always) | * * * * * = every minute |
| ' | Value list separator | 1,15,30 * * * * = at minutes 1,15,30 |
| - | Range of values | 1-5 * * * * = minutes 1 through 5 |
| / | Step values | */15 * * * * = every 15 minutes |
EDITING CRONTAB FILES
Basic Commands
# Edit your personal crontab
crontab -e
# List your current cron jobs
crontab -l
# Remove all your cron jobs
crontab -r
# Edit another user's crontab (root only)
sudo crontab -u username -e
First Time Setup
When you run crontab -e for the first time, you'll be prompted to choose an editor:
- nano (easiest for beginners)
- vim (powerful but has learning curve)
- emacs, etc.
System-wide Crontab
For system-wide tasks (requires root):
Drop-in Directories
Place scripts in these directories for scheduled execution:
- /etc/cron.hourly/ - Runs every hour
- /etc/cron.daily/ - Runs daily
- /etc/cron.weekly/ - Runs weekly
- /etc/cron.monthly/ - Runs monthly
COMMON EXAMPLES
Basic Scheduling
30 2 * * * /home/user/backup.sh # Run at 2:30 AM every day
0 17 * * 1 /home/user/weekly_report.sh # Run every Monday at 5 PM
*/5 * * * * /home/user/check_service.sh # Run every 5 minutes
0 0 1 * * /home/user/monthly_cleanup.sh # Run at midnight on the first day of every month
30 9,18 * * 1-5 /home/user/daily_task.sh # Run at 9:30 AM and 6:30 PM every weekday (Mon-Fri)
15 4 * * 0 /home/user/weekly_backup.sh # Run every Sunday at 4:15 AM
Practical Use Cases
0 1 * * * mysqldump -u root mydb > /backups/mydb_$(date +\%Y\%m\%d).sql # Database backup every day at 1 AM
0 * * * * /usr/bin/find /tmp -type f -atime +1 -delete # Clear cache every hour
0 17 * * 5 /home/user/generate_report.sh | mail -s "Weekly Report" admin@example.com # Send email report every Friday at 5 PM
*/30 * * * * df -h >> /var/log/disk_usage.log # Check disk usage every 30 minutes
* * * * * pgrep nginx || systemctl restart nginx # Restart a service if it fails (check every minute)
BEST PRACTICES
1. Use Full Paths
Cron has a limited PATH. Always use absolute paths for commands and scripts.
# Bad
0 1 * * * backup.sh
# Good
0 1 * * * /home/user/scripts/backup.sh
# Or specify PATH in crontab
PATH=/usr/local/bin:/usr/bin:/bin
0 1 * * * backup.sh
2. Redirect Output
Cron sends any output (stdout/stderr) to your local email. Prevent mailbox filling:
# Redirect all output to a log file
0 2 * * * /home/user/backup.sh >> /var/log/backup.log 2>&1
# Discard all output (not recommended for debugging)
0 2 * * * /home/user/backup.sh > /dev/null 2>&1
# Separate stdout and stderr
0 2 * * * /home/user/backup.sh >> /var/log/backup.log 2>> /var/log/backup.err
3. Test Your Commands First
Run the command manually before adding to crontab:
# Test manually
/home/user/scripts/backup.sh
# Check if it works with cron's minimal environment
env -i /bin/bash --noprofile --norc -c "/home/user/scripts/backup.sh"
4. Add Comments
Document your cron jobs:
# Daily database backup at 1 AM
0 1 * * * /usr/bin/mysqldump -u root mydb > /backups/mydb.sql
# Clear old logs every Sunday at 3 AM (run as root)
0 3 * * 0 /usr/bin/find /var/log -name "*.log" -mtime +30 -delete
5. Avoid Overlapping Jobs
Use flock to prevent concurrent execution:
# Ensure only one instance runs at a time
*/5 * * * * /usr/bin/flock -n /tmp/backup.lockfile /home/user/long_running_task
## LOGGING & TROUBLESHOOTING
### Check if Cron is Running
``` bash title="Check Status and Logs"
# Check cron service status
sudo systemctl status cron # For systemd systems
sudo service cron status # For init systems
# Check cron logs
sudo grep CRON /var/log/syslog # Debian/Ubuntu
sudo grep CRON /var/log/cron # RHEL/Centos
### View Cron Logs
``` bash title="View Logs"
# Real-time monitoring
sudo tail -f /var/log/syslog | grep CRON
# Filter cron job output
journalctl -u cron --since "1 hour ago" # systemd only
Common Issues & Solutions
| ISSUE | SOLUTION |
|---|---|
| Command not found | Use full paths: which command_name |
| Script doesn't run | Make script executable: chmod +x script.sh |
| Environment variables missing | Define them in crontab or source profile: 0 1 * * * . |
| $HOME/.profile; /path/to/script | |
| Job runs twice | Check if both user and system crontabs have the job |
| Permission denied | Check script ownership: ls -l script.sh |
Debugging Script
Create a wrapper script to capture environment:
#!/bin/bash
# debug_cron.sh
echo "=== Cron Job Debug ===" > /tmp/cron_debug.log
echo "Date: $(date)" >> /tmp/cron_debug.log
echo "User: $(whoami)" >> /tmp/cron_debug.log
echo "Path: $PATH" >> /tmp/cron_debug.log
echo "PWD: $PWD" >> /tmp/cron_debug.log
echo "Command output:" >> /tmp/cron_debug.log
/path/to/your/command >> /tmp/cron_debug.log 2>61
Then schedule: * * * * /home/user/debug_cron.sh
SPECIAL STRINGS & SHORTCUTS
Instead of the 5 fields, you can use these @ shortcuts:
| SHORTCUT | MEANING | EQUIVALENT |
|---|---|---|
| @reboot | Run once at startup | (special) |
| @yearly | Run once a year | 0 0 1 1 * |
| @annually | Same as @yearly | 0 0 1 1 * |
| @monthly | Run once a month | 0 0 1 * * |
| @weekly | Run once a week | 0 0 * * 0 |
| @daily | Run once a day | 0 0 * * * |
| @midnight | Same as @daily | O O * * * |
| @hourly | Run once an hour | O * * * * |
Examples:
@reboot /home/user/start_my_service.sh
@daily /home/user/daily_backup.sh
@weekly /home/user/weekly_cleanup.sh
SECURITY CONSIDERATIONS
Restrict Cron Access
# Allow only specific users
sudo nano /etc/cron.allow
# Add one username per line
# Or deny specific users (if cron.allow doesn't exist)
sudo nano /etc/cron.deny
Secure Your Cron Jobs
- Never store passwords directly in crontab
-
Use environment files with restricted permissions:
-
Avoid running jobs as root unless absolutely necessary
- Regularly audit your cron jobs:
crontab -l - Use absolute paths to prevent PATH hijacking
Example with Environment Variables
# In crontab
0 1 * * * /home/user/backup.sh
# In backup.sh
#!/bin/bash
source /home/user/.env_secret # Store DB passwords here
mysqldump -u $DB_USER -p$DB_PASS mydb > /backups/mydb.sql
QUICK REFERENCE
# Edit crontab
crontab -e
# List jobs
crontab -l
# Remove all jobs
crontab -r
# Edit another user's crontab (root)
sudo crontab -u username -e
# Format: m h dom mon dow command
# 0-59 0-23 1-31 1-12 0-6
# Examples
*/15 * * * * # Every 15 minutes
0 */2 * * * # Every 2 hours
0 9-17 * * * # Every hour 9 AM to 5 PM
0 O * * 1 # Every Monday at midnight
0 0 1 */3 * # First day of every quarter