Troubleshooting Guide

Cron Job Running Twice — Why & How to Fix Duplicate Runs

Your cron job is executing more often than it should. Here's how to find the duplicate and stop it.

Quick Diagnostic Checklist

Check for duplicate crontab entries crontab -l | sort | uniq -d
Check system-wide cron directories ls /etc/cron.d/ /etc/cron.daily/
Check if previous run is still going ps aux | grep your-script
Check anacron for overlap cat /etc/anacrontab

A cron job running twice can cause real damage: duplicate emails sent to customers, double database entries, duplicate charges, or corrupted data from concurrent writes. This guide covers every cause of duplicate cron execution and the exact fix for each.

1. Duplicate Crontab Entries

The simplest and most common cause. You (or a deploy script) added the same cron entry twice. This is especially common when crontab entries are added programmatically via crontab -l | { cat; echo "..."; } | crontab - without checking if the entry already exists.

Diagnose it: List your crontab and look for duplicates:

# Show your crontab
crontab -l

# Find exact duplicates
crontab -l | sort | uniq -d

Fix it: Edit your crontab and remove the duplicate line:

crontab -e

If your deploy scripts add cron entries, fix them to check for existing entries first:

# Safe way to add a cron entry (only if it doesn't exist)
(crontab -l 2>/dev/null | grep -v "/path/to/script.sh"; echo "0 2 * * * /path/to/script.sh") | crontab -

2. Same Job in User Crontab AND System Cron

There are multiple places cron jobs can be defined. If the same job appears in two locations, it runs twice:

  • User crontab — edited with crontab -e
  • /etc/crontab — the system crontab
  • /etc/cron.d/ — drop-in cron files
  • /etc/cron.daily/, /etc/cron.hourly/, etc. — periodic directories

Diagnose it: Check all locations for your script:

# User crontab
crontab -l

# System crontab
cat /etc/crontab

# Drop-in directory
ls /etc/cron.d/
grep -r "your-script" /etc/cron.d/

# Periodic directories
grep -r "your-script" /etc/cron.daily/ /etc/cron.hourly/ /etc/cron.weekly/ /etc/cron.monthly/

Fix it: Remove the duplicate from whichever location is incorrect. Typically, keep it in the user crontab and remove it from the system-wide files (or vice versa).

Track exactly when and how often your cron jobs run with CronSignal.

Sign up with Google
or

3. Overlapping Executions — Job Takes Longer Than the Interval

If your cron job runs every 5 minutes but the job itself takes 7 minutes to complete, the second instance starts while the first is still running. This is not technically running "twice" at the scheduled time — it's two instances running concurrently, which can be even worse.

Diagnose it: Check if multiple instances are running:

# Check for running instances
ps aux | grep your-script.sh

# Count instances
pgrep -c -f your-script.sh

Fix it: Use flock to create a file lock. This is the standard, reliable solution:

# In your crontab:
*/5 * * * * /usr/bin/flock -n /tmp/myjob.lock /path/to/script.sh

The -n flag means "non-blocking" — if the lock is already held by a running instance, the new instance exits immediately instead of waiting. The lock is automatically released when the process finishes.

You can also implement locking inside your script:

#!/bin/bash
LOCKFILE="/tmp/myjob.lock"

# Try to get the lock
exec 200>"$LOCKFILE"
flock -n 200 || { echo "Already running"; exit 1; }

# Your actual job logic here
/usr/bin/python3 /home/user/app/process.py

# Lock is released automatically when script exits

4. Anacron + Cron Overlap

Anacron is designed to run missed jobs after a system wakes up or boots. If you have the same job configured in both cron and anacron, it can execute twice — once by cron at the scheduled time, and once by anacron when it catches up.

Diagnose it: Check anacron configuration:

cat /etc/anacrontab

And compare with your cron entries. On many distributions, /etc/cron.daily/ and similar directories are actually run by anacron, not cron. Check:

# On Debian/Ubuntu, this is often in /etc/crontab:
cat /etc/crontab | grep -i anacron

# Or check if anacron is handling the periodic directories:
ls -la /etc/cron.daily/0anacron

Fix it: Keep the job in one system only. If you're using /etc/cron.daily/, let anacron handle it and remove the equivalent entry from your user crontab. Or vice versa — use the user crontab with a specific schedule and remove the script from /etc/cron.daily/.

5. Daylight Saving Time Causing Double Runs

When clocks "fall back" for DST (e.g., 2:00 AM becomes 1:00 AM), any cron job scheduled between 1:00 AM and 2:00 AM will run twice — once before the clock change and once after, because that hour happens twice.

Example: A job scheduled at 0 1 * * * (1:00 AM) in the US Eastern timezone will run twice on the first Sunday of November.

Fix option 1: Schedule jobs outside the DST transition window (avoid 1:00 AM - 3:00 AM):

# Instead of 1 AM, run at 4 AM
0 4 * * * /path/to/script.sh

Fix option 2: Use UTC for your cron daemon, which has no DST transitions:

# Set timezone at the top of your crontab
TZ=UTC
0 6 * * * /path/to/script.sh

Fix option 3: Use flock as a safety net, so even if cron triggers twice, only one instance runs:

0 1 * * * /usr/bin/flock -n /tmp/nightly-backup.lock /path/to/backup.sh

The Universal Fix: flock

Regardless of the root cause, adding flock to any cron job prevents concurrent execution. It's a best practice for any job where duplicate runs would be harmful:

# Template for any cron job with flock protection
*/5 * * * * /usr/bin/flock -n /tmp/JOBNAME.lock /path/to/script.sh

Key points about flock:

  • -n — exit immediately if lock is held (don't queue up)
  • -w 60 — wait up to 60 seconds for the lock before giving up
  • The lock file is automatically created if it doesn't exist
  • The lock is automatically released when the process exits (even on crash)
  • Use a unique lock file path per job

Monitor Your Cron Job Frequency

Once you've fixed the duplicate execution, how do you know it stays fixed? A deployment could re-add a duplicate entry. A system update could re-enable anacron. The next DST transition could trigger a double run.

CronSignal tracks exactly when your cron jobs ping in. If a job that should run once per hour suddenly pings twice, you'll see it immediately in your dashboard. Set up monitoring in 30 seconds:

0 2 * * * /usr/bin/flock -n /tmp/backup.lock /home/scripts/backup.sh && curl -fsS https://api.cronsignal.io/ping/your-check-id

The heartbeat ping only fires if the job succeeds. If it runs twice, if it fails, or if it doesn't run at all — you'll know.

Related Resources

Never debug silent cron failures again

CronSignal alerts you the moment a job doesn't run — or runs too often. Know about failures before they become disasters.

Sign up with Google
or

Need help with cron expressions? Use our cron validator to check syntax or cron generator to build expressions visually.

Explore More