Perl: flock() работает в Linux, игнорирует предыдущую блокировку в AIX.

В двух словах: написал Perl-скрипт, используя flock(). В Linux он ведет себя так, как ожидалось. В AIX функция flock() всегда возвращает 1, хотя другой экземпляр сценария, использующий функцию flock(), должен удерживать монопольную блокировку файла блокировки.

Мы отправляем сценарий Bash для перезапуска нашей программы, полагаясь на flock(1), чтобы предотвратить одновременный перезапуск нескольких процессов. Недавно мы выполнили развертывание на AIX, где flock(1) не используется по умолчанию и не предоставляется администраторами. Надеясь упростить задачу, я написал Perl-скрипт под названием flock, например:

#!/usr/bin/perl

use Fcntl ':flock';
use Getopt::Std 'getopts';

getopts("nu:x:");

%switches = (LOCK_EX => $opt_x, LOCK_UN => $opt_u, LOCK_NB => $opt_n);

my $lockFlags = 0;

foreach $key (keys %switches) {
    if($switches{$key}) {$lockFlags |= eval($key)};
}

$fileDesc = $opt_x || $opt_u;

open(my $lockFile, ">&=$fileDesc") ||  die "Can't open file descriptor: $!";
flock($lockFile, $lockFlags) || die "Can't change lock - $!\n";;

Я протестировал сценарий, запустив (flock -n -x 200; sleep 60)200>lockfile дважды почти одновременно с двух вкладок терминала.

В Linux второй запуск завершается с сообщением «Ресурс временно недоступен», как и ожидалось.

В AIX второй запуск получает блокировку, а функция flock() возвращает 1, что совершенно неожиданно.

Насколько я понимаю, функция flock() реализована по-разному в двух системах: в версии для Linux используется flock(1), а в версии для AIX используется, по-моему, fcntl(1). У меня недостаточно опыта, чтобы понять, как это вызывает мою проблему и как ее решить.

Большое спасибо за любой совет.


person Thomas Heywood    schedule 27.04.2012    source источник


Ответы (2)


Это не имеет ничего общего с AIX, вызов open() в вашем сценарии неверен.

Должно быть что-то вроде:

open (my $lockfile, ">>", $fileDesc) # for LOCK_EX, must be write

Вы использовали синтаксис «dup() ранее открытого дескриптора файла» с >&=, но скрипт не открыл никаких файлов для дублирования и не должен этого делать.

Мои быстрые тесты показывают правильное поведение (добавлена ​​отладка)

first window:
$ ./flock.pl -n -x lockfile
opened lockfile
locked
second window:
$./flock.pl -n -x lockfile
opened lockfile
Can't change lock - Resource temporarily unavailable
$
person CoreyStup    schedule 27.04.2012
comment
Вам также не нужно включать Fnctl:flock, так как flock() является допустимой функцией времени выполнения C, которую Perl будет использовать изначально. - person CoreyStup; 28.04.2012
comment
CoreyStup: включение дает мне удобные константы — LOCK_EX и тому подобное. - person Thomas Heywood; 30.04.2012
comment
Спасибо за подробный ответ. Я использовал ›&=, потому что предполагаемое использование моего сценария состояло в том, чтобы заблокировать дескриптор файла для файла, открытого в Bash, например так: (flock.pl -x 200; do_stuff)200›lockfile. Он работает в Linux, как и предполагалось. - person Thomas Heywood; 30.04.2012

Я полагаю, дело не в разных командах; это больше о глобальных различиях между AIX и Linux.

В системах POSIX блокировки файлов носят рекомендательный характер: каждая программа может проверить состояние файла, а затем пересмотреть, что с ним делать. Нет явных проверок = нет блокировки.

В системах Linux, однако, можно попытаться применить обязательную блокировку, хотя в самой документации говорится, что полагаться на нее было бы неразумно: реализация глючит (и, вероятно, когда-либо будет) с ошибками.

Поэтому предлагаю реализовать такие проверки рекомендательных флагов внутри самого скрипта.

Подробнее об этом: man 2 fcntl, человек 2 стадо.

person raina77ow    schedule 27.04.2012
comment
Не уверен, что я следую за вами, извините. Я ожидаю рекомендательной блокировки от Perl flock() (правильно ли это?), независимо от базовой архитектуры, если есть какая-то рекомендательная блокировка. Я также не уверен, что вы имеете в виду под проверками консультативных флагов. В любом случае, спасибо за ответ! - person Thomas Heywood; 27.04.2012