Authors Top

If you have a few years of experience in the Linux ecosystem, and you’re interested in sharing that experience with the community, have a look at our Contribution Guidelines.

1. Introduction

Both cron and its relative utility anacron are standard for scheduling in UNIX systems. Hence, many processes often rely on crontab and anacrontab entries to keep the system updated, backed up, synchronized, and generally stable. Thus, cron and anacron task maintenance is an important area of system administration.

In this tutorial, we look at where anacron and cron configuration files usually reside and how to back them up for transfer. First, we briefly discuss tasks as the atomic units of both tools. Next, we enumerate the locations of all files and directories involved in task execution. Finally, we automate a backup process for those objects.

We tested the code in this tutorial on Debian 11 (Bullseye) with GNU Bash 5.1.4. It should work in most POSIX-compliant environments.

2. anacron and cron Tasks

The atomic units of both anacron and cron are jobs called tasks. These tasks execute as specified to serve the system in many ways:

Effectively, commands and scripts create, run, update, and maintain the Linux environment, so, along with init systems and rc files, we can look at anacron and cron as puppet masters responsible for a system running correctly.

But what makes anacron and cron tick?

3. Location of anacron and cron Configuration Files

Although they are fairly simple systems, anacron and cron use several locations for their settings. Notably, most related files begin with the word cron, but almost all contain it.

3.1. System-Wide Tasks

The /etc/crontab and /etc/anacrontab files, along with the /etc/cron.d directory, contain all system tasks. Further, /etc/crontab is the only file that includes user information as part of the task syntax:

$ cat /etc/anacrontab
[...]
# Example of job definition:
# .------- days
# |  .---- delay (minutes)
# |  |
# *  * job-id command to be executed
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
$ cat /etc/crontab
[...]
# Example of job definition:
# .---------------- minute (0 - 59)
# |  .------------- hour (0 - 23)
# |  |  .---------- day of month (1 - 31)
# |  |  |  .------- month (1 - 12) OR jan,feb,mar,apr ...
# |  |  |  |  .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# |  |  |  |  |
# *  *  *  *  * user-name command to be executed
17 *    * * *   root    cd / && run-parts --report /etc/cron.hourly
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 )
#

Although usually available by default, without a correct /etc/*crontab and the contents of /etc/cron.d, we could miss important tasks. Here, we already see the next type of cron data.

3.2. cron Intervals

By default, we have several types of periodic execution:

  • /etc/cron.hourly
  • /etc/cron.daily and /var/spool/anacron/cron.daily
  • /etc/cron.weekly and /var/spool/anacron/cron.weekly
  • /etc/cron.monthly and /var/spool/anacron/cron.monthly

Since anacron has a granularity of days, it doesn’t use the cron.hourly path.

These directories are meant to hold scripts for both utilities, which run at predefined regular intervals, as hinted in the name. Scheduled tasks are only as good as their actions, so any scripts in /etc/cron.*, /var/spool/anacron/cron.*, and other directories are critical.

3.3. Usage Permissions

Since scheduling is a powerful tool, limiting access to it can be vital. Hence, we have the /etc/cron.allow and /etc/cron.deny files with one username per line:

  • by default, neither file exists, meaning only superusers have access to crontab
  • cron.deny alone denies access to the usernames it contains
  • cron.allow overrules cron.deny, but no users outside the former may use crontab

Usually, these settings are specific to a given system. Attempting to use crontab without permission results in an error:

$ crontab
You (user1) are not allowed to use this program (crontab)
See crontab(1) for more information

When a user can have a crontab file, the latter resides at a different location.

3.4. User Tasks Files

Of course, another important element for scheduling is the user crontab files in /var/spool/cron/crontabs. Once a user runs crontab -e to create their own tasks, the resulting changes are stored in a file with the user’s name under the aforementioned path:

$ whoami
user1
$ tree /var/spool/cron
/var/spool/cron
└── crontabs

1 directory, 0 files
$ crontab -e
[...]
no crontab for user1 - using an empty one
crontab: installing new crontab
$ tree /var/spool/cron
/var/spool/cron
└── crontabs
    └── user1

1 directory, 1 file

Before editing the crontab of user1, /var/spool/cron/crontabs is empty. After the changes, the user now has their own file. Depending on their contents, ignoring a user’s scheduled tasks under /var/spool/cron can have consequences ranging from an inconvenience to a security hole.

3.5. Global Configuration

While the crontab files have additional options in the form of variables, the /etc/default/*cron files hold the general settings and additional command-line parameters that we can pass to each command:

$ cat /etc/default/anacron
# Environment File for anacron

[...]

# ANACRON_ARGS
#
# Arguments/options to pass to anacron.
# By default, "-s" is used to ensure serialised job arrangements.
# If you want tasks to execute in parallel when the jobs are due to
# start, do not pass "-s" here.

ANACRON_ARGS=-s

#
$ cat /etc/default/cron
# Cron configuration options

# Whether to read the system's default environment files (if present)
# [...]
READ_ENV="yes"

# Extra options for cron, see cron(8)
#
# For example, to enable LSB name support in /etc/cron.d/, use
# EXTRA_OPTS='-l'
#
# Or, to log standard messages, plus jobs with exit status != 0:
# EXTRA_OPTS='-L 5'
# [...]
#EXTRA_OPTS=""

To that end, /etc/default/cron and /etc/default/anacron affect most task runs by cron and anacron.

4. Backup cron and anacron

After going through the important related files, let’s jump right into a simple script to automatically backup and move the configuration of both cron and anacron via built-in Linux tools:

#!/usr/bin/env bash
BACKUPDIR="cronbak-$(date +%Y%m%d%H%M%S)"
mkdir "$BACKUPDIR"
pushd "$BACKUPDIR"
mkdir --parents ./etc/default
mkdir --parents ./var/spool/
cp --archive /etc/crontab ./etc/crontab
cp --archive /etc/anacrontab ./etc/anacrontab
cp --archive /etc/cron.* ./etc/
cp --archive /etc/default/cron ./etc/default/cron
cp --archive /etc/default/anacron ./etc/default/anacron
cp --archive /var/spool/cron ./var/spool/
cp --archive /var/spool/anacron ./var/spool/
popd

Here, we use the –archive (-a) option of cp. It behaves the same as -dR –preserve=all:

  • -d, equivalent to –no-dereference –preserve=links, keeps links as they are
  • -R, equivalent to -r and –recursive, copies recursively
  • –preserve=all ensures we leave all object attributes as they are in the original

First, the script generates a backup name $BACKUPDIR with the cronbak- prefix and the current timestamp as the date YYYYmmdd and time HHMMSS. Next, we create that directory in the current working path and switch to it via pushd, so popd can get us back later. Finally, we prepare the directory structure and copy all objects with cp.

Placing these lines in a script and running it, we get the whole tree of data:

$ cat cronbak.sh
#!/usr/bin/env bash
BACKUPDIR="cronbak-$(date +%Y%m%d%H%M%S)"
[...]
$ bash cronbak.sh >/dev/null
$ tree cronbak-20221030010656
cronbak-20221030010656/
├── etc
│   ├── anacrontab
│   ├── cron.allow
│   ├── cron.d
│   │   ├── anacron
│   │   └── e2scrub_all
│   ├── cron.daily
│   │   ├── 0anacron
│   │   ├── apt-compat
│   │   ├── dpkg
│   │   ├── logrotate
│   │   └── man-db
│   ├── cron.hourly
│   ├── cron.monthly
│   │   └── 0anacron
│   ├── crontab
│   ├── cron.weekly
│   │   ├── 0anacron
│   │   └── man-db
│   └── default
│       ├── anacron
│       └── cron
└── var
    └── spool
        ├── anacron
        │   ├── cron.daily
        │   ├── cron.monthly
        │   └── cron.weekly
        └── cron
            └── crontabs
                └── noot

12 directories, 19 files

Notably, we replicate the entire structure from the filesystem root, so we can easily restore it in another environment:

$ cp --archive --no-target-directory ./etc/ /etc
$ cp --archive --no-target-directory ./var/ /var

Of course, armed with the knowledge above, we can always go the rsync route for our purposes.

5. Summary

In this article, we discussed the anacron and cron tools, their configuration file structure, and a simple way to back them up.

In conclusion, because of how critical scheduling can be, understanding how to configure it, as well as preserve all related files, can be paramount.

Authors Bottom

If you have a few years of experience in the Linux ecosystem, and you’re interested in sharing that experience with the community, have a look at our Contribution Guidelines.

Comments are closed on this article!