anacron — Periodic Catch-Up Scheduler
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.
- 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.
# 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:
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:
- Read the last-run date from
/var/spool/anacron/<job-identifier>. - Compare today's date with the last-run date.
- If the period (in days) has elapsed, mark the job eligible.
- Wait the configured delay in minutes (plus any
RANDOM_DELAYoffset). - If within the
START_HOURS_RANGEwindow, execute the command. - Record the new date stamp in the spool file.
Lifecycle Diagram
Key Behavioral Rules
| Behavior | Details |
|---|---|
| Frequency is day-based | Minute/hour precision is not possible |
| Catch-up on boot | If a job was due while machine was off, anacron runs it on next startup |
START_HOURS_RANGE gating | If the startup window is missed entirely, the run is skipped until the next eligible day |
RANDOM_DELAY | Adds 0–N random minutes per job to prevent fleet-wide thundering herd |
| Active job locking | A running job blocks another anacron instance from starting the same job |
Where Anacron Data Lives
| Location | Purpose |
|---|---|
/etc/anacrontab | Main 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 |
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
| Scenario | Anacron Fit | Why |
|---|---|---|
| Daily/weekly/monthly maintenance | Strong | Built for day-based recurring jobs |
| Host may be offline at schedule time | Strong | Catch-up execution behavior |
| Need exact minute/hour scheduling | Weak | Anacron is not a precision clock scheduler |
| Need sub-daily cadence (hourly, every 5 min) | Weak | Use cron or systemd timers instead |
| Need dependency ordering or journald logs | Weak | Use 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
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
/usr/local/bin/anacron-heartbeat.sh
cat /tmp/anacron-heartbeat.log
[2026-03-02T04:10:00+00:00] anacron heartbeat
Step 3 — Add the job to /etc/anacrontab
Open with:
sudo nano /etc/anacrontab
Add this line at the bottom (after any existing entries):
@daily 5 anacron-heartbeat /usr/local/bin/anacron-heartbeat.sh >> /tmp/anacron-heartbeat.log 2>&1
Step 4 — Validate the config
sudo anacron -T && echo "Syntax OK"
Syntax OK
Step 5 — Force a test run now
sudo anacron -f -n -s # Force all eligible jobs, no delay, serial
cat /tmp/anacron-heartbeat.log
[2026-03-02T04:10:05+00:00] anacron heartbeat
Step 6 — Check the spool timestamp was recorded
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:
1 5 cron.daily nice run-parts /etc/cron.daily
Field meanings
| Field | Meaning | Example |
|---|---|---|
period | Frequency in days or macro | 1, 7, 30, @daily, @weekly, @monthly |
delay | Delay in minutes before run after becoming eligible | 0, 5, 30 |
job-identifier | Unique job name — maps to spool file | wp-db-backup, backup-prune |
command | Shell command or script to execute | /usr/local/bin/wp-backup.sh |
Period macros
| Macro | Equivalent | Meaning |
|---|---|---|
@daily | 1 | Once per day |
@weekly | 7 | Once per week |
@monthly | Month-aware | Once 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:
| Variable | Purpose | Typical Value |
|---|---|---|
SHELL | Shell used for commands | /bin/sh or /bin/bash |
PATH | Command search path | /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin |
MAILTO | Recipient for job output mail | root, ops@example.com, or "" |
NO_MAIL_OUTPUT | Disables mailing output if non-empty | 1 |
RANDOM_DELAY | Maximum extra random minutes added per job | 0, 10, 30 |
START_HOURS_RANGE | Allowed start window by hour | 6-8, 1-5, 0-23 |
Recommended production 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
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 exportat exactly boot+5min, your database host will notice. - Keep values moderate so critical jobs don't drift too far from their window.
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:
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.
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
| Command | What It Does |
|---|---|
anacron -T | Validate anacrontab syntax |
anacron -f | Force all jobs, ignore timestamps |
anacron -u | Update timestamps without running jobs |
anacron -n | Run immediately, ignore delays (implies serial mode) |
anacron -s | Run jobs serially — one after another |
anacron -d | Stay in foreground, log to stderr and syslog |
anacron -q | Quiet stderr (used with -d) |
anacron -t FILE | Use alternate anacrontab file |
anacron -S DIR | Use alternate spool directory |
anacron -V | Show version |
Common operational flows:
# 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.
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 Flag | Meaning |
|---|---|
-n | Non-blocking — skip immediately if already locked |
-w SECONDS | Wait up to N seconds for lock |
-E CODE | Custom 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:
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
# 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
1 5 daily-maint /usr/local/bin/daily-maint.sh >> /var/log/daily-maint.log 2>&1
2. Daily health check with no delay
@daily 0 health-check /usr/local/bin/health-check.sh >> /var/log/health-check.log 2>&1
3. Daily WordPress database backup with lock
@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
@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
@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
@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
@daily 5 disk-alert /usr/local/bin/disk-alert.sh >> /var/log/disk-alert.log 2>&1
8. Daily Nginx logrotate force
@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
@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
@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)
@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
@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
@weekly 60 phpfpm-restart /usr/bin/systemctl restart php8.2-fpm >> /var/log/phpfpm-restart.log 2>&1
14. Weekly package metadata refresh
@weekly 15 apt-update /usr/bin/apt-get update >> /var/log/apt-update.log 2>&1
Monthly and Multi-Day Jobs
15. Monthly report
@monthly 15 monthly-report /usr/local/bin/monthly-report.sh >> /var/log/monthly-report.log 2>&1
16. Monthly security report
@monthly 35 security-report /usr/local/bin/security-report.sh >> /var/log/security-report.log 2>&1
17. Every 2 days
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)
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)
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
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
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
sudo anacron -f -n -s
23. Run only one job by identifier
sudo anacron -f -n wp-db-backup
24. Test custom anacrontab without root
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)
sudo anacron -u
Safe Script Template for Anacron Jobs
Use script wrappers for anything non-trivial. Every anacron job script should follow this pattern:
#!/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:
@daily 10 myjob-wrapper /usr/local/bin/myjob-wrapper.sh
Debugging Workflow
Step-by-step debug protocol
- Validate syntax before anything:
sudo anacron -T && echo "OK"
- Force a run in foreground to see what's happening:
sudo anacron -f -n -d
- Check spool timestamps to understand when jobs last ran:
sudo ls -lah /var/spool/anacroncat /var/spool/anacron/wp-db-backup # Shows last run date
- Inspect logs for job execution evidence:
debug-anacron-workflow.shjournalctl -u cron --since '24 hours ago' --no-pager | grep -i anacronsudo grep -i 'anacron\|CRON' /var/log/syslog 2>/dev/null | tail -20
- Run one specific job by identifier:
sudo anacron -f -n wp-db-backup
- Verify script path and permissions:
which /usr/local/bin/myjob.shls -lah /usr/local/bin/myjob.sh # Must have execute bit
Common failure patterns
| Symptom | Likely Cause | Fix |
|---|---|---|
| Job never runs | anacron not installed or not invoked by cron | Install anacron; verify cron/anacron integration |
| Job skipped for the day | START_HOURS_RANGE window missed at boot | Widen the range or adjust host startup time |
| Command not found | PATH too minimal | Set explicit PATH= in /etc/anacrontab; use absolute paths |
| No output in log file | Relying on mail only | Redirect to log; set MAILTO=""; add >> redirect to entry |
| Jobs overlap or run twice | Long run time with no lock | Add flock -n; design idempotent scripts |
| Unexpected cadence | Using 30 instead of @monthly | Choose @monthly for calendar-month cadence |
| Spool shows old date but job didn't run | START_HOURS_RANGE skipped the run | Check if boot time falls within the window |
anacron -T exits non-zero | Syntax error in anacrontab | Read the error message; check field count and identifier uniqueness |
WordPress VPS Patterns with Anacron
| Task | Period | Delay | Identifier | Command Pattern |
|---|---|---|---|---|
| DB backup | @daily | 20 | wp-db-backup | wp db export ... + flock |
| Backup prune | @weekly | 30 | backup-prune | find /mnt/backups -mtime +14 -delete |
| Plugin audit | @weekly | 20 | wp-plugin-audit | wp plugin list --update=available |
| Cache flush | @daily | 10 | cache-flush | wp cache flush |
| Cert renew check | @daily | 40 | certbot-renew | certbot renew --quiet |
| PHP-FPM restart | @weekly | 60 | phpfpm-restart | systemctl restart php8.2-fpm |
| Security report | @monthly | 35 | security-report | Custom 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-partslayout — 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
cronor systemd timers when time precision matters. - Keep commands idempotent — catch-up behavior means jobs may run soon after boot on any day.
- Set explicit
PATHandSHELLin/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 identifiers —
wp-db-backup,backup-prune,disk-alertare better thanjob1,task-a. - Tune
START_HOURS_RANGEintentionally — prevents jobs from running at bad times, but can skip a full day if the window is missed entirely. - Use
RANDOM_DELAYon fleets — avoids thundering herd behavior when many servers share a schedule. - Validate config with
anacron -Tbefore rollout — catches syntax mistakes before jobs fail silently.
Tips & Strategy
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".
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
If a job can be destructive, add dry-run checks and explicit safety conditions inside the script rather than in the anacrontab entry.
Short anacrontab lines and dedicated scripts make debugging and auditing much easier. Never put complex logic directly in the anacrontab command field.
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)
- Install/check anacron and inspect
/etc/anacrontab— note the existing default entries. - Add one
@dailytest job that appends a timestamp to/tmp/anacron-test.log. - Validate with
anacron -Tand force a run withsudo anacron -f -n -d. - Add
RANDOM_DELAY=10and observe its presence in the config — understand how it shifts the delay. - Add
flockto 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
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
sudo anacron -T && echo "Syntax OK"
sudo anacron -f -n -s # Force all jobs for testing
Mini Quiz
- What is the main difference between cron scheduling and anacron scheduling?
- What are the four fields in a job line inside
/etc/anacrontab? - What is the practical difference between
30and@monthlyperiod values? - What does
START_HOURS_RANGE=6-8control? - What does
RANDOM_DELAY=30add to job timing? - Which command validates
/etc/anacrontabsyntax? - Which option forces execution while ignoring timestamps?
- Where are per-job timestamp files typically stored?
- Why is
flockstill necessary even with anacron? - When should you choose systemd timers instead of anacron?
Cheat Sheet
# ── 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
# ── 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