Народ подскажите как лучше сделать синхронизацию.
Есть перл скрипт, который занимается обработкой неких данных. На обработку данных уходит от 10 сек до минуты. Во время работы скрипта может быть запущена еще одина копия скрипта. Необходимо сделать так чтоб скрипт начинал обработку данных, если только предыдущий запуск скрипта завершил обработку.
сейчас у меня сделанно следующим образом.
#вначале скрипта
$var="run";#делаем чтоб цикл while выполнился хотя один раз
while($var eq "run"){# ждем пока предыдущий скрипт завершит обработку
open(RUN,"<runfile");
$var=<RUN>;#запихиваем содержимое файла в переменную
close RUN;
}
$var="run";
open(RUN,">runfile");#переписываем содержимое файла
print RUN $мфк."\n";#пишем строку "run" скрипт начал обработку
close(RUN);
#
.....
#
#вконце скрипта
$var="notrun";
open(RUN,">runfile"); #переписываем содержимое файла
print RUN $var."\n";
#пишем строку "notrun" скрипт закончил обработку
close(RUN);
Мне кажется что работать с файлами не очень хорошо. Поскольку это замедляет работу скрипта.
Может кто предложит другой способ, более "красивый";
А это. Семафор разве нельзя? Вроде есть такое в перле...
>$var="run";#делаем чтоб цикл while выполнился хотя один раз
Если паскаль прет во все щели при чем здесь PERL?
НАЧАЛО ПРОГИ
if (-e lock.file)
{
die "прога уже запущена\n";
}
else
{
`touch lock.file`
}КОНЕЦ ПРОГИ
unlink lock.file;что-то типа этого! создаеш лок файл в начале програмки, если он уже существует програма делает екзит, если нет то создает локфайл! в конце проги удаляеш его!
может я и не прав, может есть и более простые решения!
С .lock файлами все очень хорошо но еать одно изящное решение:ps -aux | grep $AAA | grep -v grep | wc -l
результат количество запущенных процессов с именем $AAAA если !=1 то exit :)
Для читоты выполнения, в начало добавляем
@a=split /\//,$0;
### теперь $a[$#a] - 'чистое' имя запущенной программы, без путей.
### print $a[$#a]."\n";ps -aux | grep $a[$#a] | grep -v grep | wc -l
@a=split /\//,$0;кстати как мзящно снять результат работы :
ps -aux | grep $a[$#a] | grep -v grep | wc -lчто-то красиво не получается.
die if ${\scalar(` ps uaxw | grep $0 | grep -v grep |wc -l`)} > 1;можно сделать так! хотя я не любитель исспользования внешних прог!
"#!/usr/bin/perl -wT" - вот эелательная для использования строка, именно с такими ключиками!
>die if ${\scalar(` ps uaxw | grep $0 | grep -v grep |wc -l`)} > 1;
>
>можно сделать так! хотя я не любитель исспользования внешних прог!
>"#!/usr/bin/perl -wT" - вот эелательная для использования строка, именно с такими ключиками!
>Решения действительно изящны тока вот...
#!/usr/bin/perl
die if ${\scalar(' ps uaxw | grep $0 | grep -v grep |wc -l')} > 1;
sleep (100);
не работает, удается запустить подряд несколько копий.
тоже самое
#!/usr/bin/perl -wT
sleep (100);
странно :) теоретически должно работать :) значит надо вернуться к старым-добрым лок файлам :)
нет от файлов надо отказываться... глючат инногда...open(cmd, ' ps -a | grep $0 | grep -v grep -|');
while (<cmd>){
print $_."==\n";
}
так работает а вот так :
open(cmd, ' ps -a | grep $0 | grep -v grep | wc -l -|');уже нет.
Можето кто поможет ... поелчит...
вот еще вариант(знакомый прислал):my $line;
open (PS,"/bin/ps -axo 'pid,command'|");
while ( defined ( $line = <PS> )) {
chomp($line);
if ( $line =~ m#(\d+) /usr/bin/perl -w .*$SCRIPTNAME# )
{
if ($$ != $1) {
if ( $debug ) {
print "Another instance of script exists. Quiting\n";
};
exit;
};
};
};
close(PS);
>НАЧАЛО ПРОГИ
>if (-e lock.file)
>{
>die "прога уже запущена\n";
>}
>else
>{
>`touch lock.file`
>}
>Не будет это работать.
Между '-e lock.file' и 'touch lock.file' может
быть переключение на другой процесс, который также хочет
этот lock, а поскольку lock.file еще не создан, они оба
получат доступ.Про упражнения с записью "run" в файл я уж помолчу...
Проще всего в perl пользоваться flock.
да ну вы чего :) юзайте лок файлы и будет счастье :) все остальное - бред имхо! да ил лок файлы самое надежное!
>Народ подскажите как лучше сделать синхронизацию.
>Есть перл скрипт, который занимается обработкой неких данных. На обработку данных уходит
>от 10 сек до минуты. Во время работы скрипта может быть
>запущена еще одина копия скрипта. Необходимо сделать так чтоб скрипт начинал
>обработку данных, если только предыдущий запуск скрипта завершил обработку.
>сейчас у меня сделанно следующим образом.
>#вначале скрипта
>$var="run";#делаем чтоб цикл while выполнился хотя один раз
>while($var eq "run"){# ждем пока предыдущий скрипт завершит обработку
> open(RUN,"<runfile");
> $var=<RUN>;#запихиваем содержимое файла в переменную
> close RUN;
>}
>$var="run";
>open(RUN,">runfile");#переписываем содержимое файла
>print RUN $мфк."\n";#пишем строку "run" скрипт начал обработку
>close(RUN);
>#
>.....
>#
>#вконце скрипта
>$var="notrun";
>open(RUN,">runfile"); #переписываем содержимое файла
>print RUN $var."\n";
>#пишем строку "notrun" скрипт закончил обработку
>close(RUN);
>Мне кажется что работать с файлами не очень хорошо. Поскольку это замедляет
>работу скрипта.
>Может кто предложит другой способ, более "красивый";Hi,
I'm not a perl guy, but procmail has lockfile command-line utility which is very convinient to use from shell scripts. I'm not sure though if it is bulletproof solution. Never saw it's source code :(
Also I'm positive other people already did that using plain perl
Thanks
--- Sas
Попробуй вот что! Я не смог запустить больше 1 экземпляра! Скажи че получится, самому интересно!
#!/usr/bin/perl -wTuse Fcntl;
sysopen (FH, "file.lock", O_WRONLY|O_EXCL|O_CREAT) or die "can't run script!\n";
print FH $$;
close FH;print "\n\n+++ RUUUUUUUUUUUUUUN +++\n\n";
>use Fcntl;
можно даже use Fcntl qw(:DEFAULT :flock);
#!/usr/bin/perl -wuse Fcntl;
@a=split /\//,$0;
sysopen (FH, "/tmp/$a[$#a].lock", O_WRONLY|O_EXCL|O_CREAT) or die "Script alredy running!\n";
print FH $$;
close FH;{
# programm codesleep (100);
}system "rm $a[$#a].lock";
exit();
Да можно сделать и так. только вот беда. при выпадании скрипта , т.е. если его убить принудительно файл остается и заново запустить скрипт нельзя.
Я постараюсь свормклировать требования:
Скрипт запускается проверяет что других его копий не работают.
обрабатывается и завершает работу. При падении скрипта-системы и последующего запска скрипта, проверив что запущенных копий нет, обрабатывается полноценно.Про flock вот что я слшал: что"наложение flock" снимается системой при авварийном завершении скрипта.
поэтому я пологаю надо взять любой файл (лучше чтоб он назывался также как и скрипт+".lock") залочить его и все, а при завершении скрипта система сама его "разлочит". Рекомендовали копать в этом направлении.
Буду копать, если кто "откопает" раньше просьба поделиться :)
А пока самый действенный и самый простой способ вот :
#!/usr/bin/perl
my @a=split /\//,$0;
my $script_count=0;
open (PS,"/bin/ps -axo 'pid,command'|");while ( <PS> ) {
if ( $_ =~ m/$a[$#a]/ )
{ $script_count+=1;
if ( $script_count > 1) {
print "Script copy alredy running\n";
exit();
};
};
};
close(PS);## ...
## script code ...
## ...
С локами должно нормально рабоатть
Вот работающий кусок:
#!/usr/bin/perl -w
use strict;
use Fcntl qw(:DEFAULT :flock);#Процедура проверки второго запуска и установки lock-файла, если первый запуск
sub test_ran($){
my $lockfile=shift;
if (-e $lockfile){
if (sysopen(FH, $lockfile, O_WRONLY) && flock(FH, LOCK_EX|LOCK_NB)){
return 0;
} else { return 1; }
}
sysopen(FH, $lockfile, O_WRONLY|O_CREAT) && flock(FH, LOCK_EX|LOCK_NB) || die $!;
return 0;
}my $lockfile="proga.lock";
if (test_ran($lockfile)){
print "уже запущен\n";
} else {
print "первый запуск\n";
1 while (1);
}
Я в таких случаях поступал так -
как правило, скрипт обрабатывает какие-то данные из какого-то файла(ов).
Можно ставить монопольный flock на него, даже если писать туда не собираешься. А при запуске ессно проверять, не залочен ли файл.
С lock файлами выглядит ненадёжно - например, если почему-то скрипт умрёт посередине, не удалив lock ?
Так вот говорят что если скрип слитает то "лоченность" с файла снимается..
установку лока отслеживает система, поэтому даже если файл остается, лок убирается системой после окончания работы скрипта
>установку лока отслеживает система, поэтому даже если файл остается, лок убирается системой после окончания работы скрипта
и это дело реализуется приведенным(выше) вашим скриптом?#Процедура проверки второго запуска и установки lock-файла, если первый запуск
sub test_ran($){
my $lockfile=shift;
if (-e $lockfile){
if (sysopen(FH, $lockfile, O_WRONLY) && flock(FH, LOCK_EX|LOCK_NB)){
return 0;
} else { return 1; }
}...
>>установку лока отслеживает система, поэтому даже если файл остается, лок убирается системой после окончания работы скрипта
>и это дело реализуется приведенным(выше) вашим скриптом?
>У меня это работает, скрипт убивался по SIGINT и по SIGKILL.