主机宝贝 建站教程 【Debian参考手册】第 3 章 系统初始化

【Debian参考手册】第 3 章 系统初始化

目录

3.1. 启动过程概述
3.1.1. 第一阶段:UEFI
3.1.2. 第二阶段:引载加载程序
3.1.3. 第三阶段:迷你 debian 系统
3.1.4. 第四阶段:常规 Debian 系统
3.2. Systemd 初始化
3.2.1. 主机
3.2.2. 文件系统
3.2.3. 网络接口初始化
3.3. 内核消息
3.4. 系统消息
3.5. 系统管理
3.6. 其它系统监控
3.7. 定制 systemd
3.7.1. 套接字激活
3.8. udev 系统
3.8.1. 内核模块初始化

作为系统管理员,粗略地了解 Debian 系统的启动和配置方式是明智的。尽管准确的细节在安装的软件包及对应的文档中,但这些知识对我们大多数人来说都是必须掌握的。

下面是 Debian 系统初始化的要点概述。由于 Debian 系统在不断发展,您应该参考最新的文档。

  • Debian Linux 内核手册 是关于 Debian 内核的主要信息来源。

  • bootup(7) 介绍了基于 systemd 的系统启动流程。(近期的 Debian)

  • boot(7) 介绍了基于 UNIX System V Release 4 的系统启动流程。(旧版的 Debian)

3.1. 启动过程概述

计算机系统从上电事件到能为用户提供完整的操作系统(OS)功能为止,需要经历几个阶段的启动过程。

为简便起见,笔者将讨论范围限定在具有默认安装的典型 PC 平台上。

典型的启动过程像是一个四级的火箭。每一级火箭将系统控制权交给下一级。

  • 第 3.1.1 节 “第一阶段:UEFI”

  • 第 3.1.2 节 “第二阶段:引载加载程序”

  • 第 3.1.3 节 “第三阶段:迷你 Debian 系统”

  • 第 3.1.4 节 “第四阶段:常规 Debian 系统”

当然,这些阶段可以有不同的配置。比如,你编译了自己的内核,则可能会跳过迷你 Debian 系统的步骤。因此,在读者亲自确认之前,请勿假定自己系统的情况也是如此。

3.1.1. 第一阶段:UEFI

Unified Extensible Firmware Interface (UEFI) 统一可扩展固件接口 定义了启动管理器作为 UEFI 规范的一部分。当一个计算机打开电源,启动管理器是启动流程的第一阶段,它检查启动配置并基于启动配置的设置,执行特定的操作系统引导加载程序或操作系统内核(通常是引导加载程序)。启动配置通过变量存储在 NVRAM,变量包括指示操作系统引导加载程序或操作系统内核的文件系统路径的变量。 EFI system partitiON (ESP) EFI 系统分区 是一个数据存储设备分区,在计算机里用来遵照 UEFI 规范。当计算机打开电源时,由 UEFI 固件来访问,它存储了 UEFI 应用程序和这些应用程序运行所需要的文件,包括操作系统的引导加载程序。(在老的 PC 系统,存放在 MBR 里的 BIOS 可以用来代替。)

3.1.2. 第二阶段:引载加载程序

引导加载程序是启动过程的第二阶段,由 UEFI 启动。引导加载程序将系统内核映像和 initrd 映像加载到内存并将控制权交给它们。initrd 映像是根文件系统映像,其支持程度依赖于所使用的引导加载程序。

Debian 系统通常使用 Linux 内核作为默认的系统内核。当前的 5.x Linux 内核的 initrd 映像在技术上是 initramfs(初始 RAM 文件系统)映像。

有许多引导加载程序和配置选项存在。

表 3.1. 引导加载程序列表

软件包 流行度 大小 initrd 引导加载程序 说明
grub-efi-amd64 I:236 158 支持 GRUB UEFI 可智能识别磁盘分区和文件系统,例如 vfat、ext4…(UEFI)
grub-pc V:25, I:737 533 支持 GRUB 第 2 版 可智能识别磁盘分区和文件系统,例如 vfat、ext4…(BIOS)
grub-rescue-pc V:0, I:1 6476 支持 GRUB 第 2 版 此为 GRUB 第 2 版的可引导修复映像(CD 和软盘)(PC / BIOS 版本)
lilo V:0, I:1 697 支持 Lilo 依赖于数据在硬盘上的扇区位置。(较老)
syslinux V:3, I:43 344 支持 Isolinux 可识别 ISO9660 文件系统。引导 CD 使用此项。
syslinux V:3, I:43 344 支持 Syslinux 可识别 MSDOS 文件系统(FAT)。引导软盘使用此项。
loadlin V:0, I:0 90 支持 Loadlin 新系统从 FreeDOS 或 MSDOS 中启动。
mbr V:0, I:6 50 不支持 Neil Turton 的 MBR 此为取代 MSDOS MBR 的自由软件。只可识别硬盘分区。

警告

假如没有从 grub-rescue-pc 软件包中的映像制作出来的可引导修复盘(U盘、CD 或软盘),请勿玩弄引导加载程序。即使硬盘上没有可正常工作的引导加载程序,可引导修复盘也能引导你的系统。

GRUB 2 的菜单配置文件位于 /boot/grub/grub.cfg,它的菜单条目的关键部分看起来像:

menuentry 'Debian GNU/Linux' ... {
        load_video
        insmod gzio
        insmod part_gpt
        insmod ext2
        search --no-floppy --fs-uuid --set=root fe3e1db5-6454-46d6-a14c-071208ebe4b1
        echo    'Loading Linux 5.10.0-6-amd64 ...'
        linux   /boot/vmlinuz-5.10.0-6-amd64 root=UUID=fe3e1db5-6454-46d6-a14c-071208ebe4b1 ro quiet
        echo    'Loading initial ramdisk ...'
        initrd  /boot/initrd.img-5.10.0-6-amd64
}

对于这部分的 /boot/grub/grub.cfg,这个菜单条目的意义如下。

表 3.2. /boot/grub/grub.cfg 文件上面部分菜单条目意义

设置
GRUB2 模块加载 gzio, part_gpt, ext2
使用的根文件系统分区UUID=fe3e1db5-6454-46d6-a14c-071208ebe4b1 指定的分区标识
内核镜像文件在根文件系统中的路径 /boot/vmlinuz-5.10.0-6-amd64
使用的内核启动参数root=UUID=fe3e1db5-6454-46d6-a14c-071208ebe4b1 ro quiet
initrd 镜像文件在根文件系统中的路径 /boot/initrd.img-5.10.0-6-amd64

提示

通过设置在 /etc/default/grubGRUB_BACKGROUND 变量指向到图像文件,或者把图像文件本身放入 /boot/grub/,你能够定制 GRUB 的启动图像。

参见 “info grub” 及 grub-install(8)。

3.1.3. 第三阶段:迷你 Debian 系统

迷你 Debian 系统是启动流程的第三阶段,由引导加载程序启动。它会在内存中运行系统内核和根文件系统。这是启动流程的一个可选准备阶段。

注意

“迷你 Debian 系统”是笔者自创的术语,用于在本文档中描述启动流程的第三个阶段。这个系统通常被称为 initrd 或 initramfs 系统。内存中类似的系统在 Debian 安装程序中使用。

/init 程序是内存中的根文件系统上执行的第一个程序。这个程序在用户空间把内核初始化,并把控制权交给下一阶段。迷你 Debian 系统能够在主引导流程之前添加内核模块或以加密形式挂载根文件系统,使引导流程更加灵活。

  • 如果 initramfs 是由 initramfs-tools 创建,则”/init” 程序是一个 shell 脚本程序。

    • 通过给内核添加 “break=init” 等启动参数,你可以中断这部分启动流程以获取 root shell。更多中断条件请参见 ”/init“ 脚本。这个 shell 环境已足够成熟,你可通过它很好地检查机器的硬件。

    • 迷你 Debian 系统中可用的命令是精简过的,且主要由一个称为 busybox(1) 的 GNU 工具提供。

  • 如果 initramfs 是由 dracut 创建,则 “/init” 程序是一个二进制 systemd 程序。

    • 迷你 Debian 系统中可用的命令是一个精简过的 systemd(1) 环境。

小心

当在一个只读的根文件系统上时,使用 mount 命令需要添加 -n 选项。

3.1.4. 第四阶段:常规 Debian 系统

常规 Debian 系统是启动流程的第四阶段,由迷你 Debian 系统启动。迷你 Debian 系统的内核在此环境下继续运行。根文件系统将由内存切换到实际的硬盘文件系统上。

init 程序是系统执行的第一个程序(PID=1),它启动其它各种程序以完成主引导流程。init 程序的默认路径是 ”/sbin/init“,但可通过内核启动参数修改,例如 ”init=/path/to/init_program“。

在 Debian 8 jessie(2015 年发布)版本后,”/sbin/init” 是一个到 “/lib/systemd/systemd” 的符号链接。

提示

你的系统中实际使用的 init 命令可以使用 “ps --pid 1 -f” 命令确认。

表 3.3. Debian 系统启动工具列表

软件包 流行度 大小 说明
systemd V:849, I:941 16625 基于事件且支持并发的 init(8) 守护进程(可替代 sysvinit
systemd-sysv V:820, I:939 147 systemd 需用的用以代替 sysvinit 的手册页和符号链接
init-system-helpers V:687, I:952 133sysvinitsystemd 之间进行转换的帮助工具
initscripts V:64, I:238 172 用于初始化和关闭系统的脚本
sysvinit-core V:7, I:8 279 类 System V 的 init(8) 工具
sysv-rc V:127, I:251 82 类 System V 的运行级别修改机制
sysvinit-utils V:403, I:999 81 类 System V 的实用工具(startpar(8),bootlogd(8),……)
lsb-base V:895, I:999 49Linux 标准规范 3.2 版的 init 脚本功能
insserv V:153, I:248 153 利用 LSB init.d 脚本依赖性来组织启动步骤的工具
uswsusp V:1, I:5 714 使用 Linux 提供的用户态软件 suspend 的工具
kexec-tools V:1, I:7 289 用于 kexec(8) 重启(热启动)的 kexec 工具
systemd-bootchart V:0, I:1 128 启动流程性能分析器
bootchart2 V:0, I:0 NOT_FOUND 启动流程性能分析器
pybootchartgui V:0, I:0 NOT_FOUND 启动流程性能分析器(可视化)
mingetty V:0, I:3 38 仅包含控制台的 getty(8)
mgetty V:0, I:0 315 可智能调制解调的 getty(8) 替代品

提示

有关启动流程加速的最新信息,请参见 Debian 维基:启动流程加速词条。

3.2. Systemd 初始化

本节描述系统是怎样通过 PID=1systemd(1) 程序来启动(即初始化进程)。

systemd 初始化进程基于单元配置文件 (参见 systemd.unit(5)) 来并行派生进程,这些单元配置文件使用声明样式来书写,代替之前的类 SysV 的过程样式。这些单元配置文件从下面的一系列路径来加载 (参见 systemd-system.conf(5)) :

派生的进程被放在一个单独的 Linux control groups,在单元后命名,它们属于一个私有的 systemd 层级结构(参见 cgroups 和 第 4.7.4 节 “Linux 安全特性”)。

单元配置文件从下列一系列路径中加载(参见 systemd-system.conf(5)):

  • /lib/systemd/system“: OS 默认配置文件

  • /etc/systemd/system“: 系统管理员的配置文件,它将忽略操作系统默认的配置文件

  • /run/systemd/system“: 运行时产生的配置文件,它将忽略安装的配置文件

他们的相互依赖关系通过”Wants=“, “Requires=“, “Before=“, “After=“, … 等指示来配置,(参见 systemd.unit(5) 里的 “MAPPING OF UNIT PROPERTIES TO THEIR INVERSES”)。 资源控制也是被定义 (参见 systemd.resource-control(5)).

根据单元配置文件的后缀来区分它们的类型:

  • *.service 描述由 systemd 控制和监管的进程.参见 systemd.service(5).

  • *.device 描述在 sysfs(5) 里面作为 udev(7) 设备树展示的设备。参见 systemd.device(5).

  • *.mount 描述由 systemd 控制和监管的文件系统挂载点。参见 systemd.mount(5).

  • *.automount 描述由 systemd 控制和监管的文件系统自动挂载点。参见 systemd.automount(5).

  • *.swap 描述由 systemd 控制和监管的 swap 文件或设备。参见 systemd.swap(5).

  • *.path 描述被 systemd 监控的路径,用于基于路径的活动。参见 systemd.path(5).

  • *.socket 描述被 systemd 控制和监管的套接字,用于基于套接字的活动。参见 systemd.socket(5).

  • *.timer 描述被 systemd 控制和监管的计时器,用于基于时间的活动。参见 systemd.timer(5).

  • *.slice 管理 cgroups(7) 的资源。参见 systemd.slice(5).

  • *.scope 使用 systemd 的总线接口来程序化的创建,用以管理一系列系统进程。 参见 systemd.scope(5).

  • *.target 把其它单元配置文件分组,在启动的时候,来创建同步点。参见systemd.target(5).

系统启动时(即,init),systemd 进程会尝试启动”/lib/systemd/system/default.target(通常是到”graphical.target“的符号链接)。首先,一些特殊的 target 单元(参见 systemd.special(7)),比如 “local-fs.target“、”swap.target“和”cryptsetup.target“会被引入以挂载文件系统。之后,其它 target 单元也会根据单元依赖关系而被引入。详细情况,请阅读 bootup(7)。

systemd 提供向后兼容的功能。在 “/etc/init.d/rc[0123456S].d/[KS]name” 里面的 SysV 风格的启动脚本仍然会被分析;telinit(8) 会被转换为 systemd 的单元活动请求。

小心

模拟的运行级别 2 到 4 全部被符号链接到了相同的“multi-user.target”。

3.2.1. 主机名

内核维护系统主机名。在启动的时候,通过 systemd-hostnamed.service 启动的系统单位设置系统的主机名,此主机名保存在 “/etc/hostname“。这个文件应该包含系统主机名,而不是全称域名。

不带参数运行 hostname(1) 命令可以打印出当前的主机名。

3.2.2. 文件系统

硬盘和网络文件系统的挂载选项可以在 “/etc/fstab” 中设置,参见 fstab(5) 和 第 9.6.7 节 “通过挂载选项优化文件系统”。

加密文件系统的配置设置在“/etc/crypttab”中。参见 crypttab(5)

软 RAID 的配置 mdadm(8) 设置在 “/etc/mdadm/mdadm.conf“. 参见 mdadm.conf(5).

警告

每次启动的时候,在挂载了所有文件系统以后,”/tmp“, “/var/lock“, 和 “/var/run” 中的临时文件会被清空。

3.2.3. 网络接口初始化

对于使用 systemd 的现代 Debian 桌面系统,网络接口通常由两个服务进行初始化:lo 接口通常在“networking.service”处理,而其它接口则由“NetworkManager.service”处理。

参见 第 5 章 网络设置 来获取怎样来配置它们的信息。

3.3. 内核消息

在控制台上显示的内核错误信息,能够通过设置他们的阈值水平来配置。

# dmesg -n3

表 3.4. 内核错误级别表

错误级别值 错误级别名称 说明
0 KERN_EMERG 系统不可用
1 KERN_ALERT 行为必须被立即采取
2 KERN_CRIT 危险条件
3 KERN_ERR 错误条件
4 KERN_WARNING 警告条件
5 KERN_NOTICE 普通但重要的条件
6 KERN_INFO 信息提示
7 KERN_DEBUG debug 级别的信息

3.4. 系统消息

systemd 下, 内核和系统的信息都通过日志服务 systemd-journald.service (又名 journald)来记录,放在”/var/log/journal“下的不变的二进制数据,或放在”/run/log/journal/“下的变化的二进制数据.这些二进制日志数据,可以通过 journalctl(1) 命令来访问。例如,你可以显示从最后一次启动以来的日志,按如下所示:

$ journalctl -b

表 3.5. 典型的 journalctl 命令片段列表

操作 命令片段
查看从最后一次启动开始的系统服务和内核日志journalctl -b --system
查看从最后一次启动开始的当前用户的服务日志journalctl -b --user
查看从最后一次启动开始的 “$unit” 工作日志journalctl -b -u $unit
查看从最后一次启动开始的 “$unit“的工作日志 (“tail -f” 式样)journalctl -b -u $unit -f

systemd 下,系统日志工具 rsyslogd(8) 可以被卸载。如果安装了它,它会改变它的行为来读取易失性二进制日志数据(代替在 systemd 之前默认的 “/dev/log“)并创建传统的永久性 ASCII 系统日志数据。”/etc/default/rsyslog” 和 “/etc/rsyslog.conf” 能够自定义日志文件和屏幕显示。参见 rsyslogd(8) 和 rsyslog.conf(5),也可以参见第 9.3.2 节 “日志分析”。

3.5. 系统管理

systemd 不仅仅提供系统初始化,还用 systemctl(1) 命令提供通用的系统管理操作。

表 3.6. 典型的 systemctl 命令片段列表

操作 命令片段
列出所有 target 单元配置systemctl list-units --type=target
列出所有 service 单元配置systemctl list-units --type=service
列出所有单元配置类型systemctl list-units --type=help
列出内存中所有 socket 单元systemctl list-sockets
列出内存中所有 timer 单元systemctl list-timers
启动 “$unitsystemctl start $unit
停止 “$unitsystemctl stop $unit
重新加载服务相关的配置systemctl reload $unit
停止和启动所有 “$unitsystemctl restart $unit
启动 “$unit” 并停止所有其它的systemctl isolate $unit
转换到 “图形” (图形界面系统)systemctl isolate graphical
转换到 “多用户” (命令行系统)systemctl isolate multi-user
转换到 “应急模式” (单用户命令行系统)systemctl isolate rescue
向”$unit“发送杀死信号systemctl kill $unit
检查”$unit“服务是否是活动的systemctl is-active $unit
检查”$unit“服务是否是失败的systemctl is-failed $unit
检查”$unit|$PID|device“的状态systemctl status $unit|$PID|$device
显示”$unit|$job“的属性systemctl show $unit|$job
重设失败的”$unitsystemctl reset-failed $unit"
列出所有单元服务的依赖性systemctl list-dependencies --all
列出安装在系统上的单元文件systemctl list-unit-files
启用 “$unit” (增加符号链接)systemctl enable $unit
禁用 “$unit” (删除符号链接)systemctl disable $unit
取消遮掩 “$unit” (删除到 “/dev/null” 的符号链接)systemctl unmask $unit
遮掩 “$unit” (增加到 “/dev/null” 的符号链接)systemctl mask $unit
获取默认的 target 设置systemctl get-default
设置默认 target 为”graphical” (图形系统)systemctl set-default graphical
设置默认的 target 为”multi-user” (命令行系统)systemctl set-default multi-user
显示工作环境变量systemctl show-environment
设置环境变量 “variable” 的值为 “valuesystemctl set-environment variable=value
取消环境变量 “variable” 的设置systemctl unset-environment variable
重新加载所有单元文件和后台守护进程(daemon)systemctl daemon-reload
关闭系统systemctl poweroff
关闭和重启系统systemctl reboot
挂起系统systemctl suspend
休眠系统systemctl hibernate

这里, 上面例子中的”$unit“,可以是一个单元名(后缀.service.target 是可选的),或者,在很多情况下,也可以是匹配的多个单元 (shell 式样的全局通配符”*“, “?“, “[]“,通过使用 fnmatch(3) ,来匹配目前在内存中的所有单元的基本名称).

上面列子的系统状态改变命令,通常是通过”sudo“来处理,用以获得需要的系统管理权限。

systemctl status $unit|$PID|$device” 的输出使用有颜色的点(“●”)来概述单元状态,让人看一眼就知道。

  • 白色的 “●” 表示一个 “不活动”或”变为不活动中”的状态。

  • 红色的 “●”表示“失败”或者“错误”状态。

  • 绿色”●”表示“活动”、“重新加载中”或“激活中”状态。

3.6. 其它系统监控

这里是 systemd 下其它零星的监控命令列表。请阅读包括 cgroups(7) 在内的相关的 man 手册页。

表 3.7. systemd 下其它零星监控命令列表

操作 命令片段
显示每一个初始化步骤所消耗的时间systemd-analyze time
列出所有单元的初始化时间systemd-analyze blame
加载”$unit“文件并检测错误systemd-analyze verify $unit
简洁的显示用户调用会话的运行时状态信息loginctl user-status
简洁的显示调用会话的运行时状态信息loginctl session-status
跟踪 cgroups 的启动过程systemd-cgls
跟踪 cgroups 的启动过程ps xawf -eo pid,user,cgroup,args
跟踪 cgroups 的启动过程 读取 “/sys/fs/cgroup/systemd/” 下的 sysfs

3.7. 定制 systemd

3.7.1. 套接字激活

使用默认安装,通过 systemd 启动的过程中,在 network.target 启动后,很多网络服务 (参见 第 6 章 网络应用)作为后台守护进程(daemon)启动。 “sshd” 也不列外。让我们修改为按需启动”sshd” 作为一个定制化的例子。

首先,禁用系统安装的服务单元。

 $ sudo systemctl stop sshd.service
 $ sudo systemctl mask sshd.service

传统 Unix 服务的按需套接字激活(on-demand socket activation)系统由 inetd (或 xinetd)超级服务来提供。在 systemd 下, 相同功能能够通过增加*.socket*.service 单元配置文件来启用。

sshd.socket 用来定义一个监听的套接字

[Unit]
Description=SSH Socket for Per-Connection Servers

[Socket]
ListenStream=22
Accept=yes

[Install]
WantedBy=sockets.target

sshd@.service 作为 sshd.socket 匹配的服务文件

[Unit]
Description=SSH Per-Connection Server

[Service]
ExecStart=-/usr/sbin/sshd -i
StandardInput=socket

然后重新加载。

 $ sudo systemctl daemon-reload

3.8. udev 系统

从 Linux 内核 2.6 版开始,udev 系统 提供了自动硬件发现和初始化机制。(参见 udev(7)).在内核发现每个设备的基础上,udev 系统使用从 sysfs 文件系统 (参见 第 1.2.12 节 “procfs 和 sysfs”)的信息启动一个用户进程,使用 modprobe(8) 程序 (参见 第 3.8.1 节 “内核模块初始化”)加载支持它所要求的内核模块, 创建相应的设备节点。

提示

如果由于某些理由,”/lib/modules/kernel-version/modules.dep“没有被 depmod(8) 正常生成,模块可能不会被 udev 系统按期望的方式加载。执行”depmod -a” 来修复它。

/etc/fstab“里面的挂载规则,设备节点不必需是静态的。你能够使用 UUID 来挂载设备,来代替”/dev/sda“之类的设备名. 参见 第 9.6.3 节 “使用 UUID 访问分区”.

由于 udev 系统是一个正在变化的事物,我在其它文档进行了详细描述,在这里只提供了最少的信息。

3.8.1. 内核模块初始化

通过 modprobe(8) 程序添加和删除内核模块,使我们能够从用户进程来配置正在运行的 Linux 内核。udev 系统(参见 第 3.8 节 “udev 系统”)自动化它的调用来帮助内核模块初始化。

下面的非硬件模块和特殊的硬件驱动模块,需要被预先加载,把它们在”/etc/modules“文件里列出 (参见 modules(5)).

  • TUN/TAP 模块提供虚拟的 Point-to-Point 网络设备 (TUN) 和虚拟的 Ethernet 以太网网络设备 (TAP),

  • netfilter 模块提供 netfilter 防火墙能力(iptables(8), 第 5.6 节 “Netfilter 网络过滤框架”),

  • watchdog timer 驱动模块。

modprobe(8) 程序的配置文件是按 modprobe.conf(5)的说明放在”/etc/modprobes.d/” 目录下,(如果你想避免自动加载某些内核模块,考虑把它们作为黑名单放在”/etc/modprobes.d/blacklist” 文件里.)

/lib/modules/version/modules.dep” 文件由 depmod(8) 程序生成,它描述了 modprobe(8) 程序使用的模块依赖性.

注意

如果你在启动时出现模块加载问题,或者 modprobe(8)时出现模块加载问题, “depmod -a” 可以通过重构”modules.dep“来解决这些问题。

modinfo(8) 程序显示 Linux 内核模块信息。

lsmod(8) 程序以好看的格式展示”/proc/modules“的内容,显示当前内核加载了哪些模块。

提示

你能够精确识别你系统上的硬件。 参见第 9.5.3 节 “硬件识别”.

你可以在启动时配置硬件来激活期望的硬件特征。参见 第 9.5.4 节 “硬件配置”.

你可以重新编译内核来增加你的特殊设备的支持。参见 第 9.10 节 “内核”.

本文来自网络,不代表主机宝贝立场,转载请注明出处:http://www.idcbaby.com/77974/