Skip to main content
SysAdmin Shell Scripting Essentials

Crontab Every 4 Hours — Verified Syntax, Flags & Troubleshooting

crontab every 4 hours is a cron schedule expression using the step value */4 in the hour field to run a command at minute 0 of every fourth hour (0, 4, 8, 12, 16, 20).

# Run /path/to/script every 4 hours at the start of the hour
0 */4 * * * /path/to/script

# Add the entry via crontab editor
crontab -e

Syntax and Examples

Standard cron syntax uses five space-separated fields: minute, hour, day of month, month, day of week. The */4 in the hour field means every 4th hour from 0 to 23. The minute field must be set to 0 to avoid running every minute during those hours.

# Basic health check every 4 hours
0 */4 * * * /usr/local/bin/healthcheck.sh

# Log rotation with date stamp, starting at 02:00
0 */4 * * * /usr/bin/tar -czf /backups/logs-$(date +%Y%m%d%H%M).tar.gz /var/log/app/*.log 2>&1

# Prevent overlap with flock
0 */4 * * * /usr/bin/flock -n /var/run/mytask.lock /usr/local/bin/longrunning_job.py

Tested on Ubuntu 22.04 with cron 3.0pl1‑132.

Options and Flags

Flag Type Default Description
-e Edit mode N/A Edit the current user’s crontab file with the default editor (vi, nano, etc.)
-l List N/A Display the current user’s crontab entries on stdout
-r Remove N/A Remove the current user’s crontab file entirely
-u User (root only) current user Specify a different user’s crontab to edit or inspect
See also  How to Call a PowerShell Script from Another PowerShell Script

Troubleshooting & Common Errors

Error Message / Symptom Root Cause Resolution
Job runs every minute during every 4th hour Missing minute field – * */4 * * * instead of 0 */4 * * * Change to 0 */4 * * * – the * in minute means “every minute”
Email: “/bin/sh: line 1: somecommand: command not found” Relative command path without full path Use full path: /usr/local/bin/somecommand
Job does not run at all cron daemon not running or crontab syntax error systemctl status cron (or crond) and crontab -l to inspect current entries
Job runs but produces no log or email No MAILTO set and stdout/stderr not redirected Add at top of crontab: MAILTO=admin@example.com or append >> /var/log/mycron.log 2>&1

Exit Codes

Code Meaning Operational Impact
0 Command executed and exited successfully No action needed; job ran as scheduled
126 Command found but not executable Check script permissions – chmod +x /path/to/script
127 Command not found Verify absolute path; do not rely on PATH in cron
>0 (non‑zero) User‑defined failure or system error CRON will send MAILTO if configured; investigate exit code

Performance Considerations and Tuning

  • Job overlap: Use flock to prevent multiple instances. Example: 0 */4 * * * /usr/bin/flock -n /tmp/myjob.lock /path/to/script
  • Mail spool size: Set MAILTO="" at the top of the crontab to suppress email output, or redirect stdout/stderr to a file.
  • Environment and PATH: Specify paths explicitly inside each job; cron’s default PATH is minimal (often /usr/bin:/bin).
  • Time drift compensation: For long‑running jobs, add a sleep loop inside the script rather than relying on cron’s exact schedule.
  • Logging overhead: Rotate cron logs daily via logrotate to avoid disk space exhaustion.
  • Maximum execution time: Use job timeout wrappers (e.g., timeout 3600) to prevent runaway processes.
# Tuned crontab entry with environment variables
MAILTO=""
SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

0 */4 * * * /usr/bin/flock -n /tmp/myjob.lock /usr/bin/timeout 3600 /path/to/script

Frequently Asked Questions

What is the difference between using */4 and 0,4,8,12,16,20 in crontab?

Functionally identical; both schedule execution at hours 0, 4, 8, 12, 16, and 20 UTC. The */4 syntax is more compact. Use the explicit list if you need an offset start (e.g., 2,6,10,14,18,22).

# Equivalent lines:
0 */4 * * * /usr/bin/script.sh
0 0,4,8,12,16,20 * * * /usr/bin/script.sh

When should I use the */4 syntax instead of explicit hour list?

Use */4 for simple, regular intervals every N hours starting from hour 0. Avoid it if you need offset start times; then specify explicit hours.

# Every 4 hours starting at 0
0 */4 * * * /opt/health-check.sh

# Offset by 2 hours:
0 2,6,10,14,18,22 * * * /opt/health-check.sh

How do I fix the “bad day-of-week” error?

This error occurs when the day-of-week field (5th) has an invalid value (e.g., 7 instead of 0-6) or conflicts with day-of-month. For every-4-hour jobs, set both day fields to *.

# Correct syntax:
0 */4 * * * /usr/local/bin/monitor.sh

# Invalid (causes error):
0 */4 1-31 1-12 7,0

Does crontab every 4 hours work on AWS EC2 Amazon Linux 2?

Yes, standard cron syntax is fully supported on Amazon Linux 2, Ubuntu, RHEL, and all POSIX-compliant distributions. Cron implementations (cronie, Vixie cron) all recognize */4. Be aware of the instance’s timezone; default is UTC. To change, set TZ before the command or modify /etc/localtime.

# Verify cron is running:
systemctl status crond

# Example with explicit timezone:
0 */4 * * * TZ=UTC /path/to/backup.sh

What is the fastest way to set crontab every 4 hours across multiple servers?

Use configuration management tools like Ansible’s cron module for idempotent deployment. Example playbook:

# ansible-playbook -i inventory cron.yml
- name: Add every-4-hour cron job
  cron:
    name: "health check"
    minute: "0"
    hour: "*/4"
    job: "/usr/local/bin/health-check.sh"

For AWS EC2, use userdata in a launch template:

#!/bin/bash
cat >> /var/spool/cron/root <