首页 文章

创建没有Cron作业的计划任务

提问于
浏览
2

需要创建计划任务但不能使用Cron作业(主机提供商发出警告“在45分钟内多次运行cron作业是违反规则的,可能会导致关闭帐户 . ”

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

还有别的办法吗?

5 回答

  • 3

    做重复性工作有多种方法 . 我能立刻想到的一些方法是:

    使用这样的外部网站按设定的时间间隔启动您的网址

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

    • Javascript / Ajax刷新 . 与上面的例子类似 .

    • 设置cron作业 . 大多数共享主机确实提供了一种设置cron作业的方法 . 看看你托管的cPanel .

  • 6

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

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

    while(true) {
        sleep(60);
        //script here
    
    
        //end your script
    }
    

    或者你可以用ajax或meta refresh做一个“可怜的勒芒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
    

    所有这一切,你可能会被主机 grab 并终止 .

    所以你最好的解决方案

    go and sign up for a 5-10 dollar a month vps, and say good bye to shared hosting and hello to running your own little server.

    如果你这样做,你甚至可以停止使用蹩脚的PHP并使用facebook的hhvm代替并享受其超棒的性能 .

  • 0

    我知道这个问题有点陈旧,但我在一周前偶然发现了这个问题,我们发现最好和最安全的选择是使用Web服务 .

    Our context:

    我们的系统包括共享主机和私有 Cloud .

    我们需要在一个月内激活一次脚本(有计划创建更多的计划并允许用户创建一些预定的操作)

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

    What we've done is:

    1 - 在任何主要屏幕上访问时调用ajax调用 .

    2 - Web服务在我们的数据库上读取调度表,并调用任何需要调用的内容

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

    这也是分配负载 balancer 的一种方式,并且计划不会影响具有用户交互的系统 .

  • 1

    这里有免费服务

    http://cron-job.org

    这可以让你设置一个不错的小选择 .

  • 0

    Option 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 .

    Option 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个请求) .

相关问题