Подтвердить что ты не робот

Викинг в PHP на Windows

Мы запускаем 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.

4b9b3361

Ответ 2

Получите PSExec и запустите команду:

exec("psexec -d php-cgi.exe myfile.php");

Ответ 3

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, которые вам нужны в подсистеме.

Ответ 4

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

Например, файл 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>');