The boot process is what happens from the time the user powers on the host (physical or virtual) until the operating system is fully loaded.

It mainly consists of three phases: the initial startup performed by the hardware (physical hardware or virtual hardware), the initial phase loading of the operating system, and the initiation of mechanisms to run the required services in the system. This chapter discusses these three phases and touches on some system rescue-related operations.

The first two stages of the boot process don't require much modification, but being familiar with them can help with recovery in the event of a failure.

The third stage is managed by systemd , where services that run by default in the system can be modified. In the previous chapters, a lot of systemd -related knowledge has been introduced , and this chapter will review them a little bit.

Enter the first stage of the discussion.

23.1 Introduction to BIOS, UEFI Boot Process

Computers contain a hardware-embedded software controller, also known as firmware, through which the underlying hardware can be managed. The firmware first identifies the hardware available in the system and which features are enabled by the hardware (eg pre-boot network execution, PXE).

The embedded firmware of a personal computer (PC) with the x86 architecture is called BIOS, which is short for Basic Input and Output System.

The BIOS boot process of a Linux system has the following steps:

  1. Power on the host and load the BIOS firmware;
  2. Firmware initializes devices, such as keyboard, mouse, storage and other peripherals;
  3. The firmware reads the configuration, including the boot order, specifying the storage device to continue the boot process on;
  4. After selecting the storage device, the BIOS loads the MBR (Master Boot Record) on it and runs the operating system loader. In Linux, the operating system loader is called GRUB (Grand Unified Bootloader);
  5. GRUB loads the configuration with the operating system kernel and initramfs specified in the configuration. The kernel is stored in a file starting with vmlinuz, and the initial boot image is stored in a file starting with initramfs. GRUB configuration files, vmlinuz, initramfs are all stored in the /boot/partition ;
  6. The initial boot image loads the first process in the system, systemd ;
  7. systemd loads other services of the system.

For this process to work, there must be an MBR partition table on the disk and /boot/the must be marked "bootable"

The MBR partition table format is limited, allowing only four primary partitions, and uses extended features such as extended partitions to make up for this limitation. MBR partitions are not recommended unless necessary.

The boot process of UEFI (Unified Extensible Firmware Interface) is very similar to that of BIOS, the main difference is that UEFI can directly access and read disk partitions. The process is as follows:

  1. Power on the machine and load the UEFI firmware;
  2. Firmware initializes devices, such as keyboard, mouse, storage and other peripherals;
  3. The firmware reads the configuration, specifies the storage device and bootable partition to continue the boot process, no longer requires MBR boot;
  4. After selecting a storage device, the partitions are read from the GUID Partition Table (GPT). Access the first partition in VFAT format. Load and run the EFI bootloader. The EFI bootloader is located in the /boot/efi/directory . The EFI bootloader loads GRUB.
  5. GRUB loads the operating system kernel, the kernel is stored in a file starting with vmlinuz, and the initial boot image is stored in a file starting with initramfs. GRUB configuration, vmlinuz, initramfs files are all stored in the /boot/partition ;
  6. The initial boot image loads the first process in the system, systemd ;
  7. systemd loads the rest of the system's services.

UEFI has several advantages over BIOS, enabling a more complete pre-boot environment and other features such as secure boot and GPT partitions, which can go beyond the 2TB limit of MBR partitions.

The installer is responsible for creating the boot and, if needed, the UEFI partition and binaries.

Via BIOS or UEFI, it is possible to choose from which storage device the operating system is loaded and proceed to the next stage.

The next section begins the discussion of the second phase.

23.2 GRUB, bootloader, initramfs

After the pre-boot execution is complete, the system will run the GRUB bootloader.

GRUB's job is to load the operating system kernel, pass arguments and options to the kernel, and load the initramfs.

GRUB can be installed with the grub2-install command. You need to identify the disk to use as the device boot, in this case /dev/nvme0n1:

[root@rocky08-host ~]# grub2-install /dev/nvme0n1Installing for i386-pc platform.Installation finished. No error reported.

The disk used to boot the system is specified after the grub-install command, that is, the boot disk configured in the BIOS or UEFI. This command will manually rebuild or repair a corrupt system boot.

GRUB files are stored in the /boot/grub2/directory . The main configuration file is /boot/grub2/grub.cfg. Looking at the file, you will see the following beginning:

[root@rocky08-host ~]# head -n 6 /boot/grub2/grub.cfg## DO NOT EDIT THIS FILE## It is automatically generated by grub2-mkconfig using templates# from /etc/grub.d and settings from /etc/default/grub#

The file is automatically generated, do not edit this file. If you have to modify it, there are two ways:

  • The first method is grub.cfgto edit the contents of the /etc/default/grubfiles and /etc/grub.d/directories as instructed in the file, and then regenerate the GRUB configuration with the grub2-mkconfig command.
  • The second method is to use the grubby command.

In Linux, when updating the kernel, the existing kernel is not upgraded, but the new kernel version is installed, the old kernel version is kept, and an entry is added in GRUB. This makes it easy to roll back the kernel version if needed. During the installation of a new kernel, a new updated initramfs is created for the new kernel.

The current kernel configuration can be viewed using the grubby command. The --default-kernel option displays the default loaded kernel files:

[root@rocky08-host ~]# grubby --default-kernel/boot/vmlinuz-4.18.0-372.9.1.el8.x86_64

The --default-title option can display the name used at boot:

[root@rocky08-host ~]# grubby --default-titleRocky Linux (4.18.0-372.9.1.el8.x86_64) 8.6 (Green Obsidian)

With the --info option, you can view more information about the kernel:

[root@rocky08-host ~]# grubby --info /boot/vmlinuz-4.18.0-372.9.1.el8.x86_64index=0kernel="/boot/vmlinuz-4.18.0-372.9.1.el8.x86_64"args="ro crashkernel=auto resume=/dev/mapper/rl-swap rd.lvm.lv=rl/root rd.lvm.lv=rl/swap biosdevname=0 net.ifnames=0 rhgb quiet $tuned_params"root="/dev/mapper/rl-root"initrd="/boot/initramfs-4.18.0-372.9.1.el8.x86_64.img $tuned_initrd"title="Rocky Linux (4.18.0-372.9.1.el8.x86_64) 8.6 (Green Obsidian)"id="259d4d4e70e8414fb7dc745fbd14737e-4.18.0-372.9.1.el8.x86_64"

You can see the options passed to GRUB:

  • index: Display the index number of the specified kernel;
  • kernel: contains the kernel files that will be loaded to run the operating system core;
  • root: the partition or logical volume assigned to the /directory and mounted;
  • initrd: file containing the RAM disk, used to perform the initial part of the boot process;
  • title: descriptive information displayed to the user during startup;
  • id: The identifier of the boot entry.

Use the grubby command to view information about the default kernel:

[root@rocky08-host ~]# grubby --info $(grubby --default-kernel)

The boot parameters of the kernel can be modified, such as deleting the quiet and rhbg parameters to make the boot process more detailed:

[root@rocky08-host ~]# grubby --remove-args="rhgb quiet" --update-kernel=/boot/vmlinuz-4.18.0-372.9.1.el8.x86_64[root@rocky08-host ~]# grubby --info $(grubby --default-kernel)index=0kernel="/boot/vmlinuz-4.18.0-372.9.1.el8.x86_64"args="ro crashkernel=auto resume=/dev/mapper/rl-swap rd.lvm.lv=rl/root rd.lvm.lv=rl/swap biosdevname=0 net.ifnames=0 $tuned_params"root="/dev/mapper/rl-root"initrd="/boot/initramfs-4.18.0-372.9.1.el8.x86_64.img $tuned_initrd"title="Rocky Linux (4.18.0-372.9.1.el8.x86_64) 8.6 (Green Obsidian)"id="259d4d4e70e8414fb7dc745fbd14737e-4.18.0-372.9.1.el8.x86_64"

Reboot the host with the systemctl reboot command to verify the above modifications:

[root@rocky08-host ~]# systemctl reboot

Arguments can also be added to the kernel using the --args option:

[root@rocky08-host ~]# grubby --args="quiet rhbg" --update-kernel=/boot/vmlinuz-4.18.0-372.9.1.el8.x86_64

To view boot information after boot, you can use the dmesg command.

The --info and --update-kernel options accept the ALL option to check or perform operations on all configured kernels. E.g:

[root@rocky08-host ~]# grubby --info ALLindex=0kernel="/boot/vmlinuz-4.18.0-372.9.1.el8.x86_64"args="ro crashkernel=auto resume=/dev/mapper/rl-swap rd.lvm.lv=rl/root rd.lvm.lv=rl/swap biosdevname=0 net.ifnames=0 $tuned_params quiet rhbg"root="/dev/mapper/rl-root"initrd="/boot/initramfs-4.18.0-372.9.1.el8.x86_64.img $tuned_initrd"title="Rocky Linux (4.18.0-372.9.1.el8.x86_64) 8.6 (Green Obsidian)"id="259d4d4e70e8414fb7dc745fbd14737e-4.18.0-372.9.1.el8.x86_64"index=1kernel="/boot/vmlinuz-4.18.0-348.23.1.el8_5.x86_64"args="ro crashkernel=auto resume=/dev/mapper/rl-swap rd.lvm.lv=rl/root rd.lvm.lv=rl/swap biosdevname=0 net.ifnames=0 rhgb quiet $tuned_params"root="/dev/mapper/rl-root"initrd="/boot/initramfs-4.18.0-348.23.1.el8_5.x86_64.img $tuned_initrd"title="Rocky Linux (4.18.0-348.23.1.el8_5.x86_64) 8.5 (Green Obsidian)"id="259d4d4e70e8414fb7dc745fbd14737e-4.18.0-348.23.1.el8_5.x86_64"index=2kernel="/boot/vmlinuz-4.18.0-348.el8.0.2.x86_64"args="ro crashkernel=auto resume=/dev/mapper/rl-swap rd.lvm.lv=rl/root rd.lvm.lv=rl/swap biosdevname=0 net.ifnames=0 rhgb quiet $tuned_params"root="/dev/mapper/rl-root"initrd="/boot/initramfs-4.18.0-348.el8.0.2.x86_64.img $tuned_initrd"title="Rocky Linux (4.18.0-348.el8.0.2.x86_64) 8.5 (Green Obsidian)"id="259d4d4e70e8414fb7dc745fbd14737e-4.18.0-348.el8.0.2.x86_64"index=3kernel="/boot/vmlinuz-0-rescue-259d4d4e70e8414fb7dc745fbd14737e"args="ro crashkernel=auto resume=/dev/mapper/rl-swap rd.lvm.lv=rl/root rd.lvm.lv=rl/swap biosdevname=0 net.ifnames=0 rhgb quiet"root="/dev/mapper/rl-root"initrd="/boot/initramfs-0-rescue-259d4d4e70e8414fb7dc745fbd14737e.img"title="Rocky Linux (0-rescue-259d4d4e70e8414fb7dc745fbd14737e) 8.5 (Green Obsidian)"id="259d4d4e70e8414fb7dc745fbd14737e-0-rescue"

The above is how to modify the kernel parameters. Now go to the initramfs section.

The initramfs file contains the minimal system used to boot the system. Through the grubby --info command, you can see which is currently used /boot/initramfs-4.18.0-348.23.1.el8_5.x86_64.img. The initramfs file can be regenerated with the dracut command:

[root@rocky08-host ~]# dracut --force --verbose...dracut: *** Creating initramfs image file '/boot/initramfs-4.18.0-372.9.1.el8.x86_64.img' done ***...

When the initramfs file is damaged, you can use this command to rebuild the initramfs. This command can also be used to generate the correct storage driver when restoring the system from a backup on different hardware.

The above is the basic knowledge in the early stage of the boot process, which is enough to troubleshoot startup problems. Then enter the third stage of discussion.

23.3 Managing the Boot Order with systemd

GRUB loads the kernel and initramfs in preparation for system boot. Then start the first process of the system, that is, the process with PID 1. This process is responsible for loading the services required by the system. In Rocky Linux, the process with PID 1 is systemd .

The first two things systemd does with respect to the boot order are rebooting the system and powering off. Use the systemctl command to do both:

[root@rocky08-host ~]# systemctl reboot

Execute the above command and the system will reboot. You can use the uptime command to see how long the system has been running:

[root@rocky08-host ~]# uptime20:03:37 up 0 min,  1 user,  load average: 0.85, 0.30, 0.11

Next we discuss poweroff . But before doing so, make sure there is a way to start the host. Command to shut down the host:

[root@rocky08-host ~]# systemctl poweroff

After executing this command, you need to restart the power of the host.

The systemctl halt command suspends the system without sending a signal to power off the host. This command is rarely used, but it doesn't hurt to know it.

The previous commands can be abbreviated as reboot and poweroff . Looking at the /usr/sbin/powerofffile , you will see that it is a symbolic link to systemctl .

Chapter 5 describes systemctl setting the default systemd target. However, the default configuration can be overridden by passing the systemd.unit parameter to the kernel at boot time using the grubby command :

[root@rocky08-host ~]# systemctl get-defaultmulti-user.target[root@rocky08-host ~]# grubby --args="systemd.unit=emergency.target" --update-kernel=$(grubby --default-kernel)[root@rocky08-host ~]# systemctl reboot

The system restarts, the "systemd.unit=emergency.target" parameter has been passed to the kernel by GRUB, and then passed to systemd by the kernel , which will ignore the default configuration and load the services required by the "emergency target".

Finally the system boots in emergency mode, waiting for the "root" password to be entered to log into the console:

picture
23.1 Enter the root password to log in to emergency mode

In emergency mode, no network is configured and no other processes are running. In this mode, changes can be made to the system without other users accessing the system. Also, the /filesystem is mounted in read-only mode.

If the operating system's filesystem is corrupted, this is a good way to check the filesystem without any service access. Use the fsck command to check the file system:

[root@rocky08-host ~]# fsck /boot

The filesystem in the example is normal. But if there is something to fix, you can run the xfs_repair command on it, since it's an xfs filesystem.

The root filesystem is mounted read-only /on , how can I change it? The /filesystem remounted read-write:

[root@rocky08-host ~]# mount -o remount -o rw /

The root filesystem is now mounted read-write /in . You also need to execute the mount /boot command:

[root@rocky08-host ~]# mount /boot

/bootOnce mounted , perform some administrative tasks, such as removing the systemd.unit=emergency.target parameter used in GRUB:

[root@rocky08-host ~]# grubby --remove-args="systemd.unit=emergency.target" --update-kernel=$(grubby --default-kernel)[root@rocky08-host ~]# reboot

The system can start normally again. In Linux, this may not be a practical way to enter emergency mode, but it demonstrates how to pass arguments to systemd at boot time .

rescue.target can load more services and is also easier, you can try to enter rescue.target mode by following the steps above.

23.4 Intervening in the boot process to gain access to the system

During the handover of work, there are times when I encounter a system that loses the root password.

To retrieve the root password, you need to restart the operating system. After the BIOS/UEFI check is complete, the system loads GRUB. In the interface waiting to select the kernel, press the up or down arrow to terminate the count, as shown in Figure 23.2:

picture
Figure 23.2 Manual kernel selection in the GRUB menu

Select the first entry.

Read the help information at the bottom of the screen to find instructions for editing the selected item. Press the Ekey to edit the line selected in the menu, and the following five lines will be output:

picture
Figure 23.3 GRUB manual kernel selection

The first three lines with load_video , set gfx_payload=keep , and insmod gzio are the GRUB setting options. The last two options are important:

  • linux: Defines the loaded kernel and the parameters passed to the kernel.
  • initrd: Defines where the initrd is loaded and if there are any options.

Move the cursor to the end of the linux line and add the rd.break option, as shown in Figure 23.4:

picture
Figure 23.4, Edit linux line, add rd.break option

Press Ctrl + x to navigate the edited line. The rd.break option stops the boot process before loading the initrd. The current situation is as follows:

  • load single shell;
  • The filesystem currently mounted /on is a minimal filesystem with basic administrative commands;
  • The target root filesystem is mounted read-only on /sysroot(not on /);
  • No other file systems are mounted;
  • SELinux is not started.

Use the chroot command to switch to the /filesystem :

chroot /sysroot

Remount the /filesystem :

mount -o remount -o rw /

Use the passwd command to change the password of the root user:

passwd

The root user's password has been changed and the /etc/shadowfiles have been updated. But modifying it without SELinux enabled may cause problems on the next boot. To avoid this, /.autorelabelhidden and the system fixes SELinux labels on next boot. Then reboot the system:

touch /.autorelabel

In this state, it may be necessary to forcibly power off and then power on the host. After the system reboots, you can log in to the operating system using the root user and its new password.