Получите эксклюзивную блокировку чтения / записи для файла для атомарных обновлений


10

Я хочу иметь файл, который используется в качестве счетчика. Пользователь A запишет и увеличит это число, а пользователь B попросит прочитать файл. Возможно ли, что пользователь A может заблокировать этот файл, чтобы никто не мог читать или писать в него, пока запись пользователя A не будет завершена?

Я посмотрел в, flockно не могу заставить его работать, как я ожидаю.

flock -x -w 5 /dev/shm/counter.txt echo "4" >  /dev/shm/counter.txt && sleep 5

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

Моя цель:

LOCK counter.txt; write to counter.txt;

в то же время

Read counter.txt; realize it's locked so wait until that lock is finished.

1
«не могу заставить его работать так, как я этого ожидаю». Что конкретно это означает?
John1024

Я уверен, что я использую его неправильно, но, используя приведенный выше код, я могу использовать две оболочки и заставить их обе отредактировать файл счетчика, пока я думал, что одна его блокирует. Поэтому, если я дважды запускаю эту строку на двух отдельных оболочках (каждая со своим собственным номером для эха), я все равно вижу, как пишется второе число
d -_- b

1
Когда первый завершает работу и снимает блокировку, второй запускается. Разве так не должно работать? (В приведенном выше коде && sleep 5выполняется после того, как стадо снимает блокировку.)
John1024

Хм, интересно ... Так что в таком случае мой человеческий глаз не поймал бы слишком быстро. Большой! Моя следующая задача - как ввести несколько команд flock, но я поставлю это как отдельный вопрос. Спасибо Джон!
d -_- b

3
@d -_- b Мне нравится твое имя пользователя. Это самое умное имя пользователя, которое я когда-либо видел.
Девин Кольер Джонсон

Ответы:


10

Обработка команды Bash ниже может быть удивительной:

flock -x -w 5 /dev/shm/counter.txt echo "4" >  /dev/shm/counter.txt && sleep 5

Сначала запускается Bash, flock -x -w 5 /dev/shm/counter.txt echo "4" > /dev/shm/counter.txtи, если он завершается успешно (снятие блокировки), он запускается sleep 5. Таким образом, блокировка не удерживается в течение 5 секунд, которые можно ожидать.

Помимо &против&&

Если одна имеет две команды, Aа Bзатем:

  1. A & Bначинается Aв фоновом режиме, а затем начинается, Bне дожидаясь Aокончания.

  2. A && Bзапускается A, ожидает его завершения, а затем, если он успешно завершается (код выхода 0), запускается B. Если происходит Aсбой (ненулевой код выхода), то Bон никогда не запускается.

В сумме &и &&два совершенно разных оператора списка.


3
это удивило бы меня , если в A && B, Aбудет ждать Bдо конца.
Андрас Гомрей

1
в A && B, A выполняется первым. B выполняется, только если A выполнен и успешно завершен. Использовать; B всегда выполнять B независимо от статуса выполнения A.
Капад

15

Блокировки файлов не являются обязательными 1 - то есть вы не можете заблокировать файл, чтобы другой процесс не мог получить к нему доступ. Блокировка файла означает, что если (другой) процесс проверяет, не заблокирован ли он, он узнает об этом.

Цель flockсостоит в том, чтобы делать что-то вроде того, что вы хотите, но вы должны затем использовать его flockдля каждой попытки доступа . Имейте в виду, что это блокировка звонков; от man flock:

если блокировка не может быть немедленно получена, стадо ждет, пока блокировка не будет доступна


1. Что делает эту функцию бесполезной, если вы используете ее, например, для безопасности, но это не является целью блокировок файлов - они предназначены для синхронизации, что вы и делаете. Пользователь Leo указал, что в ядре linux может быть нестандартная реализация обязательной блокировки файлов ( см. Это обсуждение ), основанная на исторических параллелях из других операционных систем * nix. Тем не менее, это выглядит только интерфейс уровня C.


Спасибо! Это помогает понять «консультативный» аспект и то, как я должен использовать flockкаждый раз. очень полезно!
d -_- b

2

Вы можете использовать «sh -c command ...» для запуска всей команды оболочки, включая перенаправление файлов, с удерживаемой блокировкой. Кроме того, поскольку вы используете файл в качестве счетчика, вам необходимо постоянно удерживать блокировку во время чтения и обратной записи. Таким образом, вы хотите сделать что-то вроде этого, чтобы увеличить счетчик и вернуть его новое значение:

flock --exclusive --wait 5 /dev/shm/counter.txt sh -c 'read count < /dev/shm/counter.txt ; echo $((count + 1)) > /dev/shm/counter.txt ; echo $((count + 1))'

Изменение знака плюс на знак минус должно уменьшить счетчик:

flock --exclusive --wait 5 /dev/shm/counter.txt sh -c 'read count < /dev/shm/counter.txt ; echo $((count - 1)) > /dev/shm/counter.txt ; echo $((count - 1))'

Я ожидаю, что вы инициализируете счетчик до того, как возникнет конфликт, так что не нужно беспокоиться о блокировке так рано:

echo 0 > /dev/shm/counter.txt

Я не думаю, что вам когда-либо понадобится затушевывать значение счетчика, пока может возникнуть конфликт, но, если вы когда-либо это сделали, вы должны сделать это так:

flock --exclusive --wait 5 /dev/shm/counter.txt sh -c 'echo 0 > /dev/shm/counter.txt'

Я думаю, вы понимаете, как сделать чтение, но я включаю его для полноты:

flock --shared /dev/shm/counter.txt cat /dev/shm/counter.txt

Похоже, это единственный ответ, который правильно замечает, что в этом вопросе файл открывается оболочкой еще до того, как стадо даже запускается ...
eichin
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.