Запуск только одной копии скрипта

Bermuda

Новичок
Запуск только одной копии скрипта

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

Очевидно, что можно оставлять метку "я живой" в (файле/базе данных) с информацией о последнем времени активности скрипта. Если эта метка устарела, то следовательно нет ни одной запущенной копии скрипта. Однако процесс конвертации видео с точки зрения скрипта атомарен и скрипт не получит контроль до тех пор, пока ffmpeg не закончит свою работу. Так как конвертация больших файлов видео (100-200 M) может занимать продолжительное время, то скрипт вследствие невозможности обновить метку "я живой" не будет обнаружен как запущенный и крон запустит его копию, которая в свою очередь также примется конвертировать видео, что приведет к уменьшению скорости (увеличению времени) кодирования в два раза, что в свою очередь приведет к запуску еще одной копии скрипта и т. д. то тех пор пока сервер не помрет. Конечно можно fork-нуть процесс кодирования и потом в цикле ждать сигнала о завершении от child-а, но мне кажется, что это как-то сложно. Должно быть более простое решение.

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

Андрейка

Senior pomidor developer
Очевидно, что можно оставлять метку "я живой" в (файле/базе данных) с информацией о последнем времени активности скрипта.
это реально самое очевидное решение? зачем нужны данные о времени?
 

Bermuda

Новичок
Автор оригинала: Андрейка
зачем нужны данные о времени?
Намек понял. Само наличие lock-а будет говорить о том, что скрипт исполняется. По окончании работы скрипта предпологаетя удаление lock-а. Однако если по неведанной причине работа скрипта будет прервана, то потребуется вмешательство пользователя для удаления lock-а, что не есть хорошо. Более того хотелось бы проверять прямые признаки того, что копия скрипта запущена. Lock - это косвенный признак.

-~{}~ 08.03.07 11:26:

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

Андрейка

Senior pomidor developer
Lock - это косвенный признак.
чет причинноследственная связь хромает

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

phprus

Moderator
Команда форума
то потребуется вмешательство пользователя
Можно применять Lock-файл который на время работы скрипта будет блокироваться при помощи [m]flock[/m] (режим LOCK_EX) А чтобы определить работает ли еще одна копия нужно попробовать еще раз заблокировать этот файл. Если удалось то это единственная копия, если нет, то есть еще один процесс.

В случае смерти php файл автоматически разблокируется.
 

Bermuda

Новичок
phprus
Как вариант, но
flock() не будет работать на NFS и многих других сетевых файловых системах. Обратитесь к документации вашей операционной системы для получения дополнительной информации.
Скорее всего видео с нескольких Apache-в будет писаться в папку подключенную по NFS. Будет ли для cron-скрипта папка являться локальной или будет подключена по NFS я не знаю (и скорее всего не должен знать).

Посидел-подумал и нашел "интелектуальное" решение. Когда ffmpeg конвертит видео в *.flv то в папке назначения появляется конечный flv фай размер которого меняется по мере работы ffmpeg. Значит в самом начале скрипта делаем листинг всех файлов *.flv, считаем суммарный размер, потом немного ждем и снова считаем суммарный размер. Для надежности процедуру можно повторить N раз в течение M секунд. Если размер не изменился, значит никто никуда ничего не пишет, если изменился, то гордо отваливаем до следующего раза.
 

serglt

Анус, ой, Ахтунг
Самое простое это сделать скрипт на шеле, запустить его в фон, а в нем вечный цикл { запуск твоего скрипта; sleep (время перекура)}

-~{}~ 08.03.07 18:54:

Еще вариант через пользовательскую блокировку в базе (GET_LOCK())
 

Bermuda

Новичок
serglt
А во всех операционных системах есть шел?
Один и тот же скрипт "на шэле" будет одинаково работать в них?
 

phprus

Moderator
Команда форума
Bermuda
и скорее всего не должен знать
А тебе и не нужно это знать. Создавай специальный Lock-файл непосредственно в файловой системе сервера и уже его блокируй.

Посидел-подумал и нашел "интелектуальное" решение.
Это не "интелектуальный", а очень ненадежный и рессурсоемкий метод.

serglt
Самое простое это сделать скрипт на шеле
Какой в этом смысл? flock то гораздо проще использовать.
 

Bermuda

Новичок
Создавай специальный Lock-файл непосредственно в файловой системе сервера
Понял. Я протормозил.

А решение таково:
PHP:
$files = scandir($dir);
$total_size = array();
$start_time = time();

do {
    $size = 0;
    foreach ($files as $file) {
        preg_match("/.*\.(.{2,})/", $file, $res);
        if ($res[1] == "flv") {
            $size = $size + filesize($dir . $file);
        }
    }
    $total_size[] = $size;
    sleep($time_to_sleep);
} while ((time() - $start_time) < $time_to_check);

sort($total_size);
reset($total_size);
$min = current($total_size);
$max = end($total_size);

if ($min != $max) {
    echo "Concurrent processing!";
    exit();
}
Если нагрузка будет велика то sleep можно увеличить, проверять будет реже.
 

serglt

Анус, ой, Ахтунг
phprus
Я молчал.. Бо с лочками были посты. А товарищ сообщил что у него NFS где лочка нихт фунципуклирен

Шел есть не во всех, но и ты тож, хорошо, соблюдай правила форума, ОСЬ пиши!

Да некоторые хосты не поддерживают процессы в фоне (тож не оповещено) (поломана система оповещения похоже).


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

PS. вопрос по теме "с какой стороны к девушке подлечь" - ответ №1: "Справа". Стартер: "не подходит" Вопрос: "поечему?" Ответ стартера "у нее нога левая болит.."

PS. праздник удался :)
 

MiksIr

miksir@home:~$
Что за крон используется? Кроны некоторые сами умеют это разруливать.
 

Bermuda

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

camka

не самка
Вариант для shell:
Код:
if [ "$(/sbin/pidof -x $(basename "$0"))" != $$ ]; then
	echo "$0: Only only instance of the script is allowed to be running at a time, exiting..."
	exit 1
fi
 

serglt

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

PS. по поводу - специально для меня.
А кроном в винде ты планировщик задач называешь? Или я что то упустил из операционной системы Windows?
 

phprus

Moderator
Команда форума
serglt
Я молчал.. Бо с лочками были посты. А товарищ сообщил что у него NFS где лочка нихт фунципуклирен
Лок-файл надо создавать В ФАЙЛОВОЙ СИСТЕМЕ СЕРВЕРА и про это я писал. Не вся вайловая система сервера примонтирована через NFS, а значит flock можно использовать. Если конечно сервак не под 98 виндой с файловой системой ФАТ.
 

serglt

Анус, ой, Ахтунг
phprus
Согласен, если в кроне одного сервера, запускается скрипт.
 

phprus

Moderator
Команда форума
Bermuda
Я понял, что вы меня поняли, а вот serglt похоже в начале меня понял не совсем правильно.

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