URL: https://www.opennet.me/cgi-bin/openforum/vsluhboard.cgi
Форум: vsluhforumID9
Нить номер: 780
[ Назад ]

Исходное сообщение
"perl & синхронизация"

Отправлено gluxoi , 04-Июн-02 12:55 
Народ подскажите как лучше сделать синхронизацию.
Есть перл скрипт, который занимается обработкой неких данных. На обработку данных уходит от 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);
Мне кажется что работать с файлами не очень хорошо. Поскольку это замедляет работу скрипта.
Может кто предложит другой способ, более "красивый";

Содержание

Сообщения в этом обсуждении
"RE: perl & синхронизация"
Отправлено digital rain , 09-Июн-02 22:32 
А это. Семафор разве нельзя? Вроде есть такое в перле...

"RE: perl & синхронизация"
Отправлено pth , 16-Июн-02 22:19 
>$var="run";#делаем чтоб цикл while выполнился хотя один раз
Если паскаль прет во все щели при чем здесь PERL?



"RE: perl & синхронизация"
Отправлено sector119 , 16-Авг-02 13:35 
НАЧАЛО ПРОГИ
if (-e lock.file)
{
die "прога уже запущена\n";
}
else
{
`touch lock.file`
}

КОНЕЦ ПРОГИ
unlink lock.file;

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


"RE: perl & синхронизация"
Отправлено gara , 21-Авг-02 10:58 
С .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


"RE: perl & синхронизация"
Отправлено gara , 21-Авг-02 11:12 
@a=split /\//,$0;

кстати как мзящно снять результат работы :
ps -aux  | grep $a[$#a]  | grep -v grep | wc -l

что-то красиво не получается.


"RE: perl & синхронизация"
Отправлено sector119 , 21-Авг-02 11:56 
die if ${\scalar(` ps uaxw | grep $0 | grep -v grep |wc -l`)} > 1;

можно сделать так! хотя я не любитель исспользования внешних прог!
"#!/usr/bin/perl -wT" - вот эелательная для использования строка, именно с такими ключиками!


"RE: perl & синхронизация"
Отправлено gara , 21-Авг-02 12:11 
>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);


"RE: perl & синхронизация"
Отправлено sector119 , 21-Авг-02 12:27 
странно :) теоретически должно работать :) значит надо вернуться к старым-добрым лок файлам :)


"RE: perl & синхронизация"
Отправлено gara , 21-Авг-02 14:49 
нет от файлов надо отказываться... глючат инногда...

open(cmd, ' ps -a |  grep $0 | grep -v grep  -|');
while (<cmd>){
print $_."==\n";
}
так работает а вот  так :
open(cmd, ' ps -a |  grep $0 | grep -v grep  | wc -l  -|');

уже нет.
Можето кто поможет ... поелчит...


"RE: perl & синхронизация"
Отправлено gara , 21-Авг-02 15:50 
вот еще вариант(знакомый прислал):

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);


"RE: perl & синхронизация"
Отправлено idle , 23-Авг-02 22:36 
>НАЧАЛО ПРОГИ
>if (-e lock.file)
>{
>die "прога уже запущена\n";
>}
>else
>{
>`touch lock.file`
>}
>

Не будет это работать.

Между '-e lock.file' и 'touch lock.file' может
быть переключение на другой процесс, который также хочет
этот lock, а поскольку lock.file еще не создан, они оба
получат доступ.

Про упражнения с записью "run" в файл я уж помолчу...

Проще всего в perl пользоваться flock.


"RE: perl & синхронизация"
Отправлено sector119 , 22-Авг-02 13:24 
да ну вы чего :) юзайте лок файлы и будет счастье :) все остальное - бред имхо! да ил лок файлы самое надежное!

"RE: perl & синхронизация"
Отправлено sas , 24-Авг-02 06:00 
>Народ подскажите как лучше сделать синхронизацию.
>Есть перл скрипт, который занимается обработкой неких данных. На обработку данных уходит
>от 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


"RE: perl & синхронизация"
Отправлено sector119 , 24-Авг-02 19:25 
Попробуй вот что! Я не смог запустить больше 1 экземпляра! Скажи че получится, самому интересно!


#!/usr/bin/perl -wT

use 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";



"RE: perl & синхронизация"
Отправлено sector119 , 25-Авг-02 03:40 
>use Fcntl;
можно даже use Fcntl qw(:DEFAULT :flock);


"RE: perl & синхронизация"
Отправлено gara , 27-Авг-02 01:46 
#!/usr/bin/perl -w

use 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 code

sleep (100);
}

system "rm $a[$#a].lock";
exit();


Да можно сделать и так. только вот беда. при выпадании скрипта , т.е. если его убить принудительно файл остается и заново запустить скрипт нельзя.


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

Про flock вот что я слшал: что"наложение flock" снимается системой при авварийном завершении скрипта.

поэтому я пологаю надо взять любой файл (лучше чтоб он назывался также как и скрипт+".lock") залочить его и все, а при завершении скрипта система сама его "разлочит". Рекомендовали копать в этом направлении.
Буду копать, если кто "откопает" раньше просьба поделиться :)


"RE: perl & синхронизация"
Отправлено gara , 27-Авг-02 01:58 
А пока самый действенный и самый простой способ вот :


#!/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 ...
## ...


"RE: perl & синхронизация"
Отправлено Alex , 27-Авг-02 23:50 
С локами должно нормально рабоатть
Вот работающий кусок:
#!/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);
}


"RE: perl & синхронизация"
Отправлено illi , 28-Авг-02 14:54 
Я в таких случаях поступал так -
как правило, скрипт обрабатывает какие-то данные из какого-то файла(ов).
Можно ставить монопольный flock на него, даже если писать туда не собираешься. А при запуске ессно проверять, не залочен ли файл.
С lock файлами выглядит ненадёжно - например, если почему-то скрипт умрёт посередине, не удалив lock ?

"RE: perl & синхронизация"
Отправлено gara , 28-Авг-02 16:16 

Так вот говорят что если скрип слитает то "лоченность" с файла снимается..


"RE: perl & синхронизация"
Отправлено Alex , 28-Авг-02 17:47 
установку лока отслеживает система, поэтому даже если файл остается, лок убирается системой после окончания работы скрипта

"RE: perl & синхронизация"
Отправлено gara , 28-Авг-02 17:54 
>установку лока отслеживает система, поэтому даже если файл остается, лок убирается системой  после окончания работы скрипта
и это дело реализуется приведенным(выше) вашим скриптом?

#Процедура проверки второго запуска и установки 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; }
}

...



"RE: perl & синхронизация"
Отправлено Alex , 28-Авг-02 18:10 
>>установку лока отслеживает система, поэтому даже если файл остается, лок убирается системой  после окончания работы скрипта
>и это дело реализуется приведенным(выше) вашим скриптом?
>

У меня это работает, скрипт убивался по SIGINT и по SIGKILL.