Викинг в PHP на Windows

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

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

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

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

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

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

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

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

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

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

 exec("psexec -d php-cgi.exe myfile.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 ('customer@email.com','important email','<b>html body!</b>');