« Глюкофокс, он же фаерглюк | Гугл спалил очередную тему »
Все знают, что для автоматической работы различных скриптов, их надо как-то запускать, что обычно делается с помошью крона (cron). Допустим у вас есть скрипт, который должен запускаться каждую минуту и что-то делать. Если скрипт выполняется “мгновенно”, то думать не о чем – прописал его в крон и спи спокойно, но если скрипт делает что-то в течении долгого времени, тут появляется пара тонких моментов, которые надо учитывать.
Во-первых, если скрипт не успевает отработать за минуту, то через минуту запустится его вторая копия, ещё черед минуту ещё одна и т.д., пока скрипт не завесит вам сервер. Бороться с этим можно, выставляя какой-нибудь флаг при запущенном скрипте, например создавая какой-то файл. При запуске скрипт смотрит – есть ли файл, и насколько он “свежий”, если файла нет то можно работать, если он есть, но “старый”, то вероятно скрипт запустился, создал файл и вылетел по ошибке, то есть не смог стереть файла, значит опять же можно работать. Если файл есть и он “свежий”, значит запущена копия скрипта и надо просто выйти.
Во-вторых, для более оптимального использования ресурсов, надо прерывать долгий скрипт так, чтобы он выходил (и сбрасывал флаг) ровно перед тем как будет запущена следующая копия. Иначе если у вас скрипт скажем работает по 70 секунд, а запускается из крона каждую минуту, то почти половину времени сервер будет простаивать.
9 Responses
September 29th, 2008 at 05:09:36
// php gravatar() ?>1ололо.
man 2 flock
а именно:
lock_fd = open(lock_path, O_RDWR);
if (lock_id == -1)
{
complain(“failed to open lock file %s, error is: %s”, lock_path, strerror(errno));
abort();
}
if (flock(lock_fd, LOCK_EX | LOCK_NB))
{
do_whatever_you_need();
flock(lock_fd, LOCK_UN);
}
else
{
if (errno == EWOULDBLOCK)
complain(“other process still has lock on %s”, lock_path)
else
complain(“failed to lock file %s, error is: %s”, lock_path, strerror(errno));
abort();
}
return 0;
трансляцию на похапе и ретрай на EAGAIN и EINTR думаю уже можно самому асилить.
September 29th, 2008 at 08:03:36
// php gravatar() ?>2Если уж создается “файл-флаг” для процесса, то удобно записать в него и идентификатор процесса, т.е. создать *.pid-файл, тогда можно не только проверить запущен ли скрипт, но и прибить его в случае слишком длительной работы.
September 29th, 2008 at 08:34:12
// php gravatar() ?>3Я почему-то думал тут увидеть способы запуска крона, параметры там и т.п.
September 29th, 2008 at 10:36:37
// php gravatar() ?>4Вообще в скрипте можно смотреть список запущенных процессов, и если копий скрипта запущено больше одной – просто завершать работу скрипта.
September 29th, 2008 at 12:02:09
// php gravatar() ?>5Офигенную тему спалил )))
Мне кажется что человек который не додумается сам даже создавать файл чтобы проверить работает ли скрипт, вряд ли сможет заниматься созданием вообще каких-то крон скриптов, да и вообще скриптов.
Кстати в если скрипт работает в линуксе то гораздо луче использовать встроенные в пхп семафоры: http://se.php.net/manual/en/book.sem.php
Да и вообще, для этого есть куча готовых классов, например как этот, работающий и в винде и в юниксах http://se.php.net/manual/en/ref.sem.php#72600
September 29th, 2008 at 12:30:22
// php gravatar() ?>6Ed и gman, вы бы примерчие для нас недалеких бы дали
типа такого на фаилах
$mdir=”/home/…”;
if (file_exists(“$mdir/running.flg”))
exit();
file_put_contents(“$mdir/running.flg”,”runing ept “.date(“D M j G:i:s T Y”));
function f_ex()
{
global $mdir;
unlink(“$mdir/running.flg”);
}
register_shutdown_function(“f_ex”);
September 29th, 2008 at 12:46:34
// php gravatar() ?>7Скрипт может запускаться из апача wget’ом, так что записывать и смотреть процессы это не универсальное решение. Как и семафоры, это не “гораздо лучше”, а как раз наоборот, поскольку их надо доставлять отдельно, то есть решение будет не универсальное.
September 29th, 2008 at 13:31:54
// php gravatar() ?>8Alexf, ты уж определись, что тебе надо. Пишешь пост про крон, тут упоминаешь про запуск wget’ом.
В любом случае, если тебе надо, чтобы число одновременно запущенных процессов не превышало заданного числа (не важно, один ли это процесс, запущенный по крону, или парсер, запущенный в 16 стволов по числу айпишников сервера), следует смотреть число выполняющихся программ, например, с помощью команды ps ax|grep
Решение с файлом не самое лучшее. Представь себе, запустил ты процесс, и он по какой-то причине пашет очень долго. Наступает момент запуска процесса (по крону, или wget-ом – неважно), процесс видит твой lock-файл и считает его уже устаревшим. Что он сделает? Правильно, удалит lock-файл и запустит второй экземпляр процесса.
to TerVer:
my @proc = `ps ax|grep parser.pl`;
if ($#proc == 1)
{
#do this dirty job
}
else
{
#exit
}
September 29th, 2008 at 14:25:41
// php gravatar() ?>9Ed, спасибо – то что нужно!
на php получилось вот так
$max_thr=3;
exec(“/bin/ps ax|/bin/grep “.__FILE__,$res,$err);
if ((count($res)-1)>=$max_thr)
exit();
Вообще с фаилами меня больше всего добивает что нужно править скрипты инициализации системы, т.е. удалять флаг-фаилы после ребута. Но от этого никуда не деться
RSS feed for comments on this post · TrackBack URI
Написать комментарий
Про что писал
Календарь
Куйворды
Архив
Подписка на блог
Статистика подписки
Страницы
Комментарии
Последние посты
Blogroll
Счётчики
Свежие записи
Последние комментарии
Интересное на блоге
Самое комментируемое
SEO блог где палят темы is proudly powered by WordPress - BloggingPro theme modified by alexf