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