Как я могу убедиться, что только одна копия сценария Perl работает одновременно?
Вопрос
Мне нужно убедиться, что только одна копия моего сценария Perl работает одновременно. Согласно предложениям здесь Я написал Sub, чтобы сделать чек:
sub check_instances {
open my $fh, '<', $0 or die $!;
unless (flock($fh, LOCK_EX|LOCK_NB)) {
print "$0 is already running. Exiting.\n";
exit 1;
}
}
Но это не работает. Что может быть проблемой?
Решение
Вы используете лексическое файловодость, выделенные внутри под. Когда check_instances
Возврат, файлHandle автоматически закрывается, который выпускает замок. Таким образом, вы никогда не увидите конфликту, если только два копии не проверяют в то же время.
Убедитесь, что файлHandle остается открытым, пока сценарий работает (или до тех пор, пока вы хотите поддерживать блокировку). Например:
{
my $fh;
sub check_instances {
return if $fh; # We already checked
open $fh, '<', $0 or die $!;
unless (flock($fh, LOCK_EX|LOCK_NB)) {
print "$0 is already running. Exiting.\n";
exit 1;
}
}
} # end scope of $fh
Это также было бы хорошим местом для использования state
переменная, Если вы можете требовать Perl 5.10.
Другие советы
Вы можете проверить список процессов для других экземпляров (Proc :: plachtable. Может помочь), но обычный маршрут, принятый программами Unix на многих языках - создать файл PID - см. Файл :: PID.
Нормальная семантика flock
Может потребовать, чтобы вы открываете файловый режим в режиме записи, скажем,
open $fh, '>>', $0;
open $fh, '+<', $0;
(От perldoc -f flock
)
Обратите внимание, что эмуляция FCNTL (2), эмуляция стада (3) требует, чтобы Filehandle быть открытым с помощью прочитанного намерения использовать lock_sh и требует, чтобы он был открыт с намерением для записи для использования lock_ex.
Блокировка файлов может потерпеть неудачу по разным причинам (например, если файл находится на сетевой файловой системе, такой как NFS).
Мое решение состоит в том, чтобы создать каталог во время прогона скрипта. Создание каталогов всегда является атомной операцией.