目录
作为系统管理员,粗略地了解 Debian 系统的启动和配置方式是明智的。尽管准确的细节在安装的软件包及对应的文档中,但这些知识对我们大多数人来说都是必须掌握的。
笔者基于自己和其他人的过往及现在的知识,尽己所能地提供关于 Debian 系统的知识要点及其配置的快速概览作为读者的参考。由于 Debian 系统在不断地更新中,系统的状况可能已经有所变化。在对系统做任何修改之前,请参考各个软件包的最新文档。
警告 | |
---|---|
本章是基于 2013 年发布的 Debian 7.0 ( |
计算机系统从上电事件到能为用户提供完整的操作系统(OS)功能为止,需要经历几个阶段的启动过程。
为简便起见,笔者将讨论范围限定在具有默认安装的典型 PC 平台上。
典型的启动过程像是一个四级的火箭。每一级火箭将系统控制权交给下一级。
当然,这些阶段可以有不同的配置。比如,你编译了自己的内核,则可能会跳过迷你 Debian 系统的步骤。因此,在读者亲自确认之前,请勿假定自己系统的情况也是如此。
注意 | |
---|---|
对于 SUN 或 Macintosh 系统等非传统 PC 平台来说,ROM 上的 BIOS 及磁盘上的分区可能大不相同(第 9.5.2 节 “硬盘分区配置”)。对于这种情况,请另寻对应平台相关的文档。 |
BIOS 是启动过程的第一阶段,在上电事件后开始。CPU 的程序计数器在上电事件后被初始化为一个特定的内存地址,驻留在只读存储器(ROM)中的 BIOS 就是从这个特定的内存地址开始执行。
BIOS 执行硬件的基本初始化(POST: 上电自检)并将系统控制权交给你指定的下一步骤。BIOS 通常和硬件一同提供。
BIOS 启动屏幕通常指示了进入 BIOS 配置界面所需的按键。流行的按键是 F1、F2、F10、Esc、Ins 和 Del 键。假如你的启动屏幕被一个漂亮的图形界面隐藏,你可以按下某些按键(比如 ESC)取消隐藏。这些按键高度依赖于硬件。
硬件位置和 BIOS 启动的代码的优先级可以在 BIOS 配置界面中选择。通常,在已选择的设备(硬盘、软件、CD-ROM……)中,最先找到的设备的最开始的几个扇区将被加载到内存,并执行其中的初始化代码。初始化代码可以是以下任意一种。
引导加载代码
类似 FreeDOS 这样的过滤型操作系统的内核代码
能够加载到如此小的空间中的目标操作系统的内核代码
通常,系统从主硬件的特定分区中引导。传统 PC 硬盘的最开始两个扇区中包含了主引导记录(MBR)。在 MBR 的末尾记录了磁盘分区信息及引导选择。BIOS 中执行的首段引导加载代码占据了 MBR 的其余部分。
引导加载程序是启动过程的第二阶段,由 BIOS 启动。引导加载程序将系统内核映像和 initrd 映像加载到内存并将控制权交给它们。initrd 映像是根文件系统映像,其支持程度依赖于所使用的引导加载程序。
Debian 系统通常使用 Linux 内核作为其默认的系统内核。当前 2.6/3.x 版本 Linux 内核的 initrd 映像从技术上说是 initramfs(初始化 RAM 文件系统)映像。initramfs 映像是根文件系统中所有文件的 cpio 归档再经过 gzip 压缩得到。
警告 | |
---|---|
使用新的 multi-segment initramfs 之后,上述内容已不正确。请参见错误 #790100。 |
Debian 系统默认将 PC 平台的 GRUB 引导加载程序的第一阶段代码安装在 MBR 中。可用的引导加载程序和配置选项如下。
表 3.1. 引导加载程序列表
软件包 | 流行度 | 大小 | initrd | 引导加载程序 | 说明 |
---|---|---|---|---|---|
grub-legacy | V:0, I:2 | 710 | 支持 | 传统 GRUB | 可智能识别磁盘分区和文件系统(例如 vfat、ext3…)。 |
grub-pc | V:35, I:878 | 542 | 支持 | GRUB 第 2 版 | 可智能识别磁盘分区和文件系统(例如 vfat、ext4…)。(默认安装) |
grub-rescue-pc | V:0, I:2 | 5238 | 支持 | GRUB 第 2 版 | 此为 GRUB 第 2 版的可引导修复映像(CD 和软盘)(PC / BIOS 版本) |
lilo | V:0, I:5 | 685 | 支持 | Lilo | 依赖于数据在硬盘上的扇区位置。(较老) |
syslinux | V:6, I:66 | 294 | 支持 | Isolinux | 可识别 ISO9660 文件系统。引导 CD 使用此项。 |
syslinux | V:6, I:66 | 294 | 支持 | Syslinux | 可识别 MSDOS 文件系统(FAT)。引导软盘使用此项。 |
loadlin | V:0, I:1 | 82 | 支持 | Loadlin | 新系统从 FreeDOS 或 MSDOS 中启动。 |
mbr | V:1, I:12 | 50 | 不支持 | Neil Turton 的 MBR | 此为取代 MSDOS MBR 的自由软件。只可识别硬盘分区。 |
警告 | |
---|---|
假如没有从 |
传统 GRUB 的菜单配置文件位于 /boot/grub/menu.lst
。例如,文件中有如下的配置条目。
title Debian GNU/Linux root (hd0,2) kernel /vmlinuz root=/dev/hda3 ro initrd /initrd.img
GRUB 第 2 版的菜单配置文件位于 /boot/grub/grub.cfg
。此文件由
/usr/sbin/update-grub
根据
"/etc/grub.d/*
" 中的模板及
"/etc/default/grub
" 中的设置自动生成。例如,文件中有如下的配置条目。
menuentry "Debian GNU/Linux" { set root=(hd0,3) linux /vmlinuz root=/dev/hda3 initrd /initrd.img }
这些示例中,GRUB 参数的含义如下。
表 3.2. GRUB 参数的含义
GRUB 参数 | 说明 |
---|---|
root
|
使用主磁盘的第 3 个分区,在传统 GRUB 中将此参数设置为 "(hd0,2) ",在 GRUB 第 2
版中将此参数设置为 "(hd0,3) "
|
kernel
|
使用位于 "/vmlinuz " 的内核,同时将 "root=/dev/hda3
ro " 作为参数传递给内核
|
initrd
|
使用位于 "/initrd.img " 的 initrd/initramfs 映像
|
注意 | |
---|---|
传统 GRUB 使用的分区号为 Linux 内核及各种实用工具使用的分区号减 1。GRUB 第 2 版修复了这个问题。 |
提示 | |
---|---|
在标识一个块设备时,可能需要使用 UUID(参见第 9.5.3 节 “使用 UUID 访问分区”)而不是类似
" |
提示 | |
---|---|
如果使用了 GRUB,内核的启动参数可以在
|
提示 | |
---|---|
通过使用链式引导技术,你可以在一个引导装载程序中启动另一个引导装载程序。 |
参见 “info grub
” 及
grub-install(8)。
迷你 Debian 系统是启动流程的第三阶段,由引导加载程序启动。它会在内存中运行系统内核和根文件系统。这是启动流程的一个可选准备阶段。
注意 | |
---|---|
“迷你 Debian 系统”是笔者自创的术语,用于在本文档中描述启动流程的第三个阶段。这个系统通常被称为 initrd 或 initramfs 系统。内存中类似的系统在 Debian 安装程序中使用。 |
/init
脚本是内存中的根文件系统上执行的第一个程序。它是一个 shell
脚本程序,用于内存在用户空间的初始化并把控制权交给下一阶段。迷你 Debian
系统能够在主引导流程之前添加内核模块或以加密形式挂载根文件系统,使引导流程更加灵活。
通过给内核添加 “break=init
" 等启动参数,你可以中断这部分启动流程以获取 root
shell。更多中断条件请参见 ”/init
“ 脚本。这个 shell
环境已足够成熟,你可通过它很好地检查机器的硬件。
迷你 Debian 系统中可用的命令是精简过的,且主要由一个称为 busybox(1) 的 GNU 工具提供。
小心 | |
---|---|
当在一个只读的根文件系统上时,使用 |
常规 Debian 系统是启动流程的第四阶段,由迷你 Debian 系统启动。迷你 Debian 系统的内核在此环境下继续运行。根文件系统将由内存切换到实际的硬盘文件系统上。
init 程序是系统执行的第一个程序(PID=1),它启动其它各种程序以完成主引导流程。init
程序的默认路径是 ”/sbin/init
“,但可通过内核启动参数修改,例如
”init=/path/to/init_program
"。
默认的 init 程序一直在变化中:
提示 | |
---|---|
" |
提示 | |
---|---|
你的系统中实际使用的 init 命令可以使用 “ |
表 3.3. Debian 系统启动工具列表
软件包 | 流行度 | 大小 | 说明 |
---|---|---|---|
initscripts
|
V:867, I:986 | 207 | 用于初始化和关闭系统的脚本 |
sysvinit-core
|
V:19, I:24 | 221 | 类 System V 的 init(8) 工具 |
sysv-rc
|
V:867, I:985 | 122 123 | 类 System V 的运行级别修改机制 |
sysvinit-utils
|
V:875, I:999 | 106 | 类 System V 的实用工具(startpar(8),bootlogd(8),……) |
lsb-base
|
V:876, I:999 | 49 | Linux 标准规范 3.2 版的 init 脚本功能 |
insserv
|
V:814, I:962 | 139 | 利用 LSB init.d 脚本依赖性来组织启动步骤的工具 |
systemd
|
V:597, I:682 | 9276 |
基于事件且支持并发的
init(8)
守护进程(可替代 sysvinit )
|
uswsusp
|
V:4, I:14 | 493 | 使用 Linux 提供的用户态软件 suspend 的工具 |
kexec-tools
|
V:1, I:7 | 258 | 用于 kexec(8) 重启(热启动)的 kexec 工具 |
bootchart2
|
V:0, I:1 | 63 | 启动流程性能分析器 |
pybootchartgui
|
V:0, I:1 | 177 | 启动流程性能分析器(可视化) |
mingetty
|
V:0, I:3 | 24 | 仅包含控制台的 getty(8) |
mgetty
|
V:0, I:2 | 289 | 可智能调制解调的 getty(8) 替代品 |
提示 | |
---|---|
有关启动流程加速的最新信息,请参见 Debian 维基:启动流程加速词条。 |
小心 | |
---|---|
当前默认的 Debian 系统已不使用 SysV 风格的 init。请阅读其它资源以获取关于现代的基于 systemd 的 init。参见 Debian 管理员手册 |
本章节描述优秀而老式的 SysV 风格的 init 是如何引导系统的。你的 Debian 系统的运作方式并不与此处描述的内容完全相同,但了解这些基础内容颇具教育意义,因为更新的 init 系统倾向于提供相同的功能。
SysV 风格的启动流程本质上经历了以下几个阶段。
Debian 系统进入运行级别 N(无)并根据
“/etc/inittab
” 的描述初始化系统。
Debian 系统进入运行级别 S 并在单用户模式下完成系统的硬件初始化等等。
Debian 系统进入某个指定的多用户运行级别(2 到 5)并启动各个系统服务。
多用户模式的初始运行级别,可通过内核启动参数 “init=
” 指定,或在
“/etc/inittab
” 中的 "initdefault" 行指定。已安装的 Debian
系统以运行级别 2 启动。
init 系统实际执行的所有脚本文件都在 “/etc/init.d/
” 目录中。
参见
init(8)、inittab(5)
及 “/usr/share/doc/sysv-rc/README.runlevels.gz
” 以获取确切的解释。
每一个运行级别都使用一个目录存放其配置,其特定的含义如下。
表 3.4. 运行级别及其使用方法描述列表
运行级别 | 目录 | 运行级别使用方法描述 |
---|---|---|
N
|
无 |
系统引导(无)级别(没有 “/etc/rcN.d/ ” 目录)
|
0
|
/etc/rc0.d/
|
将系统停止 |
S
|
/etc/rcS.d/
|
启动时的单用户模式(别名:“s ”)
|
1
|
/etc/rc1.d/
|
从多用户模式切换过来的单用户模式 |
2
|
/etc/rc2.d/
|
多用户模式 |
3
|
/etc/rc3.d/
|
同上 |
4
|
/etc/rc4.d/
|
同上 |
5
|
/etc/rc5.d/
|
同上 |
6
|
/etc/rc6.d/
|
重启系统 |
7
|
/etc/rc7.d/
|
有效的多用户模式但通常不使用 |
8
|
/etc/rc8.d/
|
同上 |
9
|
/etc/rc9.d/
|
同上 |
例如,你可在控制台中使用如下命令将运行级别修改为 4。
$ sudo telinit 4
小心 | |
---|---|
Debian 系统不对从 2 到 5 之间的运行级别预置任何特殊的含义区别。 Debian 系统的管理员可修改此值。(也就是说,Debian 既不是红帽 Linux,也不是 Sun 公司的 Solaris,也不是惠普的 HP-UX,也不是 IBM 的 AIX,也不是……) |
当 init(8) 或 telinit(8) 将运行级别设置为 “<n>” 时,系统执行初始化脚本的主要过程如下。
“/etc/rc<n>.d/
” 目录下以一个 “K
”
打头的脚本将按字母顺序且带单个 “stop
” 参数执行。(杀死服务)
“/etc/rc<n>.d/
” 目录下以一个 “S
”
打头的脚本将按字母顺序且带单个 “start
” 参数执行。(启动服务)
例如,在某个运行级别目录下有 “S10sysklogd
” 和
“S20exim4
” 两个符号链接文件,分别指向
“../init.d/sysklogd
” 和
“../init.d/exim4
”,那么 “S10sysklogd
” 将在
“S20exim4
” 之前运行。
这种简单的顺序初始化系统属于经典的 System V 风格的启动系统,在 Debian
系统 lenny
及以前的版本中使用。
相反,最近版本的 Debian 系统优化成同时执行各个初始化脚本。
insserv(8) 命令利用 LSB 包依赖信息计算出所有脚本的依赖关系。
参见 “/usr/share/doc/insserv/README.Debian
”。
在 init 脚本头部定义的 LSB 包依赖信息保证了所需资源的可用性。
警告 | |
---|---|
不建议对 ” |
例如,让我们来建立如下类似 Red Hat Linux 的运行级别系统。
init
默认以 runlevel=3 启动系统。
init
不会在 runlevel=(0,1,2,6) 时启动
gdm3(1)。
init
会在 runlevel=(3,4,5) 时启动
gdm3(1)。
可以通过修改 "/etc/inittab
" 文件来改变启动等级并且也可以使用用户友好的运行级别管理工具例如
sysv-rc-conf
或者 bum
来更改运行级别。如果你只想用命令行方式的话,如下是你应该怎样去做的步骤(默认安装 gdm
软件包后,在显示器管理工具中选中它)。
# cd /etc/rc2.d; mv S21gdm3 K21gdm3 # cd /etc; perl -i -p -e 's/^id:.:/id:3:/' inittab
请注意当启动显示器管理进程时:xdm
,gdm3
,sddm
和
wdm
,"/etc/X11/default-display-manager
"
文件会被检查。
注意 | |
---|---|
你也可以在任何控制台界面用 startx(1) 命令启动 X。 |
"/etc/init.d
" 中的每个 init 脚本的默认参数由
"etc/default
" 中的对应文件给出,此对应文件只包含环境变量分配。这些目录是 Debian 系统特定的,它们大致相当于 Red Hat Linux 和其他发行版中的
"/etc/sysconfig
"
目录。例如,“/etc/default/cron
" 可以控制
"/etc/init.d/cron
" 的运行方式。
The "/etc/default/rcS
" file can be used to customize
boot-time defaults for
motd(5),
sulogin(8),
etc.
如果通过改变这些变量不能达到你所想要的效果,那么你应该修改 init 脚本。如下是一些系统管理员可以编辑的配置文件。
内核包含了系统主机名。在启动的时候,链接到
"/etc/init.d/hostname.sh
" 运行等级为 S 的 init 脚本设置了系统主机名 (使用
hostname
命令),此主机名保存在
"/etc/hostname
"。这个文件应该只包含系统主机名,而不是全称域名。
不带参数运行 hostname(1) 命令可以打印出当前的主机名。
因为根文件系统在启动的时候被内核挂载了,其他文件系统在 S 运行等级通过如下所示的 init 脚本被挂载。
"/etc/init.d/mountkernfs.sh
" 用于
"/proc
","/sys
" 等目录下的内核文件系统。
"/etc/init.d/mountdevsubfs.sh
" 用于
"/dev
" 下的虚拟文件系统
"/etc/init.d/mountall.sh
" for normal filesystems using
"/etc/fstab
"
"/etc/init.d/mountnfs.sh
" for network filesystems
using"/etc/fstab
"
特殊内核文件系统(procfs, sysfs, 和 tmpfs 用于 /proc
,
/sys
, /tmp
, /run
等等)的挂载选项在 "/etc/default/rcS
"
中设置。参考rcS(5)。
硬盘和网络文件系统的挂载选项可以在 "/etc/fstab
" 中设置,参考 第 9.5.7 节 “通过挂载选项优化文件系统”。
注意 | |
---|---|
实际上的网络文件系统的挂载是在网络接口启动以后开始的。 |
警告 | |
---|---|
每次启动的时候,在挂载了所有文件系统以后," |
网络接口在 S 运行级别通过链接到 "/etc/init.d/ifupdown-clean
" 和
"/etc/init.d/ifupdown
" 的 init 脚本来初始化。参考第 5 章 网络设置来获得配置它们的信息。
许多网络服务(参考第 6 章 网络应用)在启动多用户模式的时候通过 init
脚本直接作为后台守护进程启动,例如 “/etc/rc2.d/S20exim4
”(运行级别为2)有一个指向
"/etc/init.d/exim4
" 的符号链接。
一些网络服务能够使用 super-server
inetd
(或者它的等价物) 启动。在启动的时候,inetd
通过链接到
"/etc/init.d/inetd
" 的
"/etc/rc2.d/S20inetd
" 启动 (运行等级为
2)。根本上,inetd
允许一个正在运行的守护进程去调用其它进程,减轻了系统的负载。
Whenever a request for service arrives at super-server inetd
, its
protocol and service are identified by looking them up in the databases in
"/etc/protocols
" and "/etc/services
".
inetd
then looks up a normal Internet service in the
"/etc/inetd.conf
" database, or a Open Network Computing Remote
Procedure Call (ONC RPC)/Sun RPC based service in
"/etc/rpc.conf
".
Sometimes, inetd
does not start the intended server
directly but starts the TCP wrapper
program,
tcpd(8),
with the intended server name as its argument in
"/etc/inetd.conf
". In this case, tcpd
runs the appropriate server program after logging the request and doing some
additional checks using "/etc/hosts.deny
" and
"/etc/hosts.allow
".
为了系统安全,应该尽可能的关掉网络服务程序。参考第 4.6.4 节 “限制访问某些服务端的服务”。
参考
inetd(8),
inetd.conf(5),
protocols(5),
services(5),
tcpd(8),
hosts_access(5),
host_options(5),
rpcinfo(8),
portmap(8),
和 "/usr/share/doc/portmap/portmapper.txt.gz
"。
"/etc/default/rsyslog
" 和
"/etc/rsyslog.conf
" 能够自定义系统消息的日志文件和屏幕显示。参见
rsyslogd(8)
和
rsyslog.conf(5),也可以参见第 9.2.2 节 “日志分析”。
"/etc/default/klogd
" 能够自定义内核消息的日志文件和屏幕显示。在文件中设置
"KLOGD='-c 3'
" 然后运行 "/etc/init.d/klogd
restart
"。参见
klogd(8)。
你也可以直接按如下所示的更改错误消息级别。
# dmesg -n3
表 3.5. 内核错误级别表
错误级别值 | 错误级别名称 | 说明 |
---|---|---|
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 级别的信息 |
Linux 内核 2.6 和更新的内核,udev 系统 提供了自动硬件发现和初始化机制。(参见 udev(7)).在内核发现每个设备的基础上,udev 系统使用从 sysfs 文件系统 (参见 第 1.2.12 节 “procfs 和 sysfs”)的信息启动一个用户进程,使用 modprobe(8) 程序 (参见 第 3.3.1 节 “内核模块初始化”)加载支持它所要求的内核模块, 创建相应的设备节点。
提示 | |
---|---|
如果由于某些理由," |
设备节点的名字,可以通过"/etc/udev/rules.d/
"里的 udev
文件来配置.当前默认的规则倾向创建动态生成的名字,除了光驱和网络设备外,会生成非静态的设备名。通过添加和光驱、网络设备类似的个性化规则,你也可以为
USB 盘之类的其它设备,生成静态设备名。 参见 "Writing udev
rules" 或
"/usr/share/doc/udev/writing_udev_rules/index.html
".
由于 udev 系统是一个正在变化的事物,我在其它文档进行了详细描述,在这里只提供了最少的信息。
提示 | |
---|---|
" |
通过 modprobe(8) 程序添加和删除内核模块,使我们能够从用户进程来配置正在运行的 Linux 内核。udev 系统(参见 第 3.3 节 “udev 系统”)自动化它的调用来帮助内核模块初始化。
下面的非硬件模块和特殊的硬件驱动模块,需要被预先加载,把它们在"/etc/modules
"文件里列出 (参见
modules(5)).
TUN/TAP 模块提供虚拟的 Point-to-Point 网络设备 (TUN) 和虚拟的 Ethernet 以太网网络设备 (TAP),
netfilter 模块提供 netfilter 防火墙能力(iptables(8), 第 5.9 节 “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)时出现模块加载问题,
" |
modinfo(8) 程序显示 Linux 内核模块信息。
lsmod(8)
程序以好看的格式展示"/proc/modules
"的内容,显示当前内核加载了哪些模块。
提示 | |
---|---|
你能够精确识别你系统上的硬件。 参见第 9.4.3 节 “硬件识别”. |
提示 | |
---|---|
你可以在启动时配置硬件来激活期望的硬件特征。参见 第 9.4.4 节 “硬件配置”. |
提示 | |
---|---|
你可以重新编译内核来增加你的特殊设备的支持。参见 第 9.9 节 “内核”. |