LINUX.ORG.RU

Зачем нужен flock?

 ,


0

3

Для того чтобы предупредить одновременный запуск сценария можно использовать lock файлы.

Насколько я понимаю, это можно реализовать проверяя наличие файла, после чего при наличии завершать работу а при отсутствии – создавать, выполняться и удалять файл перед завершением.

Но знающие люди пишут что-то про некий flock. Подскажите пожалуйста чем он лучше, нужно ли его использовать и чем плоха описанная схема?

★★★★★

Насколько я понимаю, это можно реализовать проверяя наличие файла, после чего при наличии завершать работу а при отсутствии – создавать, выполняться и удалять файл перед завершением.

Как вы собираетесь это делать? Если что-то типа

declare -r LOCK_FILE=/run/whatever.lock

if [ -e "${LOCK_FILE}" ]
then
    exit 0
fi

touch "${LOCK_FILE}"

# Продолжаем работу…

— то тут есть гонка между проверкой существования файла и его созданием: два процесса могут одновременно проверить существование файла и не обнаружить его, и потому продолжить работу.

Rootlexx ★★★★★
()

Приложение может упасть и не удалить за собой файл. Так что существование файла - такой себе признак.

flock ставит lock на файл. При этом второй раз так сделать не получится. То есть условно занятость ресурса можно проверять по результату выполнения команды.

Смотри man flock и man 2 flock

Radjah ★★★★★
()
Ответ на: комментарий от Rootlexx

Но используя при таком способе другую программу мы не избавимся от возможности такого случая? У flock другой способ? Создаёт файл и оставляет его открытым данным процессом?

sin_a ★★★★★
() автор топика
Ответ на: комментарий от Radjah

Приложение может упасть и не удалить за собой файл

Не самый страшный случай. Можно, в случае если файл старше таймаута, уведомлять человека.

flock ставит lock на файл

Можно простой пример?

sin_a ★★★★★
() автор топика
Последнее исправление: sin_a (всего исправлений: 1)
Ответ на: комментарий от Rootlexx

— то тут есть гонка между проверкой существования файла и его созданием: два процесса могут одновременно проверить существование файла и не обнаружить его, и потому продолжить работу.

Это да, но при создании файла можно задать O_EXCL, что решит проблему.

urxvt ★★★★★
()
Ответ на: комментарий от sin_a

Можно простой пример?

exec < .
flock -n 0
flres=$?
# Если никто каталог не занял, то работаем
if [ $flres -eq 0 ]
then
    # тут делаем свои дела
else
    echo [!] ERROR! Каталог уже обрабатывается!
    exit 1
fi
Radjah ★★★★★
()
Ответ на: комментарий от sin_a

Не самый страшный случай. Можно, в случае если файл старше таймаута, уведомлять человека.

А если человека нет? Программа упала, её перезапускают, а она уже не запускается. Так не пойдёт.

vbr ★★★★
()
Ответ на: комментарий от sin_a

Открываешь терминал и пишешь

flock /tmp/lalala --command "vim .vimrc"

Открываешь другой терминал и пишешь

flock /tmp/lalala --command "vim ~/.vimrc"

Пока первый vim не закроешь, второй не откроется. Вот и всё. Хотя там можно неблокирующее разрешение на чтение дать.

Это на уровне утилиты, а не уровне кода, можно на сам файл данных, а не lock файл повесить мягкую блокировку «со мной работают, обождите» и программы у которых нет коммуникации друг с дургом через общий lock файл могут дружить.

lock файл это для блокировки запуска процесса, flock свойство файла это для «блокировки» одновременной работы программ с однимаи данными без какой либо синхронизации друг с другом.

Есть утилита, а есть системный вызов. Просто flock можно использовать для организации lock файла, но не на уровне он есть или его нет, а на уровне висит на нём флаг блокировки или нет.

Может где ошибаюсь…

LINUX-ORG-RU ★★★★★
()
Ответ на: комментарий от Radjah

Спасибо, заменил точку на имя файла, его пришлось создать.

Ещё беспокоит эта история: https://habr.com/ru/articles/714884/ . У меня не ssh, но на хосте proxmox будут выполнятся команды в контейнерах. Посмотрим не будет ли той проблемы.

sin_a ★★★★★
() автор топика

Причины две, а может быть одна.

Если «одна», то вот она: лок это нативный механизм в ядре для данных целей, а создания-удаления и подобное - костыли, применяющиеся в основном по незнанию. И локфайлами они не называются! Локфайл это именно файл для flock, называть так файл для проверки его существования неграмотно.

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

Ну и ещё мелочь: занятый локфайл может наследоваться потомками занявшего его процесса (настраивается через O_CLOEXEC либо ручным вызовом close() после форка), образуя таким образом «сессию» занимаемого лока.

Если вопрос про то что же такое flock то это по сути мютекс (точнее, rwlock, но не суть), привязанный к объекту файловой системы и таким образом расшаренный между всеми процессами, которые этот файл видят.

firkax ★★★★★
()
Последнее исправление: firkax (всего исправлений: 2)
Ответ на: комментарий от urxvt

Это да, но при создании файла можно задать O_EXCL, что решит проблему.

В Bash? Речь же о нём.

В интернетах пишут, что можно использовать перенаправление и noclobber, но не проверял.

Rootlexx ★★★★★
()
Ответ на: комментарий от Rootlexx

bash тут ни при чём, это просто запускалка других программ. Ты вот для создания файла использовал программу /bin/touch, в мог бы какую-нить другую которая создаёт и файл с O_EXCL и фейлится если не вышло. Но для локов такое использовать не надо разумеется, надо flock.

firkax ★★★★★
()
Ответ на: комментарий от firkax

Ты вот для создания файла использовал программу /bin/touch, в мог бы какую-нить другую которая создаёт и файл с O_EXCL и фейлится если не вышло

Это понятно, речь шла о существующих способах. Мне о таковых, которые позволили бы обеспечить адекватную переносимость сценария, известно не было, вот теперь узнал про noclobber.

Rootlexx ★★★★★
()
Ответ на: комментарий от sin_a

Если тебе нужно такое поведение (чтобы блокировка не снималась операционной системой по завершению работы программы), тебе нужен lock файл, который создаётся через open(O_EXCL), flock тебе не нужен. Как такое сделать на sh я не знаю, но наверняка трюки есть.

Если тебе нужно поведение, когда блокировка снимается операционной системой, тебе нужен flock и open его не заменит.

Какое поведение нужно - тебе видней. В разных случаях разное. Хотя я бы сказал, что с первым случаем я в своей жизни пока не сталкивался, а со вторым сколько угодно. Как правило требуется, чтобы программа запустилась в одном экземпляре. К примеру если я делаю бэкап базы раз в час и по каким-то причинам он не успел отработать за час, следующий запуск должен подождать завершения предыдущего или отмениться, а не запускаться параллельно. При этом если по какой-то причине запуск упал, следующий запускать всё равно надо, мало ли что там упало.

vbr ★★★★
()
Последнее исправление: vbr (всего исправлений: 1)
Ответ на: комментарий от vbr

Это можно реализовать и по другому, например хранить статус в файле, как флаг файловой системы «грязная». Блокировка это независимо и пусть лучше правильным способом будет.

sin_a ★★★★★
() автор топика