Поддержите (или восстановление) полномочия файла при замене файла

Да, это может произойти, если Ваше устройство отформатировано с файловой системой, которая не поддерживает такую установку разрешения, такую как VFAT. В тех случаях umask составлен на лету от установки в fstab (или эквивалентная замена в горячем режиме).

Посмотрите, по всей вероятности, человек монтируются для деталей. Например, для VFAT, мы находим:

Смонтируйте опции для жира

uid=value и gid=value

Установите владельца и группу всех файлов. (Значение по умолчанию: uid и ценуроз текущего процесса.)

umask=value

Установите umask (битовая маска полномочий, которые не присутствуют). Значение по умолчанию является umask текущего процесса. Значение подано восьмеричное.

и т.д.

11
17.09.2013, 19:44
3 ответа

Вместо использования mv, просто перенаправление cat. Например:

TMP=$(mktemp)
modifyfile "$original" "$TMP"
cat "$TMP" > "$original"

Это перезаписывает $original с содержанием $TMP, ничего не касаясь на уровне файла.

10
27.01.2020, 19:57
  • 1
    Разве это не могло быть проблематично, если некоторая программа имеет открытый дескриптор файла в файл? –  Martin von Wittich 17.09.2013, 20:45
  • 2
    я затем имею к rm "$TMP" также, но это, кажется, делает, что я хочу. –  Stephen Ostermiller 17.09.2013, 20:49
  • 3
    @MartinvonWittich это, вероятно, была бы проблема, если бы Вы использовали mv вместо этого. Я не вижу способ решить ту проблему. превосходный –  strugee 17.09.2013, 21:45
  • 4
    @MartinvonWittich Да. Create-new-then-move дает Вам атомарное изменение и не влияет на программы, которые имеют открытый файл, но так как это создает новый файл, владение и полномочия файла потеряны. Truncate-existing-then-write сохраняет полномочия и владение, но теряет данные в случае катастрофического отказа и сильно ударяет коврик под ногами программ, которые имеют открытый файл. Вы не можете объединить хорошие части обоих. –  Gilles 'SO- stop being evil' 18.09.2013, 01:42
  • 5
    @MartinvonWittich chown только работы как корень. chmod и chgrp май или не может работать в зависимости от полномочий пользователя. Никакой копии другие атрибуты, такие как ACL или определенные для файловой системы расширенные атрибуты. –  Gilles 'SO- stop being evil' 18.09.2013, 02:03

Существует две стратегии заменить файл новой версией:

  1. Создайте временный файл с новой версией, затем переместите ее в место.

    • Преимущество: если программа откроет тот файл, то она или считает старое содержание или новое содержание, в зависимости от того, открыла ли она файл прежде или после перемещения. Нет никакой путаницы.
    • Преимущество: в случае катастрофического отказа сохраняется старое содержание.
    • Оборотная сторона: так как новый файл создается, атрибуты файла (владение, разрешение, и т.д.) не сохраняются.
  2. Перезапишите старый файл на месте.

    • Преимущество: атрибуты файла сохраняются.
    • Оборотная сторона: в случае катастрофического отказа файл можно оставить полузаписанным.
    • Оборотная сторона: если программа имеет файл, открытый, когда это обновляется, эта программа может считать непоследовательные данные.

Если Вы можете, использовать метод 1, но сначала копировать атрибуты исходного файла с cp -p --attributes-only. Это требует GNU coreutils (т.е. не встроил Linux или достаточно подобные Linux среды). Если Ваш cp не имеет --attributes-only, опустите эту опцию: это будет работать, но это будет копировать данные также.

tmp=$(mktemp)
cp -p --attributes-only "$original" "$tmp"
modifyfile "$original" "$tmp"
mv -f "$tmp" "$original"

Если Вы не можете копировать атрибуты существующего файла, например, потому что Вы имеете полномочия записи на нем, но не владеете им, и Вы хотите сохранить владельца, то только метод 2 возможен. Минимизировать риск потери данных:

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

tmp=$(mktemp)
backup="${original}~"
modifyfile "$original" "$tmp"
cp -p "$original" "$backup"
cp -f "$tmp" "$original"
10
27.01.2020, 19:57

После нашего обсуждения первого ответа я предлагаю другой ответ:

TMP="$(mktemp "$original".XXXXXXXXXX)"
modifyfile "$original" "$TMP"
chmod --reference="$original" "$TMP"
chown --reference="$original" "$TMP"
mv -f "$TMP" "$original"

Комментарии:

  • Я использую $original в mktemp шаблон, чтобы гарантировать, что временный файл не помещается в /tmp но в той же папке как $original. Я верю этому если /tmp смонтирован в другой файловой системе, операция больше не была бы атомарной.
  • Результат mktemp теперь заключается в кавычки в случае, если это содержит пробел.
  • Я использую $() вместо, '' потому что я считаю это инструментом для очистки.
  • ch{mod,own} --reference используются для передачи полномочий $original кому: $TMP. Если у кого-то есть дополнительные идеи, какие метаданные могут и должны быть переданы, то отредактируйте мое сообщение и добавьте его.
  • О, хорошо это требует корневых полномочий, как указал Gilles. Ну, я не собираюсь отбрасывать это теперь, когда я записал это :P
5
27.01.2020, 19:57

Теги

Похожие вопросы