Linux ext4 восстановление прав доступа к файлам и каталогам после неудачного резервного копирования/восстановления

Linux ext4 восстановление прав доступа к файлам и каталогам после неудачного резервного копирования/восстановления

Я немного испортил резервное копирование своего личного каталога rsync(возможно, потому что я делаю резервное копирование в файловой системе NTFS): все файлы здесь, но права доступа ко всем файлам и каталогам — 777. Мне было интересно, есть лимагияутилита, которая рекурсивно изменит:

  • каталоги от 777 до 755.
  • обычные файлы с 777 по 644. У меня дома не так много исполняемых файлов, поэтому я смогу сделать это вручную позже.
  • оставьте остальные файлы (ссылки, что-либо еще?) без изменений.

Сделать это в скорлупе легко, но это займет несколько часов...

Дополнительный вопрос: есть ли какие-либо советы по правильному резервному копированию иерархии каталогов Linux на NTFS (с помощью rsyncили другим способом).

решение1

Стандартное рекомендуемое решение простое:

find . -type d -exec chmod 0755 "{}" \+
find . -type f -exec chmod 0644 "{}" \+

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

Если вы хотите вызвать команду один раз для каждого файла, вы можете сделать следующее:

find . -type d -exec chmod 0755 "{}" \;
find . -type f -exec chmod 0644 "{}" \;

решение2

chmod -R a=,u+rwX,go+rX $DIRпохоже, работает нормально и, скорее всего, является самым быстрым, как ни посмотри.

(Я проверил с strace, и это составляет толькоодин fchmodat()системный вызов для каждого файла/каталога (для файлов это 644, а для каталогов — 755).

Хитрость заключается в Xразрешении, описанном в man chmod, которое действует xтолько для каталогов — именно то различие, которое вам и было нужно.

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

Я должен упомянуть, что это происходит в Linux, хотя беглое прочтение страницы руководства BSD для chmod позволяет предположить, что это так.долженработа там тоже.

решение3

Я провел сравнительный анализответ ситарама,Комментарий Питера Кордеса,Ответ Fanatique, иответ harrymc, ноэтот ответ имеет самый быстрый способ.

Средние значения:

  • Ответ Делтика* – 7,480 секунд
    * КредитПитер Кордесдляпредполагая параллелизм
  • Ответ ситарама – 12,962 секунды (на 73,275% медленнее лучшего)
  • Комментарий Питера Кордеса – 14,414 секунды (на 92,685% медленнее лучшего результата)
  • Ответ Fanatique – 14,570 секунд (на 94,772% медленнее лучшего результата)
  • обновленный ответ harrymc – 14,791 секунды (на 97,730% медленнее лучшего)
  • Оригинальный ответ harrymc – 1061,926 секунд (на 14096,113% медленнее лучшего)

Полная статистическая сводка:

Author              N      min     q1      median  q3      max     mean    stddev
------------------  --     ------- ------- ------- ------- ------- ------- --------
Deltik              10     7.121   7.3585  7.4615  7.558   8.005   7.4804  0.248965
sitaram             10     12.651  12.803  12.943  13.0685 13.586  12.9617 0.276589
Peter Cordes        10     14.096  14.2875 14.375  14.4495 15.101  14.4136 0.269732
Fanatique           10     14.219  14.512  14.5615 14.6525 14.892  14.5697 0.211788
harrymc (updated)   10     14.38   14.677  14.8595 14.9025 15.119  14.791  0.21817
harrymc (original)  1      1061.93 1061.93 1061.93 1061.93 1061.93 1061.93 N/A

Команда Deltik в формате бенчмарка:

найти "$(pwd)" -type d -print0 | xargs -0 -P4 chmod 755 & \
найти "$(pwd)" -ввести f -print0 | xargs -0 -P4 chmod 644 и подождать

Команда ситарама в формате бенчмарка:

chmod -R a=,u+rwX,go+rX "$(пароль)"

Команда Питера Кордеса в формате эталонного теста:

найти "$(pwd)" \( -type d -exec chmod 755 {} + \) \
           -o \( -type f -exec chmod 644 {} + \)

Команда Fanatique в формате бенчмарка:

найти "$(pwd)" -type d -print0 | xargs -0 chmod 755 ; \
найти "$(pwd)" -type f -print0 | xargs -0 chmod 644

Обновленная команда harrymc в формате бенчмарка:

найти "$(pwd)" - тип d -exec chmod 755 {} + ; \
найти "$(pwd)" -тип f -exec chmod 644 {} +

Оригинальная команда harrymc в формате бенчмарка:

найти "$(pwd)" - тип d -exec chmod 755 {} \; ; \
найти "$(pwd)" -type f -exec chmod 644 {} \;

Моя команда была самой быстрой благодаря четырем параллельным chmodпроцессам на тип файла. Это позволило запустить несколько ядер ЦП chmod, что сместило узкое место в сторону потоков ввода-вывода ядра или диска.

Команда sitaram заняла второе место, потому что все делается в chmodкоманде. Это существенно снижает накладные расходы по сравнению с другими ответами, потому что:

  • Файлы необходимо сканировать только один раз (аналогично тому, как если бы вы делали одно сканирование findвместо двух) и
  • Не нужно создавать никаких дочерних процессов.

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

Комментарий Питера Кордеса, который использует одну findкоманду, предотвращает двойной поиск записей каталога. Чем больше файлов, тем существеннее это улучшение. Он все еще имеет накладные расходы на создание дочерних chmodпроцессов, поэтому он немного медленнее, чем chmodрешение -only.

Между командой Fanatique и обновленной командой harrymc, findpiped into xargs( find | xargs) был быстрее, поскольку поток результатов обрабатывается асинхронно. Вместо того, чтобы findприостанавливать поведение поиска для -exec, найденные результаты отправляются xargsдля параллельной обработки.
(Разделитель нулевого байта ( find -print0 | xargs -0), похоже, не повлиял на время выполнения.)

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


В тестовой настройке имелось 1000002 обычных файла, содержащихся в 1001 каталоге:

root@demo:~# echo {0..999} | xargs mkdir -p
root@demo:~# find -type d -exec bash -c "cd {}; echo {0..999} | xargs touch" \;
root@demo:~# найти | wc -l
1001003
root@demo:~# find -type d | wc -l
1001
root@demo:~# find -type f | wc -l
1000002

Я установил для всех файлов и папок разрешения 777, как в начальных условиях вопроса.

Затем я провел десять тестов команд, каждый раз восстанавливая разрешения 777перед chmod -R 0777 "$(pwd)"запуском теста.

Представив OUTPUTфайл, содержащий выходные данные каждой команды бенчмарка, я рассчитал среднее время с помощью:

bc <<< "scale=3; ($(grep real OUTPUT | grep -Po '(?<=m).*(?=s)' | xargs | sed 's/ /+/g'))/10"

Результаты сравнительного анализа ответа Дельтика

root@demo:~# for i in {0..9} ; do chmod -R 0777 "$(pwd)" ; time { find "$(pwd)" -type d -print0 | xargs -0 -P4 chmod 755 & find "$(pwd)" -type f -print0 | xargs -0 -P4 chmod 644 & wait ; } ; done
[1] 9791
[2] 9793
[1]- Завершено нахождение "$(pwd)" -type d | xargs -P4 chmod 755
[2]+ Выполнено поиск "$(pwd)" -type f | xargs -P4 chmod 644

реальные 0м7.634с
пользователь 0m2.536s
система 0м23.384с
[1] 9906
[2] 9908
[1]- Завершено нахождение "$(pwd)" -type d | xargs -P4 chmod 755
[2]+ Выполнено поиск "$(pwd)" -type f | xargs -P4 chmod 644

реальный 0м7.443с
пользователь 0m2.636s
система 0м23.106с
[1] 10021
[2] 10023
[1]- Завершено нахождение "$(pwd)" -type d | xargs -P4 chmod 755
[2]+ Выполнено поиск "$(pwd)" -type f | xargs -P4 chmod 644

реальные 0м8.005с
пользователь 0m2.672s
система 0м24.557с
[1] 10136
[2] 10138
[1]- Завершено нахождение "$(pwd)" -type d | xargs -P4 chmod 755
[2]+ Выполнено поиск "$(pwd)" -type f | xargs -P4 chmod 644

реальный 0м7.480с
пользователь 0m2.541s
система 0м23.699с
[1] 10251
[2] 10253
[1]- Завершено нахождение "$(pwd)" -type d | xargs -P4 chmod 755
[2]+ Выполнено поиск "$(pwd)" -type f | xargs -P4 chmod 644

реальные 0м7.397с
пользователь 0m2.558s
система 0м23.583с
[1] 10366
[2] 10368
[1]- Завершено нахождение "$(pwd)" -type d | xargs -P4 chmod 755
[2]+ Выполнено поиск "$(pwd)" -type f | xargs -P4 chmod 644

реальные 0м7.482с
пользователь 0m2.601s
система 0м23.728с
[1] 10481
[2] 10483
[1]- Завершено нахождение "$(pwd)" -type d | xargs -P4 chmod 755
[2]+ Выполнено поиск "$(pwd)" -type f | xargs -P4 chmod 644

реальные 0м7.679с
пользователь 0m2.749s
система 0м23.395с
[1] 10596
[2] 10598
[1]- Завершено нахождение "$(pwd)" -type d | xargs -P4 chmod 755
[2]+ Выполнено поиск "$(pwd)" -type f | xargs -P4 chmod 644

реальный 0м7.243с
пользователь 0m2.583s
система 0м23.400с
[1] 10729
[2] 10731
[1]- Завершено нахождение "$(pwd)" -type d | xargs -P4 chmod 755
[2]+ Выполнено поиск "$(pwd)" -type f | xargs -P4 chmod 644

реальный 0м7.320с
пользователь 0м2.640с
система 0м23.403с
[1] 10844
[2] 10847
[1]- Завершено нахождение "$(pwd)" -type d | xargs -P4 chmod 755
[2]+ Выполнено поиск "$(pwd)" -type f | xargs -P4 chmod 644

реальный 0м7.121с
пользователь 0м2.490с
система 0м22.943с

Среднее время: 7,480 секунд

Результаты бенчмарка ответа ситарама

root@demo:~# for i in {0..9} ; do chmod -R 0777 "$(pwd)" ; time chmod -R a=,u+rwX,go+rX "$(pwd)" ; done

реальный 0м12.860с
пользователь 0m0.940s
система 0м11.725с

реальное 0м13.059с
пользователь 0m0.896s
система 0м11.937с

реальное 0м12.819с
пользователь 0m0.945s
система 0m11.706s

реальное 0м13.078с
пользователь 0m0.855s
сис 0м12.000с

реальное 0м12.653с
пользователь 0m0.856s
система 0m11.667s

реальное 0м12.787с
пользователь 0m0.820s
система 0m11.834s

реальное 0м12.651с
пользователь 0m0.916s
система 0м11.578с

реальное 0м13.098с
пользователь 0m0.939s
система 0m12.004s

реальное 0м13.586с
пользователь 0m1.024s
система 0м12.372с

реальное 0м13.026с
пользователь 0m0.976s
система 0м11.910с

Среднее время: 12,962 секунды.

Результаты сравнительного анализа комментария Питера Кордеса

root@demo:~# for i in {0..9} ; do chmod -R 0777 "$(pwd)" ; time find "$(pwd)" \( -type d -exec chmod 755 {} + \) -o \( -type f -exec chmod 644 {} + \) ; done

реальное 0м14.096с
пользователь 0м1.455с
система 0м12.456с

реальное 0м14.492с
пользователь 0м1.398с
система 0м12.897с

реальное 0м14.309с
пользователь 0м1.518с
система 0м12.576с

реальное 0м14.451с
пользователь 0m1.477s
система 0m12.776s

реальные 0м15.101с
пользователь 0m1.554s
система 0м13.378с

реальное 0м14.223с
пользователь 0м1.470с
система 0м12.560с

реальное 0м14.266с
пользователь 0m1.459s
система 0м12.609с

реальное 0м14.357с
пользователь 0м1.415с
система 0m12.733s

реальное 0м14.393с
пользователь 0m1.404s
система 0м12.830с

реальное 0м14.448с
пользователь 0m1.492s
система 0м12.717с

Среднее время: 14,414 секунд.

Результаты сравнительного анализа ответа Fanatique

root@demo:~# for i in {0..9} ; do chmod -R 0777 "$(pwd)" ; time { find "$(pwd)" -type d -print0 | xargs -0 chmod 755 ; find "$(pwd)" -type f -print0 | xargs -0 chmod 644 ; } ; done

реальное 0м14.561с
пользователь 0m1.991s
система 0м13.343с

реальное 0м14.521с
пользователь 0м1.958с
система 0м13.352с

реальное 0м14.696с
пользователь 0m1.967s
система 0m13.463s

реальное 0м14.562с
пользователь 0м1.875с
система 0м13.400с

реальное 0м14.609с
пользователь 0m1.841s
система 0м13.533с

реальное 0м14.892с
пользователь 0м2.050с
система 0м13.630с

реальное 0м14.291с
пользователь 0м1.885с
система 0м13.182с

реальное 0м14.843с
пользователь 0m2.066s
система 0м13.578с

реальное 0м14.219с
пользователь 0m1.837s
система 0м13.145с

реальное 0м14.503с
пользователь 0m1.803s
система 0м13.419с

Среднее время: 14,570 секунд

Результаты бенчмарка обновленного ответа harrymc

root@demo:~# for i in {0..9} ; do chmod -R 0777 "$(pwd)" ; time { find "$(pwd)" -type d -exec chmod 755 {} + ; find "$(pwd)" -type f -exec chmod 644 {} + ; } ; done

реальное 0м14.975с
пользователь 0m1.728s
система 0м13.050с

реальный 0м14.710с
пользователь 0m1.586s
система 0м12.979с

реальное 0м14.644с
пользователь 0m1.641s
система 0m12.872s

реальное 0м14.927с
пользователь 0m1.706s
система 0m13.036s

реальное 0м14.867с
пользователь 0м1.597с
система 0м13.086с

реальное 0м15.119с
пользователь 0m1.666s
система 0м13.259с

реальное 0м14.878с
пользователь 0м1.590с
система 0м13.098с

реальное 0м14.852с
пользователь 0m1.681s
система 0м13.045с

реальный 0м14.380с
пользователь 0m1.603s
система 0m12.663s

реальное 0м14.558с
пользователь 0m1.514s
система 0м12.899с

Среднее время: 14,791 секунды.

Результаты сравнительного анализа оригинального ответа harrymc

Из-за того, что эта команда была медленной, я запустил тест только один раз.

root@demo:~# for i in {0..0} ; do chmod -R 0777 "$(pwd)" ; time { find "$(pwd)" -type d -exec chmod 755 {} \; ; find "$(pwd)" -type f -exec chmod 644 {} \; ; } ; done
 
реальные 17м41.926с
пользователь 12м26.896с
система 4м58.332с

Затраченное время: 1061,926 секунд

решение4

Если каталоги слишком большие и содержат слишком много файлов, то оригинальный способ, который показал @harrymc, не сработает.

Если у вас слишком много файлов, вам нужно будет выполнить конвейеризацию findс xargsпомощью chmod:

find /base/dir -type d -print0 | xargs -0 chmod 755 
find /base/dir -type f -print0 | xargs -0 chmod 644

Связанный контент