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