这是有关使用cron和crontab的规范性问题。


您已被定向到这里,因为社区相当确定您的问题的答案可以是在下面找到。如果下面没有回答您的问题,那么答案将帮助您收集有助于社区帮助您的信息。该信息应编辑为您的原始问题。

回答“为什么我的crontab不能正常工作,如何解决它?”可以在下面看到。这解决了突出显示crontab的cron系统。

评论

这是crontab无法在AskUbuntu上运行的原因的极大欺骗。

@DanDascalescu好像Eric需要获得更多代表

我刚加入Server Fault SE(所以只有101个代表),但很乐意将此问题设为-1!这个问题只是为了获得代表吗? @IamtheMostStupidPerson完全同意您的看法...

在这13岁的帕达瓦人中,西方意识形态既是教科书又是致盲的,就像超新星一样。要回答您的两个问题:是的,我是为销售代表做的,是的,埃里克(Eric)需要获得更多声誉。我需要多少代表?更多。 youtu.be/IaDt9T7BF38?t=262

#1 楼

如何解决所有与crontab相关的问题/问题(Linux)


这是一个社区Wiki,如果您发现此答案有任何错误或有其他信息,请进行编辑。


首先,基本术语:


cron(8)是执行预定命令的守护程序。

crontab( 1)是用于修改用户crontab(5)文件的程序。

crontab(5)是每个用户文件,其中包含cron(8)的指令。

下一个,有关cron的知识:
系统上的每个用户都可以拥有自己的crontab文件。根目录和用户crontab文件的位置取决于系统,但它们通常位于/var/spool/cron之下。
有一个系统范围的/etc/crontab文件,/etc/cron.d目录可能包含crontab片段,也可由cron读取和操作。某些Linux发行版(例如Red Hat)也具有/etc/cron.{hourly,daily,weekly,monthly},它们是目录,并且其中的脚本将以root特权每个小时/每天/每周/每月执行一次。
root始终可以使用crontab命令;普通用户可能会或可能不会被授予访问权限。使用命令crontab -e编辑crontab文件并保存时,crond会检查其基本有效性,但不能保证crontab文件的格式正确。有一个名为cron.deny的文件,它将指定哪些用户不能使用cron。 cron.deny文件的位置取决于系统,可以删除,所有用户都可以使用cron。
如果计算机未开机或crond守护程序未运行,并且运行命令的日期/时间已过,crond将不会追赶并运行过去的查询。
crontab的细节,如何编写命令:
crontab命令用单行表示。您不能使用\将命令扩展到多行。井号(#)表示注释,这意味着cron会忽略该行上的任何内容。前导空格和空白行将被忽略。
在命令中使用百分号(%)时要非常小心。除非对它们进行了转义,否则它们将转换为换行符,并将第一个未转义的\%传递给stdin上的命令后的所有内容。
crontab文件有两种格式:


用户crontabs
 # 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)
 # |  |  |  |  |
 # *  *  *  *  *   command to be executed



系统范围的%/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)
 # |  |  |  |  |
 # *  *  *  *  * user-name  command to be executed



请注意,后者需要用户-名称。该命令将以指定的用户身份运行。
该行的前5个字段表示应运行该命令的时间。
您可以在其中使用数字或适当的日期/月份名称时间规范。

字段由空格或制表符分隔。
逗号(/etc/cron.d)用于指定列表,例如1,4,6,8表示在1处运行4,6,8。
范围用短划线(,)指定,并且可以与列表组合,例如1-3,9-12表示介于1和3之间,然后介于9和12之间。
-字符可用于引入步骤,例如2/5,表示从2开始,然后每5(2,7,12,17,22 ...)。它们不会结束。
字段中的星号(/)表示该字段的整个范围(例如,分钟字段的*)。 0-59表示从相关字段的最小值开始,然后每2例如0代表分钟(0,2 ... 58),1代表几个月(1,3 ... 11)等。

调试cron命令
检查邮件!
默认情况下,cron会将命令的任何输出邮寄给运行命令的用户。如果没有输出,将没有邮件。如果您希望cron将邮件发送到其他帐户,则可以在crontab文件中设置MAILTO环境变量,例如
MAILTO=user@somehost.tld
1 2 * * * /path/to/your/command

自己捕获输出
您可以将stdout和stderr重定向到文件。捕获输出的确切语法可能会有所不同,具体取决于所使用的Shell cron。以下是两个将所有输出保存到*/2处的文件的示例: /tmp/mycommand.log
如果需要,您可以使用例如
1 2 * * * /path/to/your/command &>/tmp/mycommand.log
1 2 * * * /path/to/your/command >/tmp/mycommand.log 2>&1

过滤cron语句。现在,我们已经了解了cron的基础知识,文件的位置以及如何使用它们,让我们来看一些常见问题。
检查cron是否正在运行
如果cron没有在运行,那么您的命令将不会被安排...
grep CRON /var/log/syslog 

应该给您类似的信息
ps -ef | grep cron | grep -v grep
root    1224   1  0 Nov16 ?    00:00:03 cron

如果不重新启动
root    2018   1  0 Nov14 ?    00:00:06 crond
/sbin/service cron start

可能还有其他方法;使用发行版提供的功能。
cron在受限环境中运行命令。
可用的环境变量可能非常有限。通常,您只会定义几个变量,例如/var/log/cron/var/log/syslog$LOGNAME
特别要注意的是$HOME仅限于$PATH。绝大多数“我的cron脚本不起作用”问题是由这种限制性路径引起的。如果您的命令位于其他位置,则可以通过以下两种方法解决此问题:


提供命令的完整路径。
/sbin/service crond start



在crontab文件中提供合适的PATH
 1 2 * * * /path/to/your/command



如果您的命令需要其他环境变量,也可以在crontab文件中定义它们。 > cron使用cwd == $ HOME
运行命令无论您执行的程序在文件系统上的哪个位置,cron运行时该程序的当前工作目录都将是用户的主目录。如果您访问程序中的文件,则在使用相对路径时必须考虑到这一点,或者(最好)在任何地方都使用完全限定的路径,这样可以避免所有人的困惑。
最后一个我的crontab中的命令无法运行
Cron通常要求命令以新行终止。编辑您的crontab;转到包含最后一条命令的行的末尾并插入新行(按Enter键)。
检查crontab格式
您不能将用户crontab格式的crontab用于/ etc / crontab或/etc/cron.d中的片段,反之亦然。用户格式化的crontab在行的第6位不包含用户名,而系统格式化的crontab包含用户名并以该用户身份运行命令。
我将文件放在/ etc / cron中。{每小时每天,每周,每月},并且它没有运行

检查文件名没有扩展名,请参见run-parts

确保文件具有执行权限。
告诉系统执行脚本时要使用的内容(例如,将PATH放在顶部)

与日期相关的错误
如果您的日期最近由用户或系统更新更改,时区或其他时区,那么crontab将开始出现异常行为,并显示出异常的bug,有时可以正常工作,有时不能正常工作。当时间从下面改变时,这是crontab尝试尝试“做您想做的事”的尝试。更改小时后,“分钟”字段将失效。在这种情况下,仅星号将被接受。重新启动cron并再次尝试,而无需连接到互联网(因此日期没有机会重置为时间服务器之一)。
再次使用百分号
以强调有关百分号的建议,下面是cron如何处理它们的示例:
 PATH=/bin:/usr/bin:/path/to/something/else
 1 2 * * * command 

将创建包含3行的〜/ cron.out文件。
# cron entry
* * * * * cat >$HOME/cron.out%foo%bar%baz

使用/bin:/usr/bin命令时,这尤其具有侵入性。确保逃脱百分号
foo
bar
baz

当以非root用户身份运行时,请注意Sudo

* * * * * /path/to/command --day "$(date "+\%Y\%m\%d")"

将打开用户的crontab,而
/>
crontab -e

将打开root用户的crontab。不建议在cron作业中运行sudo命令,因此,如果您尝试在用户的cron中运行sudo命令,请尝试将该命令移至root的cron并从命令中删除sudo。

评论


可能还想在“受限环境”部分中提到,如果您的cron任务由于找不到共享库而失败,则LD_LIBRARY_PATH可能还需要设置任何其他目录。

– DavidJ
2015年6月23日13:10在

请注意,您甚至可以编写如下内容:35 1,5-23 / 2 * * * do_something而不是35,1,5,7,9,.. * * *另外,此crontab.guru会将您输入的内容转换为人类的语言。

–丹尼斯·诺尔特
16年4月22日在13:43

输出捕获对我不起作用,可能是由于sh shell所致。我认为这更可移植:... / path / to / your / command> /tmp/mycommand.log 2>&1

–chus
16年8月2日在14:24



这对我有用:sudo apt-get install postfix

–jmunsch
17年8月2日,下午3:07

cron的工作还取决于文件的重量吗?因为我使用cron在python中运行了简单的hello世界,所以它起作用了。但是我的第二个代码有点沉重,通常可以运行,但是使用cron时,它不会向文件中提供任何输出。

–德文德拉·巴特(Devendra Bhat)
18-4-10在6:19



#2 楼

Debian Linux及其衍生版本(Ubuntu,Mint等)具有某些特性,可能会阻止您的cron作业执行;特别是/etc/cron.d/etc/cron.{hourly,daily,weekly,monthly}中的文件必须:


由root拥有
只能由root写入
,不能由组或其他用户写入
/>的名字不带点“。”。或除“-”和“ _”以外的任何其他特殊字符。

最后一个会伤害经常毫无戒心的用户;特别是这些文件夹之一中名为whatever.shmycron.pytestfile.pl等的任何脚本将永远不会执行。

根据我的经验,这是迄今为止对Debian及其衍生工具不执行cronjob的最常见原因。
如果需要,请参阅man cron了解更多详细信息。

#3 楼

如果您的cronjobs停止工作,请检查您的密码是否尚未过期。因为一旦激活,所有cron作业都将停止。
/var/log/messages中将出现类似于以下消息的消息,该消息显示验证用户身份的问题: >

(username) FAILED to authorize user with PAM (Authentication token is no longer valid; new one required)


评论


刚得到它(对我来说错误消息文件/ var / log / syslog)。在我的案例中,一个DigitalOcean框在创建时将根密码(可选)重置为另一个,显然直到您进入那里并对其进行更改之前,所有cron作业都不会运行。笨蛋修复类似于sudo -u root passwd

–rogerdpack
16-4-1在16:13



#4 楼

不常见和不规则的日程表
万事俱备,Cron被视为非常基本的日程表,并且语法不容易使管理员制定更多不常见的日程表。
考虑以下工作,通常将其解释为“运行command每5分钟一次”:
*/5 * * * * /path/to/your/command

与之相对:
*/7 * * * * /path/to/your/command

并不总是每7分钟运行一次。
请记住,/字符可用于引入一个步骤,但该步骤不会超出系列的结尾,例如command,与分钟数*/7相匹配,即每7分钟匹配一次,即0,7,14,21,28,35,42,49,56,但在一个小时和下一个小时之间,批次之间只有4分钟,在0-5900:56等处(并且批次不会在01:0001:0701:03等上运行)。

该怎么做?
创建多个批次
而不是单个cron作业,创建多个批处理,这些批处理将结果按所需的时间表进行合并。
例如每40分钟(00:00、00:40、01:20、02:00等)运行一个批处理,则创建两个批处理,一个在偶数小时运行两次,第二个仅在奇数小时运行:
# The following lines create a batch that runs every 40 minutes i.e.

# runs on   0:00, 0:40,        02:00, 02:40         04:00 etc to 22:40
0,40 */2 * * * /path/to/your/command

# runs on               01:20,               03:20,       etc to 23:20
20 1/2 * * * /path/to/your/command

# Combined: 0:00, 0:40, 01:20, 02:00, 02:40, 03:20, 04:00 etc.

运行批处理的频率较低
,而不是每7分钟运行一次批处理,这很困难计划分解为多个批次,只需每10分钟运行一次即可。
更频繁地启动批次(但要防止多个批次同时运行)
y奇怪的时间表会不断变化,因为批处理运行时间会增加/波动,然后为批处理安排一些额外的安全裕度,以防止同一批批处理的后续运行重叠并发运行。
相反,请换个思路,创建一个cronjob如果之前的运行尚未完成,则将正常运行,但否则将运行。请参阅以下问答:
* * * * * /usr/bin/flock -n /tmp/fcj.lockfile /usr/local/bin/frequent_cron_job 

一旦先前的/ usr / local / bin / frequent_cron_job运行完成,几乎可以立即开始新运行。语法是有限的,您可以决定在批处理作业本身中(或在现有批处理作业周围的包装脚本中)放置更复杂的条件和逻辑。这样一来,您就可以利用自己喜欢的脚本语言的高级功能来注释您的代码,并防止crontab条目本身难以理解的构造。 br />
#!/bin/bash
# seven-minute-job
# This batch will only run when 420 seconds (7 min) have passed
# since the file /tmp/lastrun was either created or updated

if [ ! -f /tmp/lastrun ] ; then
    touch /tmp/lastrun
fi

if [ $(( $(date +%s) - $(date -r /tmp/lastrun +%s) )) -lt 420 ] ; then
     # The minimum interval of 7 minutes between successive batches hasn't passed yet.
    exit 0
fi

####  Start running your actual batch job below
  
/path/to/your/command

#### actual batch job is done, now update the time stamp
date > /tmp/lastrun
#EOF

然后您可以安全地(尝试)每分钟运行一次: (或第二个星期三)等。只需安排该批处理在每个星期一运行,然后在日期不在1号或7号之间且星期几不是星期一的情况下退出即可。
* * * * * /path/to/your/seven-minute-job

然后您可以安全地(尝试)在每个星期一运行:
#!/bin/bash
# first-monday-of-the-month-housekeeping-job

# exit if today is not a Monday (and prevent locale issues by using the day number) 
if [ $(date +%u) != 1 ] ; then
  exit 0
fi

# exit if today is not the first Monday
if [ $(date +%d) -gt 7 ] ; then
  exit 0
fi

####  Start running your actual batch job below
  
/path/to/your/command

#EOF

不要使用cron
如果您的需求很复杂,则可以考虑使用设计用于运行复杂计划的更高级的产品(分发给多台服务器),并支持触发器,作业依赖性,错误处理,重试和重试监视等。T他的行业术语是“企业”工作计划和/或“工作量自动化”。

#5 楼

特定于PHP的

如果您有一些cron作业,例如: ,但不能-选中此选项。

PHP默认不会向STDOUT发送错误。 @see https://bugs.php.net/bug.php?id=22839

要解决此问题,请在cli的php.ini中或您的行中(或在您的bash包装器中添加) PHP)这些:


--define display_startup_errors = 1
--define display_errors ='stderr'

第一个设置将使您致命例如“ Memory oops”和“ 2nd”-将它们全部重定向到STDERR。只有在您可以睡个好觉之后,所有内容才会发送到您的根的邮件中,而不仅仅是被记录下来。

评论


该错误报告于2007年关闭,补丁程序的状态已添加到PHP 5.2+分支中。您确定这是必需的吗?我只是在PHP 5.4上尝试过,它似乎工作正常。 (尽管PHP 4仍然需要它)。

– Xeoncross
2014年5月5日20:34



@Xeoncross看到答案的日期:)

–gaRex
2014年3月6日下午3:09

是的,这就是让我感到困惑的原因,因为您在2013年回答问题,而票证早在07年就回来了。

– Xeoncross
2014年6月6日4:55

#6 楼

在此处添加我的答案以确保完整性,并添加另一个可能有用的资源:

cron用户与您使用的$PATH不同:

用户使用crontab条目经常遇到问题是他们忘记了cron在与登录用户不同的environment中运行。例如,用户在其$HOME目录中创建一个程序或脚本,并输入以下命令来运行它:

$ ./certbot ... 


该命令可以从命令行完美地运行。然后,用户将该命令添加到其crontab中,但发现此命令不起作用:

*/10 * * * * ./certbot ....


在这种情况下失败的原因是./是用于cron用户(而非已登录用户)。也就是说,environment是不同的! PATH是environment的一部分,通常对于cron用户而言是不同的。使这个问题复杂化的是,所有* nix发行版的environmentcron都不相同,并且cron有多个版本。

解决此特定问题的简单方法是为cron用户提供完整的路径crontab条目中的规范:

 0 22 * * * /path/to/certbot .....
 


cron用户的environment是什么? >
在某些情况下,我们可能需要了解系统上environment的完整cron规范(否则我们可能会感到好奇)。 environment用户的cron是什么,与我们的用户有什么不同?此外,我们可能需要知道另一个environment用户的cron-例如root ...使用rootenvironment用户的cron是什么?了解这一点的一种方法是让cron告诉我们:


在主目录(~/)中创建外壳脚本,如下所示(或使用您选择的编辑器):

$ nano ~/envtst.sh



在针对您的系统/用户进行调整之后,在编辑器中输入以下内容:

 #!/bin/sh 
/bin/echo "env report follows for user "$USER >> /home/you/envtst.sh.out 
/usr/bin/env >> /home/you/envtst.sh.out 
/bin/echo "env report for user "$USER" concluded" >> /home/you/envtst.sh.out
/bin/echo " " >> /home/you/envtst.sh.out
 



保存文件,退出编辑器并将文件权限设置为可执行文件。

 $ chmod a+rx ~/envtst.sh
 



运行您刚创建的脚本,然后在中查看输出/home/you/envtst.sh.out。此输出将以您登录的$USER的身份显示当前环境:

 $ ./envtst.sh $$ cat /home/you/envtst.sh.out
 



打开您的crontab进行编辑:

 $ crontab -e -u root
 



输入crontab底部的以下行:

 * * * * *  /home/you/envtst.sh >> /home/you/envtst.sh.err 2>&1
 


答案:输出文件/home/you/envtst.sh.out将包含“ root cron用户”的environment列表。知道这一点后,请相应地调整您的crontab条目。

我无法在crontab条目中指定所需的时间表:

当然,在crontab中定义了man crontab的时间表条目,您应该阅读此内容。但是,阅读man crontab和了解时间表是两件事。日程安排规范中的反复试验会变得非常乏味。幸运的是,这里有可以提供帮助的资源:crontab大师。输入您的日程表规范,它将以纯英语解释日程表。

最后,由于这里有一个其他答案,因此有可能被冗余,不要因为您要安排一项工作而陷入以为只有一个crontab条目的想法。您可以随意使用任意数量的crontab条目来获取所需的时间表。

评论


对我来说,不同的环境总是会导致cron问题。这个答案应该更多。

–speedplane
11月21日17:52