Usrmerge: различия между версиями
Строка 68: | Строка 68: | ||
Из перечисленных множеств пересекающихся в будущем пакетов многие уже явно конфликтуют друг с другом. | Из перечисленных множеств пересекающихся в будущем пакетов многие уже явно конфликтуют друг с другом. | ||
3) Подготовить пакет {{pkg|filesystem}} версии 3: поместить в нём | 3) Подготовить пакет {{pkg|filesystem}} версии 3: поместить в нём скрипт, срабатывающий в <tt>%pretrans</tt> и переносящий содержимое каталогов из списка 1 внутрь {{path|/usr}} (т. е. под префикс). | ||
Сценарий файлтриггера должен будет давать предельно ясную информацию и диагностические сообщения на стандартные потоки. | |||
Нужно будет либо положиться на static coreutils, либо очень осторожно обращаться с обычными и dynamic linker. | |||
Сценарий файлтриггера должен будет давать предельно ясную информацию и | |||
диагностические сообщения на стандартные потоки. Нужно будет либо | |||
положиться на static coreutils, либо очень осторожно обращаться с | |||
обычными и dynamic linker. | |||
=== Стадия 2 === | === Стадия 2 === |
Версия от 20:07, 14 апреля 2024
Usrmerge
Точный план действий сейчас вырабатывается, и его подробности могут измениться. Статус воплощения отслеживается в altbug #46738.
Глоссарий
merged-usr-иерархией называется такая FHS-подобная иерархия каталогов, в которой все неизменяемые при работе файлы из операционной системы (т. е. из состава пакетов в репозитории ОС) помещаются либо внутри префикса (/usr), либо их местоположение является ссылкой внутрь префикса. В такой иерархии /bin, /lib и т. д. будут симлинками на /usr/bin, /usr/lib и т. д. Иерархия, не отвечающая этому правилу (например, та, которую создавал инсталлятор до p11), называется unmerged-usr.
split-usr-конфигурация подразумевает, что исполнимый файл в процессе pid 1 из корневой файловой системы стартует до монтирования /usr, расположенного на отдельном разделе. split-usr не следует путать с unmerged-usr, хоть системы со свойством split-usr и являются подмножеством систем unmerged-usr.
Введение
Исторически[1] в UNIX System V, а позже и в мейнстримных линукс-дистрибутивах разделяли каталоги /bin и /usr/bin, /lib$suff и /usr/lib$suff, и т. п., давая возможность разместить /usr на отдельной файловой системе от /, содержащего все эти подкаталоги.
Позже, с увеличением средних размеров устройств хранения в машинах, сторонники разделения придумали другие обоснования (например, возможность из окружения в /{bin,sbin,libX,...}/ починить немонтирующуюся /usr). Но на сегодняшний день непонятно, какой набор утилит и нужных им so/иных файлов стоит признать частью "системы спасения", которая должна быть доступна без /usr, а какой — нет, ибо сами утилиты приобретают универсальный вид и широкие границы применимости. С развитием механизмов initramfs и живых загрузочных/установочных носителей, а также практикой "раздела восстановления" на локальном хранилище машины среди настольных дистрибутивов этот аргумент теряет всякий смысл.
Чем сохранять бесцельно дублирующие друг друга два класса мест для одних и тех же файлов, лучше оставить один из них, а другой устранить:
- либо переложить /usr/{bin,sbin,lib,libx32,lib64,libexec,local,share,src,...} в корень,
- либо поместить аналоги этих каталогов из / в /usr.
Из двух вариантов, входящих в рамки FHS[2], второй лучше хотя бы тем, что уменьшает количество top-level каталогов, куда упаковывается постоянное содержимое пакетов, до одного. Сейчас среди FHS-совместимых дистрибутивов это типичный подход, на который в том числе потихоньку начинают полагаться апстримы прикладных пакетов.
Rationale
- Один каталог (пусть с не очень удачным именем /usr) как объект манипуляции и как общий носитель фиксированного содержимого пакетов удобнее россыпи каталогов, полный список которых даже невозможно построить. Появляется даже смысл рассматривать его в виде отдельной точки монтирования, которую можно держать общей на многих машинах под общим управлением.
- Один каталог легче снапшотить, по нему легче гонять find, ...
- Упаковка всего пакетного содержимого в /usr открывает дорогу к виртуальному /, который не находится на устройстве хранения и содержит только пустые каталоги-точки-монтирования.
- Возникает осмысленное разделение между /usr, /var и /etc: первый каталог несёт в себе постоянное содержимое пакетов, не предназначенное к ручной модификации (не через пакетную систему или доставку образа), а другие два уже исторически применяются для переменного хранимого состояния и общесистемных конфигов.
- Сборочным скриптам и прочим интеграционным программным компонентам не нужно будет перебирать каталоги, в которых находится искомая программа.[3]
- Начиная с версии 255, выпущенной в декабре 2023, systemd прекратит поддержку split-usr и unmerged-usr; вот коммит.
- Из кода проекта systemd, помимо прочего, исчезнут все упоминания старых каталогов; например, директива ProtectKernelModules= больше не будет монтировать заглушку поверх /lib/modules, и т. п.
Proposed changes
Необходимые действия можно разбить на три стадии.
Стадия 1
1) Определить, что слиянию с аналогами внутри /usr подлежат следующие каталоги:
/bin /lib /lib32 /lib64 /libx32 /sbin
На каждой машине есть некоторые каталоги из этого списка; они и будут перенесены.
2) Ввести brp-модуль brp-dupe-bin, который на стадии brp завершается с ошибкой, если обнаружены разные файлы в /bin/x и /usr/bin/x, а если один из них есть ссылка на другой, устанавливает две копии такого файла по обоим путям с совпадающими атрибутами и контентом. Это нужно, чтобы приблизительно 22 пакета могли устанавливаться на все варианты иерархий: и на unmerged-usr, и на merged-usr. Создавать жёсткую ссылку нежелательно: если /bin/x и /usr/bin/x лежат на разных файловых системах, такой пакет туда не установится: RPM не рассечёт жёсткую ссылку на два одинаковых файла. Большинство пакетов, требующих исправления, достаточно будет просто пересобрать со специальным brp-модулем.
Некоторые пакеты, например, vim-common, сейчас упаковывают разные файловые объекты в /bin и /usr/bin; другие пакеты ставят файлы прямо в %buildroot/bin. Их потребуется исправить руками. (Справедливости ради, многие из них и так понадобится обновить)
Полный список таких будущих конфликтов на 2024-03-16:
[('bin/bsh', {'ash', 'bsh'}), ('bin/ksh', {'ksh', 'pdksh'}), ('bin/mail', {'mailutils', 'mailx'}), ('bin/ex', {'vi-traditional', 'vim-common', 'vim-minimal'}), ('bin/rview', {'vim-common', 'vim-minimal'}), ('bin/vi', {'vi-traditional', 'vim-minimal'}), ('sbin/halt', {'shepherd', 'systemd-sysvinit', 'sysvinit'}), ('sbin/reboot', {'shepherd', 'systemd-sysvinit', 'sysvinit'}), ('sbin/shutdown', {'shepherd', 'systemd-sysvinit', 'sysvinit'})]
Из перечисленных множеств пересекающихся в будущем пакетов многие уже явно конфликтуют друг с другом.
3) Подготовить пакет filesystem версии 3: поместить в нём скрипт, срабатывающий в %pretrans и переносящий содержимое каталогов из списка 1 внутрь /usr (т. е. под префикс). Сценарий файлтриггера должен будет давать предельно ясную информацию и диагностические сообщения на стандартные потоки. Нужно будет либо положиться на static coreutils, либо очень осторожно обращаться с обычными и dynamic linker.
Стадия 2
Этот пункт вступает в действие на каждой машине индивидуально при обновлении её пакетов. Файлтриггер из пункта 3 обнаруживает, что можно ввести симлинки, и делает это, завершая процесс usrmerge на данной системе.
Каждая инсталляция перейдёт к ней независимо, как только все пакеты в этой инсталляции будут содержать свои файлы под /usr.
Стадия 3
Заменить макросы, использующие старые каталоги (%_udevrulesdir, %_tmpfilesdir и другие), и пересобрать с ними пакеты, что-либо помещающие в эти каталоги. Приближённое число затрагиваемых бинарных пакетов:
% grep -E '^/(bin|lib[^/]*|sbin)/[a-zA-Z0-9_-]+' contents-index \ | grep -vE '^/lib/(systemd|udev|sysusers.d|modules[^/]*|modprobe.d|security|tmpfiles.d)' \ # exclude known places | cut -f2 -d$'\t' | grep -v '^/' # exclude path provides | sort -u | wc -l 524
Это оценка по x86_64 + noarch. Исходных, конечно, будет меньше (333).
При обновлении на эти пакеты будет действовать правило 2, поэтому их содержимое будет доступно.
Incompatibilities
Если корневая файловая система — каскадная композиция на базе, например, overlayfs, и каталоги /bin и подобные находятся не в верхнем слое стека — автоматически обновить такую корневую файловую систему на filesystem > 3 не выйдет. Придётся либо не обновляться, либо пересобрать контейнер/систему на обновлённой пакетной базе.
FAQ
Рекомендуем прочитать другие материалы о преимуществах предлагаемого решения[4][5].
Q: А что, если /usr на отдельном разделе по каким-то причинам не примонтируется?
A: Тогда система не сможет загрузиться, как и в случае, если / по каким-то причинам не примонтируется.
Q: А раньше можно было, пользуясь программами в /, починить /usr
A: Несколько тезисов:
- В-нулевых, для того, чтобы возникла такая ситуация, систему должны были установить так, чтобы /usr был отдельным от /, т. е. такая разметка преследовала какую-либо цель.
- Во-первых, для этого нужно, чтобы / смог смонтироваться, а /usr не смог.
- Во-вторых, всё ещё нет критерия, по которому ту или иную программу и её зависимости можно либо отнести к "системе спасения", либо исключить из неё и сослать в /usr.
- В-третьих, нет ни одного задокументированного случая, где таким образом спасли какую-либо типичную GNU/Linux-систему, включая Альт, есть только предание из 1986 года, касавшееся non-Linux тех времён на компьютере тех времён. Рецептов такого восстановления, отчуждаемых от компетенций разработчиков ALT и умелых сисадминов, нет тем более. Следовательно, можно заключить, что в общем случае цитируемая возможность восстановить /usr из / — призрачна.
- Несмотря на всё это, нет ничего плохого в том, чтобы рецепт такого спасения (при помощи операционной избыточности инсталляции альта) администратору предложить, но это должен быть явный механизм с минимумом издержек для остальной структуры системы. Есть множество вариантов это реализовать с разными преимуществами и минусами в разных установках; все они out of scope for this document.
User-visible impact
Меньше каталогов верхнего уровня в корне, кроме симлинков.
Appendix
- ↑ [1]
- ↑ [2]
- ↑ Вообще-то для этого нужно ещё провести слияние sbin и bin, но оно не несёт срочности и не рассматривается на этой странице.
- ↑ TheCaseForTheUsrMerge
- ↑ separate-usr-is-broken, примеры, где в ранней системе полагаются на наличие /usr}