Intereting Posts
Есть ли способ установить правила для минимизации в системный лоток для приложений, которые сами не поддерживают его? Как узнать, сколько каталогов на этом пути? Как я могу сбросить полную системную память? результат командной строки ansible pass shell для переменной Как установить Tomcat Server на Linux Mint 17.1? Как исправить ошибку сообщения Ошибка несоответствия суммы хеша Не удалось заполнить карты логических томов Процессы ядра и демоны? Есть ли способ узнать, сколько процессов открывает файл? Как не отображать вывод stdout запущенного процесса? Как установить Awesome Windows Manager в терминал? ripgrep: печатать только имена файлов, соответствующие шаблону Как создать функцию в zsh, которая вызывает существующую команду с тем же именем? Использование «меньше», чтобы оставить текст на экране для небольших файлов Как вы интегрируете медиаплеер с панелью задач Xfce, т. Е. Для управления воспроизведением / остановкой?

Безопасно ли перемещать файл, к которому добавляется?

У меня есть процесс node.js, который использует fs.appendFile для добавления строк в file.log . fs.appendFile("start-end") только полные строки из примерно 40 символов в строке, например, вызовы похожи на fs.appendFile("start-end") , а не на 2 вызова типа fs.appendFile("start-") и fs.appendFile("end") . Если я file2.log этот файл в file2.log могу ли я быть уверенным, что никакие строки не будут потеряны или скопированы частично?

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

Если вы mv файл в той же файловой системе, файл фактически не затрагивается, но изменяется только запись в файловой системе.

 $ mv foo bar 

на самом деле что-то вроде

 $ ln foo bar $ rm foo 

Это создало бы жесткую ссылку (вторую запись каталога) для файла (на самом деле это индекс, обозначенный позицией файловой системы) foo named bar и удалил запись foo . Поскольку теперь при удалении foo есть вторая запись файловой системы, указывающая на inode foo , удаление старой записи foo фактически не удаляет блоки, принадлежащие к inode.

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

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

Перемещение файловой системы:

Если вы перемещаете файл по границам файловой системы, все становится некрасиво. В этом случае вы не можете гарантировать постоянство сохранения вашего файла, поскольку mv фактически

  • создать новый файл в целевой файловой системе
  • скопируйте содержимое старого файла в новый файл
  • удалить старый файл

или

 $ cp /path/to/foo /path/to/bar $ rm /path/to/foo 

соответственно

 $ touch /path/to/bar $ cat < /path/to/foo > /path/to/bar $ rm /path/to/foo 

В зависимости от того, копирует ли конец файла во время записи вашего приложения, может случиться, что у вас есть только половина строки в новом файле.

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

Поскольку вы говорите, что используете node.js, я предполагаю, что вы должны использовать fs.rename() (или fs.renameSync() ) для переименования файлов. Этот метод node.js документирован для использования системного вызова rename (2) , который никак не затрагивает сам файл, а просто изменяет имя, под которым оно указано в файловой системе:

« rename () переименовывает файл, перемещая его между каталогами, если это необходимо. Любые другие жесткие ссылки на файл (созданные с помощью ссылки (2)) не затрагиваются. Открытые дескрипторы файлов для старого пути также не затрагиваются».

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


Как отмечает Андреас Вайзе в своем ответе , системный вызов rename (2) (и, следовательно, fs.rename() в node.js) не будет работать через границы файловой системы. Таким образом, попытка переместить файл в другую файловую систему таким образом просто провалится.

Команда mv пытается скрыть это ограничение, обнаружив ошибку и вместо этого переместив файл, скопировав его содержимое в новый файл и удалив оригинал. К сожалению, перемещение таких файлов может привести к потере данных, если файл перемещается во время записи. Таким образом, если вы хотите безопасно переименовать файлы, которые могут быть одновременно записаны, вы не должны использовать mv (или, по крайней мере, вы должны абсолютно убедиться, что новый и старый путь находятся в одной и той же файловой системе).