Предотвращение запуска нескольких копий скрипта

AlexeyD

Новичок
Предотвращение запуска нескольких копий скрипта

Есть некий скрипт, который выполняется достаточно долго. Типа поискового бота, если хотите. Этот скрипт должен выполняться только в единственном экземпляре. Т.е. при запуске этого скрипта должно проверяться - если скрипт уже запущен - то не продолжать его выполнение. Как это лучше организовать? Через создание файла-флага мне не подходит. Уверен, что не единственный вариант.

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

Можно как либо это сделать по PID ? Ну и вообще ваши советы по решению проблемы хотелось бы услышать.
 

Andreika

"PHP for nubies" reader
>Через создание файла-флага мне не подходит.
не подходит потому, что... ?

>Можно как либо это сделать по PID ?
у скрипта нет pid )
не ос не указал, ни как скрипт запускается.. ни зачем ему вообще http-сервер (раз уж апач упомянул)
 

AlexeyD

Новичок
Если делать через флаг (вернее у меня сейчас уже так сделано) - то по завершении работы скрипта, как водится, этот файл надо прибивать. Разумеется нельзя допустить ситуацию, когда скрипт завершит работу, а файл останется. Сейчас прибитие файла сделано через register_shutdown_function, но я хочу откзаться от ее использования, так как есть некоторый печальный опыт - иногда когда пытаются запуститься несколько копий одновременно, сервер падает. Всмысле не http сервер, а вообще весь сервак - виснет ОС (FreeBSD).

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

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

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

AlexeyD

Новичок
да, забыл. скрипт запускается через
/usr/bin/nice -n 20 /usr/local/bin/php path_to_script/script.php
(это его так крон запускает), но помимо этого пользователь может запустить его через http запрос. Вот в этом случае тут апач очень даже причем. Т.е. в этом главная задача - не дать пользователю запустить его, если он уже запущен кроном. И наоборот - если запустил пользователь - то крон должен покурить.
ос - FreeBSD

-~{}~ 22.03.06 16:42:

Автор оригинала: Andreika
[m]flock[/m] ?
обижаешь :)
все лочится. и все работает везде, кроме этого скрипта.
тем более что незалоченный файл может побиться - да, но не повесить ОС.
 

Andreika

"PHP for nubies" reader
AlexeyD
я не понял каким боком там shutdown_function, прибитие файла, блокировки вместе с flock оказались... да еще и сервер падает %)
в общем первый абзац не понял

есть еще [m]sem_get[/m] сотоварищи... но местная реализация чет не позволяет применить его для "запрещения" второй копии
 

AlexeyD

Новичок
ну каким боком...
файл надо прибивать, так? чтобы 100% независимо от того как завершился скрипт этот файл прибился я его удаление запихал в register_shutdown_function.
вот и сдается мне что эта функция реализована как то чересчур низкоуровнево чтоли, и в моей конфигурации это вызывает падения сервера. что тут не понятного? вот хочу сделать это как то по другому, чтобы отказаться от нее вообще.

но просто в конце файла unlink($file) не поставишь же, правильно? скрипт может завершиться и не дойдя до конца. только не надо советовать вместо exit использовать свою функция выхода, где перед exit делать unlink, так как скрипт может завершиться и другими способами, например тот же таймаут апача. да мало ли что может произойти, а файл нужно прибивать всегда.

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

вот например getmyinode() - это что? разве это не уникальный идентификатор скрипта? может опереться на него при определении запущен скрипт или нет?
 

Andreika

"PHP for nubies" reader
>файл надо прибивать, так?
зачем прибивать? достаточно разлочить... если этот файл используется только как блокировка, а не для каких либо еще секретных целей
код этой блокировки покажи плиз

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

AlexeyD

Новичок
всё, я понял как надо сделать.
блокировка - это вообще в никсах понятие весьма условное. уже был опыт когда билась база на текстовых файлах, да и обычные примитивные счетчики с использованием блокировки бьются влет на большом трафике.
код блокировки стандартный:
$f = @fopen($filename,$mode);
if(@flock($f,LOCK_EX))
{
fputs($f,$data);
flock($f, LOCK_UN);
fclose($f);
@chmod($filename,0666);
return true;
}
@fclose($f);
return false;

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

я понял, что выполняется ли какая то копия скрипта или нет извне узнать невозможно. я думал что можно как то идентифицировать скрипт, типа как получить ID процесса.
Но я нашел альтернативный вариант без использования shotdown_function. Сейчас бум пробовать.
 

bgm

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

Tor

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

как получить ID процесса.
он каждый раз разный

я понял, что выполняется ли какая то копия скрипта или нет извне узнать невозможно
список процессов для кого придуман?
даже если есть какие-то уникальные данные - ты их наружу (другому скрипту) не передашь... и у любого работающего в системе чужого скрипта не возьмешь
100+1 способ
 

Andreika

"PHP for nubies" reader
Tor
>100+1 способ
напиши плиз хотя бы 10ку способов (не считая вышеуказанных), которые будут к тому же соответствовать задаче
 

Tor

Новичок
напиши плиз хотя бы 10ку способов (не считая вышеуказанных), которые будут к тому же соответствовать задаче
а не много будет?
файлы, база, семафоры, разделяемая память, сокеты

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

кстати, как ты создаешь файл с "заданным временем жизни"?
 

Andreika

"PHP for nubies" reader
Tor
ты обещал 101.. хватило тебя на... эээ..
файл - не считаем, было
семафоры - можно пример использования, в котором проверяется доступность семафора, без попытки завладеть им?
разделяемая память? а что в нее записать?
а в базу что?
сокеты - тоже примерчик бы :)

в общем вместо 101 пока получилось 0.5
 

bgm

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

кстати, как ты создаешь файл с "заданным временем жизни"?
Заметил-заметил.

Самый простой вариант - время жизни указывать в названии файла, после заданного префикса, а при запуске скрипта удалять те файлы-флаги, время жизни которых истекло. Время жизни можно хранить в самом файле. Ит.д. Этот же вариант легко реализовать на базе.
 

Tor

Новичок
время жизни указывать в названии файла, после заданного префикса, а при запуске скрипта удалять те файлы-флаги, время жизни которых истекло
как это предотвращает повторный запуск?
 

bgm

 
Автор оригинала: Tor
как это предотвращает повторный запуск?
А подумать?

P.S. В очень грубом приближении. В начале работы скрипта проверяем наличие файла-флага с неистёкшим временем жизни. Если есть - скрипт заканчивает работу. Если нет - удаляем все файлы-флаги, создаём новый файл-флаг и скрипт отрабатывает. А в процессе работы необходимо время жизни флага обновлять (скажем - один раз в минуту, к примеру).
 

Tor

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

bgm

 
Автор оригинала: Tor
т.е. ситуация, когда срипт работает (висит и т.д.), но файл новый не создал (не успел, место закончилось и т.д.) не рассматривается ввиду недостаточности умственных способностей?
Отвечу Вам исключительно в последний раз: если Вы внимательно прочитаете мои реплики, то встретите слова "простой вариант", "в грубом приближении" и т.д. Учитесь вежливости.
 
Сверху