Cron Jobs
How to schedule and manage recurring tasks using cron syntax across Linux, Python, and Node.js.
Overview
Cron is the standard Unix job scheduler for running commands at specified intervals. Whether you need to back up databases, send emails, clean logs, or fetch data, cron provides a reliable mechanism for recurring automation.
Beyond system cron, most programming ecosystems offer scheduling libraries that bring cron-like functionality directly into your application.
When to Use
Use this recipe when:
- Running periodic tasks on a server (backups, cleanups, reports). See Background Jobs for task queue patterns.
- Scheduling background jobs within an application. See Scheduled Jobs for serverless cron.
- Replacing manual processes with automated scripts. See Bash Scripting Automation for script automation.
- Coordinating distributed job execution. See RabbitMQ Task Queue for distributed task coordination.
Solution
Linux (System Cron)
# Edit crontab
crontab -e
# Every day at 3:00 AM
0 3 * * * /usr/local/bin/backup.sh
# Every 15 minutes
*/15 * * * * /usr/local/bin/check-health.sh
# Every Monday at 9:00 AM
0 9 * * 1 /usr/local/bin/weekly-report.sh
# Every first day of the month at midnight
0 0 1 * * /usr/local/bin/monthly-cleanup.sh
Python
import schedule
import time
def job():
print("Running scheduled task...")
# Every 10 minutes
schedule.every(10).minutes.do(job)
# Every day at 9:30 AM
schedule.every().day.at("09:30").do(job)
# Every Monday
schedule.every().monday.do(job)
while True:
schedule.run_pending()
time.sleep(1)
JavaScript (Node.js)
const cron = require('node-cron');
// Every 15 minutes
cron.schedule('*/15 * * * *', () => {
console.log('Running every 15 minutes');
});
// Every day at 3:00 AM
cron.schedule('0 3 * * *', () => {
console.log('Running daily backup');
});
// Every Monday at 9:00 AM
cron.schedule('0 9 * * 1', () => {
console.log('Running weekly report');
});
Explanation
Cron expressions use 5 fields:
| Field | Allowed Values | Description |
|---|---|---|
| Minute | 0-59 | Minute of the hour |
| Hour | 0-23 | Hour of the day |
| Day of Month | 1-31 | Day of the month |
| Month | 1-12 | Month of the year |
| Day of Week | 0-7 (0 and 7 = Sunday) | Day of the week |
Special characters:
*— any value,— value list separator |-— range of values | |*/n— every n steps |
Common Schedules
| Expression | Schedule |
|---|---|
*/5 * * * * | Every 5 minutes |
0 * * * * | Every hour |
0 0 * * * | Every day at midnight |
0 9 * * 1 | Every Monday at 9 AM |
0 0 1 * * | First day of every month |
0 0 * * 0 | Every Sunday at midnight |
What Works
- Use absolute paths for commands and scripts in crontab
- Redirect output to a log file or
/dev/nullto avoid mail spam - Set a specific timezone if your jobs depend on business hours
- Use a process manager (systemd, PM2) for application-level schedulers
- Add error handling and alerting for failed scheduled tasks
- Test expressions with online cron validators before deploying
Common Mistakes
- Forgetting to make scripts executable (
chmod +x) - Using relative paths that fail in cron’s minimal environment
- Not handling overlapping job executions (use locking)
- Ignoring daylight saving time changes
- Running too frequent jobs without rate limiting or backoff
Performance Tips
- Stagger job schedules. Avoid running multiple heavy jobs at the same time:
# Bad: all at midnight
0 0 * * * /usr/local/bin/backup.sh
0 0 * * * /usr/local/bin/cleanup.sh
0 0 * * * /usr/local/bin/report.sh
# Good: stagger by 30 minutes
0 0 * * * /usr/local/bin/backup.sh
30 0 * * * /usr/local/bin/cleanup.sh
0 1 * * * /usr/local/bin/report.sh
- Use jitter for distributed jobs. Add random delay to prevent thundering herd:
import random
import time
def run_with_jitter(max_delay=300):
delay = random.randint(0, max_delay)
time.sleep(delay)
run_job()
- Set timeouts. Prevent runaway jobs from consuming resources:
# Kill job after 1 hour
0 3 * * * timeout 3600 /usr/local/bin/backup.sh
# Kubernetes CronJob
spec:
jobTemplate:
spec:
activeDeadlineSeconds: 3600
- Clean up old job artifacts. Set retention policies:
# Delete backups older than 30 days
0 4 * * * find /backup -name "*.sql" -mtime +30 -delete
# Kubernetes CronJob
spec:
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 5 Frequently Asked Questions
How do I see which cron jobs are running?
Use crontab -l for the current user, or sudo cat /var/spool/cron/crontabs/ for system jobs.
Can I run cron jobs inside a Docker container?
Yes, but the container must stay running. Consider using the host's cron or an external scheduler like Kubernetes CronJobs.
What happens if a job takes longer than its interval?
By default, overlapping jobs will run concurrently. Use file locks or a job queue to prevent overlap.
Related Resources
Schedule and Monitor DAGs with Apache Airflow
Define, schedule, and monitor Airflow DAGs with operators, sensors, XCom, task dependencies, and the TaskFlow API.
RecipeGit Workflow
A practical branching strategy for teams: feature branches, pull requests, and clean commit history.
PatternObserver Pattern
Define a subscription mechanism to notify multiple objects about events. A behavioral design pattern for event-driven communication.
RecipeAPScheduler BackgroundScheduler: Prevent Overlapping Jobs
Run cron-like jobs in Python using APScheduler. Covers interval, cron, and date triggers, job stores, and background scheduling.
RecipeBackground Jobs
How to schedule and run background jobs using cron, task queues, and workers.
RecipeCI/CD Pipeline Setup
Set up automated CI/CD pipelines for testing, building, and deploying applications with GitHub Actions and what works.