Advanced Techniques for Scheduling Biweekly Cron Jobs: Step-by-Step Solutions


15 views

The standard cron syntax doesn't natively support biweekly scheduling due to its fixed time unit structure. While it offers minute/hour/day/month granularity with step values, there's no direct way to express "every two weeks" in a single cron expression.

Here are three practical approaches to implement biweekly scheduling:

1. Day-of-Week + Day-of-Month Combination

# Runs every other Monday (biweekly)
0 0 * * 1 [ $(($(date +\%W)\%2)) -eq 0 ] && /path/to/command

2. Date-Based Check

# Runs on 1st and 15th of each month (approximate biweekly)
0 0 1,15 * * /path/to/command

3. Timestamp File Tracking

0 0 * * * [ ! -f /tmp/last_run ] || \
  [ $(($(date +\%s) - $(stat -c \%Y /tmp/last_run))) -gt 1209600 ] && \
  /path/to/command && touch /tmp/last_run

The most accurate method combines cron with a script that tracks execution timing:

#!/bin/bash
LAST_RUN_FILE="/var/run/biweekly_job.last"
TWO_WEEKS=$((60*60*24*14))

[ -f "$LAST_RUN_FILE" ] || touch "$LAST_RUN_FILE"
LAST_RUN=$(stat -c %Y "$LAST_RUN_FILE")
NOW=$(date +%s)

if [ $((NOW - LAST_RUN)) -ge $TWO_WEEKS ]; then
    # Your actual commands here
    echo "Running biweekly job at $(date)"
    
    # Update last run time
    touch "$LAST_RUN_FILE"
fi

Then schedule this script to run daily in crontab:

0 0 * * * /path/to/biweekly_script.sh

For modern Linux systems using systemd, create a more precise solution:

[Unit]
Description=Biweekly job

[Timer]
OnCalendar=Mon *-*-* 00:00:00
Persistent=true
AccuracySec=1h

[Install]
WantedBy=timers.target

Save as /etc/systemd/system/biweekly-job.timer and enable with:

systemctl enable --now biweekly-job.timer
  • Daylight saving time adjustments
  • Server reboots and time synchronization
  • Logging for verification
  • Error handling for missed executions

Cron's time-based job scheduler is incredibly powerful, but it has one notable limitation: it doesn't natively support biweekly (every two weeks) scheduling. The standard crontab syntax allows for minute, hour, day of month, month, and day of week specifications, but no direct way to express "every other week".

The crontab format provides these fields:

field         allowed values
-----         --------------
minute        0-59
hour          0-23
day of month  1-31
month         1-12
day of week   0-7 (0 or 7 is Sun)

While cron supports step values (like */2 for every other unit), this doesn't help with biweekly scheduling as weeks don't align neatly with the numeric fields.

Here are several approaches to implement biweekly scheduling:

1. Using Date Checks in Scripts

Create a wrapper script that checks the week number before executing:

#!/bin/bash
# Only run on even week numbers
if [ $(( $(date +%W) % 2 )) -eq 0 ]; then
    /path/to/your/actual/script.sh
fi

Then schedule it to run weekly:

0 0 * * 1 /path/to/wrapper_script.sh

2. Using Two Separate Cron Entries

For a specific weekday (e.g., Monday) every other week:

# First week's Monday
0 0 1-7 * 1 /path/to/script.sh
# Third week's Monday
0 0 15-21 * 1 /path/to/script.sh

3. Using Temporary Files as Markers

This approach alternates execution based on a flag file:

#!/bin/bash
FLAG_FILE="/tmp/biweekly_flag"

if [ -f "$FLAG_FILE" ]; then
    rm "$FLAG_FILE"
    /path/to/your/script.sh
else
    touch "$FLAG_FILE"
fi

Schedule it weekly:

0 0 * * 1 /path/to/flag_based_script.sh

For more complex scheduling needs, consider:

  • systemd timers - More flexible time specifications
  • anacron - Better for irregular schedules on systems that aren't always running
  • custom scheduler scripts - Using Python, Node.js, etc. with persistent storage

When implementing biweekly schedules:

  • Document your chosen method clearly in comments
  • Include error handling for edge cases
  • Consider daylight saving time transitions
  • Test thoroughly across week boundaries