rm -rf :Существует ли подход «все или ничего» (атомарный )?

Подстановка вашей команды захватывает stdout; сообщение о завершении работы, вероятно, записывается в stderr.

Чтобы перенаправить stderrна stdout, чтобы он также был захвачен, добавьте 2>&1, т.е.

$(df -h /; sudo shutdown -r +1 2>&1)
2
31.08.2021, 15:12
2 ответа

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

Конечно, это только логически атомарно, а не в том смысле, что «мы можем выдернуть шнур питания в любое время» атомарно; хотя это тоже можно устроить, с дополнительной логикой и неким хуком, который запускается при загрузке -up.

Сделать два прохода (один проход для проверки разрешений, а другой проход для удаления )сложно. Логика должна быть исчерпывающей для проверки всех разрешений, включая расширенные атрибуты. Например, если мы выполним sudo chattr +i file, то fileстанет неудаляемым, даже если обычные разрешения Unix выглядят хорошо :, каталог доступен для записи. Лучшая лакмусовая бумажка на вопрос «можем ли мы удалить этот файл» — это попробовать.

Вот несколько проверенный прототип концепции, в качестве доказательства концепции, с использованием rsyncдля резервного копирования и восстановления на основе жесткой -ссылки -. Этот скрипт называетсяatomic-rm.sh:

#!/bin/sh

set -eu

if [ $# -ne 1 ] ; then
  echo "specify directory to remove"
  exit 1
fi

ar_src=$(realpath "$1")
ar_tmp=$(mktemp -d "$(dirname "$ar_src")/tmp-XXXXXX")

if [ $? -ne 0 ] ; then
  echo "unable to create temporary directory"
  exit 1
fi

cleanup()
{
  find "$ar_tmp" -type d -print0 | xargs -0 chmod +w

  if ! rm -rf "$ar_tmp" ; then
    echo "removal of temporary directory $ar_tmp failed"
    exit 2 # 2 indicates dirty failure
  fi
}

trap cleanup EXIT

if ! rsync -ar --link-dest="$ar_src" "$ar_src"/ "$ar_tmp"/ ; then
  echo "unable to create hard-linked backup of $ar_src in $ar_tmp"
  exit 1
fi

if ! rm -rf "$ar_src" ; then
  if ! rsync -ar --link-dest="$ar_tmp" "$ar_tmp"/ "$ar_src"/ ; then
    echo "removal of $ar_src failed; unfortunately, so did the rollback"
    exit 2 # 2 indicates dirty failure
  fi
  exit 1
fi

exit 0

С некоторыми дополнительными усилиями он мог бы хранить некоторую информацию где-то, которую сценарий восстановления во время загрузки -мог бы использовать для очистки незакрепленных временных каталогов. Временный каталог создается как одноуровневый для -и -удаленного каталога, чтобы гарантировать, что они находятся в одной и той же файловой системе; мы не можем использовать /tmp.

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

Обратите внимание, что в cleanupмы должны сделать findпроход по каталогам, чтобы сделать их доступными для записи. Причина в том, что если удаление завершается ошибкой из-за того, что каталог недоступен для записи, то точно так же произойдет сбой в резервной копии -, потому что rsyncбудет реплицировать эти разрешения для каталога.

2
31.08.2021, 22:48

Модифицированная версия ответа Каза. Сделайте копию(cp -a)исходного дерева, попробуйте удалить эту копию и, если удаление прошло успешно, удалите исходное дерево.

  • --:в зависимости от размера дерева это может занять больше времени и больше места на диске
  • ++ :исходное дерево остается нетронутым, если его нельзя удалить атомарно
#!/bin/sh

if [ $# -ne 1 ] ; then
  echo "specify directory to remove"
  exit 1
fi

ar_src=$(realpath "$1")
ar_tmp=$(mktemp -d "$(dirname "$ar_src")/tmp-XXXXXX")

if [ $? -ne 0 ] ; then
  echo "unable to create temporary directory"
  exit 1
fi

if ! cp -a "$1" "$ar_tmp"; then
    echo "unable to copy"
    exit 1
fi

if rm -rf "$ar_tmp"; then
    rm -rf "$ar_src";
fi

exit 0

Исполнение:

$./atomic-rm2.sh d1/
rm: cannot remove '/tmp/testRMDIR/tmp-4sOBNS/d1/d2/f2': Permission denied

$ tree d1
d1
├── d2
│   └── f2
└── f1
0
01.09.2021, 08:34

Теги

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