php перезапуск скрипта при ошибке

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

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

7 ответов

PHP-скрипт также может перезапустить себя с помощью PCNTL.

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

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

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

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

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

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

Да Я может!

независимо от того, является ли он надлежащим образом?

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

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

Дитто!

но ты же знаешь, что я хочу большего, верно?

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

как я могу расторгнуть теперь его?

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

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

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

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

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

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

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

расширенное использование, а не для слабонервных.

для запуска отдельного процесса измените функцию restartMyself на:

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

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

применяются все стандартные оговорки, удачи! =)

предположим:

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

использовать баш скрипт, так что скрипт PHP после остановки / завершения / прерывания может быть возобновил:

Контроллер Жира обработчик выполнения, это ключевые функции, которые вы ищете:

очень похож на CRON, но это ключевые особенности только то, что вы нужно

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

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

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

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

вот самый простой способ сделать это, без каких-либо дополнительных вывода:

while :; do [command]; done

while :; do echo «test» && sleep 1; done

while :; do php myscript.php; done

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

обновление: Тара сделать запуск и управление флотом процессов еще проще.

Источник

PHP для начинающих. Обработка ошибок

php перезапуск скрипта при ошибке

Не совершает ошибок только тот, кто ничего не делает, и мы тому пример — сидим и трудимся не покладая рук, читаем Хабр 🙂

В этой статье я поведу свой рассказа об ошибках в PHP, и о том как их обуздать.

Ошибки

Разновидности в семействе ошибок

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

Чтобы ни одна ошибка не ушла незамеченной потребуется включить отслеживание всех ошибок с помощью функции error_reporting(), а с помощью директивы display_errors включить их отображение:

Фатальные ошибки

Самый грозный вид ошибок — фатальные, они могут возникнуть как при компиляции, так и при работе парсера или PHP-скрипта, выполнение скрипта при этом прерывается.

E_PARSE

Это ошибка появляется, когда вы допускаете грубую ошибку синтаксиса и интерпретатор PHP не понимает, что вы от него хотите, например если не закрыли фигурную или круглую скобочку:

Или написали на непонятном языке:

Лишние скобочки тоже встречаются, и не так важно круглые либо фигурные:

Отмечу один важный момент — код файла, в котором вы допустили parse error не будет выполнен, следовательно, если вы попытаетесь включить отображение ошибок в том же файле, где возникла ошибка парсера то это не сработает:

E_ERROR

Это ошибка появляется, когда PHP понял что вы хотите, но сделать сие не получилось ввиду ряда причин. Эта ошибка так же прерывает выполнение скрипта, при этом код до появления ошибки сработает:

Не был найден подключаемый файл:

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

При попытке вызвать несуществующий метод класса:

Отсутствия свободной памяти (больше, чем прописано в директиве memory_limit) или ещё чего-нить подобного:

Очень часто встречается при чтении либо загрузки больших файлов, так что будьте внимательны с вопросом потребляемой памяти

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

Не фатальные

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

E_WARNING

Бывает, если используешь неправильный тип аргументов при вызове функций:

Их очень много, и перечислять все не имеет смысла…

E_NOTICE

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

Когда обращаются к неопределенной переменной:

Когда обращаются к несуществующему элементу массива:

Когда обращаются к несуществующей константе:

Когда не конвертируют типы данных:

Для избежания подобных ошибок — будьте внимательней, и если вам IDE подсказывает о чём-то — не игнорируйте её:

php перезапуск скрипта при ошибке

E_STRICT

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

E_DEPRECATED

Так PHP будет ругаться, если вы используете устаревшие функции (т.е. те, что помечены как deprecated, и в следующем мажорном релизе их не будет):

В моём редакторе подобные функции будут зачёркнуты:

php перезапуск скрипта при ошибке

Пользовательские

Этот вид, которые «разводит» сам разработчик кода, я уже давно их не встречал, и не рекомендую вам ими злоупотреблять:

Теперь, когда вы познакомились с большинством видов и типов ошибок, пора озвучить небольшое пояснение по работе директивы display_errors :

Приручение

Для работы с ошибками в PHP существует 3 функции:

У вас не получится назначить более одной функции для обработки ошибок, хотя очень бы хотелось регистрировать для каждого типа ошибок свой обработчик, но нет — пишите один обработчик, и всю логику отображения для каждого типа описывайте уже непосредственно в нём

С обработчиком, который написан выше есть одна существенная проблема — он не ловит фатальные ошибки, и при таких ошибках вместо сайта пользователи увидят лишь пустую страницу, либо, что ещё хуже, сообщение об ошибке. Дабы не допустить подобного сценария следует воспользоваться функцией register_shutdown_function() и с её помощью зарегистрировать функцию, которая всегда будет выполняться по окончанию работы скрипта:

Данная функция будет срабатывать всегда!

Но вернёмся к ошибкам, для отслеживания появления в коде ошибки воспользуемся функцией error_get_last(), с её помощью можно получить информацию о последней выявленной ошибке, а поскольку фатальные ошибки прерывают выполнение кода, то они всегда будут выполнять роль «последних»:

Хотел обратить внимание, что данный код хоть ещё и встречается для обработки ошибок, и вы возможно вы даже с ним столкнётесь, но он потерял актуальность начиная с 7-ой версии PHP. Что пришло на замену я расскажу чуть погодя.

О прожорливости

Проведём простой тест, и выясним — сколько драгоценных ресурсов кушает самая тривиальная ошибка:

В результате запуска данного скрипта у меня получился вот такой результат:

Теперь добавим ошибку в цикле:

Результат ожидаемо хуже, и на порядок (даже на два порядка!):

Вывод однозначен — ошибки в коде приводят к лишней прожорливости скриптов — так что во время разработки и тестирования приложения включайте отображение всех ошибок!

Тестирование проводил на различных версиях PHP и везде разница в десятки раз, так что пусть это будет ещё одним поводом для исправления всех ошибок в коде

Где собака зарыта

В PHP есть спец символ «@» — оператор подавления ошибок, его используют дабы не писать обработку ошибок, а положится на корректное поведение PHP в случае чего:

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

Исключения

В эру PHP4 не было исключений (exceptions), всё было намного сложнее, и разработчики боролись с ошибками как могли, это было сражение не на жизнь, а на смерть… Окунуться в эту увлекательную историю противостояния можете в статье Исключительный код. Часть 1. Стоит ли её читать сейчас? Не могу дать однозначный ответ, лишь хочу заметить, что это поможет вам понять эволюцию языка, и раскроет всю прелесть исключений.

Исключения — исключительные событие в PHP, в отличии от ошибок не просто констатируют наличие проблемы, а требуют от программиста дополнительных действий по обработке каждого конкретного случая.

К примеру, скрипт должен сохранить какие-то данные в кеш файл, если что-то пошло не так (нет доступа на запись, нет места на диске), генерируется исключение соответствующего типа, а в обработчике исключений принимается решение — сохранить в другое место или сообщить пользователю о проблеме.

В каких случаях стоит применять исключения:

Соответственно ловить данные исключения будем примерно так:

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

Теперь, если использовать эти исключения то можно получить следующий код:

Важно помнить, что Exception — это прежде всего исключительное событие, иными словами исключение из правил. Не нужно использовать их для обработки очевидных ошибок, к примеру, для валидации введённых пользователем данных (хотя тут не всё так однозначно). При этом обработчик исключений должен быть написан в том месте, где он будет способен его обработать. К примеру, обработчик для исключений вызванных недоступностью файла для записи должен быть в методе, который отвечает за выбор файла или методе его вызывающем, для того что бы он имел возможность выбрать другой файл или другую директорию.

Чтобы избежать подобной ситуации следует использовать функцию set_exception_handler() и установить обработчик для исключений, которые брошены вне блока try-catch и не были обработаны. После вызова такого обработчика выполнение скрипта будет остановлено:

Ещё расскажу про конструкцию с использованием блока finally — этот блок будет выполнен вне зависимости от того, было выброшено исключение или нет:

Для понимания того, что это нам даёт приведу следующий пример использования блока finally :

Т.е. запомните — блок finally будет выполнен даже в том случае, если вы в блоке catch пробрасываете исключение выше (собственно именно так он и задумывался).

Для вводной статьи информации в самый раз, кто жаждет ещё подробностей, то вы их найдёте в статье Исключительный код 😉

PHP7 — всё не так, как было раньше

Так, вот вы сейчас всю информацию выше усвоили и теперь я буду грузить вас нововведениями в PHP7, т.е. я буду рассказывать о том, с чем вы будете сталкиваться работая над современным PHP проектом. Ранее я вам рассказывал и показывал на примерах какой костыль нужно соорудить, чтобы отлавливать критические ошибки, так вот — в PHP7 это решили исправить, но? как обычно? завязались на обратную совместимость кода, и получили хоть и универсальное решение, но оно далеко от идеала. А теперь по пунктам об изменениях:

Сложно? Теперь на примерах, возьмём те, что были выше и слегка модернизируем:

В результате ошибку поймаем и выведем:

И чуть-чуть деталей:

TypeError — для ошибок, когда тип аргументов функции не совпадает с передаваемым типом:

ArithmeticError — могут возникнуть при математических операциях, к примеру когда результат вычисления превышает лимит выделенный для целого числа:

AssertionError — редкий зверь, появляется когда условие заданное в assert() не выполняется:

При настройках production-серверов, директивы zend.assertions и assert.exception отключают, и это правильно

Полный список предопределённых исключений вы найдёте в официальном мануале, там же иерархия SPL исключений.

При написании данного раздела были использованы материалы из статьи Throwable Exceptions and Errors in PHP 7.

Единообразие

— Там ошибки, тут исключения, а можно это всё как-то до кучи сгрести?

Да запросто, у нас же есть set_error_handler() и никто нам не запретит внутри оного обработчика бросить исключение:

Но данный подход с PHP7 избыточен, со всем теперь справляется Throwable :

Отладка

Иногда, для отладки кода, нужно отследить что происходило с переменной или объектом на определённом этапе, для этих целей есть функция debug_backtrace() и debug_print_backtrace() которые вернут историю вызовов функций/методов в обратном порядке:

В результате выполнения функции debug_print_backtrace() будет выведен список вызовов приведших нас к данной точке:

Assert

Функция assert() поменяла своё поведение при переходе от версии 5.6 к 7.0, и ещё сильней всё поменялось в версии 7.2, так что внимательней читайте changelog’и PHP 😉

Первый случай — это когда вам надо написать TODO прямо в коде, да так, чтобы точно не забыть реализовать заданный функционал:

В результате выполнения данного кода получим E_WARNING :

PHP7 можно переключить в режим exception, и вместо ошибки будет всегда появляться исключение AssertionError :

При необходимости, можно выбрасывать произвольное исключение:

Второй вариант использования — это создание некоего подобия TDD, но помните — это лишь подобие. Хотя, если сильно постараться, то можно получить забавный результат, который поможет в тестировании вашего кода:

Третий вариант — некое подобие на контрактное программирование, когда вы описали правила использования своей библиотеки, но хотите точно убедится, что вас поняли правильно, и в случае чего сразу указать разработчику на ошибку (я вот даже не уверен, что правильно его понимаю, но пример кода вполне рабочий):

Если вас заинтересовали контракты, то специально для вас у меня есть ссылочка на фреймворк PhpDeal.

Никогда не используйте assert() для проверки входных параметров, ведь фактически assert() интерпретирует первый параметр (ведёт себя как eval() ), а это чревато PHP-инъекцией. И да, это правильное поведение, ведь если отключить assert’ы, то все передаваемые аргументы будут проигнорированы, а если делать как в примере выше, то код будет выполняться, а внутрь отключенного assert’a будет передан булевый результат выполнения. А, и это поменяли в PHP 7.2 🙂

Если у вас есть живой опыт использования assert() — поделитесь со мной, буду благодарен. И да, вот вам ещё занимательно чтива по этой теме — PHP Assertions, с таким же вопросом в конце 🙂

В заключение

Я за вас напишу выводы из данной статьи:

Это репост из серии статей «PHP для начинающих»:

Спасибо Максиму Слесаренко за помощь в написании статьи.

Источник

Php перезапуск скрипта при ошибке

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

Как мне сделать перезапуск скрипта при такой ошибке, когда сценарий останавливается и перестает работать скрипт. цикл и if вроде остаются работать, а вот некоторые действия match, patch могут не работать.

@playful тока шо опять вылетела ошибка на ровном месте в режиме записи [761202650] [14:22:49] Поток №1 : Таймаут во время выполнения exist for[documentRoot, css #nav-accordion > :nth-child(2) > ul > :nth-child(2) > a]

php перезапуск скрипта при ошибке

@playful тока шо опять вылетела ошибка на ровном месте в режиме записи [761202650] [14:22:49] Поток №1 : Таймаут во время выполнения exist for[documentRoot, css #nav-accordion > :nth-child(2) > ul > :nth-child(2) > a]

Каждое действие оборачивай в игнор ошибок, если произошла ошибка то сделай другие действия (обычно перезагрузить страницу). Также делай проверки каждый раз существует ли элемент на странице, если нет то опять делай другие действие.
Перезапускать ничего не надо, это ошибка не столько уж критическая.

@fastspace вы меня не поняли, там весь скрипт ломается, если это происходит то игнор ошибок может не сработать, а может и сработать, это уж смотря как багнет.

php перезапуск скрипта при ошибке

@fastspace вы меня не поняли, там весь скрипт ломается, если это происходит то игнор ошибок может не сработать, а может и сработать, это уж смотря как багнет.

весь скрипт в игнор оборачивай 😀

весь скрипт в игнор оборачивай 😀

А потом игнор еще раз в игнор. Проверено, работает)

нууу, нашлись советнечки))), я лучше уж подожду обновления, для данного решения проблемы.

php перезапуск скрипта при ошибке

нууу, нашлись советнечки))), я лучше уж подожду обновления, для данного решения проблемы.

Врятли будет обновление, судя по ошибке это обычный тайм-аут ввода текста в поле, он легко оборачивается в игнор ошибок. По условию was error достаточно перезагрузить страницу и меткой вернуться обратно.

php перезапуск скрипта при ошибке

нууу, нашлись советнечки))), я лучше уж подожду обновления, для данного решения проблемы.

Обновление с ИИ который будет за Вас править скрипт вряд ли когда-то выйдет.

php перезапуск скрипта при ошибке

весь скрипт в игнор оборачивай 😀

А потом игнор еще раз в игнор. Проверено, работает)

наверно проще остановиться на стадии задумки тогда 😀 точно ошибок не будет )))))

php перезапуск скрипта при ошибке

нууу, нашлись советнечки))), я лучше уж подожду обновления, для данного решения проблемы.

Обновление с ИИ который будет за Вас править скрипт вряд ли когда-то выйдет.

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

php перезапуск скрипта при ошибке

нууу, нашлись советнечки))), я лучше уж подожду обновления, для данного решения проблемы.

Обновление с ИИ который будет за Вас править скрипт вряд ли когда-то выйдет.

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

Устно.. Типа «Окей гугл, напиши мне скрипт..»

Источник

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

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

8 ответов

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

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

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

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

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

Да, я могу!

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

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

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

Ditto!

Но ты же знаешь, что я хочу большего, не так ли?

Конечно! Я могу перезапустить после убийства, даже Ctrl-C!

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

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

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

Нет проблем, я тоже умею обрабатывать ошибки!

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

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

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *