Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / PHP, Perl, Python [игнор отключен] [закрыт для гостей] / (Perl) Как проконтроллировать, чтобы был запущен только один инстанс? / 23 сообщений из 23, страница 1 из 1
05.02.2014, 17:59
    #38550842
Alibek B
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
(Perl) Как проконтроллировать, чтобы был запущен только один инстанс?
Есть скрипт, который нежелательно запускать одновременно более одного раза.
В скрипте есть проверка на такой запуск:
Код: php
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
# Блок фиксации отметки о запуске скрипта, для предотвращения запуска второй копии.
$pidfile=$ps_logpath."pid.txt";
if (-e $pidfile) {
	unless (open(PIDFILE, $pidfile)) {
		#Если найден - то выходим
		open ($ps_file101,">>".$ps_repalllog) || die;
			print $ps_file101 $zver." Find previous PID: ".$oldpid." - exit\n";
			print $ps_file101 $zver." Update FINISH at ".formatdatetime("DD.MM.YYYY hh:mm:ss", time)."\n";
			print $ps_file101 "==============================================================\n";
		close $ps_file101;
		exit(1);
	}
	$oldpid=<PIDFILE>;
	close PIDFILE;
	if ($oldpid > 1 && kill(0,$oldpid)) {
		#Если найден - то выходим
		open ($ps_file101,">>".$ps_repalllog) || die;
			print $ps_file101 $zver." Find previous PID: ".$oldpid." - exit\n";
			print $ps_file101 $zver." Update FINISH at ".formatdatetime("DD.MM.YYYY hh:mm:ss", time)."\n";
			print $ps_file101 "==============================================================\n";
		close $ps_file101;
		exit(1);
	}
}
open(PID, ">$pidfile") or die;
	print PID $$;
close(PID);



Хочу сделать такую проверку лучше и по возможности без временных файлов.
Использую такой код:
Код: php
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
{
  use Fcntl ':flock';
  open my $self, '<', $0 or die "Fail on open self: $!";
  my $locked = flock($self, LOCK_EX | LOCK_NB);
  unless ($locked)
  {
    &log("Скрипт уже запущен, завершаю работу",'*');
    exit(1);
  };
}


Но он почему-то не работает.
Даже если заменить $0 на внешний файл, а режим открытия с '<' на '>' (у меня на отладке Windows, а тут про такой баг писали), все-равно не работает.
Что не так в коде?

________________________
Мы смотрим с оптимизмом...
...в оптический прицел.
...
Рейтинг: 0 / 0
05.02.2014, 18:10
    #38550858
Alibek B
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
(Perl) Как проконтроллировать, чтобы был запущен только один инстанс?
Alibek B.(у меня на отладке Windows, а тут про такой баг писали)
В Unix (FreeBSD), кстати, тоже не работает.
...
Рейтинг: 0 / 0
05.02.2014, 18:32
    #38550883
vkle
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
(Perl) Как проконтроллировать, чтобы был запущен только один инстанс?
На фряхе у меня такое работает:

Код: php
1.
2.
3.
4.
use Fcntl qw(:flock SEEK_END);
my $okfile = "/path/to/file.log"; # имя лог-файла, куда пишет скрипт...
open(OKF, "+>>$okfile") or die "Can't open $okfile: $!\n";
flock(OKF, LOCK_EX | LOCK_NB) or die "Can't flock $okfile: $!\n";
...
Рейтинг: 0 / 0
12.05.2014, 17:33
    #38639029
Alibek B
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
(Perl) Как проконтроллировать, чтобы был запущен только один инстанс?
Апну тему.
Снова потребовалось проверить, что скрипт не запущен дважды, и желательно без дополнительных файлов.
...
Рейтинг: 0 / 0
12.05.2014, 17:35
    #38639033
ScareCrow
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
(Perl) Как проконтроллировать, чтобы был запущен только один инстанс?
Alibek B.Апну тему.
Снова потребовалось проверить, что скрипт не запущен дважды, и желательно без дополнительных файлов.

получать список процессов и искать там свой файл.
...
Рейтинг: 0 / 0
12.05.2014, 18:19
    #38639076
Alibek B
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
(Perl) Как проконтроллировать, чтобы был запущен только один инстанс?
В списке процессов будет perl.
Как я определю, какой именно скрипт он исполняет?
...
Рейтинг: 0 / 0
12.05.2014, 20:35
    #38639186
vkle
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
(Perl) Как проконтроллировать, чтобы был запущен только один инстанс?
Alibek B.и желательно без дополнительных файлов.Да не вопрос. Можно и на сам файл скрипта ставить блокировку.
...
Рейтинг: 0 / 0
13.05.2014, 00:10
    #38639295
Alibek B
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
(Perl) Как проконтроллировать, чтобы был запущен только один инстанс?
Так на $0 блокировка почему-то не работает.
На отдельном файле (у меня это лог-файл, открытый в течении работы скрипта) работает.
...
Рейтинг: 0 / 0
13.05.2014, 14:25
    #38639808
lightspeed
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
(Perl) Как проконтроллировать, чтобы был запущен только один инстанс?
может как-то так?

Код: php
1.
2.
defined( my $pid = fork ) or die "Can't fork: $!";
exit if $pid;
...
Рейтинг: 0 / 0
13.05.2014, 15:51
    #38639934
Alibek B
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
(Perl) Как проконтроллировать, чтобы был запущен только один инстанс?
А что этот код делает, можно прокомментировать?
Я видимо его не совсем понял.
...
Рейтинг: 0 / 0
14.05.2014, 00:45
    #38640435
lightspeed
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
(Perl) Как проконтроллировать, чтобы был запущен только один инстанс?
использует форк для проверки запущенного инстанса.
и если инстанс уже запущен, либо форк не удался - вываливается.
ставите в начало скрипта, и вперед..
...
Рейтинг: 0 / 0
14.05.2014, 03:02
    #38640458
Warstone
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
(Perl) Как проконтроллировать, чтобы был запущен только один инстанс?
lightspeedиспользует форк для проверки запущенного инстанса.
и если инстанс уже запущен, либо форк не удался - вываливается.
ставите в начало скрипта, и вперед..п....ц. Да простят меня модераторы. Орден Дедалла 1-й степени.
...
Рейтинг: 0 / 0
14.05.2014, 08:16
    #38640500
Alibek B
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
(Perl) Как проконтроллировать, чтобы был запущен только один инстанс?
lightspeedиспользует форк для проверки запущенного инстанса.
А в чем проверка заключается?
Ну форкнется текущий процесс, ну форк тут же закроется.
Как определяется, что параллельно запущен еще один процесс?
...
Рейтинг: 0 / 0
14.05.2014, 11:47
    #38640727
lightspeed
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
(Perl) Как проконтроллировать, чтобы был запущен только один инстанс?
эм.. чуваки, не бейте меня сильно. это просто идея и код на вскиду. проверять не локом, к форкать процесс, и проверять статус.
может быть она не верна, но блин, предложите свою тогда.
...
Рейтинг: 0 / 0
14.05.2014, 15:48
    #38641184
volodin661
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
(Perl) Как проконтроллировать, чтобы был запущен только один инстанс?
Alibek B.,

Sys::RunAlone - make sure only one invocation of a script is active at a time

Код: coco
1.
2.
3.
4.
5.
6.
7.
8.
9.
THEORY OF OPERATION ^

The functionality of this module depends on the availability of the DATA handle in the script from which this module is called (more specifically: in the "main" namespace).

At INIT time, it is checked whethere there is a DATA handle: if not, it exits with an error message on STDERR and an exit value of 2.

If the DATA handle is available, and it cannot be flocked, it exits with an error message on STDERR and an exit value of 1. The error message will be surpressed when silent = 1> was specified in the use statement.

If there is a DATA handle, and it could be flocked, execution continues without any further interference.
...
Рейтинг: 0 / 0
14.05.2014, 16:00
    #38641205
volodin661
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
(Perl) Как проконтроллировать, чтобы был запущен только один инстанс?
Alibek B.,
Proc::PID::File - a module to manage process id files

Код: coco
1.
2.
3.
DESCRIPTION ^

This Perl module is useful for writers of daemons and other processes that need to tell whether they are already running, in order to prevent multiple process instances. The module accomplishes this via *nix-style pidfiles, which are files that store a process identifier.
...
Рейтинг: 0 / 0
14.05.2014, 16:47
    #38641284
Warstone
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
(Perl) Как проконтроллировать, чтобы был запущен только один инстанс?
lightspeedэм.. чуваки, не бейте меня сильно. это просто идея и код на вскиду. проверять не локом, к форкать процесс, и проверять статус.
может быть она не верна, но блин, предложите свою тогда.Скажите, а водите машину вы тоже - управляя рулем с помощью попы?..
А код пишете путем хождения по клаве ногами?

Может это какой-то кодерский абстракционизм...

Давайте тогда и я попробую:

Решать проблему колец и утечек памяти в Перле надо путем использования модуля CGI.pm: h1($var) - сделает ссылку "слабой", в то время как h5(@array) - сделает массив неубиваемым, даже если массив вышел из области видимости.
...
Рейтинг: 0 / 0
15.05.2014, 15:00
    #38642328
vkle
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
(Perl) Как проконтроллировать, чтобы был запущен только один инстанс?
Alibek B.Так на $0 блокировка почему-то не работает.
На отдельном файле (у меня это лог-файл, открытый в течении работы скрипта) работает.Можно посмотреть Ваш нерабочий пример? У меня блокировка работает, но несколько своеобразно. При попытке запустить второй экземпляр вываливается сообщение такого вида:
Код: php
1.
2.
$ ./test.pl
bash: ./test.pl: /usr/bin/perl: плохой интерпретатор: Текстовый файл занят

В принципе, цель то предотвращения запуска второго экземпляра достинута, хоть и с генерацией ошибки (которую можно при желании отправить в /dev/null).
...
Рейтинг: 0 / 0
15.05.2014, 15:04
    #38642343
Alibek B
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
(Perl) Как проконтроллировать, чтобы был запущен только один инстанс?
Так я его в самом начале приводил.
Пробую лочить $0, но блокировка не работает.
Такой код работает:
Код: php
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
open (LAST, '+>:encoding(cp1251)', &getfilename('last')) or die "Can't open log-file for last run!\n";
{
	my $locked = flock(LAST, LOCK_EX | LOCK_NB);
	unless ($locked)
	{
		print TITLE . ' v.' . VERSION . ": Завершение работы: скрипт уже запущен.\n";
		exit(1);
	}
}
...
close(LAST);


Но это у меня в данном примере есть постоянно открытый log-файл.
А я бы хотел решение без дополнительных файлов (используя $0 или секцию _DATA_).
...
Рейтинг: 0 / 0
15.05.2014, 15:12
    #38642372
vkle
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
(Perl) Как проконтроллировать, чтобы был запущен только один инстанс?
Alibek B.,

Прошу прощения, проглядел. Попробую его помусолить.

Мой почти рабочий тестовый пример такой:
Код: php
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
#!/usr/bin/perl

use strict;
use Fcntl qw(:flock);

print "File for lock: $0\n";
print "Start\n";
open(FL, "+>>$0") or die "Can't open $0: $!\n";
print "Opened\n";
flock(FL, LOCK_EX) or die "Can't flock $0: $!\n";
print "Locked\n";
sleep 20;
print "Exit\n";
...
Рейтинг: 0 / 0
15.05.2014, 16:59
    #38642551
vkle
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
(Perl) Как проконтроллировать, чтобы был запущен только один инстанс?
Вот такой тестовый вариант вполне рабочий получился:

Код: php
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
#!/usr/bin/perl

use strict;
use Fcntl qw(:flock);

print "File for lock: $0\n";
print "Start\n";
open(FL, "<$0") or die "Can't open $0: $!\n";
print "Opened\n";
flock(FL, LOCK_EX | LOCK_NB) or die "Can't flock $0: $!\n";
print "Locked\n";
sleep 20;
print "Exit\n";



При запуске второго экземпляра получаю:
Код: php
1.
2.
3.
4.
5.
$ ./test.pl
File for lock: ./test.pl
Start
Opened
Can't flock ./test.pl: Ресурс временно недоступен
...
Рейтинг: 0 / 0
21.05.2014, 17:18
    #38647888
netwind
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
(Perl) Как проконтроллировать, чтобы был запущен только один инстанс?
кстати, почему у вас нигде в скриптах нет намеков на всякий там CGI и тд, но возникает ситуация когда скрипт все же запускают несколько раз?
не нужно чтобы запускался больше одного раза - не запускайте !
...
Рейтинг: 0 / 0
21.05.2014, 17:44
    #38647920
vkle
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
(Perl) Как проконтроллировать, чтобы был запущен только один инстанс?
netwind,

Так проблема второго запуска может возникнуть не только с использованием CGI. У меня как-то аналогичная ситуация возникла при ежеминутном запуске по крону. В нормальных условиях скрипт отрабатывает секунд за 20 и проблем не знал. А когда нагрузка на сервер как-то дико подскочила и скрипт не уложился в предполагаемую минуту - поперли дубликаты на выхлопе. Так и пришлось добавить блокировку.
...
Рейтинг: 0 / 0
Форумы / PHP, Perl, Python [игнор отключен] [закрыт для гостей] / (Perl) Как проконтроллировать, чтобы был запущен только один инстанс? / 23 сообщений из 23, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]