【问题标题】:How to run the PHP code asynchronous如何异步运行 PHP 代码
【发布时间】:2011-08-19 20:06:21
【问题描述】:

如何在不等待的情况下异步运行 PHP 代码?我有一个长时间运行(几乎无限),应该在服务器启动时运行,并且应该异步处理而无需等待。

我猜可能的选项是:

  1. 在网页中运行代码并保持打开状态以执行该任务
  2. 从某个命令行实用程序(我不确定如何)调用脚本,该实用程序将在后台处理。

我在我的本地服务器上运行 PHP 脚本,当某些事件发生时会发送电子邮件,例如生日提醒。

请建议我如何在不在浏览器中打开页面的情况下实现此目的。

【问题讨论】:

  • 最好的选择可能是 cron 作业或守护进程,但如果没有更多细节,这很难确定。
  • 听起来网络脚本不是你想要创建的。
  • 几乎infinite 是两个你不能真正并排使用的词。它是无限的,也不是无限的,没有几乎无限这样的东西。
  • “快到了,只有一个!” ad infinitum == 无限。 ;o)
  • 你的服务器运行的是什么操作系统?

标签: php


【解决方案1】:

感谢 Todd Chaffee,但它对我不起作用,所以我编辑了你的代码,希望你不会介意,也许它也会帮助其他人使用这种技术

cornjobpage.php //主页面

     <?php
//if you want to call page for multiples time w.r.t array 
//then uncomment loop start & end)
?>

<?php
//foreach ($inputkeywordsArr as $singleKeyword) {
    $url="http://localhost/projectname/testpage.php";
        $params['Keywordname'] = "testValue";//$singleKeyword 
        post_async($url, $params);

        //}//foreach ($inputkeywordsArr end
        ?>
        <?php

        /*
         * Executes a PHP page asynchronously so the current page does not have to wait for it to     finish running.
         *  
         */
        function post_async($url, array $params)
        {
            foreach ($params as $key => &$val) {
              if (is_array($val)) $val = implode(',', $val);
                $post_params[] = $key.'='.urlencode($val);  
            }
            $post_string = implode('&', $post_params);

            $parts=parse_url($url);

            $fp = fsockopen($parts['host'],
                isset($parts['port'])?$parts['port']:80,
                $errno, $errstr, 30);

            $out = "GET ".$parts['path']."?$post_string"." HTTP/1.1\r\n";//you can use POST instead of GET if you like
            $out.= "Host: ".$parts['host']."\r\n";
            $out.= "Content-Type: application/x-www-form-urlencoded\r\n";
            $out.= "Content-Length: ".strlen($post_string)."\r\n";
            $out.= "Connection: Close\r\n\r\n";
            fwrite($fp, $out);
            fclose($fp);
        }
        ?>

testpage.php

    <?
    echo $_REQUEST["Keywordname"];//Output > testValue
    ?>

【讨论】:

    【解决方案2】:

    如果您想从浏览器运行它(也许您不熟悉命令行),您仍然可以这样做。几个月前我为此研究了许多解决方案,最可靠和最简单的实现是来自How to post an asynchronous HTTP request in PHP

    <?php
    
    
    $params['my_param'] = $a_value;
    post_async('http:://localhost/batch/myjob.php', $params);
    
    /*
     * Executes a PHP page asynchronously so the current page does not have to wait for it to     finish running.
     *  
     */
    function post_async($url, array $params)
    {
        foreach ($params as $key => &$val) {
          if (is_array($val)) $val = implode(',', $val);
            $post_params[] = $key.'='.urlencode($val);  
        }
        $post_string = implode('&', $post_params);
    
        $parts=parse_url($url);
    
        $fp = fsockopen($parts['host'],
            isset($parts['port'])?$parts['port']:80,
            $errno, $errstr, 30);
    
        $out = "POST ".$parts['path']." HTTP/1.1\r\n";
        $out.= "Host: ".$parts['host']."\r\n";
        $out.= "Content-Type: application/x-www-form-urlencoded\r\n";
        $out.= "Content-Length: ".strlen($post_string)."\r\n";
        $out.= "Connection: Close\r\n\r\n";
        if (isset($post_string)) $out.= $post_string;
    
        fwrite($fp, $out);
        fclose($fp);
    }
    

    例如,假设上面的文件位于您的 Web 根目录 (/var/www) 中,名为 runjobs.php。通过访问http://localhost/runjobs.php,您的myjob.php 文件将开始运行。您可能希望向浏览器添加一些输出以告知您它已成功提交,并且如果您的 Web 服务器对世界其他地方开放,添加一些安全性也不会受到伤害。如果您添加了一些安全性,这个解决方案的一个好处是您可以在任何可以找到浏览器的地方开始工作。

    【讨论】:

    • 这没有什么异步的。您只是在写入一个套接字,然后在不等待响应的情况下关闭该套接字。异步将创建一个新线程或坐下来等待来自 curl 请求的响应并确保收到请求的东西。
    • 在某些情况下没有得到响应可能并不理想,但这绝对是异步的:“异步动作是在非阻塞方案中执行的动作,允许主程序流继续处理。”
    • 如果您需要 HTTP_GET,请将 $out = "POST ".$parts['path']." HTTP/1.1\r\n"; 替换为 if (!empty($parts['query'])) { $query = "?".$parts['query']; } $out = "GET ".$parts['path']." HTTP/1.1\r\n";
    【解决方案3】:

    听起来确实像是 cron 任务的工作。您可以设置一个 php 脚本来执行您的任务一次,并让 cron 尽可能频繁地运行。 Here's 一篇关于如何将 php 脚本作为 cron 任务运行的好文章;这很容易做到。

    【讨论】:

    • 这是一个非常常见的问题的非常常见的解决方案。大多数具有重复事件(软件更新检查、生日提醒等)的 PHP 程序都有一个“cron.php”脚本,该脚本从 crontab 运行,或者通过“wget”或“curl”等程序,或者直接通过命令行执行.这样,您就不需要一直保持脚本运行,并且可以在任务完成后立即退出。毕竟会在某个时间间隔再次调用它。
    【解决方案4】:

    如何异步运行 PHP 代码 无需等待。我有很长的路要走 (几乎无限)应该运行 服务器启动并应处理时 无需等待即可异步进行。

    假设一个典型的 LAMP 系统,你可以从命令行启动一个 PHP 守护进程

    root# php yourscript.php &
    

    yourscript.php 包含类似于

    的内容
    <?php
    
    $log = fopen('/var/log/yourscript.log', 'a+');
    // ### check if we are running already omitted
    while(true) {
        // do interesting stuff and log it.
    
        // don't be a CPU hog
        sleep(1);
    }
    ?>
    

    装饰: 使您的脚本直接可执行: chmod +x yourscript.php 并将 #!/usr/bin/php 添加到您的脚本的开头

    要启动 apache,您应该将该命令添加到您的 apache 启动脚本(通常是 apachectl)中,并确保添加代码以在 apache 停止时终止它。

    检查您是否已经在运行涉及到 /var/locks/ 中带有您的 PID 的文件 和类似 system('/bin/ps '.$thePID);它还使 kill 指令更容易编写。

    【讨论】:

      【解决方案5】:

      这并不是 PHP 的真正设计目的。您必须使用 PECL 线程库来分离异步运行的线程,我不推荐它。异步部门的新热点是 node.js - 我建议你研究一下,看看你是否可以利用它。它专为轻量级异步网络操作而设计,可用于触发 PHP 脚本。

      【讨论】:

      • 问题似乎是关于更适合普通 shell 环境的东西,而不是 Web 服务器,因此可能不需要 NodeJS 和异步 Web 请求处理。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-08-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-31
      相关资源
      最近更新 更多