Bash Cron Job Tutorial: Schedule Scripts to Run Automatically

March 17, 2026

Bash Cron Job Tutorial: Schedule Scripts to Run Automatically

March 17, 2026

Bash cron jobs are the standard way to schedule scripts to run automatically on Linux and macOS. Whether you need to back up a database every night, clean log files weekly, or send a report every hour, cron handles it without any external tools. This tutorial covers the full crontab format, 10 real scheduling examples, how to manage your crontab, and the most common cron pitfalls that catch beginners off guard.

crontab — vi # minute hour day month weekday command 0 2 * * * /usr/local/bin/backup.sh */5 * * * * /scripts/health-check.sh 0 9 * * 1 /scripts/weekly-report.sh # @reboot /scripts/startup.sh
A crontab file showing three scheduled jobs with field-level syntax coloring

1. The 5-Field Crontab Format

Every cron expression has exactly five time fields followed by the command to run. The fields go left to right:

┌───────────── minute        (0 - 59)
│ ┌─────────── hour          (0 - 23)
│ │ ┌───────── day of month  (1 - 31)
│ │ │ ┌─────── month         (1 - 12)
│ │ │ │ ┌───── day of week   (0 - 7, 0 and 7 = Sunday)
│ │ │ │ │
* * * * *  command to execute

Special values you can use in any field:

  • * — every unit (every minute, every hour, etc.)
  • */n — every nth unit (*/5 in the minute field = every 5 minutes)
  • n,m — specific values (1,15 in hour field = 1am and 3pm)
  • n-m — range (1-5 in weekday = Monday through Friday)

2. 10 Real Cron Job Examples

bash
# Every minute
* * * * * /scripts/ping-check.sh

# Every hour at :00
0 * * * * /scripts/hourly-cleanup.sh

# Every day at 2:30 AM
30 2 * * * /scripts/nightly-backup.sh

# Every 5 minutes
*/5 * * * * /scripts/health-check.sh

# Every Monday at 9 AM
0 9 * * 1 /scripts/weekly-report.sh

# First day of every month at midnight
0 0 1 * * /scripts/monthly-invoice.sh

# Every weekday (Mon-Fri) at 8 AM
0 8 * * 1-5 /scripts/workday-start.sh

# Every 15 minutes between 9 AM and 5 PM
*/15 9-17 * * * /scripts/poll-api.sh

# Run once at system boot
@reboot /scripts/startup-tasks.sh

# Every Sunday at 4 AM
0 4 * * 0 /scripts/deep-cleanup.sh

The @reboot shortcut runs your script once when the system starts — no numeric fields needed. Other shortcuts include @hourly, @daily, @weekly, and @monthly.

3. How to Edit Your Crontab

Never edit cron files directly. Use the crontab command instead:

bash
# Open the crontab editor (uses $EDITOR, defaults to vi/nano)
crontab -e

# List all current cron jobs for your user
crontab -l

# Remove all cron jobs (careful — no confirmation prompt)
crontab -r

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

When you save and exit the editor, cron validates the file automatically. A syntax error will be reported and you'll be prompted to re-edit or discard.

4. The Missing PATH Problem (Always Use Full Paths)

The most common reason cron jobs fail silently is the PATH environment variable. Cron runs with a minimal environment — typically PATH=/usr/bin:/bin. Commands that work fine in your terminal (because your shell has a richer PATH) will silently fail in cron.

Fix 1: Use full absolute paths everywhere

bash
# WRONG — python3 might not be in cron's PATH
0 6 * * * python3 /home/user/report.py

# RIGHT — use the full path
0 6 * * * /usr/bin/python3 /home/user/report.py

# Find the full path of a command:
which python3
# → /usr/bin/python3

Fix 2: Set PATH at the top of your crontab

PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

0 2 * * * backup.sh   # now works because PATH is set above

5. Logging Cron Output

By default, cron mails output to the local user account — output you'll never see. Redirect it to a log file instead:

bash
# Append stdout to log, discard stderr
0 2 * * * /scripts/backup.sh >> /var/log/backup.log

# Append both stdout and stderr to log (most useful)
0 2 * * * /scripts/backup.sh >> /var/log/backup.log 2>&1

# Discard all output silently
0 2 * * * /scripts/backup.sh > /dev/null 2>&1

# Timestamp each log entry inside your script:
echo "[$(date '+%Y-%m-%d %H:%M:%S')] Backup started" >> /var/log/backup.log

The 2>&1 part redirects stderr (file descriptor 2) into stdout (file descriptor 1), so both go to the same log file. This is essential for debugging failing cron jobs.

6. Testing and Debugging Cron Jobs

Before relying on a cron schedule, test your script runs correctly in cron's minimal environment:

# Simulate cron's environment and run your script
env -i HOME=/root LOGNAME=root PATH=/usr/bin:/bin SHELL=/bin/sh /scripts/backup.sh

# Check the system cron log (varies by distro)
grep CRON /var/log/syslog         # Debian/Ubuntu
grep crond /var/log/cron          # CentOS/RHEL

# Quick test: schedule 1 minute from now, watch the log
# Set job, wait, then check output file

For more on shell scripting fundamentals that work well with cron, see the Bash functions guide and the bash exit codes article to make your cron scripts more robust.

Summary

Cron is one of the most practical tools in any developer's or sysadmin's toolkit. The key rules to remember: use the five-field format (minute hour day month weekday), always use full absolute paths in cron commands, redirect output to log files with >> /var/log/myjob.log 2>&1, and test your script in a minimal environment before scheduling it. With these habits, your cron jobs will run reliably every time.