Есть ли в Go независимый от ОС способ атомарной перезаписи файла?
Если файл уже существует, я хочу перезаписать его. Если его не существует, я хочу создать его и написать в него. Я бы предпочел не использовать стороннюю библиотеку, такую как lockfile (которая, кажется, обрабатывает все типы блокировок).
Моей первоначальной идеей было:
- Записать во временный файл со случайно сгенерированным большим идентификатором, чтобы избежать конфликта.
- Переименуйте временное имя файла -> новый путь.
1 ответ
os.Rename
звонки syscall.Rename
который для Linux/UNIX использует переименованный системный вызов (который является атомарным *). На винде syscall.Rename
звонки MoveFileW
при условии, что источник и назначение находятся на одном устройстве (что может быть организовано), а файловая система - NTFS (что часто имеет место) - атомарная *.
Я бы позаботился о том, чтобы источник и место назначения находились на одном устройстве, чтобы переименование Linux не завершилось ошибкой, а переименование Windows на самом деле атомарное. Как упоминал Дэйв С выше, создание вашего временного файла (обычно с использованием ioutil.TempFile
) в том же каталоге, что и существующий файл - это путь; Вот как я делаю мои атомные переименования.
Это работает для меня в моем случае использования, который:
- Процесс One Go получает обновления и переименовывает файлы для обмена обновлениями.
- Другой процесс Go отслеживает обновления файлов с помощью fsnotify и повторно отображает файл при его обновлении.
В приведенном выше случае использования просто с помощью os.Rename
отлично сработал для меня.
Некоторое дальнейшее чтение:
- Является ли rename() атомарным? "Да и нет. Rename () является атомарным, если ОС не падает...."
- Возможно ли переименование атомарного файла (с перезаписью) в Windows?
* Примечание: я хочу отметить, что, когда люди говорят о файловых операциях атомарной файловой системы, с точки зрения приложения, они обычно подразумевают, что операция происходит или не происходит (с чем может помочь журналирование) с точки зрения пользователей. Если вы используете atomic в смысле операции атомарной памяти, очень немногие операции файловой системы (за исключением прямого ввода-вывода [ O_DIRECT ], который один блок записывает и читает с отключенной буферизацией диска) можно считать действительно атомарными.