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


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

Обробка команди Баша нижче, можливо, дивує:

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
в &&B, A виконується першим. B виконується лише в тому випадку, якщо A виконано та завершено успішно. Використовуйте A; B завжди виконувати B незалежно від стану виконання А.
капад

15

Блокування файлів не є обов'язковим 1 - тобто ви не можете заблокувати файл, щоб інший процес не міг отримати доступ до нього. Блокування файлу означає, що якщо процес (nother) перевіряє, чи був він заблокований, він знатиме.

Мета flock- робити такі речі, як ви хочете, але потім їх потрібно використовувати flockдля кожного спроби доступу . Майте на увазі, що вони блокують дзвінки; від man flock:

якщо замок неможливо отримати негайно, зграя чекає, поки замок буде доступний


1. Що робить цю функцію непридатною, якщо ви використовуєте її для, наприклад, безпеки, але це не є метою блокування файлів - вони для синхронізації, що і ви робите. Користувач Лео вказав, що може бути нестандартна реалізація обов'язкового блокування файлів у ядрі Linux ( див. Це обговорення ), заснованого на історичних паралелях з інших * nix операційних систем. Однак, схоже, це лише інтерфейс рівня C.


Дякую! Це допомагає зрозуміти "дорадчий" аспект і те, як мені потрібно використовувати flockщоразу. дуже корисний!
d -_- b

2

Ви можете використовувати команду "sh -c ...", щоб виконати всю команду оболонки, включаючи перенаправлення файлів, із утримуваним замком. Крім того, оскільки ви використовуєте файл як лічильник, вам потрібно тримати блокування постійно, поки ви читаєте і записуєте назад. Тож ви хочете зробити щось подібне, щоб збільшити лічильник і повернути його нове значення:

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.