Skip to main content

anacron — Periodic Catch-Up Scheduler

Learning Focus

By the end of this lesson you will be able to write an /etc/anacrontab entry, set START_HOURS_RANGE and RANDOM_DELAY, understand catch-up execution behavior, distinguish @monthly from 30, combine anacron with flock, debug failing jobs using anacron -d, and decide when to choose anacron over cron or systemd timers.

Overview

anacron runs periodic jobs based on days, not exact clock times. It is designed for systems that are not always on — laptops, small VPS hosts that reboot often, or maintenance servers that stop overnight. Unlike cron, anacron catches up jobs that were missed while the machine was down. This makes it the right tool for daily, weekly, and monthly maintenance work where reliability matters more than minute-level precision. On a WordPress VPS, anacron is a solid fallback for backups, plugin audits, and certificate renewal checks when the server's uptime is not guaranteed.

Tool Snapshot
  • Core Function: Run periodic jobs by day-based frequency with automatic catch-up for missed runs.
  • Primary Benefit: Missed-run resilience — jobs execute after downtime rather than being silently skipped.
  • Where to Use: Non-24/7 servers, laptops, maintenance hosts, or as a catch-up layer alongside cron.
  • Key Limitation: Not a precision scheduler — does not support minute, hour, or exact-clock timing.

System Check

command -v anacron || echo "anacron is not installed"
anacron -V 2>/dev/null || true
sudo test -f /etc/anacrontab && echo "anacrontab exists" || echo "anacrontab missing"
sudo ls -lah /var/spool/anacron 2>/dev/null || true

Install Anacron

If anacron is missing from your system, install it first.

install-anacron.sh
# Debian / Ubuntu
sudo apt update && sudo apt install -y anacron

# RHEL / CentOS / Alma / Rocky
sudo dnf install -y cronie-anacron

# Arch Linux
sudo pacman -S --noconfirm cronie

After installation, verify and validate the default config:

verify-anacron-after-install.sh
command -v anacron # Expected: /usr/sbin/anacron or /bin/anacron
anacron -V # Show version
sudo anacron -T # Validate /etc/anacrontab syntax (exit 0 = OK)

How anacron Works

Anacron reads /etc/anacrontab and checks each job's timestamp in its spool directory (usually /var/spool/anacron). The decision process for each job:

  1. Read the last-run date from /var/spool/anacron/<job-identifier>.
  2. Compare today's date with the last-run date.
  3. If the period (in days) has elapsed, mark the job eligible.
  4. Wait the configured delay in minutes (plus any RANDOM_DELAY offset).
  5. If within the START_HOURS_RANGE window, execute the command.
  6. Record the new date stamp in the spool file.

Lifecycle Diagram

Key Behavioral Rules

BehaviorDetails
Frequency is day-basedMinute/hour precision is not possible
Catch-up on bootIf a job was due while machine was off, anacron runs it on next startup
START_HOURS_RANGE gatingIf the startup window is missed entirely, the run is skipped until the next eligible day
RANDOM_DELAYAdds 0–N random minutes per job to prevent fleet-wide thundering herd
Active job lockingA running job blocks another anacron instance from starting the same job

Where Anacron Data Lives

LocationPurpose
/etc/anacrontabMain config — periods, delays, identifiers, commands
/var/spool/anacron/Timestamp spool — one file per job identifier
/etc/cron.daily/Daily scripts often executed through anacron via run-parts
/etc/cron.weekly/Weekly scripts often executed through anacron via run-parts
/etc/cron.monthly/Monthly scripts often executed through anacron via run-parts
/etc/crontab / /etc/cron.d/*Distro-specific glue between cron and anacron
inspect-anacron-state.sh
sudo ls -lah /etc/anacrontab /var/spool/anacron 2>/dev/null || true
sudo cat /etc/anacrontab
sudo ls -lah /etc/cron.daily /etc/cron.weekly /etc/cron.monthly 2>/dev/null || true

When to Use Anacron

ScenarioAnacron FitWhy
Daily/weekly/monthly maintenanceStrongBuilt for day-based recurring jobs
Host may be offline at schedule timeStrongCatch-up execution behavior
Need exact minute/hour schedulingWeakAnacron is not a precision clock scheduler
Need sub-daily cadence (hourly, every 5 min)WeakUse cron or systemd timers instead
Need dependency ordering or journald logsWeakUse systemd timers

Quick rule:

  • Choose anacron for periodic catch-up by days
  • Choose cron for simple exact-time schedules
  • Choose systemd timers for modern production controls, logging, and observability

Your First Anacron Entry in 5 Minutes

This hands-on walkthrough adds a test job to validate the full anacron lifecycle.

Step 1 — Create the script

create-anacron-test-script.sh
sudo tee /usr/local/bin/anacron-heartbeat.sh > /dev/null << 'EOF'
#!/usr/bin/env bash
echo "[$(date -Is)] anacron heartbeat" >> /tmp/anacron-heartbeat.log
EOF
sudo chmod +x /usr/local/bin/anacron-heartbeat.sh

Step 2 — Test the script manually

test-script-manually.sh
/usr/local/bin/anacron-heartbeat.sh
cat /tmp/anacron-heartbeat.log
expected-output.txt
[2026-03-02T04:10:00+00:00] anacron heartbeat

Step 3 — Add the job to /etc/anacrontab

Open with:

open-anacrontab.sh
sudo nano /etc/anacrontab

Add this line at the bottom (after any existing entries):

anacrontab-test-entry.txt
@daily 5 anacron-heartbeat /usr/local/bin/anacron-heartbeat.sh >> /tmp/anacron-heartbeat.log 2>&1

Step 4 — Validate the config

validate-anacrontab.sh
sudo anacron -T && echo "Syntax OK"
expected-output.txt
Syntax OK

Step 5 — Force a test run now

force-run-anacron.sh
sudo anacron -f -n -s # Force all eligible jobs, no delay, serial
cat /tmp/anacron-heartbeat.log
expected-output.txt
[2026-03-02T04:10:05+00:00] anacron heartbeat

Step 6 — Check the spool timestamp was recorded

check-spool-timestamp.sh
sudo ls -lah /var/spool/anacron/anacron-heartbeat
cat /var/spool/anacron/anacron-heartbeat # Should show today's date

You now know the complete lifecycle: create script → test manually → add entry → validate → force run → verify spool. Every anacron job follows the same pattern.


anacrontab Syntax Reference

Core job format

period delay job-identifier command

Example:

anacrontab-job-line-example.txt
1 5 cron.daily nice run-parts /etc/cron.daily

Field meanings

FieldMeaningExample
periodFrequency in days or macro1, 7, 30, @daily, @weekly, @monthly
delayDelay in minutes before run after becoming eligible0, 5, 30
job-identifierUnique job name — maps to spool filewp-db-backup, backup-prune
commandShell command or script to execute/usr/local/bin/wp-backup.sh

Period macros

MacroEquivalentMeaning
@daily1Once per day
@weekly7Once per week
@monthlyMonth-awareOnce per calendar month
@monthly is NOT the same as 30

@monthly means calendar month cadence. 30 means every 30 days. Over time these diverge — January has 31 days, February has 28. Use @monthly for genuine monthly jobs.

Environment variables

/etc/anacrontab supports environment assignments that apply to all jobs below them:

VariablePurposeTypical Value
SHELLShell used for commands/bin/sh or /bin/bash
PATHCommand search path/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
MAILTORecipient for job output mailroot, ops@example.com, or ""
NO_MAIL_OUTPUTDisables mailing output if non-empty1
RANDOM_DELAYMaximum extra random minutes added per job0, 10, 30
START_HOURS_RANGEAllowed start window by hour6-8, 1-5, 0-23

Recommended production header:

anacrontab-header.txt
SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
MAILTO=""
NO_MAIL_OUTPUT=1
RANDOM_DELAY=20
START_HOURS_RANGE=2-7

START_HOURS_RANGE and RANDOM_DELAY In Depth

These two settings strongly affect when jobs actually run.

START_HOURS_RANGE

Define the allowed start-hour window (e.g., 3-6 = 3 AM through 6 AM).

  • If the system boots before or within the window, eligible jobs run during the window.
  • If the system misses the entire window (e.g., it only comes up at 8 AM when the window was 3–6), the run is skipped for that day and anacron will try again the following day.
  • Set it to maintenance hours to avoid jobs running during business hours.

RANDOM_DELAY

Adds a random number of minutes between 0 and RANDOM_DELAY to each job's delay field.

  • Prevents all jobs from spiking at exactly the same second after boot.
  • Critical on fleets: if 50 servers all run wp db export at exactly boot+5min, your database host will notice.
  • Keep values moderate so critical jobs don't drift too far from their window.
anacrontab-range-and-random.txt
RANDOM_DELAY=30
START_HOURS_RANGE=2-6

# period delay identifier command
1 5 cron.daily nice run-parts /etc/cron.daily
7 0 cron.weekly nice run-parts /etc/cron.weekly

Cron + Anacron Integration

On many distros, cron and anacron are wired together so that /etc/cron.daily, /etc/cron.weekly, and /etc/cron.monthly scripts still run even if the host was down at their scheduled cron time.

A common pattern in /etc/crontab:

crontab-anacron-fallback-pattern.txt
25 6 * * * root test -x /usr/sbin/anacron || { cd / && run-parts --report /etc/cron.daily; }
47 6 * * 7 root test -x /usr/sbin/anacron || { cd / && run-parts --report /etc/cron.weekly; }
52 6 1 * * root test -x /usr/sbin/anacron || { cd / && run-parts --report /etc/cron.monthly; }

Interpretation: if anacron exists, it handles catch-up for the periodic directories. If anacron is absent, cron falls back to direct run-parts execution.

check-cron-anacron-integration.sh
command -v anacron || echo "anacron not installed"
sudo grep -n 'anacron\|run-parts.*cron' /etc/crontab /etc/cron.d/* 2>/dev/null || true

anacron Command Reference

CommandWhat It Does
anacron -TValidate anacrontab syntax
anacron -fForce all jobs, ignore timestamps
anacron -uUpdate timestamps without running jobs
anacron -nRun immediately, ignore delays (implies serial mode)
anacron -sRun jobs serially — one after another
anacron -dStay in foreground, log to stderr and syslog
anacron -qQuiet stderr (used with -d)
anacron -t FILEUse alternate anacrontab file
anacron -S DIRUse alternate spool directory
anacron -VShow version

Common operational flows:

anacron-ops-commands.sh
# Validate config
sudo anacron -T

# Force all jobs now, no delay, serial
sudo anacron -f -n -s

# Run only one specific job now
sudo anacron -f -n wp-db-backup

# Update timestamps without running anything
sudo anacron -u

# Foreground debug mode (shows what it's doing)
sudo anacron -f -n -d

Preventing Overlap with flock

Anacron decides when to run a job, but your command still needs concurrency protection if it is long-running or non-reentrant.

anacron-flock-pattern.txt
1 5 wp-db-backup flock -n /var/lock/wp-db-backup.lock /usr/local/bin/wp-db-backup.sh >> /var/log/wp-db-backup.log 2>&1
flock FlagMeaning
-nNon-blocking — skip immediately if already locked
-w SECONDSWait up to N seconds for lock
-E CODECustom exit code when lock fails

Logging, Mail, and Output Control

By default, anacron informational messages go to syslog (facility cron). Job output may be mailed to MAILTO if mail transport is available.

Production pattern — always redirect to log files:

anacron-logging-pattern.txt
MAILTO=""
NO_MAIL_OUTPUT=1

1 10 wp-db-backup /usr/local/bin/wp-db-backup.sh >> /var/log/wp-db-backup.log 2>&1
check-anacron-logs.sh
# journald-based systems
journalctl -u cron --since '24 hours ago' --no-pager | grep -i anacron

# Syslog-based systems
sudo grep -i 'anacron\|CRON' /var/log/syslog /var/log/cron 2>/dev/null | tail -20

Practical Examples

Examples below are anacrontab job lines unless noted otherwise.


Daily Jobs

1. Daily maintenance with 5-minute delay

anacron-daily-maintenance.txt
1 5 daily-maint /usr/local/bin/daily-maint.sh >> /var/log/daily-maint.log 2>&1

2. Daily health check with no delay

anacron-daily-healthcheck.txt
@daily 0 health-check /usr/local/bin/health-check.sh >> /var/log/health-check.log 2>&1

3. Daily WordPress database backup with lock

anacron-wp-db-backup.txt
@daily 30 wp-db-backup flock -n /var/lock/wp-db-backup.lock /usr/local/bin/wp db export /mnt/backups/wp-db-$(date +\%F).sql --path=/var/www/html >> /var/log/wp-db-backup.log 2>&1

4. Daily WordPress cron runner

anacron-wp-cron-runner-daily.txt
@daily 10 wp-cron-due /usr/local/bin/wp cron event run --due-now --path=/var/www/html >> /var/log/wp-cron-due.log 2>&1

5. Daily certbot renewal check

anacron-certbot-renew.txt
@daily 40 certbot-renew /usr/bin/certbot renew --quiet --deploy-hook "systemctl reload nginx" >> /var/log/certbot-renew.log 2>&1

6. Daily cache flush

anacron-daily-cache-cleanup.txt
@daily 8 cache-flush cd /var/www/html && /usr/local/bin/wp cache flush --path=/var/www/html >> /var/log/cache-flush.log 2>&1

7. Daily disk usage alert

anacron-disk-alert.txt
@daily 5 disk-alert /usr/local/bin/disk-alert.sh >> /var/log/disk-alert.log 2>&1

8. Daily Nginx logrotate force

anacron-nginx-logrotate.txt
@daily 25 nginx-logrotate /usr/sbin/logrotate /etc/logrotate.d/nginx >> /var/log/nginx-logrotate.log 2>&1

9. Daily retention script with low system priority

anacron-daily-retention-nice.txt
@daily 50 retention nice -n 10 ionice -c2 -n7 /usr/local/bin/retention.sh >> /var/log/retention.log 2>&1

Weekly Jobs

10. Weekly cleanup

anacron-weekly-cleanup.txt
@weekly 10 weekly-cleanup /usr/local/bin/weekly-cleanup.sh >> /var/log/weekly-cleanup.log 2>&1

11. Weekly backup prune (files older than 14 days)

anacron-backup-prune-weekly.txt
@weekly 45 backup-prune /usr/bin/find /mnt/backups -name "*.sql" -mtime +14 -delete >> /var/log/backup-prune.log 2>&1

12. Weekly WordPress plugin update audit

anacron-wp-plugin-audit.txt
@weekly 20 wp-plugin-audit /usr/local/bin/wp plugin list --update=available --path=/var/www/html >> /var/log/wp-plugin-audit.log 2>&1

13. Weekly PHP-FPM restart

anacron-phpfpm-weekly-restart.txt
@weekly 60 phpfpm-restart /usr/bin/systemctl restart php8.2-fpm >> /var/log/phpfpm-restart.log 2>&1

14. Weekly package metadata refresh

anacron-weekly-apt-update.txt
@weekly 15 apt-update /usr/bin/apt-get update >> /var/log/apt-update.log 2>&1

Monthly and Multi-Day Jobs

15. Monthly report

anacron-monthly-report.txt
@monthly 15 monthly-report /usr/local/bin/monthly-report.sh >> /var/log/monthly-report.log 2>&1

16. Monthly security report

anacron-monthly-security-report.txt
@monthly 35 security-report /usr/local/bin/security-report.sh >> /var/log/security-report.log 2>&1

17. Every 2 days

anacron-every-2-days.txt
2 5 every-2-days /usr/local/bin/every-2-days.sh >> /var/log/every-2-days.log 2>&1

18. Every 14 days (biweekly)

anacron-every-14-days.txt
14 20 biweekly-maint /usr/local/bin/biweekly-maint.sh >> /var/log/biweekly-maint.log 2>&1

19. Every 30 days (fixed-day cadence, NOT calendar month)

anacron-every-30-days.txt
30 0 every-30-days /usr/local/bin/every-30-days.sh >> /var/log/every-30-days.log 2>&1

Note: Use @monthly for calendar-month cadence. Use 30 only if you specifically need a fixed 30-day rolling period.


Advanced

20. Multiple jobs with consistent identifiers and staggered delays

anacrontab-full-wordpress-block.txt
SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
MAILTO=""
NO_MAIL_OUTPUT=1
RANDOM_DELAY=20
START_HOURS_RANGE=2-7

@daily 20 wp-db-backup flock -n /var/lock/wp-db-backup.lock /usr/local/bin/wp db export /mnt/backups/wp-db-$(date +\%F).sql --path=/var/www/html >> /var/log/wp-db-backup.log 2>&1
@weekly 30 backup-prune /usr/bin/find /mnt/backups -name "*.sql" -mtime +14 -delete >> /var/log/backup-prune.log 2>&1
@daily 10 cache-flush /usr/local/bin/wp cache flush --path=/var/www/html >> /var/log/cache-flush.log 2>&1
@daily 40 certbot-renew /usr/bin/certbot renew --quiet --deploy-hook "systemctl reload nginx" >> /var/log/certbot-renew.log 2>&1

21. Restrict starts to early-morning window

anacrontab-start-hours-range.txt
START_HOURS_RANGE=3-6
@daily 5 daily-windowed /usr/local/bin/daily-windowed.sh >> /var/log/daily-windowed.log 2>&1

22. Force-run all jobs for testing

anacron-force-run-now.sh
sudo anacron -f -n -s

23. Run only one job by identifier

anacron-force-single-job.sh
sudo anacron -f -n wp-db-backup

24. Test custom anacrontab without root

anacron-custom-file-and-spool-test.sh
mkdir -p /tmp/anacron-spool
anacron -t /tmp/anacrontab -S /tmp/anacron-spool -f -n -d

25. Update timestamps only (skip execution, useful after manual run)

anacron-update-timestamps-only.sh
sudo anacron -u

Safe Script Template for Anacron Jobs

Use script wrappers for anything non-trivial. Every anacron job script should follow this pattern:

safe-anacron-script-template.sh
#!/usr/bin/env bash
set -euo pipefail

umask 077
export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"

LOCK="/var/lock/myjob.lock"
LOG="/var/log/myjob.log"

mkdir -p "$(dirname "$LOG")"

{
echo "[$(date -Is)] start"
echo "user=$(id -un) uid=$(id -u)"

flock -n "$LOCK" /usr/local/bin/myjob

echo "[$(date -Is)] done"
} >> "$LOG" 2>&1

Corresponding anacrontab entry:

anacrontab-entry-for-safe-wrapper.txt
@daily 10 myjob-wrapper /usr/local/bin/myjob-wrapper.sh

Debugging Workflow

Step-by-step debug protocol

  1. Validate syntax before anything:
    sudo anacron -T && echo "OK"
  2. Force a run in foreground to see what's happening:
    sudo anacron -f -n -d
  3. Check spool timestamps to understand when jobs last ran:
    sudo ls -lah /var/spool/anacron
    cat /var/spool/anacron/wp-db-backup # Shows last run date
  4. Inspect logs for job execution evidence:
    debug-anacron-workflow.sh
    journalctl -u cron --since '24 hours ago' --no-pager | grep -i anacron
    sudo grep -i 'anacron\|CRON' /var/log/syslog 2>/dev/null | tail -20
  5. Run one specific job by identifier:
    sudo anacron -f -n wp-db-backup
  6. Verify script path and permissions:
    which /usr/local/bin/myjob.sh
    ls -lah /usr/local/bin/myjob.sh # Must have execute bit

Common failure patterns

SymptomLikely CauseFix
Job never runsanacron not installed or not invoked by cronInstall anacron; verify cron/anacron integration
Job skipped for the daySTART_HOURS_RANGE window missed at bootWiden the range or adjust host startup time
Command not foundPATH too minimalSet explicit PATH= in /etc/anacrontab; use absolute paths
No output in log fileRelying on mail onlyRedirect to log; set MAILTO=""; add >> redirect to entry
Jobs overlap or run twiceLong run time with no lockAdd flock -n; design idempotent scripts
Unexpected cadenceUsing 30 instead of @monthlyChoose @monthly for calendar-month cadence
Spool shows old date but job didn't runSTART_HOURS_RANGE skipped the runCheck if boot time falls within the window
anacron -T exits non-zeroSyntax error in anacrontabRead the error message; check field count and identifier uniqueness

WordPress VPS Patterns with Anacron

TaskPeriodDelayIdentifierCommand Pattern
DB backup@daily20wp-db-backupwp db export ... + flock
Backup prune@weekly30backup-prunefind /mnt/backups -mtime +14 -delete
Plugin audit@weekly20wp-plugin-auditwp plugin list --update=available
Cache flush@daily10cache-flushwp cache flush
Cert renew check@daily40certbot-renewcertbot renew --quiet
PHP-FPM restart@weekly60phpfpm-restartsystemctl restart php8.2-fpm
Security report@monthly35security-reportCustom report script

Benefits

  • Missed-run resilience — daily/weekly/monthly jobs still execute after downtime.
  • Simple frequency model — period in days plus startup delay; nothing complex to configure.
  • Good for intermittent hosts — no requirement for 24/7 uptime.
  • Works with existing run-parts layout — easy to reuse /etc/cron.daily, /etc/cron.weekly, /etc/cron.monthly.
  • Low operational complexity — one small config file (/etc/anacrontab) plus a per-job timestamp spool.
  • Compatible with classic cron stacks — many distros wire cron and anacron together transparently.

Best Practices

  • Use anacron for periodic maintenance, not exact-clock jobs — choose cron or systemd timers when time precision matters.
  • Keep commands idempotent — catch-up behavior means jobs may run soon after boot on any day.
  • Set explicit PATH and SHELL in /etc/anacrontab — avoid all environment surprises.
  • Use absolute command paths — never rely on the interactive shell PATH.
  • Wrap non-reentrant jobs with flock — prevent overlap when jobs run long.
  • Redirect output to log files — do not rely on mail delivery; it frequently fails silently.
  • Use clear job identifierswp-db-backup, backup-prune, disk-alert are better than job1, task-a.
  • Tune START_HOURS_RANGE intentionally — prevents jobs from running at bad times, but can skip a full day if the window is missed entirely.
  • Use RANDOM_DELAY on fleets — avoids thundering herd behavior when many servers share a schedule.
  • Validate config with anacron -T before rollout — catches syntax mistakes before jobs fail silently.

Tips & Strategy

Think in "at least once per period"

anacron guarantees periodic execution measured in days, then applies delay and window logic. It is not a wall-clock scheduler — think "this will run at least once in every N-day window" rather than "this will run at exactly 3 AM".

Stagger delays to avoid boot spikes

If multiple jobs are eligible at boot, they all start within the same window. Assign different delay values so heavy tasks don't all start together:

@daily 5 db-backup /usr/local/bin/db-backup.sh >> /var/log/db-backup.log 2>&1
@daily 20 cert-renew /usr/bin/certbot renew >> /var/log/certbot.log 2>&1
@daily 40 plugin-audit /usr/local/bin/wp plugin list >> /var/log/plugin-audit.log 2>&1
Gate risky actions in scripts

If a job can be destructive, add dry-run checks and explicit safety conditions inside the script rather than in the anacrontab entry.

Keep one job per script and one log per job

Short anacrontab lines and dedicated scripts make debugging and auditing much easier. Never put complex logic directly in the anacrontab command field.

If uptime is high and precision matters, migrate to systemd timers

For strict time windows, dependency ordering, and journald-native logs with systemctl status, systemd timers are usually a better default for 24/7 servers.


Hands-On Practice

Quick Lab (5 Exercises)

  1. Install/check anacron and inspect /etc/anacrontab — note the existing default entries.
  2. Add one @daily test job that appends a timestamp to /tmp/anacron-test.log.
  3. Validate with anacron -T and force a run with sudo anacron -f -n -d.
  4. Add RANDOM_DELAY=10 and observe its presence in the config — understand how it shifts the delay.
  5. Add flock to your test job and verify a second invocation is skipped.

Task: Build a Catch-Up Maintenance Profile

Create a complete /etc/anacrontab profile that:

  • Runs a DB backup daily
  • Prunes old backups weekly
  • Checks disk usage daily
  • Generates a monthly report
  • Runs only between 02:00 and 07:00 with random spread
Solution
anacrontab-maintenance-solution.txt
SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
MAILTO=""
NO_MAIL_OUTPUT=1
RANDOM_DELAY=20
START_HOURS_RANGE=2-7

@daily 20 db-backup flock -n /var/lock/db-backup.lock /usr/local/bin/db-backup.sh >> /var/log/db-backup.log 2>&1
@weekly 35 backup-prune /usr/local/bin/backup-prune.sh >> /var/log/backup-prune.log 2>&1
@daily 10 disk-alert /usr/local/bin/disk-alert.sh >> /var/log/disk-alert.log 2>&1
@monthly 25 monthly-report /usr/local/bin/monthly-report.sh >> /var/log/monthly-report.log 2>&1
validate-and-test.sh
sudo anacron -T && echo "Syntax OK"
sudo anacron -f -n -s # Force all jobs for testing

Mini Quiz

  1. What is the main difference between cron scheduling and anacron scheduling?
  2. What are the four fields in a job line inside /etc/anacrontab?
  3. What is the practical difference between 30 and @monthly period values?
  4. What does START_HOURS_RANGE=6-8 control?
  5. What does RANDOM_DELAY=30 add to job timing?
  6. Which command validates /etc/anacrontab syntax?
  7. Which option forces execution while ignoring timestamps?
  8. Where are per-job timestamp files typically stored?
  9. Why is flock still necessary even with anacron?
  10. When should you choose systemd timers instead of anacron?

Cheat Sheet
anacron-cheat-sheet.sh
# ── Installation checks ───────────────────────────────────────────────────────
command -v anacron || echo "not installed"
anacron -V 2>/dev/null || true

# ── Files and state ───────────────────────────────────────────────────────────
sudo cat /etc/anacrontab
sudo ls -lah /var/spool/anacron

# ── Validate and run ──────────────────────────────────────────────────────────
sudo anacron -T # Validate syntax
sudo anacron -f -n -s # Force all jobs, no delay, serial
sudo anacron -f -n myjob-id # Force one specific job
sudo anacron -f -n -d # Force run with foreground debug output
sudo anacron -u # Update timestamps without running

# ── Logging checks ────────────────────────────────────────────────────────────
journalctl -u cron --since '24 hours ago' --no-pager | grep -i anacron
sudo grep -i 'anacron\|CRON' /var/log/syslog 2>/dev/null | tail -20

# ── Cron/anacron wiring check ─────────────────────────────────────────────────
sudo grep -n 'anacron\|run-parts' /etc/crontab /etc/cron.d/* 2>/dev/null || true
anacrontab-template.txt
# ── Header ────────────────────────────────────────────────────────────────────
SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
MAILTO=""
NO_MAIL_OUTPUT=1
RANDOM_DELAY=20
START_HOURS_RANGE=2-7

# ── Jobs: period delay identifier command ─────────────────────────────
@daily 10 job-daily /usr/local/bin/job-daily.sh >> /var/log/job-daily.log 2>&1
@weekly 20 job-weekly /usr/local/bin/job-weekly.sh >> /var/log/job-weekly.log 2>&1
@monthly 30 job-monthly /usr/local/bin/job-monthly.sh >> /var/log/job-monthly.log 2>&1

What's Next