Pull to refresh

Comments 63

>> уникальность в рамках одного процесса
Не совсем правильно. В некоторых языках можно изолировать области и создавать по синглтону в каждой такой области. В .NET это AppDomain, в java достигается при помощи собственного class-loader-а.

P.S. А вот в саппорт вы зря отписали, евпочя ;)
Ну поэтому я написал пост исключительно в блог PHP :)
Млин, да что ж такое с Хабром стало — ни единого коммента не напишешь, чтобы в карму не заполучить. :(
Боже упаси, я таким не занимаюсь. Я посты пишу, и вот за этот в частности мне уже «нас#али».

А вы то чего жалуетесь? Это ведь ваш первый коммент в этом посте… или это такой новый тип разводки на плюсики?)))
Ой, прошу прощения, я не вам. Хабр что-то глючит и висит, и я отправил не туда
Синхронизация по именам файлов — брутально.

А как же мютексы?
А есть пример реализации, с возможностью запуска на VPS хостинге?
Зачем велосипед? Обычно создают pid-файлы и сигналы. Создавать в качестве сигнала файл вообще странно.
А можно подробнее про сигналы?
Подозреваю, что это можно реализовать только на сервере, к которому у вас есть полный доступ. Сомневаюсь, что на том же VPS хостинге такое получится.
Не знаю как насчет VPS, но если есть доступ к крону то, наверное, и доступ к kill есть. Посмотрите, man kill и php.net/pcntl
Как я и предполагал, ничего нового вы мне не рассказали.

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

Плюс ко всему вам всё равно писать «велосипед», чтобы реализовать следующее:

Если работа скрипта прерывается из-за ошибки, то он должен быть перезапущен как можно скорее.
Если скрипт подвисает на выполнении одной из итераций, то он должен быть перезапущен как можно скорее.
Скрипт должен перезапускаться каждые 5-10 часов, чтобы предотвратить возможные утечки памяти. Остановка скрипта в этом случае должна производиться безопасным образом (когда задачи текущей итерации выполнены).
Необходимо некий индикатор того, что скрипт в данный момент запущен
Необходимо наличие возможности принудительно остановить выполнение скрипта.
Видимо, вы очень мало знакомы с администрированием. В качестве «статус файлов», как вы называете, обычно используются файлы *.pid находящиеся в заранее определенном месте(например, можете посмотреть в /var/run). Скрипты, запускаемые по крону смотрят есть ли этот файл, и проверяют есть ли процесс с данным PID и если есть, то завершаются. «Возможные утечки памяти» это отдельная песня. Обработка сигналов в самом скрипте как раз и позволит завершать задачу, тогда когда это можно. А уж что тривиальнее для принудительной остановки скрипта, чем kill -9 PID.
Что-то мне слабо представляется как это будет реализовано. У меня к примеру по крону запускается 4 разных независимых скрипта (псевдо демона): один шлёт SMS-ки, второй email-ы, третий бэкапит и т.д… Как я в этих скриптах смогу по PID определить, что скрипт с таким же именем уже запущен?

P.S. Но так или иначе, все описанные действия требуют полноценного root-доступа к системе, что в наше время крайне редкостная роскошь.
А как апач узнает, что он уже запущен или остановлен? Вы так и не посмотрели в /var/run…
Я в своё время туда уже насмотрелся, и так знаю что там. Вы так и не ответили на мой вопрос.

Апач это апач, он в единственном числе всегда. А как вы будете различать разные скрипты, запушенные под одним процессом(php в частности)?

Сейчас любопытства ради ещё раз заглянул в /var/run своего сервера, и вот о трёх работающих в данный момент php-скриптах вообще никакой информации не нашёл. Вы сами попробуйте запустить парочку параллельных живых скриптов и заглянуть в ту папочку, они там себя никак не обозначают.
Pid-файлы вы сами должны создавать! В крайнем случае сделать ps aux | grep имя_скрипта.
Апач это апач, он в единственном числе всегда.

А может сначала посмотреть как запускается апач? Или попробовать запустить апач при запущенном его экземпляре, или остановить при остановленном?
Что за дикое нежелание изучать?
И кстати на VPS это получится.
Обычно для каждого запущенного процесса делают блокирующий файл <кодовое имя>.pid
Для стоп-файлов конвенции не встречал :-)
pid-файл в основном используется для сигнализации того, что процесс запущен и у него такой-то уникальный идентификатор, по которому к нему можно обратиться.

Удалять pid-файл для остановки процесса неправильно т.к. в нашем случае он будет повторно запущен CRON-ом в ближайшие 5 минут. Таким образом, чтобы заблокировать выполнение скрипта на сутки придётся каждые 5мин удалять .pid файлы.

Вот поэтому, чтобы не дёргаться с удалением pid-файлов и создаётся один стоп-файл, который и блокирует выполнение скрипта на всё время своего существования.
Ну что ж такое то… Ну хоть немножко пощупали матчасть бы. Для остановки процесса читают pid-файл и шлют сигнал тому процессу, что нужно остановиться.
Да что же вы все тут одни такие самые умные?))

Тогда читайте: en.wikipedia.org/wiki/Process_identifier

«In computing, the process identifier (normally referred to as the process ID or just PID) is a number used by some operating system kernels (such as that of UNIX, Mac OS X or Microsoft Windows) to uniquely identify a process. This number may be used as a parameter in various function calls allowing processes to be manipulated, such as adjusting the process's priority or killing it altogether

Вы читайте внимательней, что я пишу:
Удалять pid-файл для остановки процесса неправильно т.к. в нашем случае он будет повторно запущен CRON-ом в ближайшие 5 минут. Таким образом, чтобы заблокировать выполнение скрипта на сутки придётся каждые 5мин удалять .pid файлы.

Гляжу в книгу…
Никто и не предлагает удалять pid-файл для остановки процесса — это у вас свои тараканы. Процессу надо слать сигналы! А процесс должен как полагается обработать сигнал, и, если пришел сигнал завершиться, то завершается, завершив все свои неотложные дела. Все ж таки ж не почитали про сигналы…
Эта ветка комментариев началась с предложения Teapot по поводу: «Обычно для каждого запущенного процесса делают блокирующий файл <кодовое имя>.pid» вот как раз несвязном словосочетании «блокирующий файл <кодовое имя>.pid» я все это время и писал.

А вы о чём?

И насчёт слать сигналы я вам уже объяснил, что это не универсальное решение т.к. актуально только на серверах к которым есть root-доступ.
Ага, а если сервер под виндой, то что делать?
А если у php прав нет на обработку этих сигналов?

Ну вы напишите класс, который будет через pcntl работать и сравним какому проценту пользователей хабра хватит прав его хотя бы запустить на своих проектах.
А если… А если… А если под виндой, то лучше уж сервисы использовать.
И блокирующий файл <кодовое имя>.pid, означает блокировку запуска дубликата!
Ребята из википедии с вами не согласны, читайте ещё раз, только внимательней: en.wikipedia.org/wiki/Process_identifier

pid есть просто идентификация процесса, ассоциативная связь между его названием и уникальным идентификатором под которым он в данный момент в системе запущен — понимаете?

Вы зациклены на линухе и всё прочем. А что если сервер под виндовс? А под виндовс кстати может хоть 10 процессов одной и той же программы быть запущено и у каждой будет свой pid.

В общем не надо понятия каверкать.
Класс написан в первую очередь как универсальное решения. Если бы это было что-то кастомное, заточенное под unix*, под разработчиков с опытом администрирования и root-правами, то это было бы уже совсем другая статья и возможно статья нафиг никому не нужная!
А под виндовс кстати может хоть 10 процессов одной и той же программы быть запущено и у каждой будет свой pid

Угу, а под *nix'ами? У всех один? :D
Ну, ей-богу… Окститесь и почитайте… Каждый программер, имхо, хоть раз в жизни, да писал демоны, и вам тоже нужно пройти этот этап. Не воспринимайте все в штыки, просто поизучайте…
Кстати, в windows есть kill. И под вашу задачу перезапуска скрипта обычно используют kill -HUP. И как же интересно вы будете принудительно стопить зависший демон без килла? Ждать когда лимиты ваш демон превысит?
Более того, даже бог с ним, оставляйте свой «стоп файл», но теперь-то прочитав про pid-файлы, уберите свои убогие .works файлы, и используйте нормальные pid-файлы. Информация в них все равно лишняя — время запуска скрипта определяется по дате создания pid-файла.
Принудительно в процессе выполнения нельзя ничего стопить.

И да, если демон подвис, тогда ждать когда он превысит лимиты времени на каждую итерацию, что в контексте «примера» — всего 16 секунд.

И если я реализовал бы всё на .pid файлах, то 95% разработчиков просто не смогли бы её использовать т.к. статистически root-доступом в наше время располагает крайне маленький процент.
1) «если демон подвис» он у вас бесконечно будет висеть, до тех пор пока rlimit'ы не превысит, если они установлены.
2) откуда такая замечательная статистика про 95%?
3) откуда такая уверенность, что нужны права root'а для kill'a? «Я тебя породил», значит я тебя могу и убить.
4) да хотя бы свои замечательные .works убрали бы.
1) У меня на каждой итерации ставится лимит на процесс через set_time_limit равный максимальному лимиту отведённому на одну итерацию. Вы даже не разобрались как scriptAlone работает.

2) От хостинг-провайдера, и соотношения между VDS/Colocation аккаунтами и VPS.

3) Ага, а сам вызов kill вы каким местом будете делать, когда у вас даже на это прав нету?

4) Лично мне они не мешают, я по крайней мере могу хранить их в тех папках, на которые у меня права записи есть
Прочитайте, например, это habrahabr.ru/blogs/php/40432/
Затем, если вы все также упорны в своем желании дайте мне VPS, где я якобы могу плодить демоны и не могу их убивать и я напишу. И заодно напишите, чем отблагодарите кроме очередных малодушных претенциозных минусов.
В общем вы так некрасиво признаете свою неправоту. С вами все ясно.
Слушайте, что вам от меня надо? :)

Я действительно только вчера узнал, что VDS и VPS это разные вещи. Думал, что VPS это virtual shared хостинг.

В конце концов VDS — virtual dedicated server — дэдик по нашему. А VPS я думал — противоположное ему т.к. нафига одно и то же двумя разными словами называть?))
И вообще, что за идентификация процесса по имени скрипта? А если один скрипт с разными параметрами? Поизучайте, что такое демоны вообще.
А если один скрипт с разными параметрами, то генерируйте соответствующие уникальные имена state-файлов, это в общем совсем не сложно.

А насчёт «идентификации процесса по имени скрипта» какие притензии? У моих процессов есть PID, см.



см. текст Примера в статье:
PID: 12656471471193231407
Started: 2010-02-08 19:39:07
Worked: 2010-02-08 19:39:10
Expire: 2010-02-08 19:39:26


И кстати, в /var/run сервера имена .pid файлов тоже не случайный хеш, а название процесса. Так вы уже и на линукс-разработчиков наезжаете, что они .pid файлы так соответственно называют?
Я удивляюсь… Вы таки удосужились хоть немножко прочитать что такое pid-file? Я вообще-то как раз и советую пользоваться pid-файлами! По-поводу именования же pid-файлов, вам стоит узнать как запускают по два и более экземпляров демонов. Вообще погуглите на слово daemonize.
Да знаю я всё это, вот только что вы то не поймёте, что не актуально мне решение работающее только на серверах где root-доступ есть.

Не нужны мне .pid-файлы и pcntl т.к. не собираюсь я позволять прочим (не-php) процессам мои псевдо-демоны стопорить.

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

Я не хуже вашего понимаю и могу реализовать эту библиотеку на .pid & pcntl, но я не хочу этого делать, мне это не надо, это не даёт ничего кроме как дополнительного ограничение на использование её только под теми серверами, под которыми у меня есть root-доступ.

Вам хочется на .pid & pcntl всё переписать — перепишите :)
А вас потом попросят на VPS-хостинге что-нибудь аналогичное сделать и вы поднимете этот топик и скачаете scriptAlone))))
Ого, и за минус в карму отдельное спасибо… Ну что ж… от добра добра не ищут…
Читайте <a href=«habrahabr.ru/blogs/php/83506/#comment_2491031'>этот коммент и не дурите голову.

Возможно не я один тут с вами не согласен.

Меня вообще честно говоря больше интересует статистика скачиваний библиотеки, чем ваши комментарии. Для меня эта статистика более показательный фактор того, что библиотека вполне адекватна.
«библиотеку» вашу смотрят, и врядли хоть кто-нибудь будет ее использовать.--
По моему вы не совсем понимаете тему о которой пишете, вам люди объясняют что вы изобрели пятиколёсный велосипед, а вы упираетесь. Почитайте www.php.net/manual/en/refs.fileprocess.process.php, тут ведь сами разработчик, за вас, позаботились об этом…
Вы комментарии читали? Я уже много раз ответил на все такие вопросы.

Всё я понимаю. Вы мне что предлагаете экстеншены использовать, системные вызовы на уровне ОС? А представьте, что у меня нет такой возможности. Что у меня VPS хостинг и прав нет на такие выкрунтасы.

Вы напишите альтренативный вариант на pcntl и выложите, посмотрим какой процент людей его использовать возьмётся, когда у них прав доступа не хватит, даже чтобы example вашей библиотеки запустить.
Ммм… я посмотрел в википедии определение VPS и выяснил:

Каждый VPS имеет собственную копию системы, с правами доступа уровня root (UID: 0) для Unix или Administrator для Windows, что позволяет производить компиляцию, установку собственного программного обеспечения с изменённой конфигурацией.
И правда)))

Я то думал, что VPS это сокращённое название virtual-shared хостинга! Ну, теперь увы комменты не подправить… так что просто учитывайте где я писал про VPS имелось в виду shared virtual хостинг.

Спасибо за поправку!
Я не программист, поэтому когда мне надо было решить аналогичную задачу, при помощи функции touch() создавал сигнальный файл, наличие которого служило индикатором того, что процесс был запущен.

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

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

Скрипт должен перезапускаться каждые 5-10 часов, чтобы предотвратить возможные утечки памяти. Остановка скрипта в этом случае должна производиться безопасным образом (когда задачи текущей итерации выполнены).

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

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

Принудительно остановить — да, не делал такого, тоже не было необходимости.

Из требований к моему скрипту: работа на шаред-хостингах, где не всегда есть права на запись (разные хостинги, разные юзеры), но есть мускуль (вордпрессовский плагин писал), а еще есть таймлимит.

Это версия плагина Parasie Eliminator, которую я сейчас переписываю. Та надо проверять базу каментов по базе спамерских урлов и сигнатур. Базы того и другого могут быть большими весьма, а хостинги — шареды. Вот базу надо проверять по кускам, при этом не допустить перерасхода ресурсов шареда.

Для этого и делал свой костыль :)
У меня, кстати, в разработке еще решение смешанное было, чтобы параллельно запущенные копии скрипта проверяли разные куски БД.
Неплохо!

Но странно, что это за shared-хостинг такой, который прав на запись не даёт. Даже не знал, что такие бывают.

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


На самом деле, лучше чтобы скрипт завершался в перерывах между итерациями, а не когда у него time_limit закончится. А то представьте если у вас не транзакционная БД и скрипт остановится в промежутке между выполнением двух запросов (UPDATE / INSERT) одного сценария. Целостность БД может пострадать и сайт перестанет работать.
Бывают сочетания шаред-хостингов и владельцев, при которых чудесным образом не получается записать сигнальный файл. Сам бы не подумал, если бы не бета-тестирование. Вариант с файлом работает гораздо быстрее, но БД — у всех (без БД не бывает блогов на «Вордпрессе»).

Чтобы не страдала БД, я скрипт заставил работать небольшими кусочками.

Была мысль получать значение таймлимита, затем определять, сколько уже прошло времени и, исходя из этого, брать размер задачи (проверка идет в то время, которое остается от таймлимита после окончания формирования основной части страницы блога для пользователя).
Принудительную остановку можно, кстати, сделать через создание стоп-сигнального файла :)
В scriptAlone так и сделано :)
Sign up to leave a comment.

Articles