Client Area

Cron Expression Cheat Sheet: Syntax, Patterns, and Debugging

ByDomain India Team
11 min read22 Apr 20262 views

In this article

  • 1The five fields
  • 2Common misreadings
  • 3The everyday cheat sheet
  • 4Every-N-minutes
  • 5Hourly and daily

Cron Expression Cheat Sheet: Syntax, Patterns, and Debugging

Cron is 50 years old and still the backbone of scheduled tasks on every Unix and Linux server. This guide takes you from "what are these five stars?" to writing expressions for every common schedule, running cron on our cPanel and DirectAdmin plans, and debugging jobs that silently refuse to run.

The five fields

 ┌─────────── minute        (0 – 59)
 │ ┌───────── hour          (0 – 23)
 │ │ ┌─────── day of month  (1 – 31)
 │ │ │ ┌───── month         (1 – 12  or  JAN – DEC)
 │ │ │ │ ┌─── day of week   (0 – 7; Sun = 0 or 7, or SUN – SAT)
 │ │ │ │ │
 * * * * *  command-to-run

Each of the five fields accepts:

SyntaxMeaningExample
NumberExact value5
RangeEvery value in the range1-5
ListSpecific values1,15,30,45
StepEvery N starting at 0*/10 (every 10)
Step in rangeEvery N within a range0-30/5 (0, 5, 10, ..., 30)
WildcardEvery value*
Name (month / day-of-week only)Abbreviated nameMON-FRI, JAN, DEC

Common misreadings

These trip up even experienced developers:

  • `*/5 * * * *` means "at minute 0, 5, 10, 15, ..." — so effectively "every 5 minutes". Not "every 5 of every hour of every day of every month of every day of week" (it is that, but the redundant wording confuses).
  • `0 */2 * * *` means "at minute 0 of every 2nd hour". Not "every 2 minutes".
  • `0 0 * * 0` means "midnight on Sunday". Not "the 1st day of every month".

When in doubt, paste your expression into crontab.guru — it translates to plain English and shows the next several fire times.

The everyday cheat sheet

Every-N-minutes

ExpressionFires at
* * * * *Every minute
*/5 * * * *Every 5 minutes (:00, :05, :10, …)
*/15 * * * *Every 15 minutes (:00, :15, :30, :45)
0,30 * * * *:00 and :30 (equivalent to */30)
0 * * * *Top of every hour

Hourly and daily

ExpressionFires at
0 */2 * * *Every 2 hours (0:00, 2:00, 4:00, ...)
0 9 * * *9:00 AM every day
30 3 * * *3:30 AM every day
0 */6 * * *4 times a day (0, 6, 12, 18)
15 14 * * *2:15 PM every day

Weekly patterns

ExpressionFires at
0 9 * * 19:00 AM every Monday
0 9 * * 1-59:00 AM on weekdays (Mon–Fri)
0 9 * * 0,69:00 AM on weekends (Sun, Sat)
0 0 * * 0Midnight every Sunday
0 18 * * 56:00 PM every Friday

Monthly and yearly

ExpressionFires at
0 0 1 * *Midnight on the 1st of every month
0 0 15 * *Midnight on the 15th
0 0 1 */3 *Quarterly — 1st of Jan, Apr, Jul, Oct
0 0 1 1 *Once a year, midnight Jan 1st
30 23 L * *11:30 PM on the last day of month (extended cron only — not all systems support L)

Shortcut names

Some cron implementations accept named shortcuts:

ShortcutEquivalent
@rebootRun once at system startup
@hourly0 * * * *
@daily0 0 * * *
@weekly0 0 * * 0
@monthly0 0 1 * *
@yearly / @annually0 0 1 1 *

Our cPanel plans support the shortcuts. VPS Ubuntu / Debian also support them. RHEL / AlmaLinux support most.

Where to add cron jobs on Domain India hosting

cPanel

  1. Log in to cPanel → Home → Cron Jobs
  2. Use the "Common Settings" dropdown for quick presets, or type the 5-field expression
  3. Enter the command and click Add New Cron Job
  4. cPanel emails you the command output by default — useful for debugging, annoying at scale. Suppress with >/dev/null 2>&1:
* * * * * cd /home/user/app && php artisan schedule:run >/dev/null 2>&1

To capture output to a log instead:

* * * * * cd /home/user/app && php artisan schedule:run >> /home/user/cron.log 2>&1

DirectAdmin

User panel → Cron Jobs. Same 5-field format. Some plans expose crontab -e via SSH — identical syntax.

Webuzo

Dashboard → Cron Jobs. Simple UI matching the cPanel pattern.

VPS (Ubuntu / Debian / AlmaLinux)

bash
crontab -e          # edit current user's crontab
crontab -l          # list current entries
crontab -r          # remove crontab (CAREFUL — no confirmation)

System-wide crons go in:

  • /etc/cron.d/your-file — 6-field format (includes user)
  • /etc/cron.hourly/ — any executable file runs hourly
  • /etc/cron.daily/ — daily
  • /etc/cron.weekly/ — weekly
  • /etc/cron.monthly/ — monthly

systemd timers (modern alternative)

On modern VPS, systemd timers replace cron for many use cases:

  • Proper logging via journalctl
  • Dependency support (run job only after another service is up)
  • Randomised start times (spread load)
  • Better accuracy under system sleep

Covered in a future article in Background Jobs & Queues.

Real-world examples

Laravel scheduler

* * * * * cd /home/user/laravel-app && php artisan schedule:run >> /dev/null 2>&1

This runs every minute and lets Laravel's App\Console\Kernel schedule internally (hourly, daily, etc.). One cron entry — all Laravel-defined jobs managed in code.

WordPress — offload wp-cron from page loads

By default WordPress fires wp-cron on every pageview, which is slow. Disable that and run it via system cron:

*/5 * * * * wget -q -O - https://yourdomain.com/wp-cron.php?doing_wp_cron >/dev/null 2>&1

Add define('DISABLE_WP_CRON', true); to wp-config.php. Now wp-cron runs every 5 minutes reliably, regardless of traffic.

Database backup (mysqldump)

30 3 * * * /usr/bin/mysqldump -u dbuser -pdbpassword mydb | gzip > /home/user/backups/mydb-$(date +\%Y\%m\%d).sql.gz

Gotcha: % is treated as newline by cron. Escape it as \%. A % inside date +%Y%m%d without escaping breaks the command silently.

Cleanup logs older than 30 days

0 4 * * * find /home/user/logs/ -name "*.log" -mtime +30 -delete

Runs at 4:00 AM every day. -mtime +30 = modified more than 30 days ago.

Call an API webhook every 15 minutes

*/15 * * * * curl -s -X POST https://yourdomain.com/sync-external-api >/dev/null

Daily SSL expiry check

0 9 * * * /usr/bin/openssl s_client -servername yourdomain.com -connect yourdomain.com:443 2>/dev/null </dev/null | openssl x509 -noout -dates | mail -s "SSL expiry check" [email protected]

Emails you the SSL expiry dates every morning. Replace with a Slack webhook call for team use.

Laravel queue worker (reliable restart)

*/5 * * * * cd /home/user/laravel-app && php artisan queue:work --stop-when-empty >/dev/null 2>&1

Not ideal — for production queues, use a proper worker manager like PM2 or Supervisord. But on shared hosting where long-lived processes are not allowed, this cron-triggered approach works for light queue load.

Debugging cron jobs that don't run

The #1 Linux forum question. Checklist:

1. Is the cron daemon running?

On cPanel / DirectAdmin / Webuzo — yes, managed for you, always on.

On VPS:

bash
systemctl status cron      # Debian / Ubuntu
systemctl status crond     # AlmaLinux / CentOS / RHEL

If inactive, systemctl start crond (or cron) and enable on boot.

2. Is your crontab saved correctly?

bash
crontab -l

Shows what's registered. If your expected entry is not there, re-save. If crontab -e said "errors in crontab file, can't install" on save, the expression is invalid.

3. Is the command path correct?

Cron runs with a minimal PATH environment variable — just /usr/bin:/bin. Use absolute paths:

# Bad: 'php' might not be found
* * * * * cd /home/user/app && php artisan schedule:run

# Better: use absolute path
* * * * * cd /home/user/app && /usr/local/bin/php artisan schedule:run

Or set PATH at the top of your crontab:

PATH=/usr/local/bin:/usr/bin:/bin
* * * * * cd /home/user/app && php artisan schedule:run

Find your PHP path with which php.

4. Is the command failing silently?

Redirect output to log and check:

* * * * * /path/to/script >> /home/user/cron.log 2>&1

Then tail -f /home/user/cron.log to watch.

Also check system cron logs:

  • cPanel / AlmaLinux: /var/log/cron
  • Debian / Ubuntu: /var/log/syslog — grep for CRON

5. Permission problems?

Scripts need execute permission:

bash
chmod +x /home/user/myscript.sh

Test manually as the cron user:

bash
sudo -u cronuser /home/user/myscript.sh

If this fails, the cron will fail the same way.

6. Missing environment variable?

Cron doesn't source ~/.bashrc or ~/.profile. If your script needs env vars, set them explicitly:

* * * * * /bin/bash -c "source /home/user/.env && /path/to/script.sh"

Or inline:

NODE_ENV=production
* * * * * /usr/bin/node /home/user/app/script.js

7. % breaking the command?

Cron treats % as newline (as a way to pass stdin to commands). Escape with \%:

# Broken:
30 3 * * * mysqldump db > backup-$(date +%Y%m%d).sql

# Fixed:
30 3 * * * mysqldump db > backup-$(date +\%Y\%m\%d).sql

8. Timezone confusion

Cron fires in the server's timezone. On our India-region servers that is usually IST (Asia/Kolkata). Verify:

bash
date
timedatectl    # on systemd-based VPS

To change on a VPS: sudo timedatectl set-timezone Asia/Kolkata.

On shared hosting the timezone is fixed by us — contact support if you need a different zone.

9. The job runs but overlaps itself

If your job takes longer than its interval, multiple copies pile up. Use flock to prevent overlap:

*/5 * * * * /usr/bin/flock -n /tmp/myjob.lock /path/to/script.sh

The -n flag means "fail immediately if the lock is held", so the second run exits cleanly instead of piling up.

Security considerations for cron

  • Don't put passwords in the crontab directly. They're visible to ps -ef during execution. Source from an env file: source /home/user/.env && /path/to/script.
  • chmod env files 600 so only the owner can read them.
  • Validate external inputs. If your cron curls a URL built from a variable, sanitise the variable first.
  • Log responsibly. Make sure cron logs don't accidentally capture secrets.
  • Review quarterly. Cron jobs have a way of accumulating — audit crontab -l every three months and delete dead entries.

Useful external tools

  • crontab.guru — visual expression explainer and next-fire-time calculator. Use every time you write a non-trivial expression.
  • cronitor.io — cron monitoring; alerts if a job stops firing. Paid; free tier for < 5 jobs.
  • Healthchecks.io — open-source alternative, free for personal use.
  • Dead Man's Snitch — simple heartbeat monitoring.

Integration pattern: have your cron job curl a monitoring endpoint at the END of its run. If the monitoring service doesn't see the heartbeat within the expected window, it alerts you.

When cron is the wrong tool

Cron is great for scheduled tasks. It's the wrong tool when you need any of:

NeedUse instead
Precision below 1 minuteLong-running process with sleep, OR systemd timers with OnUnitActiveSec=30s
Dependency chains (job A before job B)Airflow, Temporal, GitHub Actions
Retry on failureBackground queues — see PM2 for Node.js
Process messages as they arriveQueue consumer (long-lived)
"Run N minutes after this event"Delay queue (Redis ZSET, BullMQ delay option)

Frequently asked questions

What's the difference between cron and crontab?

Cron is the daemon that fires jobs. Crontab is the file (and the command crontab) that lists what jobs to fire. You edit the crontab; cron reads it.

Can I run a cron job every second?

No. Cron's minimum interval is one minute. For sub-minute scheduling use a long-running process with a loop + sleep, or systemd timers.

Why is my cron job emailing me thousands of messages?

Your job produces output on every run (STDOUT or STDERR), and cron emails anything it writes. Suppress with >/dev/null 2>&1 at the end of the command.

Can two cron jobs run at the same time?

Yes, by default. If you want to prevent concurrent runs of the same job, use flock as shown above.

How do I stop a running cron job?

Find it with ps -ef | grep your-script-name, then kill <PID>. If it's a flock-guarded job, killing the process will release the lock automatically.

What's `@reboot` in crontab?

A job that runs once when the system starts up. Useful for launching background processes, but fragile — the process dies when the VPS restarts and comes back. Prefer systemd or a proper process manager for long-lived services.

Does cron work correctly during DST transitions?

In regions with DST, cron jobs can either fire twice (fall-back) or be skipped (spring-forward). India doesn't observe DST, so this doesn't affect our servers — but be aware if you're migrating from a US or EU provider.

Do I need a VPS for running cron jobs?

No. Cron is available on all our cPanel, DirectAdmin, and Webuzo plans. You only need a VPS if the cron job requires long-running processes, heavy CPU, or system-level tools not available on shared hosting.


Questions on a specific cron pattern? [email protected] — we help customers debug cron jobs as part of standard support.

Was this article helpful?

Your feedback helps us improve our documentation

Still need help? Submit a support ticket