> For the complete documentation index, see [llms.txt](https://book.bsdcn.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://book.bsdcn.org/ask/flat/chapter-17-system-administration/di-17.5-jie-cron-he-periodic.md).

# 17.5 Cron and Periodic

## Directory Structure of Cron and Periodic

The periodic.conf(5) file defines how daily, weekly, and monthly system maintenance tasks are run. `periodic` is FreeBSD's system maintenance task framework, responsible for periodically executing maintenance work such as log rotation and security checks. These tasks are executed by the `periodic` command, which is automatically invoked by the `cron` daemon according to a preset schedule.

Configuration and paths related to `periodic` and `cron` are as follows:

```sh
/
├── etc/
│   ├── defaults/                   # Stores some system default configuration files
│   │   └── periodic.conf           # Default configuration file, containing all system default variables and values
│   ├── periodic.conf               # System-specific variable override file (regular override, does not exist by default)
│   ├── periodic.conf.local         # Additional override file for shared or distributed scenarios (does not exist by default)
│   └── periodic/                   # Base system task script directory
│       ├── daily/                  # Daily maintenance task scripts
│       ├── weekly/                 # Weekly maintenance task scripts
│       ├── monthly/                # Monthly maintenance task scripts
│       └── security/               # Security-related task scripts
├── usr/
│   └── local/                      # Third-party software installation directory
│       └── etc/
│           └── periodic/           # Third-party application task script directory
│               ├── daily/          # Daily maintenance task scripts
│               ├── weekly/         # Weekly maintenance task scripts
│               └── security/       # Security-related task scripts
└── var/
    └── cron/
        ├── allow                   # List of users allowed to use crontab (does not exist by default)
        ├── deny                    # List of users prohibited from using crontab (does not exist by default)
        └── tabs/                   # Personal crontab file directory
```

The periodic.conf(5) file is located in the **/etc/defaults** directory. Parts of it can be overridden by a file with the same name in the **/etc** directory, and the file in **/etc** can in turn be overridden by the **/etc/periodic.conf.local** file.

Source code path structure:

* Source code related to periodic is primarily located at [usr.sbin/periodic/](https://github.com/freebsd/freebsd-src/blob/main/usr.sbin/periodic)
* Source code related to cron is primarily located at [usr.sbin/cron](https://github.com/freebsd/freebsd-src/tree/main/usr.sbin/cron).
* Source code for periodic scripts is located at [usr.sbin/periodic/etc/](https://github.com/freebsd/freebsd-src/tree/main/usr.sbin/periodic/etc).

## Cron

The cron(8) utility runs in the background, periodically checking tasks in **/etc/crontab** and looking for custom crontab files in **/var/cron/tabs**.

These files are used to schedule tasks, and cron will execute these tasks at the specified times.

> **Warning**
>
> The Vixie cron used by the FreeBSD base system is not fully compatible with Cronie commonly found on some Linux distributions. Please be sure to consult the relevant documentation before configuring, and do not rely entirely on experience!
>
> For example: Vixie cron **does not support** setting the `CRON_TZ` variable to change the scheduling timezone — Cron scheduling is always based on the system local time. `TZ` only affects the time/timezone understanding of the executed command, and does not affect Cron's determination of "when to trigger the task" at all.

Each crontab entry defines a task to be executed, called a **cron job**.

Two different types of configuration files are used:

* System crontab, which should not be modified; the system crontab **/etc/crontab** contains a `who` column, which does not exist in user crontabs. In the system crontab, cron runs commands as the user specified in that column.
* User crontab, which can be created and edited as needed. In a user crontab, all commands run as the user who created that crontab. User crontabs allow each user to schedule their own tasks. The `root` user can also have its own user `crontab` for scheduling tasks not present in the system `crontab`.

The following example entries are from the system crontab **/etc/crontab**:

```sh
# /etc/crontab - system crontab for FreeBSD # Lines starting with the `#` character are comments
#
#
SHELL=/bin/sh # ① = the equals character is used to define environment settings
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin
#
#minute	hour	mday	month	wday	who	command
#
# Save some entropy so that /dev/random can re-seed on boot.
*/11	*	*	*	*	operator /usr/libexec/save-entropy # ②③
#
# Rotate log files every hour, if necessary.
0	*	*	*	*	root	newsyslog
#
# Perform daily/weekly/monthly maintenance.
1	3	*	*	*	root	periodic daily
15	4	*	*	6	root	periodic weekly
30	5	1	*	*	root	periodic monthly
#
# Adjust the time zone if the CMOS clock keeps local time, as opposed to
# UTC time.  See adjkerntz(8) for details.
1,31	0-5	*	*	*	root	adjkerntz -a
```

* ① In this example, it is used to define `SHELL` and `PATH`. If `SHELL` is omitted, cron uses the default Bourne shell. If `PATH` is omitted, the full path to the command or script must be provided.
* ② This line defines the seven fields used in the system crontab: `minute`, `hour`, `mday`, `month`, `wday`, `who`, and `command`. The `minute` field specifies the minute when the command runs, `hour` is the hour, `mday` is the day of the month, `month` is the month, and `wday` is the day of the week. These fields must be numeric values representing a 24-hour clock, or \*, meaning all values for that field. The `who` field only exists in the system crontab and specifies which user the command should run as. The last field is the command to execute.
* ③ This entry defines the values for this cron job. `*/11` followed by multiple \* characters means **/usr/libexec/save-entropy** will be executed by `operator` every 11 minutes, every day, every week, every month. Commands can contain multiple options. If a command spans multiple lines, a backslash `\` continuation character must be used.

### Creating a User Crontab

To create a user crontab, invoke `crontab` in edit mode:

```sh
$ crontab -e
```

This opens the user's crontab using the default text editor. When the user runs this command for the first time, an empty file is opened. After the user creates a crontab, this command will open the file for editing.

Add the following lines to the top of the crontab file to set environment variables, and it is also recommended to keep the crontab field description comments for reference:

```ini
SHELL=/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin
# crontab field order
# minute hour day month weekday command
```

Add a line for each command or script to be run, specifying the time to run the command. This example runs the specified custom Bourne shell script every day at 2:00 PM. The script's path is not specified in `PATH`, so the full path to the script is given:

```ini
0 14 * * * /home/ykla/bin/custom_script.sh
```

> **Tip**
>
> The `/home/ykla/bin`, `email1@example.com`, and `email2@example.com` in the above examples are placeholders and must be replaced with actual values.

> **Tip**
>
> Before using a custom script, ensure it is executable and test it under the limited environment variables set by cron. To simulate the environment used by the cron entry above, execute the following command:
>
> ```sh
> $ env -i SHELL=/bin/sh PATH=/etc:/bin:/sbin:/usr/bin:/usr/sbin HOME=/home/user LOGNAME=user /home/user/bin/custom_script.sh
> ```
>
> It is crucial to check whether the script runs correctly in the cron environment, especially when the script contains commands that use wildcards to delete files.

After editing the crontab, save the file. The crontab will be automatically installed and take effect, and cron will read the crontab and run the cron jobs at the specified times. To list the cron jobs in the crontab, use the following command:

```sh
$ crontab -l
```

The output should be similar to the following:

```sh
0 14 * * * /home/ykla/bin/custom_script.sh
```

To delete all cron jobs from a user crontab:

```sh
$ crontab -r
```

The output should be similar to the following:

```sh
remove crontab for ykla? y
```

## Periodic

FreeBSD provides a set of system administration scripts for checking the status of various subsystems, performing security-related checks, rotating log files, and more. These scripts are executed on a periodic basis: daily, weekly, or monthly. These tasks are managed by periodic(8), and their configuration is located in periodic.conf(5). Periodic tasks are initiated by entries in the system crontab, as shown above.

The scripts executed by periodic(8) are located in **/etc/periodic/** (base tools) and **/usr/local/etc/periodic/** (third-party software).

They are distributed across 4 subdirectories: **daily**, **weekly**, **monthly**, and **security**.

### Enabling or Disabling Periodic Tasks

FreeBSD enables certain scripts to run periodically by default.

To enable `daily_status_zfs_enable`, add the following to the **/etc/periodic.conf** file:

```sh
daily_status_zfs_enable="YES"
```

To disable a task that is enabled by default, simply change `YES` to `NO`.

### Configuring Periodic Task Output

In the **/etc/periodic.conf** file, the variables `daily_output`, `weekly_output`, and `monthly_output` specify where the script execution results are sent.

By default, the output of periodic scripts is sent to the root user's mail, so it is recommended to read root's mail or alias root's mail to a monitored mailbox.

To send results to other email addresses, you can add space-separated email addresses in the **/etc/periodic.conf** file:

```ini
daily_output="email1@example.com email2@example.com"
weekly_output="email1@example.com email2@example.com"
monthly_output="email1@example.com email2@example.com"
```

If you want to log periodic output to a log file instead of receiving it via mail, you can add the following lines to the **/etc/periodic.conf** file. newsyslog(8) will rotate these files at the appropriate time:

```ini
daily_output=/var/log/daily.log
weekly_output=/var/log/weekly.log
monthly_output=/var/log/monthly.log
```

### Appendix: `locate` Command Example Analysis

Taking the path database **/var/db/locate.database** file that the `locate` command depends on as an example, this database is automatically updated once a week by the **/etc/periodic/weekly/310.locate** script.

If you need to update the database immediately, you can execute the script directly:

```sh
# locate locate.database # Attempting to find locate.database
locate: the locate database '/var/db/locate.database' does not exist.

To create a new database, please run the following command as root:

  /etc/periodic/weekly/310.locate
# /etc/periodic/weekly/310.locate  # Database not found, refresh as prompted

Rebuilding locate database:
# locate locate.database # Search again, found
/var/db/locate.database
```

## References

* FreeBSD Project. periodic.conf(5)\[EB/OL]. \[2026-04-17]. <https://man.freebsd.org/cgi/man.cgi?query=periodic.conf&sektion=5>. Periodic task configuration file manual page.
* FreeBSD Project. crontab(5)\[EB/OL]. \[2026-04-17]. <https://man.freebsd.org/cgi/man.cgi?query=crontab&sektion=5>. Cron task table manual page.

## Exercises

1. Create a custom periodic script in **/usr/local/etc/periodic/daily/**, configure `periodic.conf` to run it, and analyze the naming convention and execution order mechanism of periodic scripts.
2. Modify the execution time of periodic tasks in the **/etc/crontab** file, and compare the changes in task execution times in system logs before and after the modification.
3. Disable a default periodic task (such as weekly `310.locate`), and observe its impact on the update frequency of the `locate` command database.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://book.bsdcn.org/ask/flat/chapter-17-system-administration/di-17.5-jie-cron-he-periodic.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
