Kahibaro
Discord Login Register

4.1.4 Scheduled tasks (cron)

Why Schedule Tasks with cron

In real systems, many actions must happen at specific times without human intervention. Examples include rotating logs at midnight, backing up databases every night, or sending reports every Monday morning. On Linux, the classic tool for this type of time-based automation is cron. In this chapter you will learn how cron represents time schedules, where cron configuration lives, how user-specific crontabs work, and the main rules you must respect to make scheduled jobs run reliably.

The cron Service and crontab Files

cron is a background service that checks configuration files at regular intervals and decides which commands to run at which times. The configuration files that tell cron what to run are called crontabs.

There are two main types of crontabs. System-wide crontab files belong to the system administrator and usually live in /etc, for example /etc/crontab or files within /etc/cron.d. These are used for system tasks such as rotating logs or updating indexes. User crontab files exist per user and are managed with the crontab command instead of being edited directly. Each user can have their own list of scheduled jobs that run with that user’s permissions.

For routine automation of your own tasks as a non-root user, you will typically use your personal crontab.

Using the `crontab` Command

You interact with your personal crontab through the crontab command. You do not edit the underlying file directly. The most common operations are:

Editing your crontab uses:

crontab -e

This opens the current user’s crontab in the default editor, lets you modify or add entries, and then installs the new version when you save and exit.

Listing the currently installed crontab uses:

crontab -l

Removing all cron jobs for the current user uses:

crontab -r

You can also specify a user as root with crontab -u user -e, which edits another user’s crontab, but that is an administrative action.

When you run crontab -e for the first time, the system might ask you to choose a default editor such as nano or vim. After you save and exit, cron validates the syntax and reports any obvious errors.

The crontab Time Format

Each non-comment line in a crontab defines one scheduled job. The basic format has five time fields, followed by the command to execute. The fields are separated by spaces or tabs.

The structure of a crontab line is:

MIN HOUR DOM MON DOW COMMAND

Where:

MIN is the minute of the hour, from 0 to 59.

HOUR is the hour of the day, from 0 to 23.

DOM is the day of the month, from 1 to 31.

MON is the month, from 1 to 12, or sometimes the three-letter names jan to dec.

DOW is the day of the week, from 0 to 7, where 0 and 7 both usually mean Sunday, or the three-letter names sun to sat.

COMMAND is the shell command to run at the specified time.

Comments are any lines that start with #. Blank lines are ignored.

The most basic value for each field is a single number. For instance:

30 2  * * * /home/alex/bin/backup.sh

This runs /home/alex/bin/backup.sh at 02:30 every day. The * characters mean “every valid value for this field.”

cron schedule format:
$$\text{MIN HOUR DOM MON DOW COMMAND}$$
An asterisk * in a field means “every value” for that field.

Special Time Syntax: Lists, Ranges, and Steps

cron allows you to express more complex schedules without repeating many lines. You can use lists, ranges, and step values within the time fields.

A list uses commas to specify multiple discrete values in a single field. For example, in the hour field, 1,13 means “at 01:00 and 13:00”.

A range uses a dash to express a continuous interval. For instance, 1-5 in the day-of-week field means Monday to Friday. A range can cover any valid numeric span within that field.

A step value uses a slash to specify regular intervals. You can write */10 in the minute field to run a command every 10 minutes, which is equivalent to the list 0,10,20,30,40,50. Steps can also apply to ranges, for example 1-23/2 in the hour field means “every two hours starting at 01:00 and ending at 23:00.”

These notations can be combined with care. For example:

*/15 9-17 * * 1-5 /home/alex/bin/check_mail.sh

This runs every 15 minutes during working hours from 09:00 to 17:59 on weekdays, Monday through Friday.

Important cron patterns:
* means all values.
A,B,C is a list of specific values.
A-B is an inclusive range.
*/N is “every N units” of that field.

Predefined Macros like `@daily` and `@weekly`

To simplify common schedules, many cron implementations support macro keywords that replace the five time fields.

Some typical macros are:

@reboot to run once at system startup.

@yearly or @annually to run once a year, usually at midnight on January 1.

@monthly to run once a month, usually at midnight on the first of each month.

@weekly to run once a week, usually at midnight at the start of the week.

@daily or @midnight to run once a day, at midnight.

@hourly to run once an hour, at the top of the hour.

For example:

@daily /home/alex/bin/cleanup.sh

This has the same effect as writing 0 0 * /home/alex/bin/cleanup.sh, but is easier to read.

User Environments and cron Jobs

cron does not run your jobs inside an interactive login shell. This means the environment is different from the one you experience when you run commands manually in your terminal. Environment variables like PATH can be much more limited, and your usual shell initialization files may not be read.

Because of this, it is very common for a command that works perfectly in your terminal to fail when run by cron because an executable is not found or a variable is missing. To avoid this, you can:

Use absolute paths to executables and files. For example, specify /usr/bin/python3 instead of python3, and /home/alex/scripts/backup.sh instead of ~/scripts/backup.sh.

Define environment variables explicitly in the crontab, before any job lines. For example:

PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
0 3 * * * /home/alex/bin/nightly_job.sh

You can also set other variables such as MAILTO to control where output is sent.

Never rely on your interactive shell’s PATH or aliases in cron jobs.
Use absolute paths and, if needed, define PATH explicitly at the top of your crontab.

Output, Logging, and Notifications

Any text that a cron job writes to standard output or standard error is usually collected by cron. If the MAILTO variable is set in the crontab, cron will attempt to email this output to the specified recipient. If MAILTO is empty, output may be discarded.

To control where output goes, it is common to use redirection. For example:

0 2 * * * /home/alex/bin/backup.sh >> /var/log/backup.log 2>&1

This appends all output from the backup script, including error messages, to /var/log/backup.log. Using a log file helps you diagnose failures of scheduled jobs, since there is no terminal output to see.

If you want to silence a job completely, you can redirect both standard output and standard error to /dev/null:

*/5 * * * * /home/alex/bin/check_status.sh > /dev/null 2>&1

Be careful when throwing away output, since it also hides any error messages that could help you debug problems.

Timing Semantics and Overlapping Jobs

cron wakes up every minute, checks the crontab entries, and runs commands whose time specification matches the current time. Each matching line results in a new process. cron does not usually monitor how long jobs run and it does not automatically prevent jobs from overlapping.

If you schedule a job every minute but the command takes two minutes to complete, you can end up with multiple instances of the same command running concurrently. This can be harmless, or it can corrupt data or worsen performance, depending on what the command does.

To avoid problematic overlaps, you can design your scripts to use locking mechanisms. A simple pattern is to check for a lock file before running, and create the lock only while the job is active. For example, a script can exit immediately if it sees that another instance is already running. Another pattern involves using utilities such as flock in your cron line to enforce mutual exclusion.

You should also choose schedule intervals that are realistic for the job’s typical runtime. If a backup usually takes one hour, scheduling it every 30 minutes is almost certainly wrong.

System-wide cron Directories and `/etc/crontab`

Beyond per-user crontabs, many systems include additional cron configuration in /etc. There can be a main system crontab file, often /etc/crontab, and several directories such as /etc/cron.hourly, /etc/cron.daily, /etc/cron.weekly, and /etc/cron.monthly.

The system crontab often uses a slightly different format. It can include a user field that tells cron which user to run the command as, after the time fields and before the command. For example:

# /etc/crontab example
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
17 *   * * *   root    cd / && run-parts --report /etc/cron.hourly

In this example, commands inside /etc/cron.hourly are being executed every hour as root using a helper program.

The cron.* directories typically store scripts that are run at the associated frequency. The exact mechanism can vary between distributions. These system-wide mechanisms are mainly for administrative tasks and are commonly managed by the distribution or the system administrator rather than regular users.

Access Control and Security Considerations

Since cron allows arbitrary commands to run automatically, it has an important security impact. Some systems use /etc/cron.allow and /etc/cron.deny to control which users can create crontabs. If /etc/cron.allow exists, only users listed there may use crontab. If it does not exist but /etc/cron.deny does, only users listed in /etc/cron.deny are forbidden from using cron. The exact rules can vary slightly by implementation.

From a security perspective, any cron job effectively holds the same privileges as the user that owns it. System crontabs that run as root are powerful and can alter the entire system if misconfigured or compromised. It is best to:

Give each user the least privilege necessary. Avoid running cron jobs as root unless required.

Keep cron scripts in secure locations with proper permissions.

Be careful when editing system crontabs and do not insert untrusted content.

Also remember that cron jobs do not prompt for confirmation. If a script suddenly begins deleting files due to a bug or malicious modification, there will be no interactive warning. Logging and periodic review of cron-related logs are crucial.

Testing and Debugging cron Jobs

Debugging cron jobs can be more difficult than debugging commands run in a terminal because there is no interactive session. To test a new cron job:

First, run the script or command manually from a shell using the exact same command line you plan to put in the crontab, including full paths and any environment variables. Make sure it behaves as expected.

Next, add logging statements in your scripts, and capture output in log files when run from cron.

You can temporarily change the schedule to run more frequently for testing. For instance, if you plan a job for 03:00 daily, you might initially schedule it for every minute or every five minutes, watch it work, then switch to the final schedule.

Remember that cron uses a particular shell and environment, often /bin/sh, which may differ from your interactive shell. If your script depends on features of a specific shell, start the script with a proper shebang line such as #!/bin/bash so cron invokes the correct interpreter.

By systematically checking paths, environment, and logs, you can make your scheduled tasks with cron robust and predictable.

Views: 12

Comments

Please login to add a comment.

Don't have an account? Register now!