Глава 6. dracut

Проще говоря, dracut это некий инструментарий, который создаёт ф системах на основе Fedora соответствующую файловую систему initramfs. Системы на основе Debian и Ubuntu пользуются аналогичным инструментарием, носящим название update-initramfs. Когда вы желаете создать, повторно выработать или персонализировать уде имеющуюся initramfs, тогда вам следует знать как пользоваться этим инструментарием dracut. Кроме того, вы ознакомитесь с наиболее распространёнными проблемами "Can’t Boot", относящимися к initramfs.

Приступая к работе

Всякое ядро обладает своим собственным файлом initramfs, но для вас может оказаться интересным почему же вам никогда не приходилось применять для создания initramfs при установке некого нового ядра соответствующей команды dracut. Вместо этого вы просто отыскиваете надлежащий initramfs в имеющемся местоположении /boot. Ну хорошо, когда вы устанавливаете какое- то новое ядро, соответствующая выполняемая по завершению сценария (post-scripts) команда пакета rpm этого ядра вызывает dracut и создаёт для вас initramfs. Давайте рассмотрим как это работает в системе на основании Fedora:


# rpm -q --scripts kernel-core-5.3.7-301.fc31.x86_64
postinstall scriptlet (using /bin/sh):

if [ `uname -i` == "x86_64" -o `uname -i` == "i386" ] &&
   [ -f /etc/sysconfig/kernel ]; then
  /bin/sed -r -i -e 's/^DEFAULTKERNEL=kernel-smp$/DEFAULTKERNEL=kernel/' /etc/sysconfig/kernel || exit $?
fi
preuninstall scriptlet (using /bin/sh):
/bin/kernel-install remove 5.3.7-301.fc31.x86_64 /lib/modules/5.3.7-301.fc31.x86_64/vmlinuz || exit $?
posttrans scriptlet (using /bin/sh):
/bin/kernel-install add 5.3.7-301.fc31.x86_64 /lib/modules/5.3.7-301.fc31.x86_64/vmlinuz || exit $?
		

Как вы можете видеть, соответствующая команда post-scripts запускаемого пакета ядра вызывает надлежащий сценарий kernel-install. Этот сценарий kernel-install выполняет все те сценарии, которые доступны в /usr/lib/kernel/install.d.


# vim /bin/kernel-install

 94 if ! [[ $MACHINE_ID ]]; then
 95     ENTRY_DIR_ABS=$(mktemp -d /tmp/kernel-install.XXXXX) || exit 1
 96     trap "rm -rf '$ENTRY_DIR_ABS'" EXIT INT QUIT PIPE
 97 elif [[ -d /efi/loader/entries ]] || [[ -d /efi/$MACHINE_ID ]]; then
 98     ENTRY_DIR_ABS="/efi/$MACHINE_ID/$KERNEL_VERSION"
 99 elif [[ -d /boot/loader/entries ]] || [[ -d /boot/$MACHINE_ID ]]; then
100     ENTRY_DIR_ABS="/boot/$MACHINE_ID/$KERNEL_VERSION"
101 elif [[ -d /boot/efi/loader/entries ]] || [[ -d /boot/efi/$MACHINE_ID ]]; then
102     ENTRY_DIR_ABS="/boot/efi/$MACHINE_ID/$KERNEL_VERSION"
103 elif mountpoint -q /efi; then
104     ENTRY_DIR_ABS="/efi/$MACHINE_ID/$KERNEL_VERSION"
105 elif mountpoint -q /boot/efi; then
106     ENTRY_DIR_ABS="/boot/efi/$MACHINE_ID/$KERNEL_VERSION"
107 else
108     ENTRY_DIR_ABS="/boot/$MACHINE_ID/$KERNEL_VERSION"
109 fi
110
111 export KERNEL_INSTALL_MACHINE_ID=$MACHINE_ID
112
113 ret=0
114
115 readarray -t PLUGINS <<<"$(
116     dropindirs_sort ".install" \
117         "/etc/kernel/install.d" \
118         "/usr/lib/kernel/install.d"
119 )"
		

Здесь вы можете рассмотреть как наши сценарии выполняются kernel-install:


# ls /usr/lib/kernel/install.d/ -lh
total 36K
-rwxr-xr-x. 1 root root  744 Oct 10 18:26 00-entry-directory.install
-rwxr-xr-x. 1 root root 1.9K Oct 19 07:46 20-grubby.install
-rwxr-xr-x. 1 root root 6.6K Oct 10 13:05 20-grub.install
-rwxr-xr-x. 1 root root  829 Oct 10 18:26 50-depmod.install
-rwxr-xr-x. 1 root root 1.7K Jul 25  2019 50-dracut.install
-rwxr-xr-x. 1 root root 3.4K Jul 25  2019 51-dracut-rescue.install
-rwxr-xr-x. 1 root root 3.4K Oct 10 18:26 90-loaderentry.install
-rwxr-xr-x. 1 root root 1.1K Oct 10 13:05 99-grub-mkconfig.install
		

Как вы можете видеть, это выполняет сценарий 50-dracut.install. Именно этот конкретный сценарий выполняет соответствующую команду dracut и создаёт initramfs для какого- то определённого ядра.


46         for ((i=0; i < "${#BOOT_OPTIONS[@]}"; i++)); do
 47             if [[ ${BOOT_OPTIONS[$i]} == root\=PARTUUID\=* ]]; then
 48                 noimageifnotneeded="yes"
 49                 break
 50             fi
 51         done
 52         dracut -f ${noimageifnotneeded:+--noimageifnotneeded} "$BOOT_DIR_ABS/$INITRD" "$KERNEL_VERSION"
 53         ret=$?
 54         ;;
 55     remove)
 56         rm -f -- "$BOOT_DIR_ABS/$INITRD"
 57         ret=$?
 58         ;;
 59 esac
 60 exit $ret
		

Аналогично имеется надлежащий сценарий 51-dracut-rescue.install, который создаст initramfs для соответствующего аварийного ядра.


100         if [[ ! -f "$BOOT_DIR_ABS/$INITRD" ]]; then
101             dracut -f --no-hostonly -a "rescue" "$BOOT_DIR_ABS/$INITRD" "$KERNEL_VERSION"
102             ((ret+=$?))
103         fi
104
105         if [[ "${BOOT_DIR_ABS}" != "/boot" ]]; then
106             {
107                 echo "title      $PRETTY_NAME - Rescue Image"
108                 echo "version    $KERNEL_VERSION"
109                 echo "machine-id $MACHINE_ID"
110                 echo "options    ${BOOT_OPTIONS[@]} rd.auto=1"
111                 echo "linux      $BOOT_DIR/linux"
112                 echo "initrd     $BOOT_DIR/initrd"
113             } > $LOADER_ENTRY
114         else
115             cp -aT "${KERNEL_IMAGE%/*}/bls.conf" $LOADER_ENTRY
116             sed -i 's/'$KERNEL_VERSION'/0-rescue-'${MACHINE_ID}'/' $LOADER_ENTRY
117         fi
		

Тем самым, всякое ядро будет обладать своим собственным файлом initramfs.


# ls -lh /boot | grep -e vmlinuz -e initramfs

-rw-------. 1 root root  80M Dec  2 18:32 initramfs-0-rescue-280526b3bc5e4c49ac83c8e5fbdfdb2e.img
-rw-------. 1 root root  28M Dec 23 06:37 initramfs-5.3.16-300.fc31.x86_64.img
-rw-------. 1 root root  30M Dec  2 18:33 initramfs-5.3.7-301.fc31.x86_64.img
-rwxr-xr-x. 1 root root 8.9M Dec  2 18:32 vmlinuz-0-rescue-280526b3bc5e4c49ac83c8e5fbdfdb2e
-rwxr-xr-x. 1 root root 8.9M Dec 13 23:51 vmlinuz-5.3.16-300.fc31.x86_64
-rwxr-xr-x. 1 root root 8.9M Oct 22 01:04 vmlinuz-5.3.7-301.fc31.x86_64
		

Обратите внимание на размер файла самого ядра (vmlinuz) и связанного с ним файла initramfs. Размер файла намного больше размера ядра.

Создание некого образа initramfs

Сначала проверим при помощи данной команды проверим какое ядро было установлено в вашей системе:


# rpm -qa | grep -i kernel-5

kernel-5.3.16-300.fc31.x86_64
kernel-5.3.7-301.fc31.x86_64
		

Выберите ту версию ядра, для которой вы желаете выработать некий новый образ initramfs и передайте его в dracut.


# dracut /boot/new.img 5.3.7-301.fc31.x86_64 -v
<snip>
dracut: Executing: /usr/bin/dracut /boot/new.img 5.3.7-301.fc31.x86_64 -v
dracut: dracut module 'busybox' will not be installed, because command 'busybox' could not be found!
dracut: dracut module 'stratis' will not be installed, because command 'stratisd-init' could not be found!
dracut: dracut module 'biosdevname' will not be installed, because command 'biosdevname' could not be found!
dracut: dracut module 'busybox' will not be installed, because command 'busybox' could not be found!
dracut: dracut module 'stratis' will not be installed, because command 'stratisd-init' could not be found!
dracut: *** Including module: bash ***
dracut: *** Including module: systemd ***
dracut: *** Including module: systemd-initrd ***
dracut: *** Including module: nss-softokn ***
dracut: *** Including module: i18n ***
dracut: *** Including module: network-manager ***
dracut: *** Including module: network ***
dracut: *** Including module: ifcfg ***
dracut: *** Including module: drm ***
dracut: *** Including module: plymouth ***
.
.
</snip>
		

В нашем предыдущем коде dracut создаст некую initramfs с названием new.img в текущем каталоге для соответствующего 64- битного ядра Fedora, Kernel-5.3.7-301.fc31.x86_64.


# ls -lh new.img
-rw-------. 1 root root 28M Dec 23 08:16 new.img
		

Если запрошенная версия ядра не представлена, тогда dracut сделает initramfs для того ядра, через которое запускалась данная система. Значение передаваемой в dracut версии ядра должно соответствовать значению каталога ядра в местоположении /lib/modules/.


# ls /lib/modules/ -l
total 4
drwxr-xr-x. 6 root root 4096 Dec  9 10:18 5.3.7-301.fc31.x86_64

# ls /lib/modules/5.3.7-301.fc31.x86_64/ -l
total 18084
-rw-r--r--.  1 root root     249 Oct 22 01:04 bls.conf
lrwxrwxrwx.  1 root root      38 Oct 22 01:04 build -> /usr/src/kernels/5.3.7-301.fc31.x86_64
-rw-r--r--.  1 root root  213315 Oct 22 01:03 config
drwxr-xr-x.  5 root root    4096 Oct 24 04:44 extra
drwxr-xr-x. 13 root root    4096 Oct 24 04:43 kernel
-rw-r--r--.  1 root root 1127438 Dec  9 10:18 modules.alias
-rw-r--r--.  1 root root 1101059 Dec  9 10:18 modules.alias.bin
-rw-r--r--.  1 root root    1688 Oct 22 01:04 modules.block
-rw-r--r--.  1 root root    8324 Oct 22 01:04 modules.builtin
-rw-r--r--.  1 root root   10669 Dec  9 10:18 modules.builtin.bin
-rw-r--r--.  1 root root   60853 Oct 22 01:04 modules.builtin.modinfo
-rw-r--r--.  1 root root  415475 Dec  9 10:18 modules.dep
-rw-r--r--.  1 root root  574502 Dec  9 10:18 modules.dep.bin
-rw-r--r--.  1 root root     381 Dec  9 10:18 modules.devname
-rw-r--r--.  1 root root     153 Oct 22 01:04 modules.drm
-rw-r--r--.  1 root root      59 Oct 22 01:04 modules.modesetting
-rw-r--r--.  1 root root    2697 Oct 22 01:04 modules.networking
-rw-r--r--.  1 root root  139947 Oct 22 01:04 modules.order
-rw-r--r--.  1 root root     700 Dec  9 10:18 modules.softdep
-rw-r--r--.  1 root root  468520 Dec  9 10:18 modules.symbols
-rw-r--r--.  1 root root  572778 Dec  9 10:18 modules.symbols.bin
lrwxrwxrwx.  1 root root       5 Oct 22 01:04 source -> build
-rw-------.  1 root root 4426726 Oct 22 01:03 System.map
drwxr-xr-x.  2 root root    4096 Oct 22 01:02 updates
drwxr-xr-x.  2 root root    4096 Oct 24 04:43 vdso
-rwxr-xr-x.  1 root root 9323208 Oct 22 01:04 vmlinuz
		

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

Скажем, допустим соответствующая корневая файловая система пользователя расположена на каком- то локально подключённом жёстком диске и этот HDD это устройство SCSI. Следовательно, initramfs обязана обладать необходимыми драйверами SCSI, добавляемыми в её архив.


# lsinitrd | grep -i scsi | awk '{ print $9 }'
etc/ld.so.conf.d/libiscsi-x86_64.conf
usr/lib/modules/5.3.7-301.fc31.x86_64/kernel/drivers/firmware/iscsi_ibft.ko.xz
usr/lib/modules/5.3.7-301.fc31.x86_64/kernel/drivers/scsi
usr/lib/modules/5.3.7-301.fc31.x86_64/kernel/drivers/scsi/iscsi_boot_sysfs.ko.xz
usr/lib/modules/5.3.7-301.fc31.x86_64/kernel/drivers/scsi/libiscsi.ko.xz
usr/lib/modules/5.3.7-301.fc31.x86_64/kernel/drivers/scsi/qla4xxx
usr/lib/modules/5.3.7-301.fc31.x86_64/kernel/drivers/scsi/qla4xxx/qla4xxx.ko.xz
usr/lib/modules/5.3.7-301.fc31.x86_64/kernel/drivers/scsi/scsi_transport_iscsi.ko.xz
usr/lib/modules/5.3.7-301.fc31.x86_64/kernel/drivers/scsi/scsi_transport_srp.ko.xz
usr/lib/modules/5.3.7-301.fc31.x86_64/kernel/drivers/scsi/virtio_scsi.ko.xz
usr/lib/udev/scsi_id
		

Поверх данного устройства SCSI пользователи могут иметь настроенным некое устройство RAID. Когда и это имеет место, тогда нашему ядру также требуется иметь драйверы устройства RAID для идентификации и сборки необходимого устройства RAID. Аналогично, некоторые имеющиеся HDD пользователя могут подключаться через какую- то карту HBA. В подобных случаях нашему ядру требуются модули наподобии qlaXxxx.


# lsinitrd | grep -i qla

        usr/lib/modules/5.3.7-301.fc31.x86_64/kernel/drivers/scsi/qla4xxx
        usr/lib/modules/5.3.7-301.fc31.x86_64/kernel/drivers/scsi/qla4xxx/qla4xxx.ko.xz
		

Обратите внимание, что в наше время '/lib' это символическая ссылка на '/usr/lib/'.

В случае некоторых пользователей соответствующий HDD можем поступать через Fiber Channel over Ethernet. Тогда нашему ядру потребуются модули FCOE. В некой среде с виртуализацией такой HDD может быть каким- то виртуальным диском, выставляемым гипервизором. В такой ситуации для монтирования подобной корневой файловой системы пользователя необходим модуль virtIO. Таким образом, имеющийся перечень оборудования и соответствующих ему модулей продолжает расти.

Очевидно, что само ядро не способно хранить все такие необходимые файлы модулей (.ko) в своём собственном исполняемом файле (vmlinuz). Следовательно, одно из основных заданий initramfs состоит в хранении всех таких модулей, которые требуются для монтирования необходимой корневой файловой системы пользователя. Именно это также одна из причин, по которой размер файла initramfs намного больше по сравнению с размером файла ядра. Однако помните, что initramfs не выступает в качестве источника таких модулей. Эти модули всегда будут предоставляться в имеющееся ядро и архивироваться в initramfs через dracut. Само ядро (vmlinuz) является источником всех необходимых модулей, однако как вы могли предугадать, размер подобного ядра будет гигантским если само ядро будет хранить все подобные модули в собственном исполняемом файле vmlinuz. Следовательно, помимо некого пакета kernel, был введён некий новый пакет с названием kernel-modules и именно этот пакет и предоставляет все необходимые модули, которые представлены в соответствующем местоположении /lib/modules/<kernel-version-arch>; dracut вытаскивает лишь те модули (.ko), которые необходимы для монтирования соответствующей корневой файловой системы пользователя.


# rpm -qa | grep -i kernel

        Kernel-headers-5.3.6-300.fc31.x86_64
        kernel-modules-extra-5.3.7-301.fc31.x86_64
        kernel-modules-5.3.7-301.fc31.x86_64
        kernel-core-5.3.16-300.fc31.x86_64
        kernel-core-5.3.7-301.fc31.x86_64
        kernel-5.3.16-300.fc31.x86_64
        abrt-addon-kerneloops-2.12.2-1.fc31.x86_64
        kernel-5.3.7-301.fc31.x86_64
        libreport-plugin-kerneloops-2.10.1-2.fc31.x86_64
        Kernel-modules-5.3.16-300.fc31.x86_64

# rpm -ql kernel-modules-5.3.7-301.fc31.x86_64 | wc -l
    1698

    # rpm -ql kernel-modules-5.3.7-301.fc31.x86_64
    <snip>
    /lib/modules/5.3.7-301.fc31.x86_64/kernel/drivers/atm/atmtcp.ko.xz
    /lib/modules/5.3.7-301.fc31.x86_64/kernel/drivers/atm/eni.ko.xz
    /lib/modules/5.3.7-301.fc31.x86_64/kernel/drivers/atm/firestream.ko.xz
    /lib/modules/5.3.7-301.fc31.x86_64/kernel/drivers/atm/he.ko.xz
    /lib/modules/5.3.7-301.fc31.x86_64/kernel/drivers/atm/nicstar.ko.xz
    /lib/modules/5.3.7-301.fc31.x86_64/kernel/drivers/atm/solos-pci.ko.xz
    /lib/modules/5.3.7-301.fc31.x86_64/kernel/drivers/atm/suni.ko.xz
    /lib/modules/5.3.7-301.fc31.x86_64/kernel/drivers/auxdisplay/cfag12864b.ko.xz
    /lib/modules/5.3.7-301.fc31.x86_64/kernel/drivers/auxdisplay/cfag12864bfb.ko.xz
    /lib/modules/5.3.7-301.fc31.x86_64/kernel/drivers/auxdisplay/charlcd.ko.xz
    /lib/modules/5.3.7-301.fc31.x86_64/kernel/drivers/auxdisplay/hd44780.ko.xz
    /lib/modules/5.3.7-301.fc31.x86_64/kernel/drivers/auxdisplay/ks0108.ko.xz
    /lib/modules/5.3.7-301.fc31.x86_64/kernel/drivers/bcma/bcma.ko.xz
    /lib/modules/5.3.7-301.fc31.x86_64/kernel/drivers/bluetooth/ath3k.ko.xz
    /lib/modules/5.3.7-301.fc31.x86_64/kernel/drivers/bluetooth/bcm203x.ko.xz
    /lib/modules/5.3.7-301.fc31.x86_64/kernel/drivers/bluetooth/bfusb.ko.xz
    /lib/modules/5.3.7-301.fc31.x86_64/kernel/drivers/bluetooth/bluecard_cs.ko.xz
    /lib/modules/5.3.7-301.fc31.x86_64/kernel/drivers/bluetooth/bpa10x.ko.xz
    .
    .
    </snip>
		

Как вы можете видеть, соответствующий пакет kernel-modules, который поставляется с kernel-5.3.7-301, предоставляет почти 1 698 модулей. Кроме того, этот пакет kernel-module будет обладать некой зависимостью от своего пакета kernel; таким образом, при каждой установке kernel, операционная система Fedora будет доставлять и устанавливать kernel-modules.

Dracut и модули

Теперь мы ознакомимся с модулями dracut.

Как dracut выбирает модули?

Чтобы разобраться в том как dracut вытаскивает необходимые модули в initramfs, сначала нам необходимо понять команду depmod. depmod анализирует все имеющиеся в местоположении /lib/modules/<kernel-version-arch> модули ядра и составляет некий список всех этих модулей совместно с их модулями зависимостей. Он оставляет этот перечень в файле modules.dep. (Обратите внимание, что в системах на основании Fedora лучше ссылаться на это местоположение модулей как на /usr/lib/modules/<kernel_version>/*,) Вот некий образец:


# vim /lib/modules/5.3.7-301.fc31.x86_64/modules.dep
<snip>
.
.
kernel/arch/x86/kernel/cpu/mce/mce-inject.ko.xz:
kernel/arch/x86/crypto/des3_ede-x86_64.ko.xz: kernel/crypto/des_generic.ko.xz
kernel/arch/x86/crypto/camellia-x86_64.ko.xz:
kernel/arch/x86/crypto/blowfish-x86_64.ko.xz: kernel/crypto/blowfish_common.ko.xz
kernel/arch/x86/crypto/twofish-x86_64.ko.xz: kernel/crypto/twofish_common.ko.xz
.
.
</snip>
		

В приведённом коде вы можете обнаружить что модуль с названием des3_ede для надлежащей работы нуждается в модуле des_generic. В другом примере мы видите, что модули blowfish обладают в качестве зависимости модулем blowfish_comman. А потому dracut считывает имеющийся файл modules.dep и начинает активную доставку необходимых модулей ядра в создаваемый образ initramfs из местоположения /lib/modules/5.3.7-301.fc31.x86_64/kernel/.


# ls /lib/modules/5.3.7-301.fc31.x86_64/kernel/ -l
total 44
drwxr-xr-x.  3 root root 4096 Oct 24 04:43 arch
drwxr-xr-x.  4 root root 4096 Oct 24 04:43 crypto
drwxr-xr-x. 80 root root 4096 Oct 24 04:43 drivers
drwxr-xr-x. 43 root root 4096 Oct 24 04:43 fs
drwxr-xr-x.  4 root root 4096 Oct 24 04:43 kernel
drwxr-xr-x.  8 root root 4096 Oct 24 04:43 lib
drwxr-xr-x.  2 root root 4096 Oct 24 04:43 mm
drwxr-xr-x. 51 root root 4096 Oct 24 04:43 net
drwxr-xr-x.  3 root root 4096 Oct 24 04:43 security
drwxr-xr-x. 13 root root 4096 Oct 24 04:43 sound
drwxr-xr-x.  3 root root 4096 Oct 24 04:43 virt
		

Наше ядро предоставляет тысячи модулей, но нет нужды добавлять в initramfs все модули. Таким образом, при сборе модулей dracut вытаскивает все конкретные модули.


# find /lib/modules/5.3.7-301.fc31.x86_64/ -name '*.ko.xz' | wc -l
3539
		

Когда dracut вытягивает все модули, тогда размер initramfs был бы огромным. Кроме того, зачем вытаскивать все модули, когда это не необходимо? Итак, dracut вытаскивает лишь те модули, которые необходимы для монтажа необходимой корневой файловой системы в данной системе.


# lsinitrd | grep -i '.ko.xz' | wc -l
221
		

Как вы можете видеть, initramfs имеет лишь 221 модуль, в то время как его ядро обладает в себе почти 3 539 модулями.

Если бы мы включили в initramfs 3 539 модулей, это бы превратило initramfs в гигантский, что в конечном счёте замедлило бы производительность запуска потому как время загрузки м раскрытия архива initramfs было бы высоким. Кроме того, нам следует понимать, что главная задача initramfs состоит в монтировании основной корневой файловой системы пользователя. Таким образом, это делает существенным включение лишь только тех модулей, которые необходимы для монтирования самой корневой файловой системы. Например, в initramfs нет необходимости добавления модулей Bluetooth, ибо корневая файловая система никогда не приходит на подключаемых через Bluetooth устройствах. Поэтому в initramfs вы не найдёте связанных с Bluetooth модулей, даже хотя и имеется пара предоставляемых самим ядром (kernel-modules) модулей bluetooth.


# find /lib/modules/5.3.7-301.fc31.x86_64/ -name 'bluetooth'
    /lib/modules/5.3.7-301.fc31.x86_64/kernel/net/bluetooth
    /lib/modules/5.3.7-301.fc31.x86_64/kernel/drivers/bluetooth

# lsinitrd | grep -i blue
    <no_output> 
		

По умолчанию dracut добавит в initramfs лишь относящиеся к хосту модули. Он выполняет это инспектируя состояние своей текущей системы и тех модулей, которые в настоящий модуль применяются данной системой. Для всех ведущих дистрибутивов Linux подходом по умолчанию является отслеживание специфики хоста. Подобные Fedors и Ubuntu системы также создают некий общий образ initramfs, имеющий название аварийного образа initramfs. Такой аварийный initramfs содержит все возможные модули для устройств на которых пользователи имеют возможность создавать некую корневую файловую систему. Основная идея состоит в том, что такая общая initramfs должна подходить ко всем имеющимся системам. Следовательно, такая аварийная initramfs всегда будет большей в размере по сравнению с initramfs специфичными для конкретных хостов. Dracut обладает пакетом некой логики для принятия решения какие модули необходимы для монтирования своей корневой файловой системы. Именно об этом сообщает страница man, но помните, что в Linux на основе Fedora по умолчанию устанавливается --hostonly.

"Если вы желаете создавать более лёгкие initramfs с меньшим размером, вы можете захотеть определять вариант --hostonly или -H. Применяя данный вариант, получаемый в результате образ будет содержать лишь те dracut модули, модули ядра и файловые системы, которые необходимы для запуска этой конкретной машины. Это обладает тем недостатком, что вы можете поместить свой диск на другом контроллере или машине и вы не сможете переключиться на другую корневую файловую систему без повторного создания соответствующего образа initramfs. Применение варианта -hostonly служит лишь для профессионалов и вам придётся хранить осколки. По крайней мере храните копию образа общего назначения (и соответствующие ядра) в качестве запасного варианта для спасения своей системы."

В Главе 5 мы обнаружили, что существует большое число исполняемых файлов, модулей и файлов настройки, которые были выбраны dracut и добавлены в initramfs, но каким образом dracut выбирает файлы из корневой файловой системы пользователя большего размера?

Эти файлы выбираются запуском сценариев из /usr/lib/dracut/modules.d. Именно в этом месте хранятся все необходимые сценарии dracut. Dracut запускает эти сценарии при выработке initramfs как это показано тут:


# ls /usr/lib/dracut/modules.d/ -l
total 288
drwxr-xr-x. 2 root root 4096 Oct 24 04:43 00bash
drwxr-xr-x. 2 root root 4096 Oct 24 04:43 00systemd
drwxr-xr-x. 2 root root 4096 Oct 24 04:43 00warpclock
drwxr-xr-x. 2 root root 4096 Oct 24 04:43 01fips
drwxr-xr-x. 2 root root 4096 Oct 24 04:43 01systemd-initrd
drwxr-xr-x. 2 root root 4096 Oct 24 04:43 02systemd-networkd
drwxr-xr-x. 2 root root 4096 Oct 24 04:43 03modsign
drwxr-xr-x. 2 root root 4096 Oct 24 04:43 03rescue
drwxr-xr-x. 2 root root 4096 Oct 24 04:43 04watchdog
drwxr-xr-x. 2 root root 4096 Oct 24 04:43 05busybox
drwxr-xr-x. 2 root root 4096 Oct 24 04:42 05nss-softokn
drwxr-xr-x. 2 root root 4096 Oct 24 04:43 05rdma
drwxr-xr-x. 2 root root 4096 Oct 24 04:43 10i18n
drwxr-xr-x. 2 root root 4096 Oct 24 04:43 30convertfs
drwxr-xr-x. 2 root root 4096 Oct 24 04:43 35network-legacy
drwxr-xr-x. 2 root root 4096 Oct 24 04:43 35network-manager
drwxr-xr-x. 2 root root 4096 Oct 24 04:43 40network
drwxr-xr-x. 2 root root 4096 Oct 24 04:43 45ifcfg
drwxr-xr-x. 2 root root 4096 Oct 24 04:43 45url-lib
drwxr-xr-x. 2 root root 4096 Oct 24 04:43 50drm
drwxr-xr-x. 2 root root 4096 Oct 24 04:43 50plymouth
drwxr-xr-x. 2 root root 4096 Oct 24 04:43 80lvmmerge
drwxr-xr-x. 2 root root 4096 Oct 24 04:42 90bcache
drwxr-xr-x. 2 root root 4096 Oct 24 04:43 90btrfs
drwxr-xr-x. 2 root root 4096 Oct 24 04:43 90crypt
drwxr-xr-x. 2 root root 4096 Oct 24 04:43 90dm
drwxr-xr-x. 2 root root 4096 Oct 24 04:43 90dmraid
drwxr-xr-x. 2 root root 4096 Oct 24 04:44 90dmsquash-live
drwxr-xr-x. 2 root root 4096 Oct 24 04:44 90dmsquash-live-ntfs
drwxr-xr-x. 2 root root 4096 Oct 24 04:43 90kernel-modules
drwxr-xr-x. 2 root root 4096 Oct 24 04:43 90kernel-modules-extra
drwxr-xr-x. 2 root root 4096 Oct 24 04:43 90kernel-network-modules
drwxr-xr-x. 2 root root 4096 Oct 24 04:44 90livenet
drwxr-xr-x. 2 root root 4096 Oct 24 04:43 90lvm
drwxr-xr-x. 2 root root 4096 Oct 24 04:43 90mdraid
drwxr-xr-x. 2 root root 4096 Oct 24 04:43 90multipath
drwxr-xr-x. 2 root root 4096 Oct 24 04:43 90qemu
drwxr-xr-x. 2 root root 4096 Oct 24 04:43 90qemu-net
drwxr-xr-x. 2 root root 4096 Oct 24 04:43 90stratis
drwxr-xr-x. 2 root root 4096 Oct 24 04:43 91crypt-gpg
drwxr-xr-x. 2 root root 4096 Oct 24 04:43 91crypt-loop
drwxr-xr-x. 2 root root 4096 Oct 24 04:43 95cifs
drwxr-xr-x. 2 root root 4096 Oct 24 04:43 95debug
drwxr-xr-x. 2 root root 4096 Oct 24 04:43 95fcoe
drwxr-xr-x. 2 root root 4096 Oct 24 04:43 95fcoe-uefi
drwxr-xr-x. 2 root root 4096 Oct 24 04:43 95fstab-sys
drwxr-xr-x. 2 root root 4096 Oct 24 04:43 95iscsi
drwxr-xr-x. 2 root root 4096 Oct 24 04:43 95lunmask
drwxr-xr-x. 2 root root 4096 Oct 24 04:43 95nbd
drwxr-xr-x. 2 root root 4096 Oct 24 04:43 95nfs
drwxr-xr-x. 2 root root 4096 Oct 24 04:43 95resume
drwxr-xr-x. 2 root root 4096 Oct 24 04:43 95rootfs-block
drwxr-xr-x. 2 root root 4096 Oct 24 04:43 95ssh-client
drwxr-xr-x. 2 root root 4096 Oct 24 04:43 95terminfo
drwxr-xr-x. 2 root root 4096 Oct 24 04:43 95udev-rules
drwxr-xr-x. 2 root root 4096 Oct 24 04:43 95virtfs
drwxr-xr-x. 2 root root 4096 Oct 24 04:43 97biosdevname
drwxr-xr-x. 2 root root 4096 Jan  6 12:42 98dracut-systemd
drwxr-xr-x. 2 root root 4096 Oct 24 04:43 98ecryptfs
drwxr-xr-x. 2 root root 4096 Oct 24 04:44 98ostree
drwxr-xr-x. 2 root root 4096 Oct 24 04:43 98pollcdrom
drwxr-xr-x. 2 root root 4096 Oct 24 04:43 98selinux
drwxr-xr-x. 2 root root 4096 Oct 24 04:43 98syslog
drwxr-xr-x. 2 root root 4096 Oct 24 04:43 98usrmount
drwxr-xr-x. 2 root root 4096 Oct 24 04:43 99base
drwxr-xr-x. 2 root root 4096 Oct 24 04:43 99earlykdump
drwxr-xr-x. 2 root root 4096 Oct 24 04:43 99fs-lib
drwxr-xr-x. 2 root root 4096 Oct 24 04:44 99img-lib
drwxr-xr-x. 2 root root 4096 Oct 24 04:43 99kdumpbase
drwxr-xr-x. 2 root root 4096 Oct 24 04:43 99shutdown
drwxr-xr-x. 2 root root 4096 Oct 24 04:43 99squash
drwxr-xr-x. 2 root root 4096 Oct 24 04:43 99uefi-lib
		

Тот же самый вывод можно получить воспользовавшись #dracut --list-modules.

При каждой попытке создания initramfs dracut запускает файлы сценария module-setup.sh во всех каталогах /usr/lib/dracut/modules.d/.


# find /usr/lib/dracut/modules.d/ -name 'module-setup.sh'

/usr/lib/dracut/modules.d/95iscsi/module-setup.sh
/usr/lib/dracut/modules.d/98ecryptfs/module-setup.sh
/usr/lib/dracut/modules.d/30convertfs/module-setup.sh
/usr/lib/dracut/modules.d/90crypt/module-setup.sh
/usr/lib/dracut/modules.d/10i18n/module-setup.sh
/usr/lib/dracut/modules.d/99earlykdump/module-setup.sh
/usr/lib/dracut/modules.d/95nbd/module-setup.sh
.
.
.
/usr/lib/dracut/modules.d/04watchdog/module-setup.sh
/usr/lib/dracut/modules.d/90lvm/module-setup.sh
/usr/lib/dracut/modules.d/35network-legacy/module-setup.sh
/usr/lib/dracut/modules.d/01systemd-initrd/module-setup.sh
/usr/lib/dracut/modules.d/99squash/module-setup.sh
/usr/lib/dracut/modules.d/05busybox/module-setup.sh
/usr/lib/dracut/modules.d/50drm/module-setup.sh
		

Этот сценарий module-setup.sh выцепит модули, исполняемые файлы и файлы настройки, которые специфичны для данного хоста. К примеру, самый первый сценарий module-setup.sh, который мы запускаем в каталоге 00bash, включит в initramfs необходимый исполняемый файл bash.


# vim /usr/lib/dracut/modules.d/00bash/module-setup.sh

  1 #!/usr/bin/bash
  2
  3 # called by dracut
  4 check() {
  5     require_binaries /bin/bash
  6 }
  7
  8 # called by dracut
  9 depends() {
 10     return 0
 11 }
 12
 13 # called by dracut
 14 install() {
 15     # If another shell is already installed, do not use bash
 16     [[ -x $initdir/bin/sh ]] && return
 17
 18     # Prefer bash as /bin/sh if it is available.
 19     inst /bin/bash && ln -sf bash "${initdir}/bin/sh"
 20 }
 21
		

Как вы можете видеть, этот сценарий добавляет в initramfs соответствующий исполняемый файл /bin/bash. Давайте рассмотрим другой пример и он относится к plymouth.


# vim /usr/lib/dracut/modules.d/50plymouth/module-setup.sh

  1 #!/usr/bin/bash
  2
  3 pkglib_dir() {
  4     local _dirs="/usr/lib/plymouth /usr/libexec/plymouth/"
  5     if type -P dpkg-architecture &>/dev/null; then
  6         _dirs+=" /usr/lib/$(dpkg-architecture -qDEB_HOST_MULTIARCH)/plymouth"
  7     fi
  8     for _dir in $_dirs; do
  9         if [ -x $_dir/plymouth-populate-initrd ]; then
 10             echo $_dir
 11             return
 12         fi
 13     done
 14 }
 15
 16 # called by dracut
 17 check() {
 18     [[ "$mount_needs" ]] && return 1
 19     [ -z $(pkglib_dir) ] && return 1
 20
 21     require_binaries plymouthd plymouth plymouth-set-default-theme
 22 }
 23
 24 # called by dracut
 25 depends() {
 26     echo drm
 27 }
 28
 29 # called by dracut
 30 install() {
 31     PKGLIBDIR=$(pkglib_dir)
 32     if grep -q nash ${PKGLIBDIR}/plymouth-populate-initrd \
 33         || [ ! -x ${PKGLIBDIR}/plymouth-populate-initrd ]; then
 34         . "$moddir"/plymouth-populate-initrd.sh
 35     else
 36         PLYMOUTH_POPULATE_SOURCE_FUNCTIONS="$dracutfunctions" \
 37             ${PKGLIBDIR}/plymouth-populate-initrd -t "$initdir"
 38     fi
 39
 40     inst_hook emergency 50 "$moddir"/plymouth-emergency.sh
 41
 42     inst_multiple readlink
 43
 44     if ! dracut_module_included "systemd"; then
 45         inst_hook pre-trigger 10 "$moddir"/plymouth-pretrigger.sh
 46         inst_hook pre-pivot 90 "$moddir"/plymouth-newroot.sh
 47     fi
 48 }
		

Простой проход grep по require_binaries покажет все те исполняемые файлы, которые dracut добавит в initramfs общего назначения.


# grep -ir "require_binaries" /usr/lib/dracut/modules.d/
/usr/lib/dracut/modules.d/90mdraid/module-setup.sh:    require_binaries mdadm expr || return 1
/usr/lib/dracut/modules.d/80lvmmerge/module-setup.sh:    require_binaries lvm dd swapoff || return 1
/usr/lib/dracut/modules.d/95cifs/module-setup.sh:    require_binaries mount.cifs || return 1
/usr/lib/dracut/modules.d/91crypt-gpg/module-setup.sh:    require_binaries gpg || return 1
/usr/lib/dracut/modules.d/91crypt-gpg/module-setup.sh:       require_binaries gpg-agent &&
/usr/lib/dracut/modules.d/91crypt-gpg/module-setup.sh:       require_binaries gpg-connect-agent &&
/usr/lib/dracut/modules.d/91crypt-gpg/module-setup.sh:       require_binaries /usr/libexec/scdaemon &&
/usr/lib/dracut/modules.d/45url-lib/module-setup.sh:    require_binaries curl || return 1
/usr/lib/dracut/modules.d/90stratis/module-setup.sh:    require_binaries stratisd-init thin_check thin_repair mkfs.xfs xfs_admin xfs_growfs || return 1
/usr/lib/dracut/modules.d/90multipath/module-setup.sh:    require_binaries multipath || return 1
/usr/lib/dracut/modules.d/95iscsi/module-setup.sh:    require_binaries iscsi-iname iscsiadm iscsid || return 1
/usr/lib/dracut/modules.d/95ssh-client/module-setup.sh:    require_binaries ssh scp  || return 1
/usr/lib/dracut/modules.d/35network-manager/module-setup.sh:    require_binaries sed grep || return 1
/usr/lib/dracut/modules.d/90dmsquash-live-ntfs/module-setup.sh:    require_binaries ntfs-3g || return 1
/usr/lib/dracut/modules.d/91crypt-loop/module-setup.sh:    require_binaries losetup || return 1
/usr/lib/dracut/modules.d/05busybox/module-setup.sh:    require_binaries busybox || return 1
/usr/lib/dracut/modules.d/99img-lib/module-setup.sh:    require_binaries tar gzip dd bash || return 1
/usr/lib/dracut/modules.d/90dm/module-setup.sh:    require_binaries dmsetup || return 1
/usr/lib/dracut/modules.d/03modsign/module-setup.sh:    require_binaries keyctl || return 1
/usr/lib/dracut/modules.d/97biosdevname/module-setup.sh:    require_binaries biosdevname || return 1
/usr/lib/dracut/modules.d/95nfs/module-setup.sh:    require_binaries rpc.statd mount.nfs mount.nfs4 umount || return 1
/usr/lib/dracut/modules.d/90dmraid/module-setup.sh:    require_binaries dmraid || return 1
/usr/lib/dracut/modules.d/95fcoe/module-setup.sh:    require_binaries dcbtool fipvlan lldpad ip readlink fcoemon fcoeadm || return 1
/usr/lib/dracut/modules.d/00warpclock/module-setup.sh:    require_binaries /sbin/hwclock || return 1
/usr/lib/dracut/modules.d/35network-legacy/module-setup.sh:    require_binaries ip dhclient sed awk grep || return 1
/usr/lib/dracut/modules.d/00bash/module-setup.sh:    require_binaries /bin/bash
/usr/lib/dracut/modules.d/95nbd/module-setup.sh:    require_binaries nbd-client || return 1
/usr/lib/dracut/modules.d/90btrfs/module-setup.sh:    require_binaries btrfs || return 1
/usr/lib/dracut/modules.d/00systemd/module-setup.sh:    if require_binaries $systemdutildir/systemd; then
/usr/lib/dracut/modules.d/10i18n/module-setup.sh:    require_binaries setfont loadkeys kbd_mode || return 1
/usr/lib/dracut/modules.d/90lvm/module-setup.sh:    require_binaries lvm || return 1
/usr/lib/dracut/modules.d/50plymouth/module-setup.sh:    require_binaries plymouthd plymouth plymouth-set-default-theme
/usr/lib/dracut/modules.d/95fcoe-uefi/module-setup.sh:    require_binaries dcbtool fipvlan lldpad ip readlink || return 1
		

И снова, dracut не включает все модули из /usr/lib/dracut/modules.d. Он включает только специфичные для хоста модули. В своём следующем разделе мы изучим как добавлять или опускать определённые модули в initramfs.

Персонализация initramfs

Dracut также обладает своими собственными модулями. Модули ядра и модули dracut различны. Dracut собирает необходимые исполняемые файлы, специфичные для хоста, соответствующие ассоциированные библиотеки, требующиеся файлы настройки и необходимые модули аппаратных устройств и группирует их под названием модулей dracut. Модули основного ядра составляются из соответствующих файлов .ko аппаратных устройств. Вы можете обнаружить список модулей dracut либо в /usr/lib/dracut/modules.d/, или посредством команды dracut --list-modules.


# dracut --list-modules | xargs -n6
bash systemd warpclock fips systemd-initrd systemd-networkd
modsign rescue watchdog busybox nss-softokn rdma
i18n convertfs network-legacy network-manager network ifcfg
url-lib drm plymouth lvmmerge bcache btrfs
crypt dm dmraid dmsquash-live dmsquash-live-ntfs kernel-modules
kernel-modules-extra kernel-network-modules livenet lvm mdraid multipath
qemu qemu-net stratis crypt-gpg crypt-loop cifs
debug fcoe fcoe-uefi fstab-sys iscsi lunmask
nbd nfs resume rootfs-block ssh-client terminfo
udev-rules virtfs biosdevname dracut-systemd ecryptfs ostree
pollcdrom selinux syslog usrmount base earlykdump
fs-lib img-lib kdumpbase shutdown squash uefi-lib
		

Если вы пожелаете добавить или опустить определённые модули dracut (не модуль соответствующего аппаратного устройства) из initramfs, тогда в этом жизненно важную роль играет dracut.conf. Заметьте, что dracut.conf это файл настроек dracut, а не initramfs; таким образом, он не будет доступен внутри initramfs.


# lsinitrd | grep -i 'dracut.conf'
    <no output> 
		

Dracut при генерации initramfs применяет в качестве справочного свой файл dracut.conf. По умолчанию это будет пустой файл.


# cat /etc/dracut.conf
    # PUT YOUR CONFIG IN separate files
    # in /etc/dracut.conf.d named "<name>.conf"
    # SEE man dracut.conf(5) for options 
		

Существуют различные предоставляемые dracut.conf варианты, которыми вы можете пользоваться для добавления или пропуска соответствующих модулей.

Предположим, вы желаете опустить ов initramfs относящиеся к plymouth файлы (исполняемые, конфигурационные файлы, модули и т.п.); тогда вы либо добавляете в dracut.conf некий omit_dracutmodules+=plymouth, либо применяете переключатель omit (o) своего исполняемого файла dracut. Вот некий образец:


# lsinitrd | grep -i plymouth | wc -l
    118
		

Имеется почти 118 относящихся к plymouth файлов, которые представлены в запускаемом в настоящий момент ядре. Давайте сейчас попробуем опустить относящиеся к plymouth файлы.


# dracut -o plymouth /root/new.img

# lsinitrd /root/new.img | grep -i plymouth | wc -l
    4
		

Как вы можете заметить, все относящиеся к plymouth файлы были исключены из нашего вновь построенного initramfs. Тем самым, все связанные с plymouth исполняемые и конфигурационные файлы, библиотеки, а также модули аппаратных устройств (в случае их доступности) не будут захватываться dracut в initramfs. В точности тот же результат можно достичь добавляя в dracut.conf параметр omit_dracutmodules+=plymouth.


# cat /etc/dracut.conf | grep -v '#'
    omit_dracutmodules+=plymouth

# dracut /root/new.img --force

# lsinitrd /root/new.img | grep -i plymouth
-rw-r--r--   1 root     root          454 Jul 25  2019 usr/lib/systemd/system/systemd-ask-password-plymouth.path
-rw-r--r--   1 root     root          435 Jul 25  2019 usr/lib/systemd/system/systemd-ask-password-plymouth.service
drwxr-xr-x   2 root     root            0 Jul 25  2019 usr/lib/systemd/system/systemd-ask-password-plymouth.service.wants
lrwxrwxrwx   1 root     root           33 Jul 25  2019 usr/lib/systemd/system/systemd-ask-password-plymouth.service.wants/systemd-vconsole-setup.service -> ../systemd-vconsole-setup.service 
		

Ниже приводится выдержка из страницы man.

Пропуск Модулей dracut

Порой вы не желаете включать некий модуль dracut по причинам скорости, размера или функциональности. Для этого вы либо определяете в файле настроек dracut.conf или /etc/dracut.conf.d/myconf.conf, либо применяете параметр -o или --omit в командной строке: # dracut -o "multipath lvm" no-multipath-lvm.img

В точности так же как мы пропускали соответствующий модуль dracut, мы можем добавлять лишь те модули, которые доступны в /usr/lib/dracut/modules.d. В dracut.conf мы можем воспользоваться переключателем dracut --add или add_dracutmodules+=. К примеру, вы можете заметить, что у нас нет NFS модулей/ файлов/ исполняемого кода в нашем initramfs new.img, поскольку наша тестовая система не загружается из NFS и не применяет для себя никаких точек монтирования NFS. Очевидно, что dracut пропустит модуль nfs из /usr/lib/dracut/modules.d. А потому давайте добавим его в свою initramfs.


#lsinitrd | grep -i nfs
<no_output>

# cat /etc/dracut.conf
    # PUT YOUR CONFIG IN separate files
    # in /etc/dracut.conf.d named ".conf"
    # SEE man dracut.conf(5) for options
    #omit_dracutmodules+=plymouth
    add_dracutmodules+=nfs

# dracut /root/new.img --force

# lsinitrd /root/new.img | grep -i nfs | wc -l 
		

Мы также можем достичь в точности того же результата воспользовавшись командой dracut с переключателем --add.


# lsinitrd /root/new.img | grep -i nfs
# dracut --add nfs /root/new.img --force
# lsinitrd /root/new.img | grep -i nfs
Arguments: --add 'nfs' --force
nfs
-rw-r--r--   1 root     root           15 Jul 25  2019 etc/modprobe.d/nfs.conf
drwxr-xr-x   2 root     root            0 Jul 25  2019 usr/lib64/libnfsidmap
-rwxr-xr-x   1 root     root        50416 Jul 25  2019 usr/lib64/libnfsidmap/nsswitch.so
-rwxr-xr-x   1 root     root        54584 Jul 25  2019 usr/lib64/libnfsidmap.so.1.0.0
lrwxrwxrwx   1 root     root           20 Jul 25  2019 usr/lib64/libnfsidmap.so.1 -> libnfsidmap.so.1.0.0
-rwxr-xr-x   1 root     root        42744 Jul 25  2019 usr/lib64/libnfsidmap/sss.so
-rwxr-xr-x   1 root     root        46088 Jul 25  2019 usr/lib64/libnfsidmap/static.so
-rwxr-xr-x   1 root     root        62600 Jul 25  2019 usr/lib64/libnfsidmap/umich_ldap.so
-rwxr-xr-x   1 root     root          849 Oct  8  2018 usr/lib/dracut/hooks/cleanup/99-nfsroot-cleanup.sh
-rwxr-xr-x   1 root     root         3337 Oct  8  2018 usr/lib/dracut/hooks/cmdline/90-parse-nfsroot.sh
-rwxr-xr-x   1 root     root          874 Oct  8  2018 usr/lib/dracut/hooks/pre-udev/99-nfs-start-rpc.sh
drwxr-xr-x   5 root     root            0 Jul 25  2019 usr/lib/modules/5.3.7-301.fc31.x86_64/kernel/fs/nfs
drwxr-xr-x   2 root     root            0 Jul 25  2019 usr/lib/modules/5.3.7-301.fc31.x86_64/kernel/fs/nfs/blocklayout
-rw-r--r--   1 root     root        16488 Jul 25  2019 usr/lib/modules/5.3.7-301.fc31.x86_64/kernel/fs/nfs/blocklayout/blocklayoutdriver.ko.xz
drwxr-xr-x   2 root     root            0 Jul 25  2019 usr/lib/modules/5.3.7-301.fc31.x86_64/kernel/fs/nfs_common
-rw-r--r--   1 root     root         2584 Jul 25  2019 usr/lib/modules/5.3.7-301.fc31.x86_64/kernel/fs/nfs_common/grace.ko.xz
-rw-r--r--   1 root     root         3160 Jul 25  2019 usr/lib/modules/5.3.7-301.fc31.x86_64/kernel/fs/nfs_common/nfs_acl.ko.xz
drwxr-xr-x   2 root     root            0 Jul 25  2019 usr/lib/modules/5.3.7-301.fc31.x86_64/kernel/fs/nfs/filelayout
-rw-r--r--   1 root     root        11220 Jul 25  2019 usr/lib/modules/5.3.7-301.fc31.x86_64/kernel/fs/nfs/filelayout/nfs_layout_nfsv41_files.ko.xz
drwxr-xr-x   2 root     root            0 Jul 25  2019 usr/lib/modules/5.3.7-301.fc31.x86_64/kernel/fs/nfs/flexfilelayout
-rw-r--r--   1 root     root        20872 Jul 25  2019 usr/lib/modules/5.3.7-301.fc31.x86_64/kernel/fs/nfs/flexfilelayout/nfs_layout_flexfiles.ko.xz
-rw-r--r--   1 root     root       109684 Jul 25  2019 usr/lib/modules/5.3.7-301.fc31.x86_64/kernel/fs/nfs/nfs.ko.xz
-rw-r--r--   1 root     root        18028 Jul 25  2019 usr/lib/modules/5.3.7-301.fc31.x86_64/kernel/fs/nfs/nfsv3.ko.xz
-rw-r--r--   1 root     root       182756 Jul 25  2019 usr/lib/modules/5.3.7-301.fc31.x86_64/kernel/fs/nfs/nfsv4.ko.xz
-rwxr-xr-x   1 root     root         4648 Oct  8  2018 usr/lib/nfs-lib.sh
-rwsr-xr-x   1 root     root       187680 Jul 25  2019 usr/sbin/mount.nfs
lrwxrwxrwx   1 root     root            9 Jul 25  2019 usr/sbin/mount.nfs4 -> mount.nfs
-rwxr-xr-x   1 root     root          719 Oct  8  2018 usr/sbin/nfsroot
drwxr-xr-x   4 root     root            0 Jul 25  2019 var/lib/nfs
drwxr-xr-x   2 root     root            0 Jul 25  2019 var/lib/nfs/rpc_pipefs
drwxr-xr-x   3 root     root            0 Jul 25  2019 var/lib/nfs/statd
drwxr-xr-x   2 root     root            0 Jul 25  2019 var/lib/nfs/statd/sm
		

В точности также, как мы добавляли в свой initramfs дополнительный модуль nfs, мы способны добавлять в свой initramfs лишь модуль nfs при помощи добавления в dracut.conf оператора dracutmodules+=. Это означает, что получаемый в результате initramfs будет обладать в своём составе только nfs. Все прочие модули из /usr/lib/dracut/modules.d/ будут отвергнуты.


# cat /etc/dracut.conf
    #omit_dracutmodules+=plymouth
    #add_dracutmodules+=nfs
    dracutmodules+=nfs

# dracut /root/new.img —force

# lsinitrd /root/new.img

Image: /root/new.img: 20M
========================================================================
Early CPIO image
========================================================================
drwxr-xr-x  3 root     root       0 Jul 25  2019 .
-rw-r—r--   1 root     root       2 Jul 25  2019 early_cpio
drwxr-xr-x  3 root     root       0 Jul 25  2019 kernel
drwxr-xr-x  3 root     root       0 Jul 25  2019 kernel/x86
drwxr-xr-x  2 root     root       0 Jul 25  2019 kernel/x86/microcode
-rw-r—r--   1 root     root       100352 Jul 25  2019 kernel/x86/microcode/GenuineIntel.bin
========================================================================
Version:

Arguments: --force

dracut modules:
nss-softokn
network-manager
network
kernel-network-modules
nfs
=======================================================================
		

Как вы можете видеть, был добавлен лишь модуль nfs вместе со своими зависимостями, такими как модуль dracut network. К тому же, обратите внимание на разницу в значении размера между обеими версиями initramfs.


# ls -lh initramfs-5.3.16-300.fc31.x86_64.img
    -rw-------. 1 root root 28M Dec 23 06:37 initramfs-5.3.16-300.fc31.x86_64.img

# ls -lh /root/new.img
    -rw-------. 1 root root 20M Dec 24 11:05 /root/new.img
		

Того же самого можно достичь, воспользовавшись переключателем dracut -m или --modules.


# dracut -m nfs /root/new.img --force
		

Когда вы желаете добавить лишь определённый модуль аппаратного устройства, обратите, пожалуйста, внимание на то, что модуль аппаратного устройства подразумевает соответствующий файл *.ko, предоставляемый надлежащим пакетом kernel-modules в /lib/modules/<kernel-version>/drivers/<module-name>. Тогда соответствующие переключатели dracut --add или add_dracutmodules+= не помогут, ибо эти переключатели доьавляют соответствующие модули dracut, а не файл модуля самого ядра (.ko). Итак, чтобы добавить необходимый модуль ядра нам потребуется воспользоваться переулючателем dracut --add-drivers или же drivers+=, либо add_drivers+= в dracut.conf. Вот некий пример:


# lsinitrd /root/new.img | grep -i ath3k
		

Этот относящийся к Bluetooth модуль с названием ath3k не представлен в нашем initramfs, но он является одним из тех модулей, который предоставляется самим ядром.


#ls -lh /lib/modules/5.3.16-300.fc31.x86_64/kernel/drivers/bluetooth/ath3k.ko.xz
		

Давайте добавим его как показано здесь:


# dracut --add-drivers ath3k /root/new.img --force
		

Теперь он был добавлен, как это отображено далее:


# lsinitrd /root/new.img | grep -i ath3k
Arguments: --add-drivers 'ath3k' --force
-rw-r--r-- 1 root  root 246804 Jul 25 03:54 usr/lib/firmware/ath3k-1.fw
-rw-r--r-- 1 root  root   5652 Jul 25 03:54 usr/lib/modules/5.3.7-301.fc31.x86_64/kernel/drivers/bluetooth/ath3k.ko.xz
		

Как вы можете заметить, в initramfs был добавлен модуль ath3k.ko.

Модуль dracut или модуль ядра?

Давайте изучим когда добавлять модуль dracut, а когда добавлять модуль ядра. Вот некая ситуация: корневая файловая система вашего хоста находится на обычном устройстве SCSI. Итак, очевидно, ваш initramfs не обладает внутри себя никаким модулем ядра multipath.ko или подобным multipath.conf файлом настройки.

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

  2. Для получения полной среды этого устройства со множеством путей вам потребуется добавить здесь соответствующий модуль dracut множественного пути с тем, чтобы вся имеющаяся среда множества путей целиком была размещена в initramfs.

  3. Через несколько дней вы добавляете какую- то новую сетевую карту в ту же самую систему и производитель этой NIC снабжает её драйверами. Некий драйвер это ничто иное как какой- то файл .ko (kernel object). Для добавления этого модуля в вашу initramfs вам придётся выбрать надлежащий вариант kernel module. Именно он добавит необходимый драйвер лишь для самой сетевой карты, а не всю среду целиком.

Но что если вы желаете добавить в initramfs некий конкретный файл, который не является ни модулем ядра, ни модулем dracut? Dracut предоставляет соответствующие переменные install_items+= и --include для dracut.conf, посредством которых мы обладаем возможностью добавления определённых файлов. Такие файлы могут быть чем угодно начиная с обычного текста, вплоть до исполняемого файла и т.п..


#lsinitrd /root/new.img | grep -i date
    <no_output> 
		

Этот исполняемый файл date по умолчанию не представлен в initramfs. Однако для добавления какого- то исполняемого файла мы можем воспользоваться переключателем install_itsems+.


# cat /etc/dracut.conf
    # PUT YOUR CONFIG IN separate files
    # in /etc/dracut.conf.d named "<name>.conf"
    # SEE man dracut.conf(5) for options

    #omit_dracutmodules+=plymouth
    #add_dracutmodules+=nfs
    #dracutmodules+=nfs
    install_items+=date

# dracut /root/new.img --force

# lsinitrd /root/new.img | grep -i date
-rwxr-xr-x   1 root     root       122456 Jul 25 02:36 usr/bin/date
		

Как вы можете видеть, был добавлен исполняемый файл date, но ещё более важный момент состоит в том, что он добавил не только этот исполняемый файл; он также добавил и библиотеку, которая требуется для исполнения этой команды date. Того же самого можно достичь при помощи переключателя --install в самой команде dracut. Однако тут имеется некое ограничение; нет возможности добавления исполняемых файлов, индивидуально изготовляемых самим пользователем. Для этого нам требуется воспользоваться переключателем dracut --include. При помощи --include вы способны добавлять в initramfs обычные файлы, каталоги или даже некий исполняемый файл. В последнем случае добавления определённого исполняемого файла, когда вашему исполняемому файлу требуется некая библиотека сопровождения, тогда вам придётся определить название этой библиотеки с её абсолютным значением пути.

Проблема 4 "Can’t Boot" (initramfs)

Проблема: Некая промышленная система Linux перезапускалась после четырёх месяцев на обычное сопровождение и прекратила запускаться. Это сопровождается следующим сообщением об ошибке на экране:


<snip>
.
dracut-initqueue[444]: warning: dracut-initqueue timeout - starting timeout scripts
dracut-initqueue[444]: warning: dracut-initqueue timeout - starting timeout scripts
dracut-initqueue[444]: warning: dracut-initqueue timeout - starting timeout scripts
dracut-initqueue[444]: warning: dracut-initqueue timeout - starting timeout scripts
.
</snip>
 	   

Решение: Вот шаги по решению данной проблемы:

  1. Данное сообщение об ошибке начинается с оповещения о том, что нет возможности достичь соответствующее устройство подкачки, а далее этот процесс завершается по тайм- ауту.

    
    [TIME] Timed out waiting for device /dev/mapper/fedora_localhost--live-swap
    		

    Именно это является критически важной частью сведений, так как сообщает нам что нечто пошло не так в этих системных файловых системах.

  2. Соответствующее устройство подкачки базируется на HDD и в нём была создана необходимая файловая система подкачки. Теперь это устройство подкачки утрачено само по себе. Поэтому, либо лежащий в его основе диск сам по себе не доступен, либо разрушена его файловая система подкачки. Осознавая это, мы теперь можем сосредоточиться лишь на вопросе самого хранилища. Важна изоляция данной проблемы самой по себе, ибо проблема "can’t boot" имеет тысячи ситуаций, которые способны вызывать прекращение запуска конкретной системы.

  3. Мы выполним загрузку либо при помощи аварийного режима, либо воспользовавшись образом live того же самого дистрибутива с той же версией. Это система система Fedora 31 и, как это отражено на Рисунке 6-1, я воспользуюсь аварийным вариантом из GRUB.

     

    Рисунок 6-1


    Заставка GRUB

  4. После того как мы выполнили запуск в аварийном режиме, мы смонтируем необходимую корневую файловую систему пользователя и выполним chroot в неё. Теперь, почему аварийный режим имеет возможность запуска, в то время как обычное ядро не способно запускать ту же самую систему? Это допустимый вопрос и ответ на него рассматривается в Главе 10.

  5. Так как мы имеем возможность монтирования своей корневой файловой системы с аварийным ядром, но не способны монтировать соответствующую корневую файловую систему с обычным ядром, это означает что нечто не так в его образе initramfs. Может быть пропущен какой- то модуль, который необходим для обраьотки его HDD. Давайте проверим данную теорию.

  6. Это система с виртуализацией, что подразумевает, что она обладает неким виртуальным диском. Это можно обнаружить в каталоге /dev.

    
    #ls /dev/vd*
    vda vda1 vda2
    		
  7. Для обработки таких виртуальных дисков нам требуется обладать представленным в initramfs модулем virtio_blk.

    
    #lsinitrd /boot/new.img | grep -i virt
    Arguments: --omit-drivers virtio_blk
    -rw-r--r-- 1 root  root   14132 Jul 25 03:54
        usr/lib/modules/5.3.7-301.fc31.x86_64/kernel/drivers/char/virtio_console.ko.xz
    -rw-r--r-- 1 root  root   25028 Jul 25 03:54
        usr/lib/modules/5.3.7-301.fc31.x86_64/kernel/drivers/net/virtio_net.ko.xz
    -rw-r--r-- 1 root  root   7780 Jul 25 03:54
        usr/lib/modules/5.3.7-301.fc31.x86_64/kernel/drivers/scsi/virtio_scsi.ko.xz
    -rw-r--r-- 1 root  root   499 Feb 26  2018 usr/lib/sysctl.d/60-libvirtd.conf
    		

    Как вы можете видеть, необходимый нам модуль virtio_blk пропущен.

  8. Поскольку virtio_blk отсутствует, очевидно, что наше ядро не способно выявить диск vda и получить к нему доступ, а именно там наш пользователь имеет свои корневую файловую систему и файловую систему подкачки.

  9. Для исправления данной проблемы нам требуется добавить в initramfs отсутствующий модуль virtio_blk.

    
    #dracut --add-drivers=virtio_blk /boot/new.img --force
    # lsinitrd | grep -i virtio_blk
        -rw-r--r--   1 root     root         8356 Jul 25 03:54 usr/lib/modules/5.3.7-301.fc31.x86_64/kernel/drivers/block/virtio_blk.ko.xz
    		
  10. Мы выполним запуск воспользовавшись своей initramfs new.img. Как запускать свою систему вручную из приглашения командной строки GRUB уже обсуждалось в Проблеме 1 "Can’t Boot" (начальный загрузчик).

  11. После добавления пропущенного модуля virtio_blk наша проблема "Can’t Boot" была исправлена. На Рисунке 6-2 вы можете наблюдать успешно запускающуюся систему.

     

    Рисунок 6-2


    Экран входа в Fedora

Проблема 5 "Can’t Boot" (initramfs)

Проблема: Рисунок 6-3 показывает что видно на экране.

 

Рисунок 6-3


Сообщение консоли

Решение: Вот шаги по решению данной проблемы:

  1. Теперь в этом просто разобраться и решить.

  2. Данное сообщение об ошибке достаточно хорошо само описывает себя; отсутствует файл initramfs сам по себе.

  3. Либо отсутствует файл initramfs сам по себе, либо просто файл /boot/loader/entries/* содержит в себе ошибочную запись. В данном случае отсутствует сам файл initramfs.

  4. Поэтому нам необходимо загрузиться в аварийном режиме и смонтировать необходимую корневую файловую систему пользователя.

  5. Либо повторно установите надлежащий пакет rpm ядра, с тем чтобы его часть postscripts повторно выработала отсутствующий initramfs, либо также обновите как следует имеющиеся записи BLS.

  6. Либо вы можете повторно сгенерировать initramfs при помощи изученной нами команды dracut.

Параметры командной строки ядра

Как вы уже видели, GRUB принимает параметры командной строки ядра и передаёт их в само ядро. Конкретное ядро обладает сотнями параметров командной строки и практически невозможно кому бы то ни было охватить абсолютно все параметры. Поэтому давайте сосредоточимся только на тех параметрах, которые требуются для запуска самой операционной системы. Если вам интересны все имеющиеся параметры командной строки ядра, посетите следующую страницу.

Перечень параметров этой страницы относится к ядрам 4 последовательности, но большая часть пояснений параметров применима и к ядрам 5 последовательности. Наилучший вариант состоит в том чтобы всегда отыскивать документацию в /usr/share/doc/.

root

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

  • От имени своего ядра, запускаемый из initramfs systemd смонтирует заданную корневую файловую систему пользователя.

  • Когда данная корневая файловая система пользователя не доступна или само ядро не способно смонтировать её, тогда это будет рассматриваться как паническая ситуация для данного ядра.

init

  • Имеющееся ядро запускает из initramfs systemd и он становится самым первым процессом. Он также имеет название PID-1 и выступает в качестве прародителя всех процессов.

  • Однако если вы разработчик и вы желаете запускать свой собственный исполняемый файл вместо systemd, вы можете воспользоваться параметром командной строки ядра init. Приведём некий пример:

    
    init=/sbin/yogesh
     	   

    Как вы можете видеть на Рисунке 6-4 , это запустит исполняемы файл yogesh вместо systemd.

     

    Рисунок 6-4


    Параметры командной строки ядра

    Однако yogesh не доступен в реальной корневой файловой системе; следовательно, как это отображено на Рисунке 6-5, это приводит к отказу в запуске.

     

    Рисунок 6-5


    Аварийная оболочка

  • Наша система выбросила нас в свою аварийную оболочку. За подробностями относительно отладочных оболочек обращайтесь к Главе 8.

  • Основная причина выбрасывания нас в аварийную оболочку и сама причина данной проблемы "can’t boot" упоминается в /run/initramfs/rdsosreport.txt. Рисунок 6-6 отображает фрагмент кода этого файла rdsosreport.txt.

     

    Рисунок 6-6


    Файл rdsosreport.txt

  • Самый интересный факт, который стоит отметить здесь состоит в том, что наш исполняемый файл /sbin/yogesh будет вызываться в тот момент, когда выполняется chroot реальной корневой файловой системы. Мы пока ещё не рассматривали chroot; вы можете обнаружить подробное описание в Главе 10.

ro

  • Это сопроводительный параметр для параметра командной строки root. ro это сокращение для файловой системы с "read-only". Такая корневая файловая система пользователя будет смонтирована внутри initramfs в режиме доступа только для чтения когда передан данный параметр командной строки ядра ro. Значение ro является устанавливаемым по умолчанию для всех основных дистрибутивов Linux.

rhgb и quite

  • Почти все дистрибутивы Linux показывают свою анимацию в момент запуска чтобы сделать этот процесс запуска более привлекательным, однако данная анимация скрывает все важные сообщения консоли, которые необходимы для анализа этой последовательности запуска. Чтобы прекратить такую анимацию и просмотреть на экране расширенные сообщения консоли удалите установленные параметры rhgb и quite.

  • Когда передаются параметры rhgb и quite, как это отображено на Рисунке 6-7, будет показана анимация plymouth.

     

    Рисунок 6-7


    Экран plymuth

  • Когда rhgb и quite удалены, как вы можете видеть на Рисунке 6-8, пользователю будут выставляться все сообщения консоли.

     

    Рисунок 6-8


    Сообщения консоли

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

selinux

  • Порой, чтобы решить проблему "can’t boot”", вам требуется полностью избавиться от SELinux. В таком случае вы можете передать параметр командной строки ядра selinux=0. Это совсем отменит SELinux.

Это несколько параметров командной строки ядра, которые напрямую воздействуют на последовательность запуска. Наряду с такими параметрами командной строки ядра, GRUB способен также принимать и параметры командной строки dracut, которые будут приниматься initramfs, или точнее, systemd initramfs.

Параметры командной строки dracut

С точки зрения неспециалиста вы можете рассматривать начинающиеся с rd. параметры командной строки в качестве параметров командной строки dracut, который будет распознаваться initramfs.

rd.auto (rd.auto=1)

  • Согласно странице руководства это позволяет автоматически собирать особые устройства, такие как cryptoLUKS, dmraid, mdraid или lvm. Значением по умолчанию выступает отключение.

  • Рассмотрим сценарий, подобный приведённому ранее, когда в вашей системе не был настроен mdraid (программный raid), но теперь вы его недавно реализовали и хотите чтобы это устройство активировалось в момент запуска. Иначе говоря, состояние данного хранилища этой машины изменяется в сам момент создания своего initramfs. Теперь, причём без повторного создания такого нового initramfs, вы желаете активации в момент запуска такой новой конфигурации (LVM или LUKS).

rd.hostonly=0

  • Согласно странице руководства удаляет всё скомпилированное в данной конфигурации той системы, в которой был выстроен этот образ initramfs. Это способствует запуску когда изменяется схема любого диска, в особенности с rd.auto или иными параметрами, определяемыми этой схемой.

  • Допустим, производитель вашей графической карты (например, nVidia), предоставил вам специальные драйверы/ модули, которые представлены в вашей initramfs, но эти модули начали создавать некую проблему. Поскольку данный драйвер будет запускаться на некой ранней стадии запуска, вы желаете избежать применения этого модуля; вместо этого вы хотите воспользоваться неким общим драйвером (vesa). При подобной ситуации вы можете воспользоваться rd.hostonly=0. При помощи этого параметра initramfs загрузит свой общий драйвер и избежит применения специфичного для хоста драйвера nVidia.

rd.fstab = 0

  • В соответствии со страницей руководства если вы не желаете соблюдать особые параметры монтирования для обнаруженной в реальном каталоге /etc/fstab корневой файловой системы, пользуйтесь этим параметром.

rd.skipfsck

  • В соответствии со страницей руководства, это пропускает fsck для rootfs и /usr. Если вы монтируете /usr на доступ только для чтения и инструкция init системы выполняет fsck пере повторным монтированием, вы можете применять этот параметр во избежание дублирования.

  • Большинство администраторов Linux обладают неверным представлением относительно fsck и того как она сочетается с параметром командной строки ядра ro. Большинство из нас предполагает что имеющееся ядро сначала монтирует реальную корневую файловую систему в режиме ro и затем выполняет в ней fsck с тем, чтобы fsck не разрушал данные этой корневой файловой системы. После того как fsck завершается успешно, будет произведено перемонтирование этой файловой системы в режиме чтения- записи через обращение к /etc/fstab.

  • Однако такое представление обладает основным недостатком, который заключается в том, что fsck не может выполняться в смонтированной файловой системе безотносительно к режиму ro или rw.

Следующая корневая файловая система системы Fedora расположена на устройстве sda5 и в настоящий момент монтируется в режиме только чтения, поэтому fsck завершится неудачно, ибо эта файловая система смонтирована:


# fsck.ext4 /dev/sda5
    e2fsck 1.45.3 (14-Jul-2019)
    /dev/sda5 is mounted.
    e2fsck: Cannot continue, aborting.
		

Таким образом это доказывает, что основная цель монтирования этой корневой файловой системы пользователя в режиме ro состоит не в том чтобы выполнять fsck. Тогда зачем передавать своему ядру параметр командной строки ro в своё ядро? Давайте обсудим это в последовательности запуска.

  • Установленной ядро распаковывает initramfs и передаёт такие параметры как root и ro в systemd, который запускается из initramfs.

  • systemd отыщет реальную корневую файловую систему.

  • После того, как необходимая корневая файловая система (диск) выявлена, systemd выполнит в ней fsck.

  • Если fsck успешен, тогда systemd смонтирует эту корневую файловую систему как ro (в соответствии с таким переданным параметром командной строки ядра) внутри самой initramfs. Она будет смонтирована как доступная только для чтения в каталоге /sysroot/code> initramfs.

  • Как вы можете увидеть на Рисунке 6-9, наше ядро распаковало initramfs и запустило из неё systemd (я удалил параметры rhgb и quite).

     

    Рисунок 6-9


    Сообщения консоли

Systemd затем сканирует все подключённые устройства хранения на предмет корневой файловой системы и её обнаружения. Перед монтирование такой корневой файловой системы пользователя, вначале в ней выполнится fsck и далее она монтируется внутри initramfs в каталоге sysroot. Эта корневая файловая система будет смонтирована в режиме доступа только на чтение.

  • Основную причину для монтирования её в режиме исключительного чтения понять просто. Допустим, эта система отказывает в запуске, однако она управляется для монтирования своей корневой файловой системы пользователя в sysroot и снабжает нас некой оболочкой для исправления данной проблемы "can’t boot". Пользователи могут случайно разрушить или даже удалить эту корневую файловую систему пользователя которая смонтирована в sysroot. Поэтому для предотвращения подобных происшествий с корневой файловой системой пользователя, предпочтительно монтируется в режиме для исключительного чтения.

    
    #switch_root:/# ls -ld /sysroot/
        dr-xr-xr-x 19 root 0 4096 Sep 10  2017 /sysroot/
    		
  • То как применять соответствующие отладочные оболочки и как initramfs предоставляет их будет обсуждаться в Главе 8.

  • Рисунок 6-10 показывает systemd продолжает свою последовательность запуска и покидает среду своего initramfs.

     

    Рисунок 6-10


    Сообщения консоли

  • Как вы можете видеть на Рисунке 6-10, переключаемый корень покидает свою текущую среду initramfs и изменяет свой корень с временной корневой файловой системы initramfs на /sysroot, которая имеет смонтированной корневую файловую систему пользователя. (Такой процесс переключения корня будет обсуждаться в Главе 9.)

  • Сразу после входа в смонтрованную корневую файловую систему пользователя, systemd этой корневой файловой системы пользователя считывает /etc/fstab и предпринимает надлежащие действия в точках монтирования. Например, в данной системе Fedora имеется соответствующая запись корневой файловой системы пользователя помимо записи /boot (boot в отдельном разделе):

    
    #cat /etc/fstab
    
    /dev/mapper/fedora_localhost--live-root  /     ext4    defaults    1 1
    UUID=eea3d947-0618-4d8c-b083-87daf15b2679 /boot  ext4    defaults  1 2
    /dev/mapper/fedora_localhost--live-swap none   swap    defaults     0 0
    		
  • Как вы можете видеть на Рисунке 6-11, на данном этапе systemd выполнит fsck лишь в своём загрузочном устройстве перед её монтированием. Обратите, пожалуйста внимание что fsck не выполняется в соответствующей корневой файловой системе пользователя, так как она уже была осуществлена внутри среды initramfs. Кроме того, корневая файловая система пользователя в настоящий момент смонтирована и мы все знаем что она не придаёт внимания выполнению fsck на своём устройстве подкачки.

     

    Рисунок 6-11


    Сообщения консоли fsck

  • Если бы присутствовали какие- либо иные точки монтирования, такие как /usr, пришлось бы выполнять fsck и в этом устройстве.

  • fsck зависит от пятого параметра /etc/fstab. Если он равен 1, тогда fsck будет выполняться в момент запуска. Эта настройка fstab не применима к корневой файловой системе пользователя, так как fsck будет принудительно выполняться в корневой файловой системе пользователя внутри initramfs, что происходит перед считыванием этого файла /etc/fstab.

  • rd.skipfsck применим только к корню и устанавливаемой корневой файловой системой пользователя. Он не применяется ко всем прочим файловым системам, таким как /boot.

rd.driver.blacklist, rd.driver.pre и rd.driver.post

Вот страница руководства по rd.driver.blacklist:

rd.driver.blacklist=<drivername>[,<drivername>,...]

не загружать модуль ядра <drivername>. Данный параметр может задаваться множество раз.

rd.driver.blacklist является одним из наиболее важных параметров командной строки dracut. Как и предполагает название этого параметра, это будет чёрный список всех определяемых модулей. Давайте попробуем занести в чёрный список относящиеся к virtio драйверы, которые достаточно важны для виртуальных гостевых систем.


# lsmod | grep -i virt
    virtio_balloon         24576  0
    virtio_net             57344  0
    virtio_console         40960  2
    virtio_blk             20480  3
    net_failover           20480  1 virtio_net
		

Они также доступны и в initramfs.


# lsinitrd | grep -i virtio
-rw-r--r-- 1 root  root  8356 Jul 25 03:54 usr/lib/modules/5.3.7-301.fc31.x86_64/kernel/drivers/block/virtio_blk.ko.xz
-rw-r--r--   1 root     root        14132 Jul 25 03:54 usr/lib/modules/5.3.7-301.fc31.x86_64/kernel/drivers/char/virtio_console.ko.xz
-rw-r--r--   1 root     root        25028 Jul 25 03:54 usr/lib/modules/5.3.7-301.fc31.x86_64/kernel/drivers/net/virtio_net.ko.xz
-rw-r--r--   1 root     root         7780 Jul 25 03:54 usr/lib/modules/5.3.7-301.fc31.x86_64/kernel/drivers/scsi/virtio_scsi.ko.xz
		

Помните, что для занесения в чёрный список соответствующего модуля, как вы это можете видеть на Рисунке 6-12, вам требуется убедиться, что все прочие зависимости модуля также занесены в чёрный список; в противном случае такие модули зависимости вытащили бы и сам занесённый в чёрный список модуль. Например, в данном случае модули virtio_balloon, virtio_net, virtio_console, virtio_blk и virtio_pci зависят друг от друга. Это означает, что если мы занесём в чёрный список только virtio_blk, прочие имеющиеся модули зависимостей всё же загрузят и этот модуль virtio_blk.

 

Рисунок 6-12


Параметр командной строки ядра

Все относящиеся к virtio драйверы важны. Именно они выступают теми драйверами, которые выставляются гипервизором в свою гостевую операционную систему виртуальные диски и сетевые среды. Поскольку мы занесли их в чёрный список, наша гостевая ОС прекратит запускаться. Вы сможете видеть на Рисунке 6-13 сообщение консоли "can't boot".

 

Рисунок 6-13


Сообщения консоли

Итак, занесение в чёрный список модулей virtio выполнено успешно, но при данном подходе имеются две проблемы.

  • rd.driver.blacklist будет лишь блокировать эти модули для загрузки в initramfs.

  • Нам требуется всякий раз вручную предоставлять данный список модулей для rd.driver.blacklist.

Когда определённый модуль не находится в initramfs, тогда вы не можете в реальности блокировать его загрузку. Например, модуль bluetooth не загружается из initramfs, однако имеющееся ядро загружает их после выхода из среды initramfs.


# lsmod | grep -i bluetooth
    bluetooth             626688  37 btrtl,btintel,btbcm,bnep,btusb,rfcomm
    ecdh_generic           16384  1 bluetooth
    rfkill                 28672  5 bluetooth

# lsinitrd | grep -i bluetooth
    <no_output> 
		

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

Сделаем новый файл blacklist.conf (Вы можете выбрать иное название, но оно обязано иметь суффикс .conf) и занесём в чёрный список этот модуль.


#cat /etc/modprobe.d/blacklist.conf
    blacklist bluetooth
		

Однако после перезапуска вы обнаружите что bluetooth снова загрузится своим ядром.


#lsmod | grep -i bluetooth
    bluetooth             626688  37 btrtl,btintel,btbcm,bnep,btusb,rfcomm
    ecdh_generic           16384  1 bluetooth
    rfkill                 28672  5 bluetooth
		

Это происходит потому, что данный модуль bluetooth находится в зависимостях множества прочих модулей, таких как btrtl, btintel, btbcm, bnep, btusb, rfcomm и rfkill. Следовательно, modprobe загрузил bluetooth в качестве зависимости от прочих модулей. В подобной ситуации нам требуется обмануть команду modprobe добавляя строку install bluetooth /bin/true в соответствующий файл blacklist.conf, как это показано здесь:


# cat /etc/modprobe.d/blacklist.conf
    install bluetooth /bin/true
		

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


# lsmod | grep -i bluetooth
    <no_output> 
		

Вы можете применять вместо /bin/true /bin/false.

После нашего объяснения rd.driver.blacklist, параметры командной строки dracut rd.driver.pre и rd.driver.post проще понять и здесь показаны поясняющие себя самостоятельно страницы руководства:

rd.driver.pre=<drivername>[,<drivername>,...]

принудительно загружает модуль ядра <drivername>. Данный параметр может задаваться множество раз.

rd.driver.post=<drivername>[,<drivername>,...]

принудительно загружает модуль ядра <drivername>. Данный параметр может задаваться множество раз.

rd.debug

Вот что сообщает страница руководства:

Установите -x для оболочки dracut. Если systemd активен в данной initramfs, весь вывод регистрируется в соответствующем журнале systemd, который вы можете проинспектировать через "journalctl -ab". Когда systemd не активен, тогда всё регистрируемое записывается в dmesg и /run/initramfs/init.log. Если установлена &quit;quiet&quit;, тогда записи также регистрируются в самой консоли.

rd.debug включит регистрацию отладки systemd, что приведёт к регистрации гигантского числа сообщений как в сакой консоли, так и в журналах systemd. Такие подробные предоставляемые rd.debug сообщения будут полезными при выявлении проблем, относящихся к "can’t boot".

rd.memdebug= [0-4]

Вот что сообщает страница руководства:

Выдаёт на печать сведения об используемой памяти в различных точках, устанавливается уровень подробности от 0 до 4. Более высокий уровень означает больше отладочной информации.


	0 - без вывода
	1 - частичный /proc/meminfo
	2 - /proc/meminfo
	3 - /proc/meminfo + /proc/slabinfo
	4 - /proc/meminfo + /proc/slabinfo + tracekomem
 	   
  • Это выдаст на печать в экране все относящиеся к подсистемам сведения о памяти, такие как содержимое файлов meminfo и slabinfo.

lvm, raid и относящиеся к множественной загрузке параметры командной строки dracut

Вот что сообщают страницы руководства:

rd.lvm=0

отключает определение LVM

rd.lvm.vg=<volume group name>

активирует только определённые группы томов с заданным названием. rd.lvm.vg может определяться множество раз в командной строке ядра.

rd.lvm.lv=<volume group name>

активирует только определённые логические тома с заданным названием. rd.lvm.lv может определяться множество раз в командной строке ядра.

rd.lvm.conf=0

удаляет /etc/lvm/lvm.conf, который может иметься в текущем initramfs.

  • Из всех этих параметров вы по крайней мере должны наблюдать передаваемый GRUB параметр rd.lvm.lv. Основная цель rd.lvm.lv состоит в активации задаваемого устройства LVM на неком раннем этапе запуска. По умолчанию основные распространители Linux активируют только устройства LV корня и подкачки (при их настройке). Активирование только самой корневой файловой системы на момент запуска ускоряет всю процедуру запуска. После переключения текущего корня с initramfs на реальную корневую файловую систему, systemd способен активировать остающиеся группы томов в соответствии со списком /etc/fstab.

  • Аналогично dracut предоставляет параметры командной строки, относящиеся к множеству путей и RAID, которые опять- таки сами себя объясняют.

    MD RAID
    rd.md=0

    отключает определение MD RAID

    rd.md.imsm=0

    отключает определение MD RAID для raid imsm/isw, вместо этого применяйте DM RAID

    rd.md.ddf=0

    отключает MD RAID для raid SNIA ddf, вместо этого применяйте DM RAID

    rd.md.conf=0

    игнорировать включённый в initramfs mdadm.conf

    rd.md.waitclean=1

    дожидаться любой активности для завершения повторной синхронизации, восстановления или трансформации прежде чем продолжить

    rd.md.uuid=<md raid uuid>

    активирует только определённые raid с заданным UUID. Данный параметр может определяться множество раз

    DM RAID
    rd.dm=0

    отключает определение DM RAID

    rd.dm.uuid=<dm raid uuid>

    активирует только определённые raid с заданным UUID. Данный параметр может определяться множество раз

    MULTIPATH
    rd.multipath=0

    отключает определение множества путей

  • dracut предоставляет n чисел параметров командной строки для сетевых сред, NFS, CIFS, iSCSI, FCoE и т.п.. Это также означает что существует различные варианты, которыми вы можете помещать свою корневую файловую систему, но практически невозможно охватить абсолютно все параметры командной строки dracut. К тому же я не сторонник запуска системы из таких сложных структур. Я полагаю, что корневая файловая система должна находиться на локальном диске чтобы процедура запуска была простой и в целом потому, что более простую последовательность запуска быстрее исправлять в случае ситуации "can’t boot".

rd.break и rd.shell

rd.shell предоставляет нам оболочку в самом конце последовательности запуска, а с помощью rd.break мы можем прерывать последовательность своего запуска. Однако чтобы разобраться с этими параметрами, нам требуется обладать хорошим пониманием systemd. Следовательно, прежде чем обсуждать rd.break и специальные точки входа dracut мы вначале в своей следующей главе рассмотрим systemd. Ниже приводятся все параметры, принимаемые rd.break:

Таблица 6-1. Параметры rd.break
Параметр Назначение

cmdline

Эта специальная точка входа собирает все параметры командной строки ядра.

pre-udev

Эта специальная точка входа запускается перед установленным обработчиком udev.

pre-trigger

В этой специальной точке входа вы можете настроить переменные среды udev с 'udevadm' control --property=KEY=value или управлять дальнейшим исполнением udev.

pre-mount

Эта специальная точка входа запускается перед монтированием корневой файловой системы пользователя /sysroot.

mount

Эта специальная точка входа запускается после монтированием корневой файловой системы пользователя /sysroot.

pre-pivot

Эта специальная точка входа запускается в точности перед переключением на реальную корневую файловую систему.