Использование переименования для безопасной перезаписи общего файла в Linux

Вот настройка: у меня есть общий файл (давайте назовем его status.csv), который читается многими процессами (давайте назовем их потребителями) только для чтения. У меня есть один производитель, который периодически обновляет status.csv, создавая временный файл, записывая в него данные и используя обсуждаемую здесь функцию C:

http://www.gnu.org/software/libc/manual/html_node/Renaming-Files.html

переименовать временный файл (фактически перезаписать) в status.csv, чтобы потребители могли обрабатывать новые данные. Он хочет попытаться гарантировать (насколько это возможно в мире Linux), что потребители не получат искаженный/поврежденный/наполовину старый/наполовину новый файл status.csv (я хочу, чтобы они получили либо все старые данные или все новое). Кажется, я не могу гарантировать это, прочитав описание переименования: кажется, что действие переименования само по себе является атомарным, но я хочу знать, если у потребителя уже открыт файл status.csv, он продолжит читать то же самое. файл, каким он был, когда он был открыт, даже если файл был переименован/перезаписан производителем в середине этой операции чтения.

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

Кстати, эти процессы выполняются на одном компьютере (RHEL 6).

Спасибо!


person andrew    schedule 13.01.2014    source источник


Ответы (1)


В Linux и подобных системах, если в процессе есть открытый файл и этот файл удаляется, сам файл остается не удаленным до тех пор, пока все процессы не закроют его. Все, что происходит немедленно, это то, что запись в каталоге удаляется, чтобы ее нельзя было открыть снова.

То же самое происходит, если переименование используется для замены открытого файла. Старый файловый дескриптор по-прежнему держит старый файл открытым. Однако новые открытия увидят новый файл.

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

Примечание: ваши потребители могут узнать, был ли файл заменен, используя вызов stat(2). Если запись st_dev или st_ino (или обе) были изменены, то файл был заменен и должен быть закрыт и снова открыт. Вот как работает tail -F.

person DoxyLover    schedule 13.01.2014
comment
Замечу, что в целом это верно, но не универсально. Это зависит от базовой файловой системы, и есть некоторые, которые на самом деле не работают таким образом (обычно потому, что они изначально не были файловыми системами Linux/Unix, но все же...)... - person twalberg; 14.01.2014