Форкинг в PHP на Windows - PullRequest
13 голосов
/ 16 марта 2010

Мы запускаем PHP на сервере Windows (действительно, это является источником многих проблем, но в настоящее время миграция невозможна). Есть несколько моментов, когда инициируемому пользователем действию нужно будет запустить несколько вещей, которые занимают некоторое время, и о которых пользователю не нужно знать, удастся ли им это или нет, например, отправка электронного письма или проверка некоторых сторонние аккаунты обновляются. Если бы я мог просто раскошелиться на pcntl_fork(), это было бы очень просто, но функции PCNTL недоступны в Windows.

Кажется, самое близкое, что я могу сделать, это сделать что-то подобное:

exec( 'php-cgi.exe somescript.php' );

Однако это было бы намного сложнее. Действия, которые мне нужно выполнить, основаны на большом количестве контекста, который уже будет существовать в процессе выполнения; чтобы использовать приведенный выше пример, мне нужно было бы выяснить основные данные и каким-то образом передать их новому сценарию. Если бы я мог разветвляться, это было бы вопросом раннего возврата родительского процесса, чтобы ребенок работал над еще несколькими вещами.

Я обнаружил, что несколько человек говорили о своей работе по компиляции различных функций PCNTL в Windows, но ни у одного из них не было ничего доступного (неработающие ссылки и т. Д.).

Несмотря на то, что этот вопрос имеет практически то же имя, что и у меня, похоже, проблема заключалась в большем времени ожидания выполнения, чем в форке. Итак, мой лучший вариант - просто немного изменить рефакторинг для вызова php-cgi или есть другие варианты?

Редактировать: Кажется, exec() не сработает для этого, по крайней мере, если бы я не вычислил какой-то другой аспект этого, так как он ждет, пока вызов не вернется. Я подумал, что мог бы использовать START, вроде exec( 'start php-cgi.exe somescript.php' );, но он все еще ждет, пока другой скрипт завершит работу.

Ответы [ 3 ]

13 голосов
/ 17 марта 2010

как насчет установки psexec и использования опции -d (не ждите)

exec('psexec -d php-cgi.exe somescript.php');
3 голосов
/ 17 марта 2010

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

exec("psexec -d php-cgi.exe myfile.php");
1 голос
/ 09 ноября 2013

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

Например, файл 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 ('customer@email.com','important email','<b>html body!</b>');
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...