Как предотвратить повторный запуск скрипта

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

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

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

<?php

// 8916 - случайный номер порта, выберите свой собственный, 
// какой вам больше нравится, но имейте ввиду, что он не должен
// быть занят какой-то другой программой на вашем сервере
$socket = stream_socket_server("tcp://0.0.0.0:8916", $errno, $errstr);
if (!$socket) {
	echo "Копия скрипта уже запущена!\n";
} else {
	
	/** Начало долгого скрипта **/
	
	//.....
	
	/** Конец долгого скрипта **/
	
	
	// Этой функции тут могло бы и не быть, поскольку
	// PHP автоматически закрывает все сокеты при завершении
	// скрипта
	socket_close($socket);
}

 

Работает этот код предельно просто: в самом начале выполнения он пытается создать сервер-сокет по фиксированному номеру порта. Система устроена так, что два сервер-сокета с одним и тем же номером порта открыть невозможно. Поэтому по успешности этого действия скрипт может сделать вывод о том — запущен ли уже такой же скрипт или нет.

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

На сегодня это всё. Программируйте креативно!

 

Подписаться
Уведомить о
guest
2 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
Arthur Yakovlev
9 лет назад

Круто, Алексей, думаю будет полезно! Я бы еще хотел почитать о том, как сделать кросс-браузерный плавный скролл колесиком. Полагаю это будет полезная информация, т.к. нормального готового решения я в нете не нашел, а думать иногда самому на проектах времени не хватает!

9 лет назад
Ответить на  Arthur Yakovlev

Вообще плавность скролла настраивается в системе, поскольку не всем пользователям нравится плавный скролл. Возможно, имеет смысл оставить это предпочтение пользователям.
Если же необходимо сделать плавное движение чего-либо, то можно использовать метод jQuery.animate(), которая позволяет задать автоматическое плавное изменение какого-либо параметра (например, координаты, яркости, прозрачности и т.п.).