Linux 引导启动配置与关机
启动引导程序
目前在 Linux 下主要的引导启动程序是 Grub(Grand Unified Bootloader)或 Grub2。通常,Grub2 的主程序会将配置文件放到 /boot/grub2
目录下。而 Grub 则直接修改 /boot/grub/grub.conf
,这是一个非常简单的配置文件。
Grub2 引导程序的特点有:
-
它能够识别和支持更多的文件系统,并且可以使用 Grub2 的主程序在文件系统中直接搜索内核文件名。
-
在启动时,可以自行编辑和修改启动设置项目,类似于 bash 的命令模式。
-
它能够动态搜索配置文件,无需在修改配置后重新安装 Grub2。
Grub2 对硬盘的代号设置与 Linux 中不同,一般用下面代号:
-
(hd0,1)
:这是默认的语法,Grub2 会自动判断分区的格式。 -
(hd0,msdos1)
:这表示磁盘的分区采用传统的 MBR 模式。 -
(hd0,gpt1)
:这表示磁盘的分区采用 GPT 模式。
硬盘代号用小括号 ()
括起来,并按搜索顺序对硬盘进行编号,第一个分区从 1 开始计算,与 Grub 的从 0 开始计算不同。
默认情况下,系统已经安装了 Grub2。在特殊情况下,如果需要手动安装 Grub2,可以使用 grub2-install
命令。例如,将其安装到 /dev/sdc
下:
[root@101c7 ~]$ grub2-install /dev/sdc
Installing for i386-pc platform.
Installation finished. No error reported.
Grub2 配置文件
Grub2 的配置文件路径为 /boot/grub2/grub.cfg
:
[root@101c7 ~]$ cat /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
#
### BEGIN /etc/grub.d/00_header ###
set pager=1
if [ -s $prefix/grubenv ]; then
此文件内容繁多,开头第一句就警告应该由 grub2-mkconfig
命令来创建配置,而不是直接修改它。
第一部分以 ### BEGIN /etc/grub.d/00_header ###
开头,包含了环境设置和默认值设置等内容。其中比较重要的是 set default
默认开机选项和 set timeout
默认超时时间。
第四部分以 ### BEGIN /etc/grub.d/10_linux ###
开头,设置了各个开机选择项 menuentry
。每个选项都具有不同的启动参数和模块载入。其中比较重要的内容包括:
-
set root
:设置 Grub2 配置文件所在的分区(hd0,msdos1)
,可以使用mount
命令查看挂载的分区。[root@101c7 ~]$ mount | grep boot /dev/sda1 on /boot type xfs (rw,relatime,seclabel,attr2,inode64,noquota) [root@101c7 ~]$ fdisk -l Disk /dev/sda: 21.5 GB, 21474836480 bytes, 41943040 sectors Units = sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disk label type: dos
结果显示
/boot
被挂载在/dev/sda1
下,分区格式为 MBR。 -
linux16 /vmlinuz
:指定内核文件以及内核文件运行时的参数。由于/boot
是独立分区,这里的内核文件路径是(hd0,msdos1)/vmlinuz
。如果/boot
挂载在根目录下,内核文件路径将变为(hd0,msdos1)/boot/vmlinuz
,即linux16 /boot/vmlinuz
。root
后面指定的是 Linux 系统中根目录挂载的设备。 -
initrd16 /initramfs
:指定虚拟文件系统 img 的位置。
Grub2 配置维护
可以通过修改 /etc/default/grub
文件和 /etc/grub.d/
目录内的相关配置文件来修改 Grub2 的配置。
查看 /etc/default/grub
文件的内容:
[root@101c7 ~]$ cat /etc/default/grub
GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"
GRUB_DEFAULT=saved
GRUB_DISABLE_SUBMENU=true
GRUB_TERMINAL_OUTPUT="console"
GRUB_CMDLINE_LINUX="crashkernel=auto rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet"
GRUB_DISABLE_RECOVERY="true"
其中,重要选项的含义如下:
-
GRUB_TIMEOUT
:设置选择菜单等待超时的秒数。设为 0 表示不等待,设为 -1 表示必须手动选择。 -
GRUB_TIMEOUT_STYLE
:可以设置的值为menu
、countdown
、hidden
等,默认为menu
。该参数用于确定是否显示菜单。将其设置为countdown
或hidden
可使用户看不到任何内容。 -
GRUB_DEFAULT
:菜单默认选择的项目。可以设置为saved
、数字、title 名、ID 名等,具体取决于menuentry
的设置。例如,如果配置中定义了三个menuentry
:menuentry 'CentOS' --unrestricted $menuentry_id_option 'linux-1' menuentry 'Debian' --unrestricted $menuentry_id_option 'gnulinux' menuentry 'Windows' --unrestricted $menuentry_id_option 'win'
那么对应
GRUB_DEFAULT
的值:- 值为 1 表示选择排在第二个定义的 Debian 系统,因为数字编号从 0 开始。
- 值为 win 表示选择排在第三个定义的 Windows 系统,通过 ID 选取。
- 值为 saved 表示使用
grub2-set-default
来设置默认值,通常默认为 0。
-
GRUB_TERMINAL_OUTPUT
:信息输出的终端模式。可以设置的值有console
、serial
、gfxterm
、vga_text
等。 -
GRUB_CMDLINE_LINUX
:内核的额外参数功能,用于设置内核启动时需要添加的额外参数。
例如,将菜单等待时间修改为 30 秒,然后使用 grub2-mkconfig
命令重建 grub.cfg
:
[root@101c7 ~]$ sed -i 's/GRUB_TIMEOUT=5/GRUB_TIMEOUT=30/g' /etc/default/grub ; head -1 /etc/default/grub
GRUB_TIMEOUT=30
[root@101c7 ~]$ grub2-mkconfig -o /boot/grub2/grub.cfg
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-3.10.0-1160.41.1.el7.x86_64
Found initrd image: /boot/initramfs-3.10.0-1160.41.1.el7.x86_64.img
Found linux image: /boot/vmlinuz-3.10.0-862.el7.x86_64
Found initrd image: /boot/initramfs-3.10.0-862.el7.x86_64.img
Found linux image: /boot/vmlinuz-0-rescue-77a36143eb014dd5a0d6e738b1d84778
Found initrd image: /boot/initramfs-0-rescue-77a36143eb014dd5a0d6e738b1d84778.img
done
[root@101c7 ~]$ grep timeout /boot/grub2/grub.cfg
if [ x$feature_timeout_style = xy ] ; then
set timeout_style=menu
set timeout=30
# Fallback normal timeout code in case the timeout_style feature is
set timeout=30
接下来看一下 /etc/grub.d
文件夹的内容:
[root@101c7 ~]$ ll /etc/grub.d
total 72
-rwxr-xr-x. 1 root root 8702 Mar 16 2021 00_header
-rwxr-xr-x. 1 root root 1043 Mar 21 2019 00_tuned
-rwxr-xr-x. 1 root root 232 Mar 16 2021 01_users
-rwxr-xr-x. 1 root root 10781 Mar 16 2021 10_linux
-rwxr-xr-x. 1 root root 10275 Mar 16 2021 20_linux_xen
-rwxr-xr-x. 1 root root 2559 Mar 16 2021 20_ppc_terminfo
-rwxr-xr-x. 1 root root 11169 Mar 16 2021 30_os-prober
-rwxr-xr-x. 1 root root 214 Mar 16 2021 40_custom
-rwxr-xr-x. 1 root root 216 Mar 16 2021 41_custom
-rw-r--r--. 1 root root 483 Mar 16 2021 README
可以看到文件名与 grub.cfg
中的段头对应。其中主要的文件包括:
00_header
:用于创建初始的显示项目,包括需要加载的模块分析、屏幕终端格式、倒数秒数、菜单是否隐藏等。大部分设置在/etc/default/grub
中的变量会在这个脚本中使用,用于重建grub.cfg
。01_users
:用于设置账号密码,以控制每个菜单选项的访问权限。权限分为三种:不受限(unrestricted
)、用户(users
)、超级用户(superusers
)。只有超级用户可以使用启动项编辑模式。10_linux
:根据分析/boot
下面的文件,尝试找到正确的 Linux 内核文件与虚拟文件系统镜像等,脚本会将找到的文件路径写入到grub.cfg
中。因为每一个内核文件都会建立一个启动选项,所以可以适当删除旧内核文件来精简启动菜单。30_os-prober
:这个脚本用来找其他分区中可能存在的操作系统,如果找到则将其加入启动菜单中。可以在/etc/default/grub
中加上GRUB_DISABLE_OS_PROBER=true
参数来取消这一扫描。40_custom
:用来手动添加菜单项目。例如想新增一个menuentry
来指定开机进入图形模式,可以在grub.cfg
中复制一个menuentry
段,修改对应的title
、id
与linux16
后面的参数(增加systemd.unit=graphical.target
),然后再用grub2-mkconfig
命令重建grub.cfg
即可。
设置多重引导
多重引导使用开机管理程序的链接(Chain Loader)功能,将开机引导程序指向其他位置。只需要设置另一个开机引导程序所在分区代号和所在扇区就可以了。
假设系统有一块硬盘两个分区,分别装了 Linux(sdb1)和 Windows(sdb2),我们需要增加两个开机选项,一个指向 Windows 开机菜单,一个回到 MBR 的默认环境。40_custom
文件内容大致如下:
[root@101c7 ~]$ vi /etc/grub.d/40_custom
#!/bin/sh
exec tail -n +3 $0
# This file provides an easy way to add custom menu entries. Simply type the
# menu entries you want to add after this comment. Be careful not to change
# the 'exec tail' line above.
menuentry 'Windows' --id 'win' {
insmod chain
insmod ntfs
set root=(hd0,msdos2)
chainloader +1
menuentry 'MBR' --id 'mbr' {
insmod chain
set root=(hd0)
chainloader +1
"/etc/grub.d/40_custom" 14L, 469C written
其中最重要的是载入 chain
和 ntfs
模块,由此 Grub2 才能正确读取文件系统执行 Chain Loader 功能。
启动项编辑模式
在启动菜单出现后,可以按下 e
进入启动项编辑模式。也就是直接编辑 grub.cfg
文件内容。
例如,可以在 systemd.unit
中指定为 rescue.target
,这样就能直接进入救援模式,而不需要先进入系统。修改完毕后,使用快捷键 [Ctrl]+x
来执行。
启动异常处理
通常因为某些不正常的设置或不正常关机导致无法顺利开机时,可以进入 rescue 模式去处理.
忘记 root 密码
在使用 grub 做引导的系统可以这样处理:
- 启动系统,在选择启动项的界面下,按
e
进入默认启动项 grub 编辑模式。 - 移动到有 kernel 那行,再按一次
e
进入编辑界面,在最后方输入single
。 - 按下回车,再按下
b
就可以进入单用户维护模式。 - 这一模式下可以直接用
passwd
命令修改 root 密码。
CentOS 7 中 rescue 模式也需要 root 密码才能登录,因此可以进入 emergency 救援模式:
- 按
e
进入编辑默认启动项 grub,找到 linux16 那行,在最末尾输入init=/bin/sh
,按[Ctrl]+x
执行; - 进入 emergency 模式后,输入
mount -o remount,rw /
命令将根目录挂载为可读写模式; - 然后使用
passwd
命令设置新的 root 密码; - 最后输入
touch /.autorelabel
更新系统信息,让 SELinux 生效; - 执行
exec /sbin/init
或reboot
即可退出救援模式。
通过 rd.break(Ram Disk 里面的操作系统)内核启动参数也可以处理:
- 同样在编辑默认启动项 grub,在 linux16 那行末尾加入
rd.break
参数,按[Ctrl]+x
执行; - 此时进入的是 Ram Disk 环境,系统被挂载到
/sysroot
目录下,用mount -o remount,rw /sysroot
重新挂载; - 用命令
chroot /sysroot
来切换根目录,并使用passwd
命令修改密码; - 同样用
touch /.autorelabel
来变回 SELinux 的安全标签。重启即可。
touch /.autorelabel
命令的作用:
-
在救援模式下系统没有 SELinux,所以用
passwd
命令修改了/etc/shadow
文件后,它的 SELinux 安全标签会被取消,在 SELinux 为 Enforcing 模式下会无法登录系统。 -
创建
/.autorelabel
文件就是要让系统在开机时自动使用默认 SELinux 类型重写入 SELinux 安全标签到每个文件。 -
如果不想让每个文件都更新标签,可以改完密码后,将 SELinux 运行模式改为 permissive(修改
/etc/selinux/config
文件)。再重新开机后运行restorecon -Rv /etc
仅恢复/etc
目录下的默认安全上下文类型。最后将 SELinux 配置文件的运行模式改回 enforcing,用setenforce 1
来生效。
文件系统错误
断电或不正常关机会导致文件系统错误,通常是软件数据问题。如果根目录没有损坏,可以进入维护模式下使用fsck
命令修复ext4
格式的分区。修复完毕后以reboot
重启即可:
[root@101c7 ~]$ fsck /dev/sda2
fsck from util-linux 2.23.2
如果是xfs
格式分区则使用xfs_repair
命令:
[root@101c7 ~]$ xfs_repair /dev/sda2
xfs_repair: cannot open /dev/sda2: Device or resource busy
如果整个硬盘只有一个大区,那文件系统错误一定是根目录的问题。这时候需要将硬盘拔下来,接到另外一台 Linux 系统的机器上,并且不要挂载,以root
身份执行fsck
或xfs_repair
命令修复。
还有一种方法是使用 U 盘刻成 Live CD,在 U 盘启动的系统中执行修复命令。
关机重启
切换运行级别和模式并不会重启.
查看用户在线状态
如果有其他用户在线,强制关机可能会导致用户文件丢失,可以先使用who
命令查看当前已登录的用户信息:
[user1@101c7 root]$ who -Hu
NAME LINE TIME IDLE PID COMMENT
root tty1 2021-09-11 09:35 old 897
root pts/0 2021-09-15 12:12 . 5334 (192.168.2.101)
root pts/1 2021-09-14 08:40 old 55207 (192.168.2.101)
数据写回
默认情况下,某些加载到内存中的数据不会直接被写回硬盘,而是暂存在内存中。可以手动同步将数据写入硬盘:
[user1@101c7 root]$ sync
使用重启或关机命令前也会自动调用sync
命令。
当非管理员使用sync
命令时,只会更新该用户的操作数据。
关机操作
通常使用 shutdown
命令来进行关机操作。
立即关机:
[user1@101c7 root]$ shutdown -h now
预定在 21:00 关机。如果当前时间超过 21:00 则会在隔天 21:00 才关机:
[user1@101c7 root]$ shutdown -h 21:00
预定 2 分钟后关机,并发送消息:
[root@101c7 ~]$ shutdown -P 120 "will poweroff"
Shutdown scheduled for Wed 2021-09-15 16:01:48 EDT, use 'shutdown -c' to cancel.
取消即将进行的关机操作:
[root@101c7 ~]$ shutdown -c
[root@101c7 ~]$
Broadcast message from root@101c7 (Wed 2021-09-15 14:01:54 EDT):
The system shutdown has been cancelled at Wed 2021-09-15 14:02:54 EDT!
重启操作
重启命令可用 reboot
或 halt
,选择其一即可。
立即强制关机:
[root@101c7 ~]$ halt -P -f
同步后重启系统:
[root@101c7 ~]$ sync; sync; sync; reboot
切换执行等级
可以通过 init
命令来切换运行级别,例如进入单用户维护模式:
[root@localhost ~]$ init 1
Broadcast message from root@localhost.localdomain on pts/1 (Fri 2019-07-05 15:40:59 CST):
The system is going down to rescue mode NOW!
在 CentOS 7 中则是由 systemctl
来管理模式之间的切换,例如切换到救援模式:
[root@101c7 ~]$ systemctl isolate rescue.target