如何每隔X分钟运行一次cronjob?

124

我正在cronjob中运行一个PHP脚本,希望每5分钟发送一封电子邮件。

我的当前(crontab) cronjob:

10 * * * * /usr/bin/php /mydomain.in/cromail.php > /dev/null 2>&1

cronmail.php 的内容如下:

<?php
$from = 'D'; // sender
$subject = 'S';
$message = 'M';
$message = wordwrap($message, 70);
mail("myemail@gmail.com", $subject, $message, "From: $from\n");
?>

但是按照这个配置,我已经30分钟没有收到邮件了。


2
你的绝对路径可能不正确。 - Rene Pot
请为我建议正确的路径,我的php文件cromail.php位于根目录中 - mydomain.in/cromail.php - Savan Paun
cromail.php 还是 cronmail.php - Biffen
仅用于测试的cromail.php - Savan Paun
是的 @fedorqui,php文件路径没问题*/5 * * * * usr/bin/php/ mydomain.in/cronmail.php > /dev/null 2>&1 - Savan Paun
显示剩余4条评论
7个回答

206

crontab文件中,各字段的含义如下:

  • 每小时的分钟数。
  • 每天的小时数。
  • 每月的日期。
  • 每年的月份。
  • 每周的星期几。

因此:

10 * * * * blah

表示每小时的第10分钟执行blah

如果您想要每五分钟执行一次,请使用以下任一选项:

*/5 * * * * blah

每分钟都有,但仅限于每五分钟中的第一次。

0,5,10,15,20,25,30,35,40,45,50,55 * * * * blah

对于那些不理解 */x 表示法的旧版 cron 可执行文件。

如果在那之后它似乎仍然没有工作,请将命令更改为例如:

date >>/tmp/debug_cron_pax.txt

监控该文件以确保每五分钟写入一次内容。如果有,则表示您的PHP脚本存在问题。如果没有,则表示您的cron守护程序存在问题。


我更新了 */5 * * * * mydomain.in/cronmail.php > /dev/null 2>&1,但是没有收到邮件。 - Savan Paun
我也使用了这里提到的命令,但它没有起作用,因为我在它后面加了一个返回语句。请确保不要以返回语句结束语句,并注意,当创建新的cron时,它会显示“crontab:安装新的crontab”消息。 - damndemon

35

你的CRON应该像这样:

*/5 * * * *

CronWTF在你需要测试你的CRON设置时非常有用。

建议将输出重定向到日志文件中,这样你就可以看到脚本是否抛出任何错误,因为在终端中是看不到的。

还可以尝试在PHP文件顶部使用shebang,这样系统就知道在哪里找PHP。例如:

#!/usr/bin/php

这样你就可以像这样调用整个过程:

*/5 * * * * php /path/to/script.php > /path/to/logfile.log


我更新了 */5 * * * * mydomain.in/cronmail.php > /dev/null 2>&1,但是没有收到邮件。 - Savan Paun
2
你尝试手动运行脚本而不是通过cron吗?问题实际上可能出在脚本本身。 - Gary Jones
未来的旅行者们注意了 - CronWTF 似乎永久关闭了。我尝试编辑原文但无法成功。 - Optimesh

7
如果您想每隔n分钟运行cron作业,取决于n的值,有几种可能的选项。 n可以被60整除(1、2、3、4、5、6、10、12、15、20、30) 在这种情况下,可以简单地使用/符号解决问题。
# 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
m-59/n  *  *  *  *   command

上述代码中,n代表值nm表示小于n*的值。这将在每个分钟执行命令m,m+n,m+2n,...

n不能整除60

如果n不能整除60,就无法使用cron清洁地完成此操作,但是可以实现。要做到这一点,需要在cron中放置一个测试来检查时间。最好在查看UNIX时间戳时执行此操作,即自1970-01-01 00:00:00 UTC以来的总秒数。假设我们希望在Marty McFly抵达Riverdale时首次运行该命令,然后每隔n分钟重复一次。

% date -d '2015-10-21 07:28:00' +%s 
1445412480

要让定时任务在“2015-10-21 07:28:00”之后的每个第42分钟运行,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)
# |  |  |  |  |
# *  *  *  *  *   command to be executed
  *  *  *  *  *   minutetestcmd "2015-10-21 07:28:00" 42 && command

如果定义了minutetestcmd

#!/usr/bin/env bash
starttime=$(date -d "$1" "+%s")
# return UTC time
now=$(date "+%s")
# get the amount of minutes (using integer division to avoid lag)
minutes=$(( (now - starttime) / 60 ))
# set the modulo
modulo=$2
# do the test
(( now >= starttime )) && (( minutes % modulo == 0 ))

备注:UNIX时间不受闰秒的影响。

备注:cron没有亚秒精度。


“m/n”符号在我的系统(Debian 9,Ubuntu 16.04)上似乎无法工作。只有“*/n”可以使用。例如,“5/5”或“4/10”会在syslog中(在cron v. 3.0pl1-128ubuntu2的Ubuntu中)显示“Error: bad minute; while reading /etc/crontab”。这个“m/n”符号已经被废弃了吗?还是只有某些系统才能使用? - mivk
@mivk 感谢您指出这个问题。这是我的错误。它应该是 m-59/n。只有范围可以有步长。(请参阅 man 5 crontab)。我已经更新了答案。 - kvantour

6
你把cron设置为在每个小时的第10分钟运行。
若要将其设置为每5分钟一次,请更改为*/5 * * * * /usr/bin/php /mydomain.in/cronmail.php > /dev/null 2>&1

@user3705511 你忘记通过PHP来运行它了 - 缺少 usr/bin/php 部分。 - Justinas
已添加 */5 * * * * usr/bin/php/mydomain.in/cronmail.php > /dev/null 2>&1但仍未收到电子邮件。 - Savan Paun
@user3705511 */5 * * * * /usr/bin/php /mydomain.in/cromail.php > /dev/null 2>&1 的意思是每5分钟执行一次 /usr/bin/php /mydomain.in/cromail.php 命令,并将输出重定向到 /dev/null,错误信息也会被重定向到同一个地方。 - Justinas
我使用 HostGator,有什么方法可以检查吗? - Savan Paun
我认为这是用户名或简单错误。 /usr/bin/php - Savan Paun
显示剩余3条评论

4
# .---------------- 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

如果要设置x分钟,请在第一个参数中设置x分钟,然后设置您脚本的路径。

例如,设置为15分钟:

*/15 * * * *  /usr/bin/php /mydomain.in/cromail.php > /dev/null 2>&1

1
这并不是每隔 x (15) 分钟运行一次任务。它是在每个整点后的 x (1) 分钟运行。 - silverdr

3

检查cronjob是否正常工作的2个步骤:

  1. 使用执行cronjob的用户登录服务器
  2. 手动运行php命令:

    /usr/bin/php /mydomain.in/cromail.php

检查是否显示任何错误信息。


0
尝试使用类似这样的crontab记录
*/5 * * * * php /usr/bin/php/mydomain.in/cromail.php

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接