【问题标题】:creating schedule task without Cron job创建没有 Cron 作业的计划任务
【发布时间】:2014-05-26 13:33:21
【问题描述】:

需要创建计划任务,但无法使用 Cron 作业(托管服务提供商警告说“在 45 分钟内多次运行 cron 作业违反了他们的规则,并可能导致关闭帐户。”

php脚本(将数据从txt插入mysql数据库)应该每分钟执行一次,即这个链接应该被称为http://www.myserver.com/ImportCumulusFile.php?type=dayfile&key=letmein&table=Dayfile&file=./data/Jan10log.txt

还有其他方法吗?

【问题讨论】:

  • 您可以每 60 分钟使用一个 cron 作业并让它执行 60 分钟,每分钟触发您的请求,或者您可以看看“可怜的人 cron”的想法,尽管那是在低流量页面上不可靠。

标签: php mysql cron


【解决方案1】:

如果你有 shell 访问权限,你可以通过 shell 执行一个 php 脚本

这样的事情将是一个无限循环,它将休眠 60 秒执行,收集垃圾并重复直到时间结束。

while(true) {
    sleep(60);
    //script here


    //end your script
}

或者您可以使用 ajax 或元刷新来执行“可怜的 mans cron”。我以前做过。基本上,您只需在脚本开始时使用 javascript 或 html 的元刷新进行重定向。从您的浏览器访问此脚本,然后将其保持打开状态。它会每 60 秒刷新一次,就像 cronjob 一样。

cronjob 的另一种替代方法是 bash 脚本,例如:

#!/bin/bash
while :

do
sleep 60
 wget http://127.0.0.1/path/to/cronjob.php -O Temp --delete-after

done

说了这么多,你很可能会被主人抓住并被终止。

所以你最好的解决方案:

去注册一个每月 5-10 美元的 vps,告别共享主机,向运行自己的小服务器问好。

如果你这样做了,你甚至可以停止使用蹩脚的 php 并改用 facebook 的 hhvm 并享受其出色的性能。

【讨论】:

    【解决方案2】:

    有多种方法可以从事重复性工作。我可以立即想到的一些方法是:

    1. 使用:https://www.setcronjob.com/

    使用这样的外部网站以设定的时间间隔触发您的网址

    1. 使用元刷新。更多here。您必须打开页面并让它继续运行。

    2. Javascript/Ajax 刷新。类似于上面的例子。

    3. 设置 cron 作业。大多数共享主机确实提供了一种设置 cron 作业的方法。查看您主机的 cPanel。

    【讨论】:

    • 我知道这已经有一年了,如果您仍然处于活动状态,您能否回答是否必须加载元刷新和 js/ajax 刷新文件才能使它们工作,或者它们在没有您实际调用的情况下工作文件(独立)?
    • @nothingness 您需要加载页面,以便运行 meta/js/ajax。
    • @nothingness 我们曾经在windows服务器中将其设置为浏览器的主页。你明白了 - 它是有限的。
    【解决方案3】:

    有免费服务

    http://cron-job.org

    这让您可以设置一个不错的小替代方案。

    【讨论】:

      【解决方案4】:

      我知道这个问题有点老了,但一周前我偶然发现了这个问题,我们发现最好和最安全的选择是使用网络服务。

      我们的背景:

      我们的系统在共享主机和私有云中都有。

      我们需要每月激活一次脚本(计划创建更多时间表并允许用户创建一些预定操作)

      我们的系统提供对许多客户端的访问,因此,当任何人使用该系统时,它通过 Ajax 调用 Web 服务并且不关心响应(毕竟所有内容都记录在我们的数据库中并且必须在没有用户交互的情况下运行)

      我们所做的是:

      1 - 在任何主屏幕中访问时都会调用 ajax 调用。

      2 - Web 服务读取我们数据库中的日程表并调用任何需要调用的内容

      3 - 为了避免许多堆叠的 Web 服务调用,我们在实际执行任何操作之前每隔 10 分钟检查一次日期时间

      这也是一种分配负载平衡的方式,并且计划不会影响系统与用户交互。

      【讨论】:

        【解决方案5】:

        选项 A

        实现它的一种简单方法是创建一个包含 php 脚本执行时间的文件/数据库条目:

        <?php
        // crons.php
        return [
            'executebackup.php' => 1507979485,
            'sendnewsletter.php' => 1507999485
        ];
        ?>
        

        并且在通过您的访问者提出的每个请求中,您检查当前时间,如果它更高,您包括您的 php 脚本:

        <?php
        // cronpixel.php
        $crons = @include 'cache/crons.php';
        foreach ($crons as $script => $time) {
            if ($time < time()) {
                // create lock to avoid race conditions
                $lock = 'cache/' . md5($script) . '.lock';
                if (file_exists($lock) || !mkdir($lock)) {
                    continue;
                }
                // start your php script
                include($script);
                // now update crons.php
                $crons[ $script ] += 86400; // tomorrow
                file_put_contents('cache/crons.php', '<?php return ' . var_export($crons, true) . '; ?' . '>')
                // finally delete lock
                rmdir($lock);
            }
        }
        header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
        // image data
        $im = imagecreate(1, 1);
        $blk = imagecolorallocate($im, 0, 0, 0);
        imagecolortransparent($im, $blk);
        // image output
        header("Content-type: image/gif");
        imagegif($im);
        // free memory
        imagedestroy($im);
        ?>
        

        注意:它很少会在准确的第二秒被调用,因为您不知道访问者何时会打开您的页面(可能会在 2 秒后)。因此,设置第二天的新时间而不是通过添加 86400 秒是有意义的。而是使用mktime

        选项 B

        This is a little project 我过去意识到,这与@r3wt 的想法相似,但涵盖了竞争条件,并且可以像 cronjob 在调度程序中那样在精确的时间上工作,而无需点击max_execution_time。而且它大部分时间都可以正常工作而无需重新启动它(就像选项 A 中的访问者所做的那样)。

        说明: 该脚本在一分钟的第 15、30、45 和 60 秒写入锁定文件(以避免竞争条件):

        // cron monitoring
        foreach ($allowed_crons as $cron_second) {
            $cron_filename = 'cache/' . $cron_second . '_crnsec_lock';
            // start missing cron requests
            if (!file_exists($cron_filename)) {
                cron_request($cron_second);
            }
            // restart interrupted cron requests
            else if (filemtime($cron_filename) + 90 < time()) {
                rmdir($cron_filename);
                cron_request($cron_second);
            }
        }
        

        每次缺少锁定文件时,脚本都会创建它并使用sleep() 精确到秒:

        if (file_exists($cron_filename) || !mkdir($cron_filename)) {
            return;
        }
        // add one minute if necessary
        $date = new DateTime();
        $cron_date = new DateTime();
        $cron_date->setTime($cron_date->format('H'), $cron_date->format('i'), $sec);
        $diff = $date->diff($cron_date);
        if ($diff->invert && $diff->s > 0) {
            $cron_date->setTime($cron_date->format('H'), $cron_date->format('i') + 1, $sec);
        }
        $diff = $date->diff($cron_date);
        // we use sleep() as time_sleep_until() starts one second to early (https://bugs.php.net/bug.php?id=69044)
        sleep($diff->s);
        

        再次唤醒后,通过fopen()向自己发送请求:

        // note: filter_input returns the unchanged SERVER var (http://php.net/manual/de/function.filter-input.php#99124)
        // note: filter_var is unsecure (http://www.d-mueller.de/blog/why-url-validation-with-filter_var-might-not-be-a-good-idea/)
        $url = 'http' . isSecure() . '://' . filter_input(INPUT_SERVER, 'HTTP_HOST', FILTER_SANITIZE_URL) . htmlspecialchars($request_uri, ENT_QUOTES, 'UTF-8');
        $context = stream_context_create(array(
            'http' => array(
                'timeout' => 1.0
            )
        ));
        // note: return "failed to open stream: HTTP request failed!" because timeout < time_sleep_until
        if ($fp = @fopen($url, 'r', false, $context)) {
            fclose($fp);
        }
        rmdir($cron_filename);
        

        通过它无限调用自己,您可以定义不同的开始时间:

        if (isset($_GET['cron_second'])) {
            if ($cron_second === 0 && !(date('i') % 15)) {
                mycron('every 15 minutes');
            }
            if ($cron_second === 0 && !(date('i') % 60)) {
                mycron('every hour');
            }
        }
        

        注意:它每天产生 5760 个请求(每分钟 4 个)。不多,但 cronjob 使用的资源要少得多。如果您的 max_execution_time 足够高,您可以将其更改为每分钟仅调用一次(1440 个请求/天)。

        【讨论】:

          猜你喜欢
          • 2023-01-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-08-31
          • 1970-01-01
          • 2018-06-04
          • 1970-01-01
          相关资源
          最近更新 更多