Как запустить PHP-код асинхронно
Как я могу запустить код PHP асинхронно, не дожидаясь? У меня есть долгосрочный запуск (почти бесконечный), который должен работать при запуске сервера и должен обрабатываться асинхронно, без ожидания.
Я предполагаю, что возможны следующие варианты:
- Запустите код на веб-странице и оставьте его открытым для выполнения этой задачи.
- Вызов сценария из какой-либо утилиты командной строки (я не уверен, как), которая будет обрабатываться в фоновом режиме.
Я запускаю сценарии PHP на моем локальном сервере, которые будут отправлять электронные письма при возникновении определенных событий, например, напоминаний о днях рождения.
Подскажите, пожалуйста, как мне этого добиться, не открывая страницу в браузере.
5 ответов
Если вы хотите запустить его из браузера (возможно, вы не знакомы с командной строкой), вы все равно можете это сделать. Несколько месяцев назад я исследовал множество решений для этого, и наиболее надежным и простым для реализации было следующее из публикации Как разместить асинхронный 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
файл начнет работать. Возможно, вы захотите добавить некоторые выходные данные в браузер, чтобы сообщить, что они были успешно отправлены, и не мешало бы добавить некоторую защиту, если ваш веб-сервер открыт для остального мира. Хорошая особенность этого решения, если вы добавите некоторую безопасность, это то, что вы можете начать работу везде, где сможете найти браузер.
Определенно звучит как работа для задачи cron. Вы можете настроить php-скрипт для выполнения своей задачи один раз и запускать cron так часто, как вам нравится. Вот хорошая статья о том, как запустить скрипт php в качестве задачи cron; это очень легко сделать.
Это не совсем то, для чего предназначен PHP. Вы должны использовать библиотеку потоков PECL для выделения потоков, которые работают асинхронно, и я не рекомендую это делать. Новая проблема в асинхронном отделе - это node.js - я рекомендую вам изучить это и посмотреть, сможете ли вы его использовать. Он предназначен для облегченных асинхронных сетевых операций и может использоваться для запуска сценариев PHP.
Как я могу запустить код 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 остановится.
Проверка, если вы уже работаете, включает в себя файл с вашим PID в /var/locks/ и что-то вроде system('/bin/ps '.$ ThePID); Это также облегчает написание команды kill.
Спасибо Тодд Чаффи, но он не работает для меня, поэтому я отредактировал твой код, надеюсь, ты не будешь возражать, и, возможно, он также поможет другим с этой техникой
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
?>