Intereting Posts
Каково значение числа, 32767? SHA1 vs md5 vs SHA256: что использовать для входа в PHP? ?: оператор («оператор Элвиса») в PHP Как загрузить изображения в базу данных MySQL с помощью PHP-кода Будет ли сокращение количества включений / требует повышения производительности? В PHP объедините дублирующийся набор элементов многомерного массива и суммируйте значения определенного ключа получить хэш в URL с php? PHP $ GLOBALS отсутствует $ _SERVER Динамически, именования элементов формы в PHP Кодировать строку для соответствия имени поля кодированной формы в массиве PHP POST PHP Загрузить файл, ограничить максимальную скорость и рассчитать скорость загрузки "Preg_match (): Ошибка компиляции: несогласованные скобки" в PHP для допустимого шаблона как отправлять / получать файлы через веб-службы в php Как вы отслеживаете файлы в SMB с помощью приложения? Получить ответ от PHP-файла с помощью AJAX

Автоматический перезапуск PHP-скрипта на выходе

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

Сценарий PHP также может перезапускаться с помощью PCNTL.

Отказ от ответственности: точка этого упражнения заключается только в том, чтобы доказать, что PHP вполне способен перезапустить себя и ответить на вопрос:

Есть ли способ, с помощью которого я могу автоматически перезапускать скрипт PHP всякий раз, когда он выходит, независимо от того, был ли он завершен должным образом или завершился из-за ошибки?

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

В примерах мы предположим, что это скрипт PHP CLI, запущенный в среде * nix с терминала с полупристойной оболочкой с помощью команды:

$ php i-can-restart-myself.php 0 

Мы передаем атрибут счетчика перезапуска в качестве индикатора, что процесс был перезапущен.

Могу ли я автоматически перезапустить скрипт PHP?

Да, я могу!

 <?php echo ++$argv[1]; // count every restart $_ = $_SERVER['_']; // or full path to php binary echo "\n======== start =========\n"; // do a lot of stuff $cnt = 0; while( $cnt++ < 10000000 ){} echo "\n========== end =========\n"; // restart myself pcntl_exec($_, $argv); 

Независимо от того, было ли оно прекращено должным образом?

Да, я могу перезапустить, если это прекращено!

 <?php echo ++$argv[1]; $_ = $_SERVER['_']; register_shutdown_function(function () { global $_, $argv; // note we need to reference globals inside a function // restart myself pcntl_exec($_, $argv); }); echo "\n======== start =========\n"; // do a lot of stuff $cnt = 0; while( $cnt++ < 10000000 ){} echo "\n========== end =========\n"; die; // exited properly // we can't reach here pcntl_exec($_, $argv); 

Или прекращено из-за ошибки?

То же самое!

 <?php echo ++$argv[1]; $_ = $_SERVER['_']; register_shutdown_function(function () { global $_, $argv; // restart myself pcntl_exec($_, $argv); }); echo "\n======== start =========\n"; // do a lot of stuff $cnt = 0; while( $cnt++ < 10000000 ){} echo "\n===== what if? =========\n"; require 'OOPS! I dont exist.'; // FATAL Error: // we can't reach here echo "\n========== end =========\n"; die; // exited properly // we can't reach here pcntl_exec($_, $argv); 

Но вы знаете, что я хочу больше, чем это правильно?

Безусловно! Я могу перезапустить на kill, hub даже Ctrl-C!

 <?php echo ++$argv[1]; $_ = $_SERVER['_']; $restartMyself = function () { global $_, $argv; pcntl_exec($_, $argv); }; register_shutdown_function($restartMyself); pcntl_signal(SIGTERM, $restartMyself); // kill pcntl_signal(SIGHUP, $restartMyself); // kill -s HUP or kill -1 pcntl_signal(SIGINT, $restartMyself); // Ctrl-C echo "\n======== start =========\n"; // do a lot of stuff $cnt = 0; while( $cnt++ < 10000000 ){} echo "\n===== what if? =========\n"; require 'OOPS! I dont exist.'; // FATAL Error: // we can't reach here echo "\n========== end =========\n"; die; // exited properly // we can't reach here pcntl_exec($_, $argv); 

Как мне его прекратить?

Если вы наполнили процесс, удерживая Ctrl-C, вы можете просто поймать его где-нибудь в выключении.

Я не хочу, чтобы все эти ошибки можно было перезапустить тоже?

Без проблем я тоже могу обрабатывать ошибки!

 <?php echo ++$argv[1]; $_ = $_SERVER['_']; $restartMyself = function () { global $_, $argv; pcntl_exec($_, $argv); }; register_shutdown_function($restartMyself); pcntl_signal(SIGTERM, $restartMyself); pcntl_signal(SIGHUP, $restartMyself); pcntl_signal(SIGINT, $restartMyself); set_error_handler($restartMyself , E_ALL); // Catch all errors echo "\n======== start =========\n"; // do a lot of stuff $cnt = 0; while( $cnt++ < 10000000 ){} echo $CAREFUL_NOW; // NOTICE: will also be caught // we would normally still go here echo "\n===== what if? =========\n"; require 'OOPS! I dont exist.'; // FATAL Error: // we can't reach here echo "\n========== end =========\n"; die; // exited properly // we can't reach here pcntl_exec($_, $argv); 

Хотя на первый взгляд это работает нормально, потому что pcntl_exec работает в одном процессе, мы не замечаем, что все ужасно неправильно. Если вы хотите создать новый процесс и позволить старому умереть вместо этого, что является вполне жизнеспособной альтернативой, см. Следующий пост, вы заметите, что на каждой итерации запускается 2 процесса, потому что мы запускаем PHP NOTICE и ERROR из-за общего контроля , Который, конечно, может быть легко исправлен, гарантируя, что мы умрем () или exit () после вызова pcntl_exec в обработчике ошибок, иначе PHP предполагает, что допуски были приняты и продолжаются.

То, что я пытаюсь сделать, состоит в том, что даже если вы можете перезапустить сценарий, который потерпел неудачу, это не повод для отказа от кода. Хотя для этой практики могут существовать жизнеспособные варианты использования, я категорически не согласен с тем, что перезапуск при сбое должен использоваться как решение для сбоев сценариев из-за ошибок! Как мы можем видеть из этих примеров, нет никакого способа точно узнать, где это произошло, поэтому мы не можем быть уверены, где он начнется снова. Переход на решение «быстрого исправления», которое может показаться работоспособным, может иметь больше проблем, чем раньше.

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

Здесь будут драконы.

Продвинутое использование, а не слабое сердце.

Чтобы запустить отдельный процесс, измените функцию restartMyself, чтобы:

 <?php $restartMyself = function () { global $_, $argv; if(!pcntl_fork()) // We only care about the child fork pcntl_exec($_, $argv); die; // insist that we don't tolerate errors } 

Это, безусловно, может быть приключением, преследующим процессы, которые возобновляют иммунитет к вашему убийству, если вам удастся поймать их в процессе. знак равно

Убедитесь, что сценарий достаточно, чтобы у вас было достаточно времени, чтобы убить его.

Пытаться:

 $ kill -9 

или:

 $ kill -s KILL 

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

Все стандартные отказы распространяются, удачи! знак равно

Предполагая , что:

  • Вызовите один и тот же файл сценария x количество раз
  • Повторный вызов, если он прерывается / заканчивается / останавливается
  • Автоматизированный процесс для бесконечного цикла

Некоторые варианты приходят на ум для достижения вашей цели [Решения на базе Unix / Linux]:

  1. Используйте BASH-скрипт , чтобы скрипт PHP после остановки / окончания / прерывания можно было возобновить:

     #!/bin/bash clear date php -f my_php_file.php sleep 100 # rerun myself exec $0 
  2. Обработчик выполнения Fat Controller – вот основные функции, которые вы ищете:

    • Используется для многократного запуска других программ
    • Может запускать много экземпляров любого скрипта / программы параллельно
    • любой сценарий может быть повторно запущен, как только он завершит выполнение

    очень похож на CRON, но эти ключевые функции – это то, что вам нужно

  3. Используя CRON , вы можете вызвать его скрипт PHP через интервалы, например, одну минуту , а затем с помощью этого кода в самом начале вашего PHP-скрипта вы сможете контролировать количество запущенных потоков, выходящих, если 8 уже Бег:

     exec('ps -A | grep ' . escapeshellarg(basename(__FILE__)) , $results); if (count($results) > 7) { echo "8 Already Running\n" die(0); } 

    поиск процессов, работающих с одним и тем же путем текущего файла, и возвращает количество найденных процессов. Затем, если их больше 7, выйдет.

Использование CRON

 #!/bin/sh process = 'script.php' if ps ax | grep -v grep | grep $process then echo "$process is running..." else echo "$process not running, relaunching..." php /your/php/script.php fi 

Чтобы дополнить ответ ow3n , скрипт CLI PHP похож на любую другую команду и может быть легко повторен в бесконечном цикле while. Он будет работать точно так же, как запуск команды сам по себе, но будет работать снова, когда она закончится. Просто нажмите Ctrl + C, когда вы хотите завершить цикл.

Edit: Если ваш процесс ловит сигналы (что необходимо, если это приложение с 12 факторами ), вам нужно будет удерживать Ctrl + C, а не просто нажимать на него. Пресса будет захвачена процессом (который должен завершиться сам), но цикл while снова перезапустит процесс (что полезно, если вы просто хотите перезапустить процесс, а не прекратить его). Если ваш процесс не захватывает сигналы, тогда Ctrl + C убьет как процесс, так и цикл while.

Вот простейший способ сделать это без лишнего вывода:

while :; do [command]; done

while :; do echo "test" && sleep 1; done

while :; do php myscript.php; done

Тем не менее, я немного обеспокоен последствиями в ваших комментариях:

О потоках:

  1. Я бы дважды подумал об использовании потоков в PHP. Языки, которые используют эту модель, имеют гораздо лучшую / стабильную / зрелую среду, чем PHP (например, Java).
  2. Использование нескольких процессов вместо нескольких потоков может показаться неэффективным, но поверьте мне, это больше, чем делает его с точки зрения простоты, ремонтопригодности, легкости отладки и т. Д. Многопоточность может быстро привести вас к обслуживанию ад , что объясняет появление актера Модель .
  3. Является ли эффективность бизнес-требованиями? Обычно это из-за ограниченных ресурсов (например, встроенных устройств), но я сомневаюсь, что это ваш случай, иначе вы бы не использовали PHP. Подумайте, что в наши дни люди намного дороже компьютеров . Поэтому, чтобы свести к минимуму затраты, гораздо более выгодно максимизировать эффективность ваших людей, а не ваших компьютеров ( см. Правило экономики Unix ). Многопоточность, если все будет хорошо, сэкономит вам немного денег, оптимизируя использование ваших компьютеров, но будет стоить вам гораздо больше с точки зрения головных болей, которые это вызовет для ваших людей.
  4. Если вам абсолютно необходимо использовать потоки, я настоятельно рекомендую вам рассмотреть модель Actor. Акка – отличная реализация.

О процессах:

  1. Если вы запускаете свои скрипты в процессе разработки, одного процесса [каждого типа] должно быть достаточно.
  2. Если вы запускаете свои сценарии на производстве, вам следует полагаться на диспетчер процессов для управления вашими процессами, такими как Upstart .
  3. Избегайте превращать ваши процессы в дьямонов.
  4. Узнайте о 12 факторных приложениях , особенно о процессах , параллельности и одноразовости .

Обновление. Контейнеры упрощают управление и управление флотом процессов.

Чтобы перезапустить скрипт каждый раз, когда он перестает работать, вы можете обернуть скрипт user1179181 в цикле.

 #!/bin/bash while true do if ps ax | grep -v grep | grep "script.php" then echo "process is running..." else clear date echo "process not running, relaunching..." php script.php fi sleep 10 done 

Только мои 5 центов. Перезапуск PCNTL с пользовательской обработкой ошибок.

 register_shutdown_function("shutdownHandler"); function shutdownHandler() //will be called when php script ends. { $lasterror = error_get_last(); switch ($lasterror['type']) { case E_ERROR: case E_CORE_ERROR: case E_COMPILE_ERROR: case E_USER_ERROR: case E_RECOVERABLE_ERROR: case E_CORE_WARNING: case E_COMPILE_WARNING: case E_PARSE: $error = "[SHUTDOWN] lvl:" . $lasterror['type'] . " | msg:" . $lasterror['message'] . " | file:" . $lasterror['file'] . " | ln:" . $lasterror['line']; myCustomLogHandler("FATAL EXIT $error\n"); } $_ = $_SERVER['_']; global $_; pcntl_exec($_); }