使用 cron 调度任务
cron 定时
![](/data/attachment/album/202105/12/120220f7wwchadgwmsg1dw.jpg)


cron 是一个调度守护进程，它以指定的时间间隔执行任务，这些任务称为 corn 作业，主要用于自动执行系统维护或管理任务。例如，你可以设置一个 cron 作业来自动执行重复的任务，比如备份数据库或数据，使用最新的安全补丁更新系统，检查磁盘空间使用情况，发送电子邮件等等。 cron 作业可以按分钟、小时、日、月、星期或它们的任意组合运行。


### cron 的一些优点


以下是使用 cron 作业的一些优点：


* 你可以更好地控制作业的运行时间。例如，你可以精确到分钟、小时、天等。
* 它消除了为循环任务逻辑而去写代码的需要，当你不再需要执行任务时，可以直接关闭它。
* 作业在不执行时不会占用内存，因此你可以节省内存分配。
* 如果一个作业执行失败并由于某种原因退出，它将在适当的时间再次运行。


### 安装 cron 守护进程


幸运的是，Fedora Linux 预先配置了运行重要的系统任务来保持系统更新，有几个实用程序可以运行任务例如 cron、`anacron`、`at` 和 `batch` 。本文只关注 cron 实用程序的安装。cron 和 cronie 包一起安装，cronie 包也提供 `cron` 服务。


要确定软件包是否已经存在，使用 `rpm` 命令：



```
$ rpm -q cronie
 Cronie-1.5.2-4.el8.x86_64

```

如果安装了 cronie ，它将返回 cronie 包的全名。如果你的系统中没有安装，则会显示未安装。


使用以下命令安装：



```
$ dnf install cronie

```

### 运行 cron 守护进程


cron 作业由 crond 服务来执行，它会读取配置文件中的信息。在将作业添加到配置文件之前，必须启动 crond 服务，或者安装它。什么是 crond 呢？crond 是 cron 守护程序的简称。要确定 crond 服务是否正在运行，输入以下命令：



```
$ systemctl status crond.service
● crond.service - Command Scheduler
      Loaded: loaded (/usr/lib/systemd/system/crond.service; enabled; vendor pre>
      Active: active (running) since Sat 2021-03-20 14:12:35 PDT; 1 day 21h ago
    Main PID: 1110 (crond)

```

如果你没有看到类似的内容 `Active: active (running) since…`，你需要启动 crond 守护进程。要在当前会话中运行 crond 服务，输入以下命令：



```
$ systemctl run crond.service

```

将其配置为开机自启动，输入以下命令：



```
$ systemctl enable crond.service

```

如果出于某种原因，你希望停止 crond 服务，按以下方式使用 `stop` 命令：



```
$ systemctl stop crond.service

```

要重新启动它，只需使用 `restart` 命令：



```
$ systemctl restart crond.service

```

### 定义一个 cron 作业


#### cron 配置


以下是一个 cron 作业的配置细节示例。它定义了一个简单的 cron 作业，将 `git` master 分支的最新更改拉取到克隆的仓库中：



```
*/59 * * * * username cd /home/username/project/design && git pull origin master

```

主要有两部分：


* 第一部分是 `*/59 * * * *`。这表明计时器设置为第 59 分钟执行一次。（LCTT 译注：原文此处有误。）
* 该行的其余部分是命令，因为它将从命令行运行。 在此示例中，命令本身包含三个部分：
	+ 作业将以用户 `username` 的身份运行
	+ 它将切换到目录 `/home/username/project/design`
	+ 运行 `git` 命令拉取 master 分支中的最新更改


#### 时间语法


如上所述，时间信息是 cron 作业字符串的第一部分，如上所属。它决定了 cron 作业运行的频率和时间。它按以下顺序包括 5 个部分：


* 分钟
* 小时
* 一个月中的某天
* 月份
* 一周中的某天


下面是一种更图形化的方式来解释语法：



```
  .--------------- 分钟 (0 - 59)
 |  .------------- 小时 (0 - 23)
 |  |  .---------- 一月中的某天 (1 - 31)
 |  |  |  .------- 月份 (1 - 12) 或 jan、feb、mar、apr …
 |  |  |  |  .---- 一周中的某天 (0-6) (周日=0 或 7)
 |  |  |  |  |            或 sun、mon、tue、wed、thr、fri、sat
 |  |  |  |  |               
 *  *  *  *  *  user-name  command-to-be-executed 

```

#### 星号的使用


星号（`*`）可以用来替代数字，表示该位置的所有可能值。例如，分钟位置上的星号会使它每分钟运行一次。以下示例可能有助于更好地理解语法。


这个 cron 作业将每分钟运行一次：



```
* * * * [command]

```

斜杠表示分钟的间隔数。下面的示例将每小时运行 12 次，即每 5 分钟运行一次：



```
*/5 * * * * [command]

```

下一个示例将每月的第二天午夜（例如 1 月 2 日凌晨 12:00，2 月 2 日凌晨 12:00 等等）：



```
0 0 2 * * [command]

```

（LCTT 译注：关于 cron 时间格式，还有更多格式符号，此处没有展开）


#### 使用 crontab 创建一个 cron 作业


cron 作业会在后台运行，它会不断检查 `/etc/crontab` 文件和 `/etc/cron.*/` 以及 `/var/spool/cron/` 目录。每个用户在 `/var/spool/cron/` 中都有一个唯一的 crontab 文件。


不应该直接编辑这些 cron 文件。`crontab` 命令是用于创建、编辑、安装、卸载和列出 cron 作业的方法。


更酷的是，在创建新文件或编辑现有文件后，你无需重新启动 cron。



```
$ crontab -e

```

这将打开你现有的 crontab 文件，或者创建一个。调用 `crontab -e` 时，默认情况下会使用 `vi` 编辑器。注意：要使用 Nano 编辑 crontab 文件，可以设置 `EDITOR=nano` 环境变量。


使用 `-l` 选项列出所有 cron 作业。如果需要，使用 `-u` 选项指定一个用户。



```
$ crontab -l
$ crontab -u username -l

```

使用以下命令删除所有 cron 作业：



```
$ crontab -r

```

要删除特定用户的作业，你必须以 root 用户身份运行以下命令：



```
$ crontab -r -u username

```

感谢你的阅读。cron 作业看起来可能只是系统管理员的工具，但它实际上与许多 Web 应用程序和用户任务有关。


### 参考


Fedora Linux 文档的 [自动化任务](https://docs.fedoraproject.org/en-US/Fedora/12/html/Deployment_Guide/ch-autotasks.html)




---


via: <https://fedoramagazine.org/scheduling-tasks-with-cron/>


作者：[Darshna Das](https://fedoramagazine.org/author/climoiselle/) 选题：[lujun9972](https://github.com/lujun9972) 译者：[MjSeven](https://github.com/MjSeven) 校对：[wxy](https://github.com/wxy)


本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


OK
Cron is a scheduling daemon that executes tasks at specified intervals. These tasks are called *cron* jobs and are mostly used to automate system maintenance or administration tasks. For example, you could set a *cron* job to automate repetitive tasks such as backing up database or data, updating the system with the latest security patches, checking the disk space usage, sending emails, and so on. The *cron* jobs can be scheduled to run by the minute, hour, day of the month, month, day of the week, or any combination of these.

**Some advantages of cron**

These are a few of the advantages of using *cron* jobs:

- You have much more control over when your job runs i.e. you can control the minute, the hour, the day, etc. when it will execute.
- It eliminates the need to write the code for the looping and logic of the task and you can shut it off when you no longer need to execute the job.
- Jobs do not occupy your memory when not executing so you are able to save the memory allocation.
- If a job fails to execute and exits for some reason it will run again when the proper time comes.

## Installing the cron daemon

Luckily Fedora Linux is pre-configured to run important system tasks to keep the system updated. There are several utilities that can run tasks such as *cron*, *anacron*, *at* and *batch*. This article will focus on the installation of the *cron* utility only. Cron is installed with the *cronie* package that also provides the* cron* services.

To determine if the package is already present or not, use the rpm command:

$ rpm -q cronieCronie-1.5.2-4.el8.x86_64

If the *cronie * package is installed it will return the full name of the *cronie* package. If you do not have the package present in your system it will say the package is not installed.

To install type this:

$ dnf install cronie

## Running the cron daemon

A *cron* job is executed by the *crond* service based on information from a configuration file. Before adding a job to the configuration file, however, it is necessary to start the *crond* service, or in some cases install it. What is *crond*? *Crond* is the compressed name of cron daemon (crond). To determine if the *crond* service is running or not, type in the following command:

$ systemctl status crond.service● crond.service - Command Scheduler Loaded: loaded (/usr/lib/systemd/system/crond.service; enabled; vendor pre> Active: active (running) since Sat 2021-03-20 14:12:35 PDT; 1 day 21h ago Main PID: 1110 (crond)

If you do not see something similar including the line “Active: active (running) since…”, you will have to start the *crond* daemon. To run the *crond* service in the current session, enter the following command:

$ systemctl start crond.service

To configure the service to start automatically at boot time, type the following:

$ systemctl enable crond.service

If, for some reason, you wish to stop the *crond* service from running, use the *stop* command as follows:

$ systemctl stop crond.service

To restart it, simply use the *restart* command:

$ systemctl restart crond.service

## Defining a cron job

### The cron configuration

Here is an example of the configuration details for a *cron* job. This defines a simple *cron* job to pull the latest changes of a *git* master branch into a cloned repository:

*/59 * * * * username cd /home/username/project/design && git pull origin master

There are two main parts:

- The first part is “*/59 * * * *”. This is where the timer is set to every 59 minutes.
- The rest of the line is the command as it would run from the command line.

The command itself in this example has three parts:- The job will run as the user “username”
- It will change to the directory
/home/username/project/design
- The git command runs to pull the latest changes in the master branch.


**Timing syntax**

The timing information is the first part of the *cron* job string, as mentioned above. This determines how often and when the cron job is going to run. It consists of 5 parts in this order:

- minute
- hour
- day of the month
- month
- day of the week

Here is a more graphic way to explain the syntax may be seen here:

.---------------- 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,thr,fri,sat | | | | | * * * * * user-name command-to-be-executed

### Use of the **asterisk**

An asterisk (*) may be used in place of a number to represents all possible values for that position. For example, an asterisk in the minute position would make it run every minute. The following examples may help to better understand the syntax.

This cron job will run every minute, all the time:

* * * * * [command]

A slash (/) indicates a multiple number of minutes The following example will run 12 times per hour, i.e., every 5 minutes:

*/5 * * * * [command]

The next example will run once a month, on the second day of the month at midnight (e.g. January 2nd 12:00am, February 2nd 12:00am, etc.):

0 0 2 * * [command]

### Using crontab to create a cron job

Cron jobs run in the background and constantly check the */etc/crontab* file, and the */etc/cron.*/* and */var/spool/cron/* directories. Each user has a unique crontab file in */var/spool/cron/ *.

These *cron* files are not supposed to be edited directly. The *crontab* command is the method you use to create, edit, install, uninstall, and list cron jobs.

The same *crontab* command is used for creating and editing cron jobs. And what’s even cooler is that you don’t need to restart cron after creating new files or editing existing ones.

$ crontab -e

This opens your existing *crontab* file or creates one if necessary. The *vi* editor opens by default when calling *crontab -e*. Note: To edit the *crontab* file using Nano editor, you can optionally set the **EDITOR**=nano environment variable.

List all your *cron* jobs using the option *-l* and specify a user using the *-u* option, if desired.

$ crontab -l $ crontab -u username -l

Remove or erase all your *cron* jobs using the following command:

$ crontab -r

To remove jobs for a specific user you must run the following command as the *root user*:

$ crontab -r -u username

Thank you for reading. *cron* jobs may seem like a tool just for system admins, but they are actually relevant to many kinds of web applications and user tasks.

### Reference

Fedora Linux documentation for [Automated Tasks](https://docs.fedoraproject.org/en-US/Fedora/12/html/Deployment_Guide/ch-autotasks.html)

## Thomas

I really suggest to move away from cron jobs to systemd timers.

Many blog posts out there describing it – search for “systemd timers to replace cron”.

## hugotrip

FWIW you can also use systemd timers

https://opensource.com/article/20/7/systemd-timers

syntax can be simpler.

I use it for my backups in “user mode” :

https://wiki.archlinux.org/index.php/systemd/User

## laolux

Thanks for the article, automating things is a good habit.

I have a question though: Why use systemd to start a cron daemon when systemd does that job itself already? Is there anything I can do with cronie which systemd cannot? I myself use systemd rather often and find the timer units very helpful. They can even be used by regular users without sudo rights.

Another thing:

does not create a crontab file for me. And it also does not open anything if I

. What am I missing?

## Matěj Cepl

Wow! This is strange. Now, when the whole world switched from cron to systemd timers, your article feels like a bit of archeology.

## Oscar

There´s already Systemd timers.

## Mary Biggs

There’s a REALLY useful command in crontab which will start a process at boot time. The crontab line looks like:

@reboot

I use this to start services on my server when (if) Fedora 33 needs to be rebooted. Since this happens very infrequently, this command means that I always get the correct and complete list of services restarted.

## Mary Biggs

Sorry…..crontab line looks like this:

@reboot [your boot time command here]

## Erik

Good article!

One correction: Instead of ‘crontab -i’, I think ‘crontab -e’ is the right invocation to edit a crontab.

## Gregory Bartholomew

Thanks Erik. I’ve made the correction.

## Erik

The crontab format in the article is missing a field. It should be (per /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

## Gregory Bartholomew

Thanks Erik. I’ve made the correction.

## Erik

Thank you!

## leslie Satenstein

The following is my template for crontab (header

it contains some extra stuff that is very useful

#########################################################

string meaning

—— ——-

@reboot Run once, at startup.

@yearly Run once a year, “0 0 1 1 *”.

@annually (same as @yearly)

@monthly Run once a month, “0 0 1 * *”.

@weekly Run once a week, “0 0 * * 0”.

@daily Run once a day, “0 0 * * *”.

@midnight (same as @daily)

@hourly Run once an hour, “0 * * * *”.

#

#minute hr mnthday Mth DoW COMMAND

#………………………………….Minute of the hour

#| ……………………………Hour in the day (0..23)

#| | …………………….Day of month, 1..31

#| | | ……………..Month (1.12) Jan, Feb.. Dec

#| | | | ………day of the week 0-6 7==0 OR sun,mon,tue,wed,thr,fri,sat

#| | | | | command to be executed

With crontab I can schedule a job for the last day of the month, or even for the second Friday in a month. Is it possible with systemd.

## Gregory Bartholomew

How do you schedule a job for the last day of the month? I’ve done this before by running a script daily and aborting at the top if [[ $(date -d tomorrow ‘+%-d’) -ne 1 ]]. If there is a better way, I’m interested in knowing what it is. Thanks! 🙂

## laolux

The easy solution is to use systemd timers. They support the ~01 syntax to indicate the last day of the month. So, the last day of every month would be

–~01. And you can be even fancier: The last Monday of the month is “Mon–~07/1″. Nicely explained in the man page of. And while we’re at it:

will tell you the next time your expression is met, so you can easily check if your rules are valid.

No clue about how to to any of this with cron, though.

## Joao Rodrigues

Some cron implementations allow the usage of the non-standard “L” to represent “last”.

Otherwise use 0 0 28-31 * * [ $(date -d +1day +%d) -eq 1 ] && your-command.sh

## Sebastiaan Franken

You can do something along the following lines in a Systemd timer:

Inspired by cron, but expanded. The syntax for OnCalendar is “DayOfWeek Year-Month-Day Hour:Minute:Second”

## Mark

The post is a little confusing in the way it mixes the two crontab entry formats, the ‘username’ field is only available in files under /etc/cron.d and in /etc/crontab. It is not available in individual user crontabs would could be made a little clearer, the explaination of course being that individual user crontabs are run as the user the /var/spool/crontabs file is named and owned for so does not need to be specified.

The advantages of cron as mentioned are that it is easy to schedule repeating jobs, another advantage over systemd timers is that its simply editing a text file, and text files are easy to push out with tools like puppet/chef. Another advantage over systemd timers is that all *nix server have cron but not all have systemd.

The ‘info crontab’ page mentions cron jobs can run in a clustered environment, something I have not looked at but perhaps another adventage over systemd timers that are tied to one host.

There are a few disadvantages to cron that must be lived with

* one disadvantage you actually mentioned as an advantage with ‘If a job fails to execute and exits for some reason it will run again when the proper time comes’. That is an issue if the job must run every day; and why people tend to avoid scheduling jobs in cron between the hours of 2am and 3am to avoid the once a year issue of automatic daylight savings time skipping ahead one hour and missing them; that may be an issue with systemd timers as well but I haven’t really played with them

* any stdout/stderr from a cron job is by default mailed to the user of the crontab (although configurable), a badly written script can be a bit spammy

* /var/log/cron records jobs run, useless for alerting or fault solving when you want to know why a job failed; it cannot be easily hooked into external monitoring tools

* if a badly written cron job prompts for user input it will just hang waiting for it

For every disadvantage listed I wrote my own scheduler to solve every issue, as well as job dependency on prior jobs completing or files existing and most importantly alerting failures to external tools and a lot more bells and whistles; that was written on Fedora Core 3 and still in use. And guess what, I still make extensive use of cron jobs as well.

There are systemd timers, cron, and custom solutions out there. You don’t choose one and force it to fit, you just use the best for what you are trying to achieve and if that involves multiple solutions on a server thats fine.

In the response to the comment to the post ‘when the whole world switched from cron to systemd timers’, wrong; not all *nix platforms use systemd so a post on cron is still relevant in this day and age.

Thanks for the post; while I’ve played with /etc/cron.d|hourly|daily etc I wasn’t really aware of /etc/crontab on rhel based systems which is nothing but comments on my machines; which I will probably never use but nice to know its there as I wasn’t checking it.

I have learnt something new so the post was worthwhile.

Thanks

## laolux

While it is certainly true that not all systems run systemd, this fedora magazine is about… well, Fedora. And perhaps RHEL, which also uses systemd in all support versions that I am aware of.

## Mark

I agree. The comment that not all *nix systems support systemd is not relevant here so should not have been entered.

But fedora and rhel systems do still support cron and a post on using cron is still relevant.

Maybe one day someone will write an article on scheduling jobs using systemd I will look at.

But this article covers cron and does so quite well. It is probably the comments on systemd does it differently that are truely irrelevant to this article which is focused on using cron. There are probably many places systemd may be better, but this is not a systemd post 🙂

## Andrew

Well written comments Mark. I appreciated the advantages/disadvantages you posted.

## Ed Grimm

I’m always confused by people talking about the daylight savings time issue. It’s pretty easy to configure the system to use UTC, and then configure login and SSH to set the timezone to whatever the appropriate local timezone, so your system has a strictly linear concept of time, but your users can deal with all the madness that is DST if they want (or override that setting back to UTC if they don’t.)

## Bruno

Nice article, but as others already mentioned, why not use systemd ??

What are the avantages over systemd that would be worth having 2 differents systems to schedule task? 2 differents places to check in case of issues, 2 differents services to check for status …

Since systemd is not even mentioned in the article, a genuine user would think that installing cronie is required to schedule a task. At this stage it is misleading.

One more point, the link in “Reference” points to Fedora 12 documentation 🙂

It demonstrates how backward this article is, especially for a distribution featuring recent (cutting edge) techno.

## Göran Uddeborg

There is a little typo where you write

that should have been

.

## Gregory Bartholomew

Thanks Göran. I’ve made the correction.

## Göran Uddeborg

To all of you who point to systemd timers, one advantage of cron is that it is up all the time, while a user systemd instance might not. I can set up a user level cron job that runs on schedule as long as the machine is up, regardless if there is any systemd user instance for my account running.

Personally, I also find it much simpler to write a simple one-liner in my crontab than to create two (.timer and .service) complete systemd unit files in the common case when I don’t need the extra expressiveness of systemd. It’s like you could do anything you can do with grep using gawk instead, but for the simple cases where grep is enough, I still use that.

But of course, the latter part is a matter of taste.

## laolux

To have user systemd timers running without the user being logged in, one can use

. This command can be run by the user for his own username or by root for any user.

Using one-liners is fine for simple tasks, but for more complex ones systemd timer units have some perks. For example systemd timer units have the fancy

keyword. This is very useful if the computer was unavailable (shut down for example) when the timer was supposed to run. The timer will then execute the next time that the computer is available. I find this feature difficult to achieve with a one-liner in cron.

## Göran Uddeborg

That is kind of my point. If you want to do something simple, cron is a simpler tool. If you have more complex requirements than cron meets, systemd timers are more powerful. I want to use the right tool for the right task, trying to avoid the Law of the instrument trap. (https://en.wikipedia.org/wiki/Law_of_the_instrument)

## Erik

I agree with Göran.

In addition, even though I have been using systemd since Fedora switched to it from SysV, I find cron to be simpler and more straightforward than using systemd timers, especially for a repeating user job.

## Trey

Thank you … I hope to use Cronie to form a Conky based slide show!