Как запустить PHP-код асинхронный

Как я могу запустить PHP-код асинхронно, не ожидая? У меня длинный пробег (почти бесконечный), который должен запускаться во время запуска сервера и должен обрабатываться асинхронно, не ожидая.

Возможные варианты, которые я предполагаю:

  • Запуск кода на веб-странице и его открытие для выполнения этой задачи
  • Вызов script из некоторой утилиты командной строки (я не уверен, как), которая будет обрабатываться в фоновом режиме.

Я запускаю скрипты PHP на своем локальном сервере, которые будут отправлять электронные письма, когда происходят определенные события, например. напоминания дня рождения.

Пожалуйста, предложите, как я могу достичь этого, не открывая страницу в браузере.

Ответ 1

Если вы хотите запустить его из браузера (возможно, вы не знакомы с командной строкой), вы все равно можете это сделать. Я исследовал множество решений для этого несколько месяцев назад, и самым надежным и простым в реализации было следующее из Как разместить асинхронный HTTP-запрос в 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);
}

Скажем, файл, приведенный выше, находится в корневом каталоге вашего веб-сайта (/var/www) и называется runjobs.php. Посещая http://localhost/runjobs.php, ваш файл myjob.php начнет работать. Вероятно, вы захотите добавить некоторый вывод в браузер, чтобы вы знали, что он был отправлен успешно, и не помешает добавить некоторую безопасность, если ваш веб-сервер открыт для остального мира. Одна хорошая вещь об этом решении, если вы добавляете некоторую безопасность, заключается в том, что вы можете запускать работу везде, где вы можете найти браузер.

Ответ 2

Определенно звучит как задание для задачи cron. Вы можете настроить php script для выполнения своей задачи один раз и запустить cron так часто, как вам нравится. Вот хорошая запись о том, как запустить php script как задачу cron; это очень легко сделать.

Ответ 3

На самом деле PHP не предназначен. Вы должны использовать библиотеку потоков PECL, чтобы открутить потоки, которые запускаются асинхронно, и я не рекомендую это. Новая жара в асинхронном отделе node.js - я рекомендую вам изучить это и посмотреть, можете ли вы его использовать. Он предназначен для легкого веса, асинхронных сетевых операций и может использоваться для запуска скриптов PHP.

Ответ 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);
}
?>

Украшательства: Чтобы сделать ваш script напрямую исполняемым: chmod + x yourscript.php и добавьте #!/usr/bin/php в начало вашего документа

Чтобы начать с apache, вы должны добавить эту команду в ваш apache startup script (обычно apachectl) и не забудьте добавить код, чтобы убить его, когда apache останавливается.

Проверка, если вы уже работаете, включает файл с вашим PID в /var/locks/ и что-то вроде системы ('/bin/ps'. $thePID); Это также упрощает запись команды kill.

Ответ 5

спасибо Todd Chaffee, но он не работает для меня, поэтому я отредактировал ваш код. Надеюсь, вы не будете возражать, и может быть, это также поможет другим с этой техникой.

cornjobpage.php//mainpage

     <?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
    ?>