A cron job is a scheduled task that runs automatically on a Unix or Linux system at a defined time or interval, without any manual trigger. The name comes from cron , a time-based job scheduler built into Unix systems since the 1970s, derived from the Greek word chronos (time). If you have ever wondered how a web server backs itself up at 3 AM, or how a newsletter platform sends thousands of emails every morning at 9 AM sharp, the answer is almost always a cron job.
Content Table
How Cron Works
The cron daemon (
crond
) is a background process that wakes up every minute and checks a configuration file called the
crontab
(cron table). If any scheduled task is due to run at that minute, cron executes it. The crontab file lists one job per line, each line combining a schedule expression with a shell command.
You interact with your crontab using the
crontab
command:
crontab -e # Open your crontab for editing
crontab -l # List all current cron jobs
crontab -r # Remove your crontab entirely
Each user on a Linux system has their own crontab, and the root user can also manage system-wide cron jobs stored in
/etc/cron.d/
or
/etc/crontab
. The
Vixie Cron implementation
, written by Paul Vixie in 1987, is still the most widely deployed version on Linux systems today.
Cron Syntax and Expressions Explained
Every cron job scheduling entry follows the same five-field structure. Understanding this structure is the core skill you need to write any cron expression confidently.
# ┌─────────── minute (0–59)
# │ ┌───────── hour (0–23)
# │ │ ┌─────── day of month (1–31)
# │ │ │ ┌───── month (1–12)
# │ │ │ │ ┌─── day of week (0–7, where 0 and 7 are Sunday)
# │ │ │ │ │
# * * * * * command to execute
Each field accepts specific values and a handful of special characters:
- * (asterisk): "every" possible value in that field
-
,
(comma): a list of values, e.g.
1,15,30 -
-
(hyphen): a range, e.g.
9-17means 9 through 17 -
/
(slash): a step, e.g.
*/5means every 5 units
Here are a few practical examples to make cron expressions concrete:
# Run every day at midnight
0 0 * * * /usr/bin/backup.sh
# Run every 15 minutes
*/15 * * * * /usr/bin/health-check.sh
# Run at 8:30 AM on weekdays (Monday through Friday)
30 8 * * 1-5 /usr/bin/send-report.sh
# Run on the 1st of every month at 6 AM
0 6 1 * * /usr/bin/monthly-cleanup.sh
# Run every hour between 9 AM and 5 PM on weekdays
0 9-17 * * 1-5 /usr/bin/sync-data.sh
0 9 * * *
will run at 9 AM UTC, not 9 AM Eastern. Always check your server's time zone with
timedatectl
before scheduling time-sensitive jobs.
Cron Syntax Quick Reference
| Expression | Meaning | Example command |
|---|---|---|
* * * * *
|
Every minute | Heartbeat ping |
0 * * * *
|
Every hour at :00 | Clear temp files |
0 0 * * *
|
Every day at midnight | Database backup |
0 0 * * 0
|
Every Sunday at midnight | Weekly report |
0 0 1 * *
|
First day of every month | Monthly invoice generation |
*/5 * * * *
|
Every 5 minutes | Queue worker poll |
30 8 * * 1-5
|
8:30 AM, Monday to Friday | Send daily digest email |
0 2 * * 6
|
2 AM every Saturday | Full site backup |
Special Strings Like @daily and @reboot
Most modern cron implementations (including Vixie Cron and systemd's cron-compatible layer) support shorthand strings that replace the five-field expression. They are easier to read and less error-prone for common schedules.
| Shorthand | Equivalent expression | Runs when |
|---|---|---|
@reboot
|
N/A | Once at system startup |
@yearly
/
@annually
|
0 0 1 1 *
|
January 1st at midnight |
@monthly
|
0 0 1 * *
|
First day of each month |
@weekly
|
0 0 * * 0
|
Every Sunday at midnight |
@daily
/
@midnight
|
0 0 * * *
|
Every day at midnight |
@hourly
|
0 * * * *
|
Start of every hour |
A practical use for
@reboot
is starting a Node.js application server automatically after a VPS reboots, without a full process manager:
@reboot /usr/bin/node /var/www/myapp/server.js >> /var/log/myapp.log 2>&1
Common Cron Job Use Cases
Task automation via cron jobs covers a wide range of developer and sysadmin workflows. Here are the most common ones you will encounter in real projects:
Automated Backups
Backing up a MySQL database every night at 2 AM is one of the most universal uses of cron job scheduling. A simple one-liner handles the whole thing:
0 2 * * * mysqldump -u root -pYOURPASS mydb > /backups/mydb_$(date +\%F).sql
Sending Scheduled Emails
Many applications use a cron job to trigger a PHP or Python script that sends newsletters, weekly digests, or billing reminders. The cron job does not send the email itself; it calls the script that does. A typical setup runs a mailer script every day at 7 AM:
0 7 * * * /usr/bin/php /var/www/app/send_digest.php >> /var/log/mailer.log 2>&1
Database Cleanup
Old session records, expired tokens, soft-deleted rows, and temporary data accumulate fast. A weekly cleanup job keeps your database lean:
0 3 * * 0 /usr/bin/python3 /scripts/cleanup_expired_sessions.py
Server Maintenance Tasks
Server maintenance tasks that run well with cron include log rotation, disk usage checks, SSL certificate renewal reminders, cache warming, and security scans. For example, Certbot (the most popular Let's Encrypt client) installs its own cron job or systemd timer to renew SSL certificates automatically twice a day.
Syncing and Reporting
Cron jobs are commonly used to pull data from external APIs on a schedule, generate PDF reports, sync files to S3, or update search index snapshots. If you are working with APIs that enforce rate limits, understanding how those limits work can help you schedule your sync jobs without hitting caps. Our guide on API rate limiting and how services control request traffic is a useful companion read for designing these kinds of scheduled integrations.
Common Mistakes Developers Make
Writing cron expressions looks simple until something silently fails at 3 AM. These are the mistakes that catch developers most often:
-
Wrong PATH environment.
Cron runs with a minimal environment. Commands that work in your terminal may fail in cron because
/usr/local/binor~/.nvm/versions/node/...is not in cron's PATH. Always use absolute paths for every binary and script. -
Missing output redirection.
By default, cron emails output to the local user. If mail is not configured, output is silently dropped. Redirect stdout and stderr to a log file:
>> /var/log/myjob.log 2>&1 -
Forgetting the percent sign escape.
The
%character has special meaning in crontab (it acts as a newline). If your command usesdate +%F, you must escape it as\%F. -
Day-of-month and day-of-week conflict.
If you specify both a day-of-month and a day-of-week value (neither is
*), cron treats them as an OR condition, not AND.0 0 1 * 5runs on the 1st of every month AND every Friday, not just Fridays that fall on the 1st. - Not testing the script independently first. Always run your script manually as the cron user before scheduling it. Many failures come from permission issues or missing dependencies that only appear in the cron environment.
-
Overlapping jobs.
If a cron job takes longer than its interval (e.g., a 5-minute job that sometimes runs for 8 minutes), multiple instances can stack up. Use a lock file or a tool like
flockto prevent overlapping runs.
If you manage configuration files alongside your cron jobs, knowing the right format for those configs matters too. Our comparison of YAML vs JSON for config files can help you decide which format to use when your cron scripts read external configuration.
Cron remains one of the most reliable and universally available tools in a developer's toolkit precisely because it is simple, stateless, and built into every Unix-like system. A cron job you write today will still work on a server provisioned ten years from now - that kind of stability is rare in software. However, as projects grow, managing dozens of scheduled tasks across multiple servers quickly becomes complex. For developers who want to go beyond basic cron and manage, test, and monitor their scheduled workflows in one place, devdeck.dev offers a modern environment built with exactly that in mind.
Manage and test your developer workflows in one place
DevDeck gives developers a suite of free tools to build, test, and manage their workflows efficiently. Whether you are debugging cron job output, formatting config files, or testing scripts, DevDeck keeps everything in reach without switching tabs.
Try DevDeck Free →
A crontab (cron table) is the configuration file that stores your scheduled tasks. A cron job is a single entry inside that file, representing one specific task with its schedule. Think of the crontab as the list and each cron job as an item on that list. You edit the crontab with
crontab -e
, and the cron daemon reads it to know when to run each job.
Standard cron has a one-minute resolution, so it cannot natively schedule a job to run every 10 or 30 seconds. To work around this, developers often chain multiple commands with a
sleep
call inside a single cron job, or use a more capable scheduler like systemd timers (which support second-level precision) or a language-specific task queue for sub-minute intervals.
The most reliable method is redirecting the job's output to a log file using
>> /path/to/logfile.log 2>&1
at the end of the cron command. You can also check system logs with
grep CRON /var/log/syslog
on Debian-based systems or
grep CRON /var/log/cron
on Red Hat-based systems. These logs show when cron attempted to run each job and whether it succeeded.
Cron is a Unix/Linux tool and does not exist natively on Windows. The Windows equivalent is the Task Scheduler, which provides a GUI and XML-based configuration for scheduled tasks. If you are running Windows Subsystem for Linux (WSL), you can technically use cron within the WSL environment, though it requires manually starting the cron service since WSL does not run a full init system by default.
Standard cron simply skips the job if the server is powered off or the cron daemon is not running at the scheduled time. It does not catch up or retry missed jobs. If you need missed jobs to run after the server comes back online, you can use
anacron
, which is designed for machines that are not always on and will run missed daily, weekly, and monthly jobs on the next startup.
Cron itself is secure, but misconfigured cron jobs can create vulnerabilities. Running jobs as root when a less-privileged user would suffice is the most common risk. Also, if a cron job reads from a world-writable directory or calls a script that can be overwritten by other users, an attacker could hijack it. Always apply the principle of least privilege: run cron jobs as the lowest-permission user that can still complete the task.