Виконання операцій з атомним записом у файлі в bash


13

Після проходження Баша документації , цей питання , і це один він все ще не ясно мені , як я можу виконати атомну запис (додавання) операції в файл в БАШЕЄВ. У мене є сценарій, який запускається в декількох екземплярах і в якийсь момент повинен записати дані у файл:

echo "$RESULT" >> `pwd`/$TEMP_DIR/$OUT_FILE

Як можна зробити всі операції запису з усіх одночасно запущених сценаріїв до цього атомарного файлу (щоб дані з одного примірника не перекривали дані з іншого)?


1
FYI вам не потрібен `pwd`; ви можете просто використовувати крапку ( .). Також слід навести ціле ім'я файлу, оскільки воно містить змінні .
Wildcard

1
Ви також можете розглянути можливість використання FIFO .
Wildcard

@Wildcard Дякую Я pwdраніше використовував сценарій, щоб сповістити користувача про поточний робочий каталог, а також записати записи у файл журналу. переглядаючи FIFO зараз.
Себі

1
Насправді є кращий вступ до FIFO саме на цьому веб-сайті; Посилання, яке я надав кілька хвилин тому, - це специфікації POSIX для mkfifoта не зовсім вступного рівня.
Wildcard

Будь то FIFO або файл, ви все одно ризикуєте, що два екземпляри пишуть одночасно і видають результати один одному.
клак

Відповіді:


10

Здається, потрібно використовувати flockяк у прикладі від man ( http://linux.die.net/man/1/flock )

(
flock -x 200

# Put here your commands that must do some writes atomically

) 200>/var/lock/mylockfile 

І покладіть всі свої команди, які повинні бути атомними, в ().


Операція запису буде атомною, хоча (flock -s 200 # Покладіть сюди ваші команди, які повинні виконати деякі записи атомно) 200> / var / lock / mylockfile sread у кількох одночасно запущених сценаріях? Або, навпаки, блокування лише відносно / var / lock / mylockfile?
Себі

1
Ваш сценарій блокує / var / lock / mylockfile, але лише один екземпляр вашого сценарію може отримати блокування запису на ньому. Інші екземпляри будуть чекати, поки /var/lock/mylockfileдоступно для блокування.

-s - це загальний замок - підходить для читання, для блокування запису потрібно використовувати -x / -e. Це на сторінці чоловіка, яку ви пов’язали.
Еван Бенн

У який момент відбувається розблокування у цьому коді? Як тільки щось записується до /var/lock/mylockfileпроцесу, який викликав flock -x?
Кріс Стричинський

@ChrisStryczynski Ви можете запустити цей приклад (flock -x 200; date; sleep 10; date;) 200>/var/lock/mylockfileу двох оболонках і побачити, що розблокування відбувається лише після того, як всі команди в () будуть виконані (тобто в

4

flockє одним із способів операцій блокування. Утиліта є частиною набору інструментів util-linux і доступна лише для Linux. Інші утиліти, доступні на більш широкому спектрі платформ, базуються на setlockутиліті Даніеля Бернштейна з його пакету daemontools:

  • setlock від демонтів
  • setlock з демонтів Брюса Гентера - на біс
  • s6-setlock від s6 Лорана Беркота
  • chpst від пробігу Герріта Папа
  • runlock від переслідувача Уейна Маршалла
  • setlock з мого набору інструментів ніс

Ці інструменти оперують дещо іншою парадигмою до тієї, що використовується у відповіді М. Куренкова (та, яка flockтакож може використовувати, але не відповідає у цій відповіді). Один викликає setlockпрограму для ланцюгового завантаження команди, яка повинна бути замкненою. setlockсам відкриває і блокує файл блокування, і залишає дескриптор файлу для нього відкритим у процесі. Блокування зберігається до тих пір, поки це робить процес (якщо тільки наступна команда, прикавана до явного звільнення блокування, шляхом пошуку та закриття дескриптора відкритого файлу).

Для випадку у запитанні слід замикати команду, яка створює вихідний рядок, маючи на увазі, що це викликає зовнішню echo замість вбудованої echoкоманди оболонки :

setlock mylockfile echo "$ RESULT" >> ./$TEMP_DIR/$OUT_FILE

У цьому випадку не потрібно блокувати відкриття вихідного файлу в режимі додавання. Якби це було, можна було б відкрити цей файл в замку, що вимагає або з допомогою програм , як fdredir/ redirfd:

setlock mylockfile fdredir --додайте 1 "./$TEMP_DIR/$OUT_FILE" echo "$ RESULT"
яку можна перетворити на функцію оболонки, якщо хочеться:

outfile () {setlock mylockfile fdredir --додайте 1 "./$TEMP_DIR/$OUT_FILE" "$ @"; } 
[…]
Відлуння відлуння "$ РЕЗУЛЬТАТ"
або дотримуватися синтаксису оболонки і інтерпретувати його за допомогою другої оболонки, що працює під блоком, що вимагає деякого нетривіального цитування, якщо змінні оболонки не експортуються як змінні середовища:

setlock mylockfile sh -c 'echo' "$ RESULT" '>> "./'$TEMP_DIR'/'$OUT_FILE'" '

Це, звичайно, узагальнює інші речі, крім запису у вихідні файли:

setlock mylockfile sh -c '… замкнений; речі ... '

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.