2016-12-15 4 views
1

Я должен убедиться, что определенный PHP-скрипт (запущенный веб-запросом) не запускается более одного раза одновременно.Надежный блокиратор реестров PHP-скриптов

С двоичными файлами довольно легко проверить, существует ли уже процесс определенного двоичного файла.

Однако PHP-скрипт может выполняться несколькими путями, например. CGI, FCGI, внутри модулей веб-сервера и т. Д., Поэтому я не могу использовать системные команды для его поиска.

Как проверить, проверен ли другой экземпляр определенного скрипта?

+1

Установите флаг какого-либо типа: создайте файл, сохраните флаг в базе данных или используйте ключ Redis или memcached. Просто убедитесь, что вы окончательно закончили его или очистили вручную, если первый скрипт умирает. –

+0

Трудно реализовать надежное «истечение», когда скрипт может работать в течение длительного времени. Если это не удастся, нам нужно подождать неизвестное время, чтобы убедиться, что оно умерло ... – dronus

+1

Это может быть проблемой XY. По какой именно причине вам нужна эта проверка, что PHP-скрипт работает только один раз? Я спрашиваю, потому что есть, вероятно, лучший подход к реальной проблеме, с которой вы сталкиваетесь, что не связано с этим воспринимаемым решением. – Mjh

ответ

4

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

Процесс управляет «файл блокировки».

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

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


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

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

+0

Отличный и точный ответ, мне бы просто понравилось, если бы вы могли предоставить код, который иллюстрирует ваши точки :) – Mjh

+1

Хранение PID внутри файла не будет работать, так как нет PID в зависимости от способа запуска PHP. Если там где PID, я бы просто проверил процесс, как я уже упоминал. Кроме того, связь всего в два раза (начало и завершение) сильно подвержена ошибкам, поскольку скрипты PHP могут прекратить выполнение по нескольким причинам (прерывание пользователя, из памяти, перезапуск веб-сервера), и нет надежного способа прикрепления кода завершения. – dronus

+0

Таким образом, использование файла блокировки означало бы обновить этот файл блокировки во время работы скрипта, что является своеобразной процедурой (например, совместная многозадачность с ручным управлением). – dronus

0

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

PHP-скрипт может, например, вызвать другой интерпретатор PHP в его варианте CLI. Это обеспечило бы уникальный PID, который можно было бы проверить для блокировки. ПИД-код должен быть сохранен в некотором файле блокировки, а затем проверяется на наличие устаревших блокировок, запрашивая, работает ли процесс с использованием ПИД-регулятора.

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

Также могут использоваться семафоры (http://php.net/manual/de/book.sem.php), которые явно управляются интерпретатором PHP, чтобы отображать время жизни скриптов. Они, кажется, работают достаточно хорошо, однако не так много о том, насколько они надежны в случае преждевременной смерти сценария.

Также имейте в виду, что внешние процессы, запускаемые PHP-скриптом, могут продолжаться, даже если скрипт заканчивается. Например, пользователь прерывает на FCGI релизы passthru процессы, которые продолжают работать, несмотря на закрытие клиентского соединения. Они могут быть убиты позже, если достаточное количество накоплений или вообще не будет достигнуто. Таким образом, такие внешние процессы также должны блокироваться, что невозможно сделать с помощью семафоров с поддержкой PHP.

Смежные вопросы