Ответ 1
как насчет установить psexec и использовать -d
(не ждите) вариант
exec('psexec -d php-cgi.exe somescript.php');
Мы запускаем PHP на сервере Windows (на самом деле это источник многих проблем, но миграция в данный момент не является вариантом). Есть несколько моментов, когда действие, инициированное пользователем, должно начинаться с нескольких вещей, которые требуют времени, и о том, что пользователю не нужно знать, удастся ли им преуспеть или нет, например, отправив электронное письмо или убедиться, что некоторые сторонние учетные записи обновляются. Если бы я мог просто развиваться с pcntl_fork()
, это было бы очень просто, но функции PCNTL недоступны в Windows.
Кажется, что ближе всего я могу сделать что-то подобное:
exec( 'php-cgi.exe somescript.php' );
Однако это было бы намного сложнее. Действия, которые мне нужно выполнить, зависят от большого контекста, который уже будет существовать в текущем процессе; для использования вышеприведенного примера мне нужно было бы выяснить основные данные и каким-то образом предоставить их новому script. Если бы я мог раскошелиться, было бы просто позволить родительскому процессу вернуться раньше, оставив ребенка работать над еще несколькими вещами.
Я обнаружил, что несколько человек говорили о своей собственной работе по созданию различных функций PCNTL, скомпилированных в Windows, но ни у кого не было ничего доступного (сломанные ссылки и т.д.).
Несмотря на этот вопрос, имеющий практически то же имя, что и мое, кажется, проблема была больше времени выполнения, чем для вилки. Итак, мой лучший вариант - просто реорганизовать бит, чтобы иметь дело с вызовом php-cgi, или есть другие варианты?
Изменить: Кажется, что exec()
не будет работать для этого, по крайней мере, не без меня, чтобы понять какой-то другой аспект, поскольку он ждет, пока вызов не вернется. Я решил, что могу использовать START
, вроде как exec( 'start php-cgi.exe somescript.php' );
, но он все еще ждет, пока не закончится другой script.
как насчет установить psexec и использовать -d
(не ждите) вариант
exec('psexec -d php-cgi.exe somescript.php');
Получите PSExec и запустите команду:
exec("psexec -d php-cgi.exe myfile.php");
PSTools - хороший патч, но я оставлю это здесь:
Если ваш сервер работает под управлением Windows 10 и на нем установлены последние обновления, вы можете установить подсистему Linux, которая имеет собственное ядро, которое поддерживает встроенное разветвление.
Это официально поддерживается Microsoft.
Вот хорошее руководство о том, как это сделать.
После того, как вы установили саму подсистему, вам нужно установить php в подсистеме.
Диск Windows c:\можно найти в папке "/mnt/c", поэтому вы можете запустить свой php из подсистемы, которая поддерживает разветвление (и, соответственно, подсистема php может использовать pcntl_fork).
Пример: php /mnt/c/xampp/htdocs/test.php
Если вы хотите запустить php подсистемы непосредственно из командной строки Windows, вы можете просто использовать команду "wsl".
Предполагая, что вы запускаете это из-под "C:\xampp\htdocs \"
Пример: wsl php main.php
Команда "wsl" определит путь для вас, поэтому вам не нужно делать какую-либо темную магию, если вы вызовете команду в каталоге c:\xampp\htdocs, подсистема разрешит ее как "/mnt/c/xampp/HTDOCS/".
Если вы используете свой сервер как сервер Apache, вам не нужно ничего делать, просто остановите сервер Windows Apache и запустите Linux, и все готово. Очевидно, вам нужно установить все недостающие модули php, которые вам нужны в подсистеме.
Вы можете создать процесс демона/фона для запуска кода (например, отправки электронной почты), и запрос просто должен будет добавить элементы в очередь, пусть деамон сделает тяжелый подъем.
Например, файл send_emails.bat:
cls
C:\PHP533\php.exe D:\web\server.php
exit
открыть планировщик задач Windows и запустить вышеуказанный файл send_emails.bat каждые 30 минут. Убедитесь, что за один раз запускается только один экземпляр, или вы можете запускать каждую задачу в нескольких экземплярах или отправлять каждое письмо дважды. Я говорю 30 минут, если что-то временно прерывается (проблемы с памятью, база данных недоступна и т.д.), Она будет запускаться каждые 30 минут, а не бесконечный процесс, который останавливается. Ниже приведен демон скелета... не полный или не проверенный Я просто печатаю пример:
<?php
set_time_limit(60*30); // don't run
$keepgoing = true;
$timeout = time()+ 60*29; // 29 minutes
while(time() < $timeout)
{
// grab emails from database
$result = $db->query('select subject, body, to_email FROM email_queue');
if($result->num_rows == 0)
{
sleep(10); // so we are not taxing the database
}
else
{
while($row = $result->fetch_assoc())
{
// send email
}
}
}
exit;
?>
Наконец, вам просто нужен запрос на добавление элемента в очередь в базе данных, и пусть демона обрабатывает тяжелый подъем.
$db->query('insert into email_queue(to,subject,body) values ('[email protected]','important email','<b>html body!</b>');