使用Cronjobs的综合指南

There are times when there’s a need for running a group of tasks automatically at certain times in the future. These tasks are usually administrative, but could be anything – from making database backups to downloading emails when everyone is asleep.

有时候,将来有必要在某些时候自动运行一组任务。 这些任务通常是管理性的,但可能是任何事情–从进行数据库备份到每个人都睡着时下载电子邮件。

Cron is a time-based job scheduler in Unix-like operating systems, which triggers certain tasks at a point in the future. The name originates from the Greek word χρόνος (chronos), which means time.

Cron是类Unix操作系统中的基于时间的作业调度程序,它将在将来的某个时刻触发某些任务。 名称源自希腊语χρόνος (chronos),意思是时间。

The most commonly used version of Cron is known as Vixie Cron, originally developed by Paul Vixie in 1987.

最常用的Cron版本称为Vixie Cron,最初由Paul Vixie于1987年开发。

This article is an in-depth walkthrough of this program, and a reboot of this ancient, but still surprisingly relevant post.

本文是该程序的深入演练,也是该古老但仍然出乎意料的相关文章的重新启动。

Chronos Image

术语 (Terminology)

  • Job: a unit of work, a series of steps to do something. For example, sending an email to a group of users. In this article, we’ll use task, job, cron job or event interchangeably.

    工作:一个工作单元,一系列要做某事的步骤。 例如,向一组用户发送电子邮件。 在本文中,我们将交替使用taskjobcron jobevent

  • Daemon: (/ˈdiːmən/ or /ˈdeɪmən/) is a computer program which runs in the background, serving different purposes. Daemons are often started at boot time. A web server is a daemon serving HTTP requests. Cron is a daemon for running scheduled tasks.

    守护程序: (/ ˈdiːmən /或/ ˈdeɪmən /)是在后台运行的计算机程序,可用于不同目的。 守护程序通常在引导时启动。 Web服务器是服务于HTTP请求的守护程序。 Cron是用于运行计划任务的守护程序。

  • Cron Job: a cron job is a scheduled job, being run by Cron when it’s due.

    Cron作业: cron作业是计划的作业 ,在到期时由Cron运行。

  • Webcron: a time-based job scheduler which runs within the web server environment. It’s used as an alternative to the standard Cron, often on shared web hosts that do not provide shell access.

    Webcron:在Web服务器环境中运行的基于时间的作业计划程序。 它通常用作标准Cron的替代品,通常在不提供外壳程序访问权限的共享Web主机上使用。

入门 (Getting Started)

This tutorial assumes you’re running a Unix-based operating system like Ubuntu. If you aren’t, we recommend setting up Homestead Improved – it’s a 5 minute process which will save you years down the line.

本教程假定您正在运行基于Ubuntu的基于Unix的操作系统。 如果不是这样,我们建议您设置Homestead Improvement –这是一个5分钟的过程,可以节省您数年的时间。

If we take a look inside the /etc directory, we can see directories like cron.hourly, cron.daily, cron.weekly and cron.monthly, each corresponding to a certain frequency of execution. One way to schedule our tasks is to place our scripts in the proper directory. For example, to run db_backup.php on a daily basis, we put it inside cron.daily. If the folder for a given frequency is missing, we would need to create it first.

如果在/etc目录中查看,我们会看到cron.hourlycron.dailycron.weeklycron.monthly /etc目录,每个目录都对应于一定的执行频率。 安排任务的一种方法是将脚本放置在正确的目录中。 例如,要每天运行db_backup.php ,请将其放入cron.daily 。 如果缺少给定频率的文件夹,则需要首先创建它。

Note: This approach uses the run-parts script, a command which runs every executable it finds within the specified directory.

注意:此方法使用run-parts脚本,该命令运行在指定目录中找到的每个可执行文件。

This is the simplest way to schedule a task. However, if we need more flexibility, we should use Crontab.

这是安排任务的最简单方法。 但是,如果需要更大的灵活性,则应使用Crontab。

Crontab文件 (Crontab Files)

Cron uses special configuration files called crontab files, which contain a list of jobs to be done. Crontab stands for Cron Table. Each line in the crontab file is called a cron job, which resembles a set of columns separated by a space character. Each row specifies when and how often a certain command or script should be executed.

Cron使用称为crontab文件的特殊配置文件,其中包含要完成的作业列表。 Crontab代表Cron Table 。 crontab文件中的每一行都称为cron作业,它类似于一组由空格分隔的列。 每行指定应在何时以及多久执行一次特定命令或脚本。

In a crontab file, blank lines or lines starting with #, spaces or tabs will be ignored. Lines starting with # are considered comments.

在crontab文件中,空白行或以#开头的行,空格或制表符将被忽略。 以#开头的行被视为注释。

Active lines in a crontab are either the declaration of an environment variable or a cron job, and comments are not allowed on the active lines.

crontab中的活动行是环境变量的声明或cron作业,并且活动行中不允许注释。

Below is an example of a crontab file with just one entry:

以下是仅包含一个条目的crontab文件的示例:

0 0 * * *  /var/www/sites/db_backup.sh

The first part 0 0 * * * is the cron expression, which specifies the frequency of execution. The above cron job will run once a day.

第一部分0 0 * * *是cron表达式,它指定执行频率。 上面的cron作业每天运行一次。

Users can have their own crontab files named after their username as registered in the /etc/passwd file. All user-level crontab files reside in Cron’s spool area. These files should not be edited directly. Instead, we should edit them using the crontab command-line utility.

用户可以使用在/etc/passwd文件中注册的用户名命名自己的crontab文件。 所有用户级crontab文件都位于Cron的假脱机区域中。 这些文件应该被直接编辑。 相反,我们应该使用crontab命令行实用工具对其进行编辑。

Note: The spool directory varies across different distributions of Linux. On Ubuntu it’s /var/spool/cron/crontabs while in CentOS it’s /var/spool/cron.

注意:假脱机目录在Linux的不同发行版中有所不同。 在Ubuntu上是/var/spool/cron/crontabs而在CentOS中是/var/spool/cron

To edit our own crontab file:

要编辑我们自己的 crontab文件:

crontab -e

The above command will automatically open up the crontab file which belongs to our user. If a default system editor for the crontab hasn’t been selected before, a choice will be presented listing the installed ones. We can also explicitly choose or change our desired editor for editing the crontab file:

上面的命令将自动打开属于我们用户的crontab文件。 如果以前没有为crontab选择默认的系统编辑器,则会显示一个选项,列出已安装的程序。 我们还可以显式选择或更改所需的编辑器来编辑crontab文件:

export VISUAL=nano; crontab -e

After we save the file and exit the editor, the crontab will be checked for accuracy. If everything is set properly, the file will be saved to the spool directory.

保存文件并退出编辑器后,将检查crontab的准确性。 如果一切设置正确,文件将保存到假脱机目录。

Note: Each command in the crontab file is executed from the perspective of the user who owns the crontab, so if your command runs as root (sudo) you will not be able to define this crontab from your own user account unless you log in as root.

注意: crontab文件中的每个命令都是从拥有crontab的用户的角度执行的,因此,如果您以root(sudo)身份运行命令,则除非您以根。

To list the installed cron jobs belonging to our own user:

列出属于我们自己用户的已安装cron作业:

crontab -l

We can also write our cron jobs in a file and send its contents to the crontab file like so:

我们还可以将cron作业写入文件中,然后将其内容发送到crontab文件中,如下所示:

crontab /path/to/the/file/containing/cronjobs.txt

The preceding command will overwrite the existing crontab file with /path/to/the/file/containing/cronjobs.txt.

前面的命令将使用/path/to/the/file/containing/cronjobs.txt the /path/to/the/file/containing/cronjobs.txt file /path/to/the/file/containing/cronjobs.txt覆盖现有的crontab文件。

To remove the crontab, we use the -r option:

要删除crontab,我们使用-r选项:

crontab -r

Crontab条目的剖析 (Anatomy of a Crontab Entry)

The anatomy of a user-level crontab entry looks like the following:

用户级crontab条目的结构如下所示:

# ┌───────────── min (0 - 59) 
 # │ ┌────────────── hour (0 - 23)
 # │ │ ┌─────────────── day of month (1 - 31)
 # │ │ │ ┌──────────────── month (1 - 12)
 # │ │ │ │ ┌───────────────── day of week (0 - 6) (0 to 6 are Sunday to Saturday, or use names; 7 is Sunday, the same as 0)
 # │ │ │ │ │
 # │ │ │ │ │
 # * * * * *  command to execute

The first two fields specify the time (minute and hour) at which the task will run. The next two fields specify the day of the month and the month. The fifth field specifies the day of the week.

前两个字段指定任务运行的时间( 分钟小时 )。 接下来的两个字段指定当月的日期月份 。 第五个字段指定星期几

The command will be executed when the minute, hour, month and either day of month or day of week match the current time.

当分钟,小时,月份以及月份中的某天一周中的某天与当前时间匹配时,将执行该命令。

If both day of week and day of month have certain values, the event will be run when either field matches the current time. Consider the following expression:

如果星期几月份中的某几天都具有特定值,则任一字段与当前时间匹配时将运行事件。 考虑以下表达式:

0 0 5-20/5 Feb 2 /path/to/command

The preceding cron job will run once per day every five days, from 5th to 20th of February plus all Tuesdays of February.

2月5日至20日加上 2月的所有星期二,之前的cron作业将每5天每天运行一次。

Important: When both day of month and day of week have certain values (not an asterisk), it will create an OR condition, meaning both days will be matched.

重要说明 :当月份中的 某天和一周中的某天都具有特定值(而不是星号)时,它将创建OR条件,这意味着这两天将匹配。

The syntax in system crontabs (/etc/crontab) is slightly different than user-level crontabs. The difference is that the sixth field is not the command, but it is the user we want to run the job as.

系统crontabs( /etc/crontab )中的语法与用户级crontabs略有不同。 区别在于第六个字段不是命令,而是我们要以其身份运行作业的用户

* * * * * testuser /path/to/command

It’s not recommended to put system-wide cron jobs in /etc/crontab, as this file might be modified in future system updates. Instead, we put these cron jobs in the /etc/cron.d directory.

不建议将系统范围的cron作业放在/etc/crontab ,因为此文件可能在以后的系统更新中被修改。 相反,我们将这些cron作业放在/etc/cron.d目录中。

编辑其他用户的Crontab (Editing Other Users’ Crontab)

We might need to edit other users’ crontab files. To do this, we use the -u option as below:

我们可能需要编辑其他用户的crontab文件。 为此,我们使用-u选项,如下所示:

crontab -u username -e

Note We can only edit other users’ crontab files as the root user, or as a user with administrative privileges.

注意我们只能以root用户或具有管理特权的用户身份编辑其他用户的crontab文件。

Some tasks require super admin privileges, thus, they should be added to the root user’s crontab file:

一些任务需要超级管理员特权,因此,应将它们添加到root用户的crontab文件中:

sudo crontab -e

Note: Please note that using sudo with crontab -e will edit the root user’s crontab file. If we need to to edit another user’s crontab while using sudo, we should use -u option to specify the crontab owner.

注意:请注意,将sudocrontab -e一起使用将编辑root用户的crontab文件。 如果在使用sudo需要编辑其他用户的crontab,则应使用-u选项指定crontab所有者。

To learn more about the crontab command:

要了解有关crontab命令的更多信息:

man crontab

标准和非标准值 (Standard and Non-Standard Values)

Crontab fields accept numbers as values. However, we can put other data structures in these fields, as well.

Crontab字段接受数字作为值。 但是,我们也可以在这些字段中放置其他数据结构。

范围 (Ranges)

We can pass in ranges of numbers:

我们可以传递数字范围:

0 6-18 1-15 * * /path/to/command

The above cron job will be executed from 6 am to 6 pm from 1st to 15th of each month in the year. Note that the specified range is inclusive, so 1-5 means 1,2,3,4,5.

上面的Cron工作将从每年的每月1号到15号从上午6点到下午6点执行。 请注意,指定的范围是包括在内的,因此1-5表示1,2,3,4,5。

清单 (Lists)

A list is a group of values separated by commas. We can have lists as field values:

列表是一组用逗号分隔的值。 我们可以将列表作为字段值:

0 1,4,5,7 * * * /path/to/command

The above syntax will run the cron job at 1 am, 4 am, 5 am and 7 am every day.

以上语法将在每天的凌晨1点,4点,5点和7点运行cron作业。

脚步 (Steps)

Steps can be used with ranges or the asterisk character (*). When they are used with ranges they specify the number of values to skip through the end of the range. They are defined with a / character after the range, followed by a number. Consider the following syntax:

步骤可以与范围或星号(*) 。 与范围一起使用时,它们指定要跳过范围末尾的值的数量。 它们在范围后用/字符定义,后跟数字。 考虑以下语法:

0 6-18/2 * * * /path/to/command

The above cron job will be executed every two hours from 6 am to 6 pm.

上述cron作业将从上午6点至下午6点每两个小时执行一次。

When steps are used with an asterisk, they simply specify the frequency of that particular field. As an example if we set the minute to */5, it simply means every five minutes.

当步骤与星号一起使用时,它们仅指定该特定字段的频率。 例如,如果将分钟设置为*/5 ,则表示每五分钟一次

We can combine lists, ranges, and steps together to have more flexible event scheduling:

我们可以将列表,范围和步骤组合在一起,以进行更灵活的事件调度:

0 0-10/5,14,15,18-23/3 1 1 * /path/to/command

The above event will run every five hours from midnight of January 1st to 10 am, 2 pm, 3 pm and also every three hours from 6pm to 11 pm.

上述活动从1月1日午夜至上午10点,下午2点,下午3点每五小时运行一次,从下午6点至晚上11点每三小时运行一次。

名字 (Names)

For the fields month and day of week we can use the first three letters of a particular day or month, like Sat, sun, Feb, Sep, etc.

对于月份星期几,我们可以使用特定日期或月份的前三个字母,例如SatsunFebSep等。

* * * Feb,mar sat,sun /path/to/command

The preceding cron job will be run only on Saturdays and Sundays of February and March.

之前的cron作业将仅在2月和3月的周六和周日运行。

Please note that the names are not case-sensitive. Ranges are not allowed when using names.

请注意,名称区分大小写。 使用名称时不允许使用范围。

预定义的定义 (Predefined Definitions)

Some cron implementations may support some special strings. These strings are used instead of the first five fields, each specifying a certain frequency:

一些cron实现可能支持一些特殊的字符串。 使用这些字符串代替前五个字段,每个字段指定特定的频率:

  • @yearly, @annually Run once a year at midnight of January 1 (0 0 1 1 *)

    @ yearly,@ annualally每年1月1日午夜运行一次(0 0 1 1 *)

  • @monthly Run once a month, at midnight of the first day of the month (0 0 1 * *)

    @monthly每月一次,在每月第一天的午夜运行(0 0 1 * *)

  • @weekly Run once a week at midnight of Sunday (0 0 * * 0)

    @weekly在星期日的午夜每周运行一次(0 0 * * 0)

  • @daily Run once a day at midnight (0 0 * * *)

    @daily每天午夜运行一次(0 0 * * *)

  • @hourly Run at the beginning of every hour (0 * * * *)

    @hourly在每小时开始时运行(0 * * * *)

  • @reboot Run once at startup

    @reboot在启动时运行一次

同一Cron作业中的多个命令 (Multiple Commands in the Same Cron Job)

We can run several commands in the same cron job by separating them with a semi-colon (;).

我们可以在同一cron作业中运行多个命令,方法是使用分号( ; )将它们分开。

* * * * * /path/to/command-1; /path/to/command-2

If the running commands depend on each other, we can use double ampersand (&&) between them. As a result, the second command will not be executed if the first one fails.

如果运行命令互相依赖,我们可以使用双和号(&&)之间。 结果,如果第一个命令失败,则第二个命令将不会执行。

* * * * * /path/to/command-1 && /path/to/command-2

环境变量 (Environment Variables)

Environment variables in crontab files are in the form of VARIABLE_NAME = VALUE (The white spaces around the equal sign are optional). Cron does not source any startup files from the user’s home directory (when it’s running user-level crons). This means we should manually set any user-specific settings required by our tasks.

crontab文件中的环境变量采用VARIABLE_NAME = VALUE的形式(等号周围的空白是可选的)。 Cron不会从用户的主目录中获取任何启动文件(运行用户级Cron时)。 这意味着我们应该手动设置任务所需的任何特定于用户的设置。

Cron daemon automatically sets some environmental variables when it starts. HOME and LOGNAME are set from the crontab owner’s information in /etc/passwd. However, we can override these values in our crontab file if there’s a need for this.

Cron守护程序在启动时会自动设置一些环境变量。 HOMELOGNAME是从/etc/passwd的crontab所有者的信息中设置的。 但是,如果需要,我们可以在crontab文件中覆盖这些值。

There are also a few more variables like SHELL, specifying the shell which runs the commands. It is /bin/sh by default. We can also set the PATH in which to look for programs.

还有其他一些变量,例如SHELL ,用于指定运行命令的外壳。 默认情况下是/bin/sh 。 我们还可以设置要在其中查找程序的PATH

PATH = /usr/bin;/usr/local/bin

Important: We should wrap the value in quotation marks when there’s a space in the value. Please note that values are considered as ordinary strings and are not interpreted or parsed in any way.

重要提示 :如果值中有空格,则应将其用引号引起来。 请注意,值被视为普通字符串, 不会以任何方式解释或解析。

不同时区 (Different Time Zones)

Cron uses the system’s time zone setting when evaluating crontab entries. This might cause problems for multiuser systems with users based in different time zones. To work around this problem, we can add an environment variable named CRON_TZ in our crontab file. As a result, all crontab entries will be parsed based on the specified timezone.

Cron在评估crontab条目时使用系统的时区设置。 对于具有不同时区用户的多用户系统,这可能会导致问题。 要变通解决此问题,我们可以在crontab文件中添加一个名为CRON_TZ的环境变量。 结果,将基于指定的时区解析所有crontab条目。

Cron如何解释Crontab文件 (How Cron Interprets Crontab Files)

After Cron starts, it searches its spool area to find and load crontab files into the memory. It additionally checks the /etc/crontab and or /etc/cron.d directories for system crontabs.

Cron启动后,它将搜索其后台打印区域以查找crontab文件并将其加载到内存中。 此外,它还会检查/etc/crontab/etc/crontab/etc/cron.d目录中的系统crontab。

After loading the crontabs into memory, Cron checks the loaded crontabs on a minute-by-minute basis, running the events which are due.

将crontabs加载到内存中后,Cron会每分钟检查加载的crontabs,并运行到期的事件。

In addition to this, Cron regularly (every minute) checks if the spool directory’s modtime (modification time) has changed. If so, it checks the modetime of all the loaded crontabs and reloads those which have changed. That’s why we don’t have to restart the daemon when installing a new cron job.

除此之外,Cron会定期(每分钟)检查假脱机目录的modtime (修改时间)是否已更改。 如果是这样,它将检查所有已加载crontab的modetime并重新加载已更改的crontab。 这就是为什么在安装新的cron作业时我们不必重新启动守护程序。

Cron权限 (Cron Permissions)

We can specify which user should be able to use Cron and which user should not. There are two files which play an important role when it comes to cron permissions: /etc/cron.allow and /etc/cron.deny.

我们可以指定哪个用户应该可以使用Cron,哪个用户不能。 在涉及cron权限时,有两个文件起着重要作用: /etc/cron.allow/etc/cron.deny

If /etc/cron.allow exists, then our username must be listed in this file in order to use crontab. If /etc/cron.deny exists, it shouldn’t contain our username. If neither of these files exist, then based on the site-dependent configuration parameters, either the super user or all users will be able to use crontab command. For example, in Ubuntu, if neither file exists, all users can use crontab by default.

如果存在/etc/cron.allow ,则必须在此文件中列出我们的用户名才能使用crontab 。 如果/etc/cron.deny存在,则不应包含我们的用户名。 如果这两个文件都不存在,则基于站点的配置参数, 超级用户所有用户都将能够使用crontab命令。 例如,在Ubuntu中,如果两个文件都不存在,则默认情况下所有用户都可以使用crontab。

We can put ALL in /etc/cron.deny file to prevent all users from using cron:

我们可以将ALL放在/etc/cron.deny文件中,以防止所有用户使用cron:

echo ALL > /etc/cron.deny

Note: If we create an /etc/cron.allow file, there’s no need to create a /etc/cron.deny file as it has the same effect as creating a /etc/cron.deny file with ALL in it.

注意 :如果我们创建/etc/cron.allow文件,则无需创建/etc/cron.deny文件,因为它与创建包含ALL/etc/cron.deny文件具有相同的效果。

重定向输出 (Redirecting Output)

We can redirect the output of our cron job to a file, if the command (or script) has any output:

如果命令(或脚本)具有任何输出,我们可以将cron作业的输出重定向到文件:

* * * * * /path/to/php /path/to/the/command >> /var/log/cron.log

We can redirect the standard output to dev null, to get no email (more on emails below), but still allowing the standard error to be sent as email:

我们可以将标准输出重定向到dev null,以不接收电子邮件(更多有关以下电子邮件),但仍允许将标准错误作为电子邮件发送:

* * * * * /path/to/php /path/to/the/command > /dev/null

To prevent Cron from sending any emails to us, we change the respective crontab entry as below:

为防止Cron向我们发送任何电子邮件,我们如下更改相应的crontab条目:

* * * * * /path/to/php /path/to/the/command > /dev/null 2>&1

This means “send both the standard output, and the error output into oblivion”.

这意味着“同时发送标准输出和错误输出”。

通过电子邮件发送输出 (Email the Output)

The output is mailed to the owner of the crontab or the email(s) specified in the MAILTO environment variable (if the standard output or standard error are not redirected as above).

输出将邮寄给crontab的所有者或MAILTO环境变量中指定的电子邮件(如果标准输出或标准错误未如上述那样重定向)。

If MAILTO is set to empty, no email will be sent out as the result of the cron job.

如果MAILTO设置为空,则cron作业不会发送任何电子邮件。

We can set several emails by separating them with commas:

我们可以使用逗号分隔多个电子邮件:

MAILTO=admin@example.com,dev@example.com
* * * * * /path/to/command

Cron和PHP (Cron and PHP)

We usually run our PHP command line scripts using the PHP executable.

我们通常使用PHP可执行文件运行PHP命令行脚本。

php script.php

Alternatively, we can use shebang at the beginning of the script, and point to the PHP executable:

另外,我们可以在脚本的开头使用shebang ,然后指向PHP可执行文件:

#! /usr/bin/php

<?php

// PHP code here

As a result, we can execute the file by calling it by name. However, we need to make sure we have the permission to execute it.

结果,我们可以通过按名称调用文件来执行该文件。 但是,我们需要确保我们具有执行它的权限。

To have more robust PHP command line scripts, we can use third-party components for creating console applications like Symfony Console Component or Laravel Artisan. This article is a good start for using Symfony’s Console Component. Creating console commands using Laravel Artisan has been also covered here. If you’d rather use another command line tool for PHP, we have a comparison here.

为了拥有更强大PHP命令行脚本,我们可以使用第三方组件来创建控制台应用程序,例如Symfony Console ComponentLaravel Artisan本文是使用Symfony的控制台组件的一个良好的开端。 这里也介绍使用Laravel Artisan创建控制台命令。 如果您想为PHP使用其他命令行工具,请在此处进行比较。

任务重叠 (Task Overlaps)

There are times when scheduled tasks take much longer than expected. This will cause overlaps, meaning some tasks might be running at the same time. This might not cause a problem in some cases, but when they are modifying the same data in a database, we’ll have a problem. We can overcome this by increasing the execution frequency of the tasks, but still it’s not guaranteed that these overlaps won’t happen again.

有时,计划任务要花费比预期更长的时间。 这将导致重叠,这意味着某些任务可能同时运行。 在某些情况下,这可能不会引起问题,但是当他们修改数据库中的相同数据时,我们会遇到问题。 我们可以通过增加任务的执行频率来克服这一问题,但是仍然不能保证这些重叠不会再次发生。

We have several options to prevent cron jobs from overlapping.

我们有几种选择可以防止cron作业重叠。

使用羊群 (Using Flock)

Flock is a nice tool to manage lock files from within shell scripts or the command line. These lock files are useful for knowing whether or not a script is running.

Flock是一个很好的工具,可以从Shell脚本或命令行中管理锁文件。 这些锁定文件对于了解脚本是否正在运行很有用。

When used in conjunction with Cron, the respective cron jobs do not start if the lock file exists. You can install Flock using apt-get or yum depending on the Linux distribution.

与Cron结合使用时,如果存在锁定文件,则相应的cron作业不会启动。 您可以根据Linux发行版使用apt-getyum安装Flock。

apt-get install flock

Or

要么

yum install flock

Consider the following crontab entry:

考虑以下crontab条目:

* * * * * /usr/bin/flock --timeout=1 /path/to/cron.lock /usr/bin/php /path/to/scripts.php

In the preceding example, flock looks for /path/to/cron.lock. If the lock is acquired in one second, it will run the script, otherwise, it will fail with an exit code of 1.

在前面的示例中, flock查找/path/to/cron.lock 。 如果在一秒钟内获得了锁,它将运行脚本,否则将失败,退出代码为1。

在脚本中使用锁定机制 (Using a Locking Mechanism in the Scripts)

If the cron job executes a script, we can implement a locking mechanism in the script. Consider the following PHP script:

如果cron作业执行脚本,我们可以在脚本中实现锁定机制。 考虑以下PHP脚本:

<?php
$lockfile = sys_get_temp_dir() . '/' md5(__FILE__) . '.lock';
$pid      = file_exists($lockfile) ? trim(file_get_contents($lockfile)) : null;

if (is_null($pid) || posix_getsid($pid) === false) {

    // Do something here
    
    // And then create/update the lock file
    file_put_contents($lockfile, getmypid());

} else {
    exit('Another instance of the script is already running.');
}

In the preceding code, we keep pid of the current PHP process in a file, which is located in the system’s temp directory. Each PHP script has its own lock file, which is the MD5 hash of the script’s filename.

在前面的代码中,我们将当前PHP进程的pid保留在一个文件中,该文件位于系统的temp目录中。 每个PHP脚本都有其自己的锁定文件,该文件是脚本文件名的MD5哈希。

First, we check if the lock file exists, and then we get its content, which is the process ID of the last running instance of the script. Then we pass the pid to posix_getsid PHP function, which returns the session ID of the process. If posix_getsid returns false it means the process is not running anymore and we can safely start a new instance.

首先,我们检查锁定文件是否存在,然后获取其内容,该内容是脚本最后运行的实例的进程ID。 然后,将pid传递给posix_getsid PHP函数,该函数返回进程的会话ID。 如果posix_getsid返回false则意味着该进程不再运行,我们可以安全地启动一个新实例。

Anacron (Anacron)

One of the problems with Cron is that it assumes the system is running continuously (24 hours a day). This causes problems for machines which are not running all day long (like personal computers). If the system goes off during the time a task is scheduled to run, Cron will not run that task retroactively.

Cron的问题之一是它假设系统连续运行(一天24小时)。 这会导致整天未运行的计算机(例如个人计算机)出现问题。 如果在计划运行任务的时间内系统关闭,Cron将不会追溯运行该任务。

Anacron is not a replacement for Cron, but it has been developed to solve this problem. It runs the commands once a day, week or month but not on a minute-by-minute or hourly basis as Cron does. It is, however, guaranteed that the task will run even if the system goes off for an unanticipated period of time.

Anacron不能替代Cron,但已开发出用于解决此问题的方法。 它每天,每周或每月运行一次命令,但不像Cron那样每分钟或每小时运行一次。 但是,即使系统在意外的时间内关闭,也可以确保任务将运行。

Only root or a user with administrative privileges can manage Anacron tasks. Anacron does not run in the background like a daemon, but only once, executing the tasks which are due.

只有root或具有管理特权的用户才能管理Anacron任务。 Anacron不会像后台程序那样在后台运行,而只能执行一次,以执行到期的任务。

Anacron uses a configuration file (just like crontab) named anacrontabs. This file is located in the /etc directory.

Anacron使用名为anacrontabs的配置文件(就像crontab一样)。 该文件位于/etc目录中。

The content of this file looks like this:

该文件的内容如下所示:

# /etc/anacrontab: configuration file for anacron

# See anacron(8) and anacrontab(5) for details.

SHELL=/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
# the maximal random delay added to the base delay of the jobs
RANDOM_DELAY=45
# the jobs will be started during the following hours only
START_HOURS_RANGE=3-22

#period in days   delay in minutes   job-identifier   command
1       5       cron.daily              nice run-parts /etc/cron.daily
7       25      cron.weekly             nice run-parts /etc/cron.weekly
@monthly 45     cron.monthly            nice run-parts /etc/cron.monthly

In an anacrontab file, we can only set the frequencies with a period of n days, followed by the delay time in minutes. This delay time is just to make sure the tasks do not run at the same time.

anacrontab文件中,我们只能将频率设置为n天,然后以分钟为单位设置延迟时间。 此延迟时间只是为了确保任务不会同时运行。

The third column is a unique name, which is used to identify the task in the Anacron log files.

第三列是唯一名称,用于在Anacron日志文件中标识任务。

The fourth column is the actual command to be run.

第四列是要运行的实际命令。

Consider the following entry:

考虑以下条目:

1       5       cron.daily              nice run-parts /etc/cron.daily

The above tasks are run daily, 5 minutes after Anacron is run. It uses run-parts to execute all the scripts within /etc/cron.daily.

上述任务每天运行一次,运行Anacron后5分钟。 它使用run-parts来执行/etc/cron.daily所有脚本。

The second entry in the list above runs every 7 days (weekly), with a 25 minutes delay.

上面列表中的第二个条目每7天(每周)运行一次,延迟25分钟。

Cron和Anacron之间的碰撞 (Collision Between Cron and Anacron)

As you have probably noticed, Cron is also set to execute the scripts inside /etc/cron.* directories. This sort of possible collision with Anacron is handled differently in different flavors of Linux. In Ubuntu, Cron checks if Anacron is present in the system, and if it so, it won’t execute the scripts within /etc/cron.* directories.

您可能已经注意到,Cron还被设置为执行/etc/cron.*目录中的脚本。 在不同版本的Linux中,与Anacron可能发生的这种冲突的处理方式有所不同。 在Ubuntu中,Cron会检查系统中是否存在Anacron,如果存在,它将不会执行/etc/cron.*目录中的脚本。

In other flavors of Linux, Cron updates the Anacron times-stamps when it runs the tasks, so Anacron won’t execute them if they have been already run by Cron.

在其他Linux版本中,Cron在运行任务时会更新Anacron时间戳,因此如果Cron已经运行了Anacron,则Anacron不会执行它们。

快速故障排除 (Quick Troubleshooting)

命令的绝对路径 (Absolute Path to the commands)

It’s a good habit to use the absolute paths to all the executables we use in a crontab file.

使用绝对路径指向crontab文件中使用的所有可执行文件是一个好习惯。

* * * * * /usr/local/bin/php /absolute/path/to/the/command

确保Cron守护程序正在运行 (Make Sure Cron Daemon Is Running)

If our tasks are not running at all, first we need to make sure the Cron daemon is running:

如果我们的任务根本没有运行,那么首先我们需要确保Cron守护程序正在运行:

ps aux | grep crond

The output should similar to this:

输出应类似于以下内容:

root      7481  0.0  0.0 116860  1180 ?        Ss    2015   0:49 crond

检查/etc/cron.allow/etc/cron.deny文件 (Check /etc/cron.allow and /etc/cron.deny Files)

If the cron jobs are not running, then we need to check if /etc/cron.allow exists. If it does, we need to make sure our username is listed in this file. If /etc/cron.deny exists, we need to make sure our username is not listed in this file.

如果cron作业没有运行,那么我们需要检查/etc/cron.allow存在。 如果是这样,我们需要确保此文件中列出了我们的用户名。 如果存在/etc/cron.deny ,则需要确保我们的用户名未在此文件中列出。

If we edit a user’s crontab file whereas the user does not exist in the /etc/cron.allow file, including the user in the /etc/cron.allow won’t run the cron until we re-edit the crontab file.

如果我们而用户不会在存在编辑用户的crontab文件/etc/cron.allow文件,包括用户在/etc/cron.allow直到我们重新编辑crontab文件将不会运行cron的。

执行权限 (Execute Permission)

We need to make sure that the owner of the crontab has the execute permissions for all the commands and scripts in the crontab file. Otherwise, the cron will not work. Execute permissions can be added to any folder or file with chmod +x /some/file.php

我们需要确保crontab的所有者具有crontab文件中所有命令和脚本的执行权限。 否则,cron将无法工作。 可以使用chmod +x /some/file.php将执行权限添加到任何文件夹或文件中

换行符 (New Line Character)

Every entry in the crontab should end with a new line. This means there must be a blank line after the last crontab entry, or the last cron job will never run.

crontab中的每个条目都应以新行结尾。 这意味着最后一个crontab条目后面必须有一个空行,否则最后一个cron作业将永远不会运行。

结语 (Wrapping Up)

Cron is a daemon, running a list of events scheduled to take place in the future. These jobs are listed in special configuration files called crontab files. Users can have their own crontab file, if they are allowed to use Cron, based on /etc/cron.allow or /etc/cron.deny files. In addition to user-level cron jobs, Cron also loads the system-wide cron jobs which are slightly different in syntax.

Cron是一个守护程序,运行计划在将来发生的事件的列表。 这些作业在称为crontab文件的特殊配置文件中列出。 如果允许用户使用基于/etc/cron.allow/etc/cron.deny files Cron,则用户可以拥有自己的crontab /etc/cron.deny files 。 除了用户级cron作业之外,Cron还加载语法上稍有不同的系统级cron作业。

Our tasks are commonly PHP scripts or command-line utilities. In systems which are not running all the time, we can use Anacron to run the events which happen in the period of n days. When working with Cron, we should also be aware of the tasks overlapping each other, to prevent data loss. After a cron job is finished, the output will be sent to the owner of the crontab and or the email(s) specified in the MAILTO environment variable.

我们的任务通常是PHP脚本或命令行实用程序。 在并非一直运行的系统中,我们可以使用Anacron运行n天之内发生的事件。 在使用Cron时,我们还应该注意任务相互重叠,以防止数据丢失。 cron作业完成后,输出将发送给crontab的所有者或MAILTO环境变量中指定的电子邮件。

Did you learn anything new from this post? Have we missed anything? Or did you just like this post and want to tell us how awesomely comprehensive it was? Let us know in the comments below!

您从这篇文章中学到了什么吗? 我们错过了什么吗? 还是您只是喜欢这篇文章,并想告诉我们它的综合程度如何? 在下面的评论中让我们知道!

翻译自: https://www.sitepoint.com/a-comprehensive-crash-course-into-cronjobs/

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值