Tools: Cron Expression Builder Guide: Create Scheduled Tasks Like a Pro

Tools: Cron Expression Builder Guide: Create Scheduled Tasks Like a Pro

What Is Cron and Why Does It Matter?

The 5-Field Cron Syntax Explained

Field Reference Table

Special Characters in Cron Expressions

Asterisk (*) — Any Value

Comma (,) — List

Hyphen (-) — Range

Slash (/) — Step

Non-Standard Characters

Common Cron Schedule Examples

Every X Minutes

Hourly Schedules

Daily Schedules

Weekly Schedules

Monthly Schedules

Business-Oriented Schedules

Using a Cron Expression Builder: Step-by-Step

Step 1: Open the Builder

Step 2: Select the Frequency

Step 3: Customize Each Field

Step 4: Review the Human-Readable Description

Step 5: Preview the Next Run Times

Step 6: Copy and Deploy

Managing Crontab on Linux and macOS

Essential Crontab Commands

Crontab File Format

System-Wide Cron Directories

Cron Expressions in CI/CD Pipelines

GitHub Actions

GitLab CI/CD

Jenkins

AWS CloudWatch Events / EventBridge

Kubernetes CronJobs

Debugging Cron Jobs: Why Your Job Did Not Run

1. Check the Expression

2. Inspect the Cron Log

3. Verify the Environment

4. Check Permissions

5. Capture Output

6. Test Manually First

Timezone Considerations for Cron

System Crontab

Per-Job Timezone (Modern Systems)

Daylight Saving Time Pitfalls

Advanced Cron Patterns and Techniques

Combining Ranges, Lists, and Steps

Running on Specific Months

Locking to Prevent Overlap

Cron Alternatives Worth Knowing

Best Practices for Production Cron Jobs

Frequently Asked Questions

What is a cron expression?

How do I create a cron expression without memorizing the syntax?

What does */5 * * * * mean?

Why did my cron job not run?

What timezone does cron use?

Can I run a cron job every 30 seconds?

What is the difference between cron and crontab?

How do I schedule a cron job in GitHub Actions?

Conclusion If you have ever needed to run a script at 2 AM every Sunday, send a report on the first business day of each month, or purge temp files every fifteen minutes, you have encountered cron. The tiny scheduling daemon that ships with every Unix and Linux system has been quietly running the internet's background tasks since the 1970s — and its five-field expression syntax remains the lingua franca of scheduled automation everywhere from bare-metal servers to Kubernetes, GitHub Actions, and AWS CloudWatch. The problem? Cron syntax is terse. Writing 15 3 1-7 * 1 from memory and trusting it will fire on the first Monday of the month takes confidence most of us do not have. That is exactly why a cron expression builder exists — a visual tool that lets you pick the schedule you want and translates it into a valid cron string instantly. In this comprehensive cron expression builder guide, you will learn the five-field syntax inside and out, master every special character, walk through a step-by-step builder workflow using our free cron expression generator, explore cron in CI/CD pipelines, and pick up debugging and timezone tips that will save you hours of frustration. Cron is a time-based job scheduler found in Unix-like operating systems. The name comes from the Greek word chronos (time). A cron job is any command or script that cron runs on a recurring schedule you define with a cron expression. Cron matters because scheduled automation is everywhere: Any time you hear "run this every…" the answer almost always involves a cron expression. A standard cron expression consists of five fields separated by spaces. Each field constrains when the job fires: The cron daemon evaluates all five fields against the current system time every minute. When every field matches, the associated command runs. Think of it as a logical AND across all five conditions. Tip: Some implementations (Quartz, Spring, AWS EventBridge) add a sixth seconds field at the beginning or a year field at the end. Always check your platform's documentation. For the standard Unix crontab, five fields is all you need. Four special characters give cron expressions their flexibility. Mastering them is the key to building any schedule without a cron expression builder — though a builder is still handy for verification. The wildcard matches every possible value for a field. * * * * * means "every minute of every hour of every day of every month on every day of the week" — in other words, every single minute. Specifies a list of discrete values. 0 8,12,18 * * * fires at 8:00 AM, 12:00 PM, and 6:00 PM every day. You can list as many values as you need, separated by commas with no spaces. Defines an inclusive range. 0 9-17 * * 1-5 fires at the top of every hour from 9 AM to 5 PM, Monday through Friday. Ranges are cleaner than writing out every value with commas. Specifies an interval. */10 * * * * means "every 10 minutes." You can combine a starting value with a step: 5/15 * * * * fires at minutes 5, 20, 35, and 50. The slash is the most powerful character for building recurring schedules. Standard Unix crontab does not support L, W, #, or ?. If your target system is a plain Linux crontab, stick to * , - /. Here is a reference library of the schedules developers need most often. Bookmark this section or check our cron expression cheat sheet for even more patterns. While you can certainly hand-write cron expressions, a cron expression builder tool eliminates guesswork and catches mistakes before they reach production. Here is how to use our free online cron generator step by step. Navigate to the DevToolkit Cron Generator. You will see dropdown menus or input fields for each of the five cron fields: minute, hour, day of month, month, and day of week. Start with the broadest frequency that matches your requirement. Do you need something every few minutes, hourly, daily, weekly, or monthly? Many builders offer preset buttons for these common frequencies to get you started quickly. Fine-tune the individual fields. For example, if you want a job at 8:30 AM every weekday: The builder instantly shows you the resulting expression: 30 8 * * 1-5. Good cron builders display a plain-English translation of your expression, such as "At 08:30 AM, Monday through Friday." Read this carefully — it is much easier to spot a mistake in English than in cron syntax. Most builders show the next 5–10 execution times based on the current date. This is the most reliable verification: if the next run times match your expectations, the expression is correct. Pay attention to timezone settings — more on that below. Copy the generated expression and paste it into your crontab, CI/CD config, or cloud scheduler. Always test in a staging environment before deploying to production. Once you have built your cron expression, you need to install it in the system's cron scheduler. The crontab command is the standard interface. Each line in a crontab file follows this structure: Pro tip: Always redirect output with >> logfile 2>&1 so you have a trail to debug when things go wrong. Without redirection, cron emails the output to the user's local mailbox — which most people never check. In addition to per-user crontabs, Linux distributions provide system-wide cron directories: To use these directories, simply place an executable script inside them. No cron expression needed — the scheduling is handled by the directory name. Modern DevOps heavily leverages cron expressions outside of traditional crontab. Here is how cron syntax appears in popular CI/CD platforms. GitHub Actions uses the schedule trigger with standard 5-field cron expressions. All times are in UTC. Important: GitHub Actions scheduled workflows can be delayed during periods of high load. Do not rely on them for time-critical operations. Also note that scheduled workflows only run on the default branch. GitLab supports pipeline schedules configured through the UI or API. The cron syntax is identical to standard five-field expressions: Jenkins uses a cron-like syntax in the triggers block. It adds a special H symbol that distributes load by hashing the job name: AWS uses a six-field cron format that adds a year field and uses ? for either day-of-month or day-of-week: Notice the ? character — AWS requires it in either the day-of-month or day-of-week field. Use our cron expression builder to generate the correct format for your target platform. Kubernetes CronJobs use standard five-field cron syntax in YAML manifests: Cron jobs fail silently more often than any other part of a system. Here is a systematic checklist for debugging. Paste your cron expression into a cron expression builder and verify the next run times. A surprisingly common mistake is swapping the day-of-month and month fields, or using 24-hour time incorrectly (there is no hour 24 — midnight is 0). The cron log tells you whether cron attempted to execute your command. If you see no entry at the expected time, the expression itself is wrong or the cron daemon is not running. Cron runs commands in a minimal environment. Your shell profile (~/.bashrc, ~/.zshrc) is not loaded. Common issues include: Ensure the script is executable (chmod +x script.sh) and that the cron user has permission to access all files and directories the script touches. Also verify the user is not in /etc/cron.deny. Always redirect both stdout and stderr to a log file: Without this redirection, errors vanish into the void (or an unread local mailbox). This is the single most important debugging practice for cron jobs. Before scheduling, run the exact command that cron will execute in a clean shell. Simulate cron's minimal environment: If the command fails here, it will fail in cron too. Timezone handling is one of the most treacherous aspects of cron scheduling. Get it wrong and your 3 AM backup runs at 3 PM — or not at all when daylight saving time shifts. Traditional crontab uses the system timezone (whatever timedatectl or /etc/timezone reports). If your server is set to UTC but you want jobs to run at 9 AM Eastern, you must manually convert: 9 AM ET is 14:00 UTC (or 13:00 during EDT). This is error-prone. Some modern cron implementations (like systemd timers, Kubernetes CronJobs v1.25+, and cloud schedulers) let you set a timezone per job: When clocks spring forward, a 2:30 AM job may not fire because 2:30 AM does not exist that night. When clocks fall back, a 1:30 AM job may fire twice. Best practices: You can mix special characters within a single field for powerful combinations: If a cron job takes longer than its interval, you can end up with overlapping instances that corrupt data or exhaust resources. Use flock to prevent this: The -n flag tells flock to exit immediately if the lock is already held, so the second instance simply skips rather than queuing up. After years of collective experience, these practices separate reliable cron setups from fragile ones: A cron expression is a string of five fields (minute, hour, day of month, month, day of week) that defines a recurring schedule for automated tasks. Each field specifies when a job should run, and the job fires when all fields match the current time. Use a cron expression builder tool. You select your desired schedule from dropdown menus or input fields, and the tool generates the correct cron string. It also shows you the next execution times so you can verify the schedule is right. It means "every 5 minutes." The */5 in the minute field tells cron to fire at minutes 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, and 55 of every hour, every day. The most common reasons are: incorrect cron expression syntax, missing environment variables or PATH entries (cron uses a minimal environment), insufficient file permissions, the cron daemon not running, or the script failing silently. Check the cron log (/var/log/syslog on Ubuntu) and ensure your script outputs errors to a log file. By default, cron uses the system timezone configured on the server. GitHub Actions always uses UTC. Cloud platforms like AWS and GCP let you specify a timezone. Best practice for production is to run servers in UTC and convert times manually, or use a scheduler that supports explicit timezone configuration. Standard cron's smallest granularity is one minute. To run something every 30 seconds, you can create two cron entries — one that runs at the start of each minute and one delayed by 30 seconds using sleep: * * * * * /path/to/script.sh and * * * * * sleep 30 && /path/to/script.sh. For sub-minute scheduling, consider using systemd timers or a dedicated task queue instead. Cron is the background daemon (service) that reads schedule files and runs jobs at the specified times. Crontab (cron table) is the file that contains the schedule entries, and also the command (crontab -e) used to edit that file. You write cron expressions in your crontab, and the cron daemon executes them. Add a schedule trigger to your workflow YAML file with a cron key. For example, on: schedule: - cron: '0 3 * * *' runs the workflow at 3 AM UTC daily. Remember that GitHub Actions only supports UTC and may delay scheduled runs during high-demand periods. Cron expressions are deceptively simple — five fields, four special characters, infinite scheduling possibilities. Whether you are setting up a midnight database backup, a weekday-only health check, or a quarterly reporting job, the syntax remains the same. The trick is getting it right the first time. A cron expression builder takes the guesswork out of the equation. Instead of staring at 0 */4 1-15 * 1-5 and wondering if it does what you think, you get instant visual feedback, plain-English translations, and previews of upcoming execution times. Use our free cron expression generator to build, validate, and copy your next cron schedule in seconds. For a quick-reference card you can keep open in another tab, check out our cron expression cheat sheet with dozens of copy-paste-ready patterns. "@context": "https://schema.org",<br> "@type": "FAQPage",<br> "mainEntity": [<br> {<br> "@type": "Question",<br> "name": "What is a cron expression?",<br> "acceptedAnswer": {<br> "@type": "Answer",<br> "text": "A cron expression is a string of five fields (minute, hour, day of month, month, day of week) that defines a recurring schedule for automated tasks. Each field specifies when a job should run, and the job fires when all fields match the current time."<br> }<br> },<br> {<br> "@type": "Question",<br> "name": "How do I create a cron expression without memorizing the syntax?",<br> "acceptedAnswer": {<br> "@type": "Answer",<br> "text": "Use a cron expression builder tool. You select your desired schedule from dropdown menus or input fields, and the tool generates the correct cron string. It also shows you the next execution times so you can verify the schedule is right."<br> }<br> },<br> {<br> "@type": "Question",<br> "name": "What does */5 * * * * mean in cron?",<br> "acceptedAnswer": {<br> "@type": "Answer",<br> "text": "It means every 5 minutes. The */5 in the minute field tells cron to fire at minutes 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, and 55 of every hour, every day."<br> }<br> },<br> {<br> "@type": "Question",<br> "name": "Why did my cron job not run?",<br> "acceptedAnswer": {<br> "@type": "Answer",<br> "text": "The most common reasons are: incorrect cron expression syntax, missing environment variables or PATH entries (cron uses a minimal environment), insufficient file permissions, the cron daemon not running, or the script failing silently. Check the cron log and ensure your script outputs errors to a log file."<br> }<br> },<br> {<br> "@type": "Question",<br> "name": "What timezone does cron use?",<br> "acceptedAnswer": {<br> "@type": "Answer",<br> "text": "By default, cron uses the system timezone configured on the server. GitHub Actions always uses UTC. Cloud platforms like AWS and GCP let you specify a timezone. Best practice for production is to run servers in UTC and convert times manually."<br> }<br> },<br> {<br> "@type": "Question",<br> "name": "Can I run a cron job every 30 seconds?",<br> "acceptedAnswer": {<br> "@type": "Answer",<br> "text": "Standard cron's smallest granularity is one minute. To run something every 30 seconds, create two cron entries — one normal and one with 'sleep 30' prepended. For sub-minute scheduling, consider systemd timers or a dedicated task queue."<br> }<br> },<br> {<br> "@type": "Question",<br> "name": "What is the difference between cron and crontab?",<br> "acceptedAnswer": {<br> "@type": "Answer",<br> "text": "Cron is the background daemon that reads schedule files and runs jobs at specified times. Crontab (cron table) is the file containing schedule entries and the command used to edit that file. You write cron expressions in your crontab, and the cron daemon executes them."<br> }<br> },<br> {<br> "@type": "Question",<br> "name": "How do I schedule a cron job in GitHub Actions?",<br> "acceptedAnswer": {<br> "@type": "Answer",<br> "text": "Add a schedule trigger to your workflow YAML file with a cron key. For example, 'on: schedule: - cron: 0 3 * * *' runs the workflow at 3 AM UTC daily. GitHub Actions only supports UTC and may delay scheduled runs during high-demand periods."<br> }<br> }<br> ]<br>

})} /></p> Templates let you quickly answer FAQs or store snippets for re-use. Hide child comments as well For further actions, you may consider blocking this person and/or reporting abuse

Code Block

Copy

┌───────────── minute (0–59) │ ┌───────────── hour (0–23) │ │ ┌───────────── day of month (1–31) │ │ │ ┌───────────── month (1–12 or JAN–DEC) │ │ │ │ ┌───────────── day of week (0–7 or SUN–SAT; 0 and 7 both = Sunday) │ │ │ │ │ * * * * * ┌───────────── minute (0–59) │ ┌───────────── hour (0–23) │ │ ┌───────────── day of month (1–31) │ │ │ ┌───────────── month (1–12 or JAN–DEC) │ │ │ │ ┌───────────── day of week (0–7 or SUN–SAT; 0 and 7 both = Sunday) │ │ │ │ │ * * * * * ┌───────────── minute (0–59) │ ┌───────────── hour (0–23) │ │ ┌───────────── day of month (1–31) │ │ │ ┌───────────── month (1–12 or JAN–DEC) │ │ │ │ ┌───────────── day of week (0–7 or SUN–SAT; 0 and 7 both = Sunday) │ │ │ │ │ * * * * * * * * * * # Every minute */5 * * * * # Every 5 minutes */10 * * * * # Every 10 minutes */15 * * * * # Every 15 minutes */30 * * * * # Every 30 minutes * * * * * # Every minute */5 * * * * # Every 5 minutes */10 * * * * # Every 10 minutes */15 * * * * # Every 15 minutes */30 * * * * # Every 30 minutes * * * * * # Every minute */5 * * * * # Every 5 minutes */10 * * * * # Every 10 minutes */15 * * * * # Every 15 minutes */30 * * * * # Every 30 minutes 0 * * * * # Every hour at minute 0 30 * * * * # Every hour at minute 30 0 */2 * * * # Every 2 hours 0 */6 * * * # Every 6 hours 0 * * * * # Every hour at minute 0 30 * * * * # Every hour at minute 30 0 */2 * * * # Every 2 hours 0 */6 * * * # Every 6 hours 0 * * * * # Every hour at minute 0 30 * * * * # Every hour at minute 30 0 */2 * * * # Every 2 hours 0 */6 * * * # Every 6 hours 0 0 * * * # Midnight every day 0 6 * * * # 6:00 AM every day 30 8 * * * # 8:30 AM every day 0 22 * * * # 10:00 PM every day 0 0 * * * # Midnight every day 0 6 * * * # 6:00 AM every day 30 8 * * * # 8:30 AM every day 0 22 * * * # 10:00 PM every day 0 0 * * * # Midnight every day 0 6 * * * # 6:00 AM every day 30 8 * * * # 8:30 AM every day 0 22 * * * # 10:00 PM every day 0 0 * * 0 # Midnight every Sunday 0 9 * * 1 # 9:00 AM every Monday 0 17 * * 5 # 5:00 PM every Friday 0 10 * * 1-5 # 10:00 AM every weekday (Mon–Fri) 0 0 * * 0 # Midnight every Sunday 0 9 * * 1 # 9:00 AM every Monday 0 17 * * 5 # 5:00 PM every Friday 0 10 * * 1-5 # 10:00 AM every weekday (Mon–Fri) 0 0 * * 0 # Midnight every Sunday 0 9 * * 1 # 9:00 AM every Monday 0 17 * * 5 # 5:00 PM every Friday 0 10 * * 1-5 # 10:00 AM every weekday (Mon–Fri) 0 0 1 * * # Midnight on the 1st of every month 0 9 15 * * # 9:00 AM on the 15th of every month 0 0 1 1 * # Midnight on January 1st (yearly) 0 0 1 */3 * # Midnight on the 1st, every 3 months (quarterly) 0 0 1 * * # Midnight on the 1st of every month 0 9 15 * * # 9:00 AM on the 15th of every month 0 0 1 1 * # Midnight on January 1st (yearly) 0 0 1 */3 * # Midnight on the 1st, every 3 months (quarterly) 0 0 1 * * # Midnight on the 1st of every month 0 9 15 * * # 9:00 AM on the 15th of every month 0 0 1 1 * # Midnight on January 1st (yearly) 0 0 1 */3 * # Midnight on the 1st, every 3 months (quarterly) 0 9 * * 1-5 # 9 AM weekdays — morning standup trigger 0 0 1,15 * * # Midnight on 1st and 15th — bi-monthly payroll 0 3 * * 0 # 3 AM Sunday — weekly database maintenance */5 9-17 * * 1-5 # Every 5 min during business hours, weekdays only 0 9 * * 1-5 # 9 AM weekdays — morning standup trigger 0 0 1,15 * * # Midnight on 1st and 15th — bi-monthly payroll 0 3 * * 0 # 3 AM Sunday — weekly database maintenance */5 9-17 * * 1-5 # Every 5 min during business hours, weekdays only 0 9 * * 1-5 # 9 AM weekdays — morning standup trigger 0 0 1,15 * * # Midnight on 1st and 15th — bi-monthly payroll 0 3 * * 0 # 3 AM Sunday — weekly database maintenance */5 9-17 * * 1-5 # Every 5 min during business hours, weekdays only # View your current crontab crontab -l # Edit your crontab (opens in $EDITOR) crontab -e # Remove your entire crontab (use with extreme caution!) crontab -r # Edit another user's crontab (requires root) sudo crontab -u username -e # View your current crontab crontab -l # Edit your crontab (opens in $EDITOR) crontab -e # Remove your entire crontab (use with extreme caution!) crontab -r # Edit another user's crontab (requires root) sudo crontab -u username -e # View your current crontab crontab -l # Edit your crontab (opens in $EDITOR) crontab -e # Remove your entire crontab (use with extreme caution!) crontab -r # Edit another user's crontab (requires root) sudo crontab -u username -e # Environment variables (optional) SHELL=/bin/bash PATH=/usr/local/bin:/usr/bin:/bin [email protected] # Schedule entries # min hour dom month dow command 0 3 * * * /home/user/scripts/backup.sh >> /var/log/backup.log 2>&1 */5 * * * * /usr/bin/curl -s https://example.com/health > /dev/null 0 9 * * 1 /home/user/scripts/weekly-report.py # Environment variables (optional) SHELL=/bin/bash PATH=/usr/local/bin:/usr/bin:/bin [email protected] # Schedule entries # min hour dom month dow command 0 3 * * * /home/user/scripts/backup.sh >> /var/log/backup.log 2>&1 */5 * * * * /usr/bin/curl -s https://example.com/health > /dev/null 0 9 * * 1 /home/user/scripts/weekly-report.py # Environment variables (optional) SHELL=/bin/bash PATH=/usr/local/bin:/usr/bin:/bin [email protected] # Schedule entries # min hour dom month dow command 0 3 * * * /home/user/scripts/backup.sh >> /var/log/backup.log 2>&1 */5 * * * * /usr/bin/curl -s https://example.com/health > /dev/null 0 9 * * 1 /home/user/scripts/weekly-report.py name: Nightly Build on: schedule: - cron: '0 3 * * *' # 3:00 AM UTC every day - cron: '0 12 * * 1' # Noon UTC every Monday jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - run: npm run build && npm test name: Nightly Build on: schedule: - cron: '0 3 * * *' # 3:00 AM UTC every day - cron: '0 12 * * 1' # Noon UTC every Monday jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - run: npm run build && npm test name: Nightly Build on: schedule: - cron: '0 3 * * *' # 3:00 AM UTC every day - cron: '0 12 * * 1' # Noon UTC every Monday jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - run: npm run build && npm test # In GitLab UI: Pipeline Schedules → New Schedule # Cron: 0 2 * * * # Timezone: America/New_York # Target branch: main # In GitLab UI: Pipeline Schedules → New Schedule # Cron: 0 2 * * * # Timezone: America/New_York # Target branch: main # In GitLab UI: Pipeline Schedules → New Schedule # Cron: 0 2 * * * # Timezone: America/New_York # Target branch: main pipeline &#123; triggers &#123; cron('H 3 * * *') // Sometime during the 3 AM hour &#123; stages &#123; stage('Build') &#123; steps &#123; sh 'make build' &#123; &#123; &#123; &#123; pipeline &#123; triggers &#123; cron('H 3 * * *') // Sometime during the 3 AM hour &#123; stages &#123; stage('Build') &#123; steps &#123; sh 'make build' &#123; &#123; &#123; &#123; pipeline &#123; triggers &#123; cron('H 3 * * *') // Sometime during the 3 AM hour &#123; stages &#123; stage('Build') &#123; steps &#123; sh 'make build' &#123; &#123; &#123; &#123; # AWS cron format: minute hour day-of-month month day-of-week year cron(0 3 * * ? *) # 3 AM UTC every day cron(0 12 ? * MON-FRI *) # Noon UTC weekdays cron(0 0 1 * ? *) # Midnight on the 1st of every month # AWS cron format: minute hour day-of-month month day-of-week year cron(0 3 * * ? *) # 3 AM UTC every day cron(0 12 ? * MON-FRI *) # Noon UTC weekdays cron(0 0 1 * ? *) # Midnight on the 1st of every month # AWS cron format: minute hour day-of-month month day-of-week year cron(0 3 * * ? *) # 3 AM UTC every day cron(0 12 ? * MON-FRI *) # Noon UTC weekdays cron(0 0 1 * ? *) # Midnight on the 1st of every month apiVersion: batch/v1 kind: CronJob metadata: name: database-backup spec: schedule: "0 2 * * *" # 2 AM daily concurrencyPolicy: Forbid jobTemplate: spec: template: spec: containers: - name: backup image: backup-tool:latest command: ["./run-backup.sh"] restartPolicy: OnFailure apiVersion: batch/v1 kind: CronJob metadata: name: database-backup spec: schedule: "0 2 * * *" # 2 AM daily concurrencyPolicy: Forbid jobTemplate: spec: template: spec: containers: - name: backup image: backup-tool:latest command: ["./run-backup.sh"] restartPolicy: OnFailure apiVersion: batch/v1 kind: CronJob metadata: name: database-backup spec: schedule: "0 2 * * *" # 2 AM daily concurrencyPolicy: Forbid jobTemplate: spec: template: spec: containers: - name: backup image: backup-tool:latest command: ["./run-backup.sh"] restartPolicy: OnFailure # On most Linux systems grep CRON /var/log/syslog # On CentOS/RHEL grep CRON /var/log/cron # On macOS log show --predicate 'process == "cron"' --last 1h # On most Linux systems grep CRON /var/log/syslog # On CentOS/RHEL grep CRON /var/log/cron # On macOS log show --predicate 'process == "cron"' --last 1h # On most Linux systems grep CRON /var/log/syslog # On CentOS/RHEL grep CRON /var/log/cron # On macOS log show --predicate 'process == "cron"' --last 1h 0 3 * * * /home/user/backup.sh >> /home/user/logs/backup.log 2>&1 0 3 * * * /home/user/backup.sh >> /home/user/logs/backup.log 2>&1 0 3 * * * /home/user/backup.sh >> /home/user/logs/backup.log 2>&1 env -i HOME=$HOME SHELL=/bin/bash /bin/bash -c '/home/user/scripts/backup.sh' env -i HOME=$HOME SHELL=/bin/bash /bin/bash -c '/home/user/scripts/backup.sh' env -i HOME=$HOME SHELL=/bin/bash /bin/bash -c '/home/user/scripts/backup.sh' # Kubernetes CronJob with timezone (v1.25+) spec: schedule: "0 9 * * 1-5" timeZone: "America/New_York" # Kubernetes CronJob with timezone (v1.25+) spec: schedule: "0 9 * * 1-5" timeZone: "America/New_York" # Kubernetes CronJob with timezone (v1.25+) spec: schedule: "0 9 * * 1-5" timeZone: "America/New_York" # GitHub Actions — always UTC, no timezone override # Convert manually or use a step to check the time on: schedule: - cron: '0 14 * * 1-5' # 9 AM ET in winter (UTC-5) # GitHub Actions — always UTC, no timezone override # Convert manually or use a step to check the time on: schedule: - cron: '0 14 * * 1-5' # 9 AM ET in winter (UTC-5) # GitHub Actions — always UTC, no timezone override # Convert manually or use a step to check the time on: schedule: - cron: '0 14 * * 1-5' # 9 AM ET in winter (UTC-5) # Every 15 minutes during business hours on weekdays */15 9-17 * * 1-5 # At minute 0 and 30, hours 8–12 and 14–18 0,30 8-12,14-18 * * * # Every 2 hours starting at 1 AM 0 1/2 * * * # Fires at 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23 # Every 15 minutes during business hours on weekdays */15 9-17 * * 1-5 # At minute 0 and 30, hours 8–12 and 14–18 0,30 8-12,14-18 * * * # Every 2 hours starting at 1 AM 0 1/2 * * * # Fires at 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23 # Every 15 minutes during business hours on weekdays */15 9-17 * * 1-5 # At minute 0 and 30, hours 8–12 and 14–18 0,30 8-12,14-18 * * * # Every 2 hours starting at 1 AM 0 1/2 * * * # Fires at 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23 # Quarterly — 1st day of Jan, Apr, Jul, Oct at midnight 0 0 1 1,4,7,10 * # Every weekday in December (holiday prep) 0 9 * 12 1-5 # Quarterly — 1st day of Jan, Apr, Jul, Oct at midnight 0 0 1 1,4,7,10 * # Every weekday in December (holiday prep) 0 9 * 12 1-5 # Quarterly — 1st day of Jan, Apr, Jul, Oct at midnight 0 0 1 1,4,7,10 * # Every weekday in December (holiday prep) 0 9 * 12 1-5 # Only one instance runs at a time */5 * * * * /usr/bin/flock -n /tmp/myjob.lock /home/user/scripts/myjob.sh # Only one instance runs at a time */5 * * * * /usr/bin/flock -n /tmp/myjob.lock /home/user/scripts/myjob.sh # Only one instance runs at a time */5 * * * * /usr/bin/flock -n /tmp/myjob.lock /home/user/scripts/myjob.sh - Database backups — nightly dumps to S3 or GCS. - Log rotation — compress and archive logs before disks fill up. - Email digests — weekly summary emails to stakeholders. - Cache invalidation — periodic purges so stale data does not linger. - Health checks — ping services every minute and alert on failure. - CI/CD pipelines — nightly builds, scheduled deploys, dependency audits. - Data pipelines — ETL jobs, report generation, analytics aggregation. - Minute: Set to 30 - Hour: Set to 8 - Day of Month: Leave as * (any day) - Month: Leave as * (every month) - Day of Week: Set to 1-5 (Monday through Friday) - /etc/cron.d/ — drop-in cron files (include a username field after the schedule). - /etc/cron.hourly/ — scripts here run once per hour. - /etc/cron.daily/ — scripts here run once per day. - /etc/cron.weekly/ — scripts here run once per week. - /etc/cron.monthly/ — scripts here run once per month. - Missing PATH: Commands like node, python3, or docker may not be found. Use full paths like /usr/local/bin/node. - Missing environment variables: API keys, database URLs, and other secrets are not available. Source an env file at the start of your script or set variables in the crontab with ENV_VAR=value lines. - Wrong working directory: Cron starts in the user's home directory. Use cd /path/to/project && before your command, or use absolute paths throughout your script. - Schedule critical jobs in UTC to avoid DST surprises entirely. - Avoid scheduling jobs during the 1:00–3:00 AM window in timezones that observe DST. - Use idempotent scripts so running twice causes no harm. - If you must use local time, use a scheduler that supports timezone-aware scheduling (systemd timers, Kubernetes with timeZone). - systemd timers: More flexible than cron on modern Linux. Support monotonic (boot-relative) timers, randomized delays, and better logging via journalctl. - at: For one-time scheduled jobs. at now + 2 hours runs a command once, two hours from now. - Celery Beat: Python-based periodic task scheduler, ideal for Django and Flask applications. - node-cron: NPM package for running cron-scheduled functions inside Node.js processes. - Always use a cron expression builder to verify. Even experienced sysadmins double-check with a tool. Our cron generator shows next run times so you can confirm before deploying. - Log everything. Redirect stdout and stderr to timestamped log files. Rotate logs with logrotate. - Use absolute paths. Never rely on PATH or relative paths in cron commands. - Make scripts idempotent. If a script runs twice by accident, the result should be the same as running once. - Set up alerting. Use MAILTO in crontab, or have your script send a Slack/Discord/PagerDuty alert on failure. - Use lock files. Prevent overlapping executions with flock or a PID file. - Document each job. Add a comment above every crontab entry explaining what it does and who owns it. - Version-control your crontab. Export it periodically with crontab -l > crontab.bak and commit it to your repo. - Prefer UTC for servers. This eliminates DST headaches and makes cross-timezone coordination simpler. - Test in staging first. Never deploy a new cron job directly to production. Test with a short interval (e.g., every minute), verify it works, then set the real schedule.