Блокировка выполнения PHP-скрипта (cron, lock)

korwru

Новичок
Здравствуйте!

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

Запуск осуществляется по cron'у 1 раз в 1 минуту.
Скрипт импортирует каталог товаров, создаёт/изменяет разделы и теоретически он может не успеть выполниться в отведённое время.

1) Прописать set_time_limit(0); - не вариант.
2) Планировал создавать lock-файл, но похоже чего-то недопонимаю. Кому интересно - обсуждение было тут
 

Вурдалак

Продвинутый новичок
PHP:
<?php

$fh = fopen(__FILE__, 'r');

if( ! flock($fh, LOCK_EX | LOCK_NB) )
{
    die('Script is already running');
}

// ...
?
 

weregod

unserializer
Вурдалак
годное, если не нужно ломать локи от случайно вошедшего в вечный цикл предыдущего скрипта :)
 

korwru

Новичок
Спасибо!

Также на форуме нашёл высказывание:
$lockfile = fopen("lock.txt", "a+");
if (!$lockfile || !flock($lockfile, LOCK_EX | LOCK_NB)) die("Бот уже запущен…");
Правда и с ним не обошлось без проблем: если запускать cron посредством php, то он каждую минуту по запуску создает кучу незакрытых процессов, и в конце концов вешает сервер. Я просто в кроне изменил задание, чтобы он запускал бота по URL путем wget...
Правильно ли я понимаю, чтобы подобное не случилось, в конце файла нужно закрыть процессы следующим образом:
PHP:
flock($lockfile, LOCK_UN);
fclose($lockfile);
 

zerkms

TDD infected
Команда форума
Спасибо!

Также на форуме нашёл высказывание:


Правильно ли я понимаю, чтобы подобное не случилось, в конце файла нужно закрыть процессы следующим образом:
PHP:
flock($lockfile, LOCK_UN);
fclose($lockfile);
Неправильно. Говорили как раз о том, что в случае, если у вас скрипт где-то "зависнет" в середине скрипта - тогда до конца файла он не дойдёт, соответственно блокировку не снимет
 

Linker

Новичок
А ведь совсем не обязательно блокировать сам исполняемый файл.
Можно при запуске скрипта Cron'ом проверять, есть ли определённый файл и если нет - создавать пустой файл (не важно как называется, как удобно)
а затем скрипт дальше делает, что там нужно и по окончанию работы файл удаляет.
А если файл есть, скрипт ничего не делает - die или exit

Если по времени критично, то вообще стоит сделать файл очереди, в котором будут помечаться этапы выполнения скрипта,
Т.е. Cron запускает скрипт, скрипт читает файл очереди, и продолжает, если есть что продолжать или, если предыдущий запуск отработал до конца, начинает заново.
Как-то так.

P.S. Поторопился и не прочитал, что у вас по ссылке
А в чём проблема? Может просто путь не правильно указан? Всё должно быть нормально.
 

zerkms

TDD infected
Команда форума
Linker
Вот для того, чтобы не писать такую лапшу, которую предложили вы - и придумали flock()
 

Linker

Новичок
А ну да, у топикстартера проблема видимо, из-за вывода эха, да ещё под виндами... Это я поторопился.
Но подход с созданием пустого файла в никсах всегда успешно использовался, почему "лапша"?
Есть определённый файл - exit
Нет файла - работаем.
 

zerkms

TDD infected
Команда форума
Linker
Лапша - потому что if(file_exists()) & touch() не атомарны.

Поэтому и нужно:

Не получили эксклюзивный лок - выходим
Получили эксклюзивный лок - работаем
 

Linker

Новичок
Да, ещё clearstatcache() потребуется...
Тогда сливаюсь, flock - надёжнее.
 

Dovg

Продвинутый новичок
У fcron есть защита от одновременного запуска искаропки.
 
Сверху