【问题标题】:How to start/stop a cronjob using PHP?如何使用 PHP 启动/停止 cronjob?
【发布时间】:2011-09-26 18:50:12
【问题描述】:

如果我在命令行中输入crontab -l,我可以看到以下行:

# * * * * * /usr/bin/php /home/user/every_minute_script.php

要启动这个 cronjob,我需要使用crontab -e 命令编辑文件,删除行首的注释字符,保存编辑的文件,然后退出编辑器。

要停止此 cronjob,步骤相同,但在行首添加注释字符。

我想使用 PHP 脚本 实现完全相同的效果,而不是手动编辑文件。

【问题讨论】:

  • 注意:您不是在启动/停止作业本身(您的修改不会影响已经运行的作业),您只是在设置它是否会在下次启动。
  • 是的。也许有更好的方法来写这个问题。不是启动/停止,而是激活/停用?
  • 这看起来像 stackoverflow.com/questions/4421020/… 的副本
  • @J.布鲁尼:可能。我只是想确保我们在同一个页面上:)

标签: php linux cron crontab


【解决方案1】:

我做了一些研究并found in a forum,以下消息:

使用 EDITOR 调用“crontab -e” 环境变量设置为 php 脚本。该脚本可以修改 文件,当它退出 crontab 将 重新读取文件并更新。

所以,我尝试了一些方法,并且成功了。我将在下面粘贴工作代码:

#!/usr/bin/php
<?php

$on  = "* * * * * /usr/bin/php /home/user/every_minute_script.php\n";
$off = "# * * * * * /usr/bin/php /home/user/every_minute_script.php\n";

$param    = isset( $argv[1] ) ? $argv[1] : '';
$filename = isset( $argv[2] ) ? $argv[2] : '';

if ( $param == 'activate' )
{
    shell_exec( 'export EDITOR="/home/user/cron.php on"; crontab -e' );
}
elseif( $param == 'deactivate' )
{
    shell_exec( 'export EDITOR="/home/user/cron.php off"; crontab -e' );
}
elseif( in_array( $param, array( 'on', 'off' ) ) )
{
    if ( !is_writable( $filename ) )
        exit();

    $crontab = file( $filename );
    $key = array_search( $param == 'on' ? $off : $on, $crontab );

    if ( $key === false )
        exit();

    $crontab[$key] = $param == 'on' ? $on : $off;
    sleep( 1 );
    file_put_contents( $filename, implode( '', $crontab ) );
}

exit();

?>

事实上,我们有一个名为cron.php 的脚本位于/home/user 文件夹中,设置为可执行(chmod a+x cron.php)并从命令行(PHP-CLI)调用。稍后我会调整它以从网络上运行,这是我的意图。

用法:./cron.php activate 启用 cronjob,./cron.php deactivate 禁用它。

脚本正确设置 EDITOR 环境变量(对其自身),然后调用 crontab -e,后者又调用 EDITOR(现在是相同的 cron.php 脚本),将临时 crontab 文件位置作为参数传递。然后,找到并更改正确的 crontab 行,并保存修改后的版本,替换临时文件。当脚本退出时,crontab 会更新。

这正是我想要的,并且符合我的需要。

其他答案很好,可能适合不同的需求和场景,我要感谢所有做出贡献的人。

【讨论】:

  • 当我执行 ./cron.php activate 我得到?php: No such file or directory 错误
  • @Hunt:确保您使用的是有效的路径和文件名...您需要更改 /home/user 以获得现有路径
【解决方案2】:

我建议不要以编程方式使用 crontab(这很微妙且容易激怒),而是在您的 every_minute_script.php 中进行检查:

if (!file_exists('/your/path/run_every_minute_script')) {
  exit;
}

这样,脚本仍然会每分钟启动一次,但如果不满足条件(/your/path/run_every_minute_script 不存在),它将立即终止,无需进一步处理。

(当然,您可以在那里替换不同的条件,例如检查数据库的权限等)


如果您需要邮寄输出,您可以使用包装脚本。 crontab:

* * * * * /your/path/wrapper.sh > /dev/null 2> /dev/null

包装器脚本然后正确运行作业,收集其输出和错误,如果它们不为空,则将它们邮寄出去(请注意,您也可以在包装器脚本中进行检查;我们没有,因为它依赖于数据库)。

【讨论】:

  • 我喜欢这个解决方案。比乱用 crontab 优雅得多。
【解决方案3】:

Here's 一个非常酷的教程,用于使用 PHP 创建这种功能。

【讨论】:

    【解决方案4】:

    将您的停止/启动条件放在every_minute_script.php 的开头

    if($condition == false) {
        exit();
    }
    

    【讨论】:

    • 听起来不错,我考虑了一下。问题是我需要为我邮寄 cronjob 的输出(不能使用 /dev/null)。在我的设置中,即使在 PHP 脚本的开头有一个“退出”,我也会收到一封电子邮件(每分钟!)...
    • @J. Bruni:我们所做的是使用包装器:* * * * * /x/y/z/blah.sh &amp;&gt; /dev/null; blah.sh 是一个脚本,它运行实际作业,获取输出,然后邮寄,除非没有输出。
    • @J. Bruni - 如果脚本有输出,我以为只有一封电子邮件?
    【解决方案5】:

    您能否在every_minute_script.php 的开头放置某种逻辑来检查标志以查看它是否应该执行任何操作?这样它就可以旋转起来,然后在没有工作时快速停止。

    或者这对你的目的来说太低效了?

    【讨论】:

    • 我刚刚评论了亚当的答案(类似于你的)。这个想法很好,也许是很多场景的最终答案。就我而言,如果可能的话,我宁愿根本不运行every_minute_script.php。
    • 你能按照@Piskvor 的建议做一些事情,并且只在脚本实际运行并产生输出时发送电子邮件吗?
    猜你喜欢
    • 2017-06-24
    • 1970-01-01
    • 1970-01-01
    • 2016-07-31
    • 1970-01-01
    • 2012-11-06
    • 1970-01-01
    • 2013-01-09
    • 1970-01-01
    相关资源
    最近更新 更多