⏰ Linux cron & crontab

Schedule Recurring Tasks - Examples by Claude

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.

Crontab Syntax:
* * * * * command to execute └─── Day of week (0-7, Sun=0 or 7) └─────── Month (1-12) └─────────── Day of month (1-31) └─────────────── Hour (0-23) └─────────────────── Minute (0-59)

Example 1View Your Crontab

crontab -l
List (view) your current crontab entries. This shows all scheduled jobs for your user account.
30 2 * * * /home/user/scripts/backup.sh 0 */6 * * * /usr/bin/clean_temp_files.sh 15 14 * * 0 /home/user/scripts/weekly_report.sh
Pro Tip: If you get "no crontab for user", it just means you haven't created one yet. That's normal!

Example 2Edit Your Crontab

crontab -e
Opens your crontab in the default editor (usually vi/vim or nano). First time you run this, you may be asked to choose an editor.
Note: Changes take effect immediately upon saving and exiting the editor. No restart required!

Example 3Run Script Every Day at 2:30 AM

30 2 * * * /home/user/scripts/daily_backup.sh
The most common cron job pattern: run a backup script every day at 2:30 AM. The three asterisks mean "every day", "every month", and "every day of the week".
Pro Tip: Always use absolute paths in cron jobs! Cron doesn't use your normal PATH environment variable.

Example 4Run Every Hour

0 * * * * /usr/local/bin/hourly_check.sh
Runs at the top of every hour (12:00, 1:00, 2:00, etc.). The 0 in the minute field means "at minute 0", and the * in hour means "every hour".

Example 5Run Every 15 Minutes

*/15 * * * * /home/user/monitor.sh
The */15 syntax means "every 15 minutes". This runs at :00, :15, :30, and :45 of every hour.
Note: The */N syntax is called "step values". */5 = every 5 minutes, */10 = every 10 minutes, etc.

Example 6Run on Specific Days of the Week

0 9 * * 1-5 /home/user/weekday_task.sh
Runs at 9:00 AM Monday through Friday (1-5). Perfect for business-hours automation. 0=Sunday, 1=Monday, ... 6=Saturday, 7=Sunday.
Pro Tip: You can use both 0 and 7 for Sunday. Some people prefer 0, others prefer 7.

Example 7Run on the First Day of Every Month

0 0 1 * * /home/user/monthly_report.sh
Runs at midnight on the 1st day of every month. Great for monthly billing, reports, or maintenance tasks.

Example 8Run Multiple Times Per Day

0 8,12,16,20 * * * /home/user/check_status.sh
Runs at 8 AM, 12 PM, 4 PM, and 8 PM every day. Use commas to specify multiple discrete values.

Example 9Redirect Output to Log File

30 2 * * * /home/user/backup.sh >> /var/log/backup.log 2>&1
Captures both standard output and errors to a log file. The >> appends to the file, and 2>&1 redirects stderr to stdout.
Warning: Without output redirection, cron will try to email you the output (if mail is configured).

Example 10Run at System Reboot

@reboot /home/user/startup_script.sh
Special syntax that runs the command once at system startup. Very useful for initialization scripts.

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
Cron provides convenient shortcuts for common schedules. These are easier to read and remember than the full syntax.
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
Runs at midnight, 5 AM, 10 AM, 3 PM, and 8 PM. The */5 in the hour field means "every 5 hours".

Example 13Remove Your Crontab

crontab -r
Removes (deletes) your entire crontab. All scheduled jobs are gone!
Warning: This deletes everything with no confirmation prompt! Be careful. Use crontab -e to remove individual entries instead.

Example 14Edit Another User's Crontab (as root)

sudo crontab -u username -e
As root, edit another user's crontab. The -u flag specifies which user's crontab to edit.
Note: This requires root privileges. Useful for system administration.

Example 15Set Environment Variables

SHELL=/bin/bash
PATH=/usr/local/bin:/usr/bin:/bin
MAILTO=admin@example.com

30 2 * * * /home/user/backup.sh
Set environment variables at the top of your crontab. These apply to all cron jobs below them. MAILTO controls where output is emailed.
Pro Tip: Setting PATH explicitly prevents "command not found" errors. Set MAILTO="" to suppress all email.

Example 16Run on Business Days Only

0 9 * * 1-5 /home/user/business_hours_task.sh
Runs at 9 AM Monday through Friday only. Skips weekends automatically.

Example 17Run Every 2 Hours Between 9 AM and 5 PM

0 9-17/2 * * * /home/user/office_hours_check.sh
Runs at 9 AM, 11 AM, 1 PM, 3 PM, and 5 PM. The 9-17/2 means "from 9 to 5 PM, every 2 hours".

Example 18Install Crontab from File

crontab mycrontab.txt
Replace your entire crontab with the contents of a file. Useful for backup/restore or deploying standard crontabs.
Warning: This replaces your entire crontab! Back up first with: crontab -l > backup.txt

Example 19Run on Specific Dates

0 0 1,15 * * /home/user/twice_monthly.sh
Runs on the 1st and 15th of every month at midnight. Perfect for semi-monthly tasks like payroll.

Example 20Check Cron Daemon Status

systemctl status cron
Verify that the cron daemon is running. On some systems, it's called 'crond' instead of 'cron'.
● cron.service - Regular background program processing daemon Loaded: loaded (/lib/systemd/system/cron.service; enabled) Active: active (running) since Thu 2025-11-02 08:00:00 EST Main PID: 1234 (cron) Tasks: 1 Memory: 2.1M CGroup: /system.slice/cron.service └─1234 /usr/sbin/cron -f

📚 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
Note: System crontabs in /etc/crontab and /etc/cron.d/ have an additional field: the username to run as.
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

Problem: Script works manually but not in cron
Solution: Use absolute paths and set PATH variable in crontab
Problem: Not receiving email notifications
Solution: Check MAILTO variable and ensure mail system is configured
Problem: Job not running at expected time
Solution: Verify cron syntax with a cron validator tool online, check /var/log/syslog for errors
Problem: "No crontab for user" error
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
Pro Tip for Beginners: Use https://crontab.guru to validate your cron syntax. Type in your expression and it explains in plain English when it will run.
Pro Tip for Sysadmins: Use configuration management tools (Ansible, Puppet, Chef) to manage crontabs across multiple servers. This ensures consistency and provides version control.

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