Skip to content

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:

Structure of a cronjob
* * * * * 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, list and remove cronjobs
   # 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):

sudo nano /etc/crontab

Note

System crontab includes an additional user field:

    * * * * * Username command_to_execute

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

Examples
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

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.

Use full path
 # 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 outputs
 # 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:

Use flock
 # 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:

Wrapper script for debugs
 #!/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:

     # Store sensitive data in protected file
     sudo chmod 600 /etc/db_backup.conf
    

  • 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