The anacron command in Linux can catch "silent failures" such as the one described above. A user had a cron job running nightly with no issues for about 3 months. The server received a kernel update which caused the server to restart late in the week (Thursday) but none of the other admins knew that the backup scripts did not run after the restart. This type of "silent failure" is exactly what anacron was created to detect.
In my experience I've seen many instances where a job has been set to run via cron. When the system came back online (i.e. either the clock struck midnight or when the admin restarted the box), the job simply went away. In contrast, if anacron is being used, the job simply runs as soon as the box comes back online without further prompting from the administrator.
This tutorial is designed for anyone who uses/needs to use scheduled tasks on their systems (sysadmins, DevOps engineers etc.) regardless of how much they know about Linux. Once you complete reading through this tutorial, you'll be able to create, test & troubleshoot your own anacron jobs on both Ubuntu, RockyLinux and Red Hat Enterprise Linux.
Note:
If you are just starting out with scheduled tasks in Linux, it helps to get comfortable with the cron command basics first. Understanding how cron works makes anacron's design decisions a lot clearer.
Examples
What Is anacron and Why Does It Exist?
Anacron is a Linux job scheduler used to run commands periodically, measured in days. Unlike cron, which strictly follows the system clock and scheduled execution time, anacron focuses on whether enough time has passed since the job last ran. This makes it especially useful on systems that are not powered on continuously.
A simple way to understand the difference is this: cron behaves like a clock alarm. If the alarm goes off while the system is powered off, the task is missed completely. Anacron behaves more like a reminder note. It checks whether a job was missed and runs it automatically the next time the system becomes available.
Technically, anacron reads its configuration from /etc/anacrontab and checks timestamp files stored under /var/spool/anacron. For each configured job, it determines whether enough days have passed since the last successful execution. If the answer is yes, anacron waits for the configured delay (measured in minutes), executes the command, and then updates the timestamp file with the current date so it knows when the job should run again.
This makes anacron the right tool for desktops, developer workstations, laptops, and any server that gets rebooted regularly. Things like weekly database dumps, monthly log cleanups, daily backup scripts, these all belong in anacron rather than cron if there is any chance the machine will be off at the scheduled hour. You can also check our Linux automation guide for 2026 for broader context on scheduling strategies.
One thing worth knowing upfront: anacron only goes down to day-level granularity. If you need something to run every hour or every 15 minutes, that is cron territory. Anacron is for daily, weekly, monthly, or any N-day interval jobs where exact timing is less important than guaranteed execution.
Anacron Syntax and anacrontab Format
The anacron command itself has a straightforward syntax:
LinuxTeck.com
# Update timestamps only, no execution
anacron [-S spooldir] -u [-t anacrontab] [job]
# Test anacrontab file syntax
anacron -T [-t anacrontab]
# Print version
anacron -V
The real configuration lives in /etc/anacrontab. Each job line follows this four-field structure:
LinuxTeck.com
# period(days) delay(minutes) job-id command
1 5 cron.daily run-parts --report /etc/cron.daily
7 10 cron.weekly run-parts --report /etc/cron.weekly
30 15 cron.monthly run-parts --report /etc/cron.monthly
# Special @monthly macro also works for monthly period
@monthly 45 cron.monthly run-parts --report /etc/cron.monthly
Breaking down each field: the period is how many days between runs. Use 1 for daily, 7 for weekly, 30 for monthly, or any number you need. The delay is how many minutes to wait after anacron starts before actually running the job. This prevents everything from slamming the CPU at once right after boot. The job-identifier is just a unique name used in log files and to name the timestamp file in /var/spool/anacron. The command is whatever you want to run.
Note:
The @monthly macro is the only string shorthand reliably supported across all distros. On some Ubuntu versions, @daily and @weekly macros do not work correctly in anacrontab and may cause the job to run hourly instead of daily. Use numeric values like 1, 7, and 30 to avoid this entirely.
Two environment variables in anacrontab are worth knowing: START_HOURS_RANGE defines the window of hours during which anacron will start jobs (for example, 3-22 means jobs only start between 3 AM and 10 PM). If your machine powers on or anacron is triggered outside this range, say at 11:30 PM during a late maintenance window, anacron sees it is outside the allowed hours and exits immediately without running anything. Jobs wait until the next time anacron runs inside the defined range. RANDOM_DELAY adds a random number of minutes on top of your defined delay, which is useful on shared or busy systems where you do not want multiple jobs stacking up at the same instant.
Anacron Options and Flags
| Flag | What It Does | When to Use It |
|---|---|---|
| -f | Force all jobs to run, ignoring timestamp files | Testing or recovering after a missed run window |
| -u | Update timestamps to today without running anything | Resetting the schedule clock after maintenance |
| -s | Serialize jobs, run one at a time in sequence | When jobs share resources or must not overlap |
| -n | Run jobs now, skipping all defined delays | Immediate testing, implies -s automatically |
| -d | Run in foreground, output to stderr and syslog | Debugging, watching what anacron is actually doing |
| -q | Suppress stderr output (only works with -d) | When you want syslog output but not terminal noise |
| -T | Validate anacrontab syntax, exit with 0 or 1 | Always run this after editing /etc/anacrontab |
| -t file | Use a custom anacrontab file instead of the default | Per-user anacron setups or testing new configs safely |
| -S dir | Use a custom spool directory for timestamp files | Required when running anacron as a non-root user |
| -V | Print version information and exit | Confirming which version is installed on a system |
Practical Anacron Examples
I. Check the Current /etc/anacrontab Configuration
Before adding anything new, look at what is already in anacrontab. On most systems, the default file handles daily, weekly, and monthly cron directory sweeps already.
LinuxTeck.com
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
HOME=/root
LOGNAME=root
# These replace cron's entries
1 5 cron.daily run-parts --report /etc/cron.daily
7 10 cron.weekly run-parts --report /etc/cron.weekly
@monthly 15 cron.monthly run-parts --report /etc/cron.monthly
II. Install anacron on Ubuntu or Debian
On most Ubuntu and Debian systems anacron comes pre-installed, but if it is missing this installs it.
LinuxTeck.com
sudo apt install anacron -y
which anacron
Note:
On Rocky Linux and RHEL, anacron is part of the cronie package. Install or verify with: sudo dnf install cronie-anacron
III. Add a Custom Daily Backup Job
This is the most common use case. Edit anacrontab to add a daily backup script that will run whenever the machine is on, even if it missed the original scheduled time.
LinuxTeck.com
# period delay job-id command
1 10 daily-backup /bin/bash /usr/local/bin/backup.sh
Tip:
Always make sure your script has execute permissions before anacron tries to run it: sudo chmod +x /usr/local/bin/backup.sh. A job in anacrontab pointing to a non-executable file will fail silently.
IV. Validate anacrontab Syntax Before It Breaks Something
Any time you edit /etc/anacrontab, run the syntax check before walking away. A bad line does not produce an error at edit time, only when anacron tries to execute.
LinuxTeck.com
echo $?
Exit code 0 means the syntax is clean. Exit code 1 means there is an error and anacron will also print which line is the problem.
V. Force Run All Jobs Immediately for Testing
When setting up a new job, you do not want to wait days to verify it actually works. The -f -n -d combination forces all jobs to run right now with output on screen.
LinuxTeck.com
Will run job `cron.daily'
Will run job `daily-backup'
Job `cron.daily' started
Job `cron.daily' terminated (exit status: 0)
Job `daily-backup' started
Job `daily-backup' terminated (exit status: 0)
Normal exit (2 jobs run)
VI. Check Timestamp Files to See When Jobs Last Ran
The timestamp files in /var/spool/anacron are how anacron tracks job history. Checking them tells you exactly when each job last executed.
LinuxTeck.com
cat /var/spool/anacron/cron.daily
-rw------- 1 root root 9 May 25 07:03 cron.daily
-rw------- 1 root root 9 May 19 10:22 cron.monthly
-rw------- 1 root root 9 May 22 08:15 cron.weekly
20260525
VII. Update Timestamps Without Running Jobs
After doing manual maintenance or running jobs by hand, you want to reset the timestamps so anacron does not run them again immediately after. The -u flag updates the dates without executing anything.
LinuxTeck.com
cat /var/spool/anacron/cron.daily
VIII. Set Up a Per-User anacron Without Root Access
Regular users can run their own anacron setup using a custom anacrontab and a private spool directory. This is useful for developer workstations or personal automation tasks that should not be in the system-wide config.
LinuxTeck.com
mkdir -p ~/.local/etc/cron.daily ~/.var/spool/anacron
# Create custom anacrontab
cat > ~/.local/etc/anacrontab << EOF
SHELL=/bin/sh
PATH=/usr/local/bin:/usr/bin:/bin
1 0 my-daily-job /bin/bash ~/scripts/cleanup.sh
EOF
# Validate it
anacron -T -t ~/.local/etc/anacrontab -S ~/.var/spool/anacron
# Add to ~/.profile — use -d so anacron runs in foreground, not as daemon
echo 'anacron -d -t ~/.local/etc/anacrontab -S ~/.var/spool/anacron >/dev/null 2>&1' >> ~/.profile
IX. Schedule a Weekly Log Cleanup on Rocky Linux or RHEL
A real-world production task: clean up application logs older than 30 days every week. Drop the script into /etc/cron.weekly or add it directly to anacrontab for guaranteed execution. Note: if you are following along exactly, run sudo mkdir -p /var/log/myapp first so the find command has a valid target to work with.
LinuxTeck.com
cat > /usr/local/bin/log-cleanup.sh << 'EOF'
#!/bin/bash
find /var/log/myapp -name "*.log" -mtime +30 -delete
echo "Log cleanup ran: $(date)" >> /var/log/log-cleanup-history.log
EOF
chmod +x /usr/local/bin/log-cleanup.sh
# Add weekly entry to anacrontab
echo "7 15 weekly-log-cleanup /bin/bash /usr/local/bin/log-cleanup.sh" >> /etc/anacrontab
Tip:
Always have your script log its own execution with a timestamp, like the echo line above. Anacron itself does not keep a detailed run history, so your script needs to create that trail.
X. Run a Specific Job by Name
You can tell anacron to run only one specific job from the anacrontab by passing its job identifier as an argument. Useful when you want to test or re-run just one entry without triggering everything.
LinuxTeck.com
Will run job `daily-backup'
Job `daily-backup' started
Job `daily-backup' terminated (exit status: 0)
Normal exit (1 job run)
XI. Common Mistake: Using a Bash Script with /bin/sh in anacrontab
This is the silent failure that catches people. The default shell in anacrontab is /bin/sh, not /bin/bash. If your script uses bash-specific syntax (arrays, [[ ]], string operations), it will fail or behave unexpectedly when called through sh.
LinuxTeck.com
1 5 my-job /path/to/bash-script.sh
# CORRECT - explicitly call bash regardless of default shell
1 5 my-job /bin/bash /path/to/bash-script.sh
Warning:
Even if your script has #!/bin/bash as the shebang, when called from anacrontab under SHELL=/bin/sh on some systems the shebang is ignored. Always be explicit: call /bin/bash /path/to/script.sh in the command field, or change SHELL=/bin/bash at the top of your anacrontab.
XII. Serialize Jobs to Avoid Overlapping Execution
If you have multiple resource-intensive jobs in anacrontab and they pile up at startup after a long downtime, the -s flag makes sure they run one at a time. Anacron processes jobs sequentially by default when reading a standard anacrontab, but -s enforces this as a hard guarantee even if the environment or an external script tries to spawn anacron asynchronously. Think of it as a lock, not just a preference.
LinuxTeck.com
Will run job `cron.daily' in 5 min.
Will run job `daily-backup' in 10 min.
Will run job `weekly-log-cleanup' in 15 min.
Job `cron.daily' started
Job `cron.daily' terminated (exit status: 0)
Job `daily-backup' started
Job `daily-backup' terminated (exit status: 0)
Why anacron Matters in Real Environments
Most Linux users do not realize how often scheduled cron jobs fail silently. The system may have entered sleep mode, rebooted during maintenance, or simply been powered off before the scheduled runtime. A laptop lid closed at 11:55 PM is enough to prevent a midnight cron job from running. Cron does not warn you about missed executions. You usually discover the problem much later, often when you actually need the backup or maintenance task that never completed.
Anacron changes that behavior completely. Instead of following a strict “run exactly at midnight” model, anacron focuses on ensuring the task runs once within the required time period whenever the system becomes available again. For most maintenance tasks, that is usually the behavior administrators actually want. What matters is that the backup, cleanup, or maintenance task ran successfully today, not necessarily that it executed at precisely 12:00 AM.
This becomes even more important in enterprise and production environments. Servers are regularly rebooted for kernel patching, hardware maintenance, virtualization migrations, or cloud infrastructure updates. If cron jobs are scheduled during those maintenance windows, the executions are skipped entirely. Missing cleanup routines, backup jobs, certificate renewals, or database maintenance tasks can quickly create larger operational problems. Anacron helps make these scheduled jobs far more reliable without requiring you to rewrite the scripts themselves. In most cases, the only change required is registering the task through anacron instead of cron. If you are building a more reliable backup workflow, the Linux server backup strategies guide covers additional enterprise backup planning and automation practices in more detail.
There is also the quieter benefit: anacron reduces the anxiety around scheduled tasks. You stop having to wonder "did the weekly cleanup actually run this week?" and start actually knowing. The timestamp files in /var/spool/anacron give you a simple audit trail. You can inspect them any time with a quick cat and see exactly when each job last ran. That is the kind of operational visibility that saves you headaches at 2 AM. For more on building reliable automation in Linux, the automatic Linux backup script guide pairs well with what you have learned here. The official reference is the anacron man page on man7.org if you want to go deeper on any specific flag or behaviour.
Key Takeaways
- Anacron tracks job execution by writing a date to
/var/spool/anacronafter each run. It only re-runs a job when the defined number of days has passed since that date, regardless of when the machine was on or off. - Use numeric period values (1, 7, 30) instead of
@dailyand@weeklymacros in anacrontab. The@monthlymacro works, but the others behave unexpectedly on some Ubuntu versions. - Always call
/bin/bash /path/to/script.shexplicitly in the command field when your script uses bash-specific syntax. Relying on the defaultSHELL=/bin/shcauses silent failures with bash scripts. - Run
anacron -Tevery time you edit/etc/anacrontab. A syntax error in the file does not produce any warning at save time, only at execution time when nothing runs. - Use
anacron -f -n -dto force all jobs to run immediately in the foreground when testing a new setup. This is the fastest way to confirm your script actually executes without waiting for the natural schedule. - Use
anacron -uafter running jobs manually or doing maintenance. This resets timestamps and prevents anacron from running the same jobs again on next startup thinking they were missed. - For regular users without root access, set up a personal anacron with
-tpointing to a custom anacrontab and-Spointing to a home directory spool folder. Always invoke it with-din~/.profileso it runs in foreground mode rather than trying to daemonize, which causes permission errors on most distros. - Scripts placed in
/etc/cron.daily,/etc/cron.weekly, or/etc/cron.monthlymust have no file extension. Therun-partstool that processes those directories silently ignores any file with a period in its name. Name your scriptbackup, notbackup.sh.
FAQ
My anacron job ran with -f -n -d but still shows exit status 1. How do I debug it?
Exit status 1 means the command itself returned an error, not that anacron failed. Check two things first: does the script file exist at the exact path you specified, and does it have execute permissions (ls -l /path/to/script.sh)? Then run the script directly in a terminal with bash -x /path/to/script.sh to see every line as it executes and find exactly where it fails. Also check that the PATH in anacrontab includes all the directories your script needs, since anacron runs with a minimal environment.
How do I stop a job from running if it was missed multiple times while the machine was off?
Anacron does not queue up multiple missed runs. If a job was overdue by 30 days, it still only runs once when the machine comes back on. If you want to prevent even that one catch-up run, use sudo anacron -u right after the machine boots to reset all timestamps before anacron fires. This marks every job as having run today, which resets the schedule from this point forward.
Can I see the output of my anacron jobs anywhere?
By default, any output from your job gets emailed to root (or the address in the MAILTO variable in anacrontab). If mail is not configured, that output goes nowhere. The practical fix is to redirect your script's output to a log file inside the script itself: add exec >> /var/log/myjob.log 2>&1 near the top of your script. That way you always have a record. You can also check /var/log/syslog or journalctl for anacron start and finish messages.
I added a job to anacrontab but it is not running. What should I check first?
Four common culprits: first, run anacron -T to rule out a syntax error in the file. Second, check that your script has execute permissions. Third, verify the timestamp file in /var/spool/anacron matches your job identifier and has a date that is old enough to trigger a run. Fourth, check that START_HOURS_RANGE in anacrontab includes the current hour, since anacron will refuse to start jobs outside that window.
What is RANDOM_DELAY in anacrontab and should I change it?
The default is 45, which means anacron adds a random number of minutes between 0 and 45 on top of your defined delay for each job. This is designed so that if many machines on a network use the same anacrontab (like in a fleet of laptops), they do not all hammer shared resources at the exact same moment. If you are on a single machine and want jobs to start closer to your defined delay, set it to something like RANDOM_DELAY=5 or even RANDOM_DELAY=0.
Does anacron work if I place scripts directly in /etc/cron.daily or /etc/cron.weekly?
Yes, and on most modern distros this is the recommended way to add jobs. The default anacrontab already has entries that run run-parts on those directories. Place your script in /etc/cron.daily and make it executable. One critical detail that trips people up: run-parts is strict about filenames and will silently skip any file that contains a period or extension. If you name your script backup.sh, it will never run. Name it backup with no extension at all. Just remember: scripts in those directories also need to be sh-compatible by default, or call bash explicitly inside the script.
From your first terminal command to advanced sysadmin skills - every guide here is written in plain English with real examples you can run right now.