作为系统管理员,粗略地了解 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 包依赖信息保证了所需资源的可用性。
![]() |
警告 |
---|---|
不建议对 ” |
For example, let's set up runlevel system somewhat like Red Hat Linux as the following.
init
starts the system in runlevel=3 as the default.
init
does not start
gdm3(1)
in runlevel=(0,1,2,6).
init
starts
gdm3(1)
in runlevel=(3,4,5).
This can be done by using editor on the "/etc/inittab
"
file to change starting runlevel and using user friendly runlevel management
tools such as sysv-rc-conf
or bum
to
edit the runlevel. If you are to use command line only instead, here is how
you do it (after the default installation of the gdm3
package and selecting it to be the choice of display manager).
# cd /etc/rc2.d ; mv S21gdm3 K21gdm3 # cd /etc ; perl -i -p -e 's/^id:.:/id:3:/' inittab
Please note the "/etc/X11/default-display-manager
" file
is checked when starting the display manager daemons:
xdm
, gdm3
, sddm
,
and wdm
.
![]() |
注意 |
---|---|
You can still start X from any console shell with the startx(1) command. |
The default parameter for each init script in
"/etc/init.d/
" is given by the corresponding file in
"/etc/default/
" which contains environment variable
assignments only. This choice of
directory name is specific to the Debian system. It is roughly the
equivalent of the "/etc/sysconfig
" directory found in
Red Hat Linux and other distributions.
For example, "/etc/default/cron
" can be used to control
how "/etc/init.d/cron
" works.
The "/etc/default/rcS
" file can be used to customize
boot-time defaults for
motd(5),
sulogin(8),
etc.
If you cannot get the behavior you want by changing such variables then you may modify the init scripts themselves. These are configuration files editable by system administrators.
The kernel maintains the system hostname. The init script in runlevel S which is
symlinked to "/etc/init.d/hostname.sh
" sets the system
hostname at boot time (using the hostname
command) to the
name stored in "/etc/hostname
". This file should contain
only the system hostname, not a fully
qualified domain name.
To print out the current hostname run hostname(1) without an argument.
Although the root filesystem is mounted by the kernel when it is started, other filesystems are mounted in the runlevel S by the following init scripts.
"/etc/init.d/mountkernfs.sh
" for kernel filesystems in
"/proc
", "/sys
", etc.
"/etc/init.d/mountdevsubfs.sh
" for virtual filesystems in
"/dev
"
"/etc/init.d/mountall.sh
" for normal filesystems using
"/etc/fstab
"
"/etc/init.d/mountnfs.sh
" for network filesystems
using"/etc/fstab
"
The mount options of special kernel filesystems (procfs, sysfs, and tmpfs
for /proc
, /sys
,
/tmp
, /run
, etc.) are set in
"/etc/default/rcS
". See
rcS(5).
The mount options of normal disk and network filesystems are set in
"/etc/fstab
". See 第 9.5.7 节 “通过挂载选项优化文件系统”.
![]() |
注意 |
---|---|
The actual mounting of network filesystems waits for the start of the network interface. |
![]() |
警告 |
---|---|
After mounting all the filesystems, temporary files in
" |
Network interfaces are initialized in runlevel S by the init script
symlinked to "/etc/init.d/ifupdown-clean
" and
"/etc/init.d/ifupdown
". See 第 5 章 网络设置 for how to configure them.
Many network services (see 第 6 章 网络应用) are
started under multi-user mode directly as daemon processes at boot time by
the init script, e.g., "/etc/rc2.d/S20exim4
" (for
RUNLEVEL=2) which is a symlink to "/etc/init.d/exim4
".
Some network services can be started on demand using the super-server inetd
(or its
equivalents). The inetd
is started at boot time by
"/etc/rc2.d/S20inetd
" (for RUNLEVEL=2) which is a symlink
to "/etc/init.d/inetd
". Essentially,
inetd
allows one running daemon to invoke several others,
reducing load on the system.
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
".
For system security, disable as much network service programs as possible. See 第 4.6.4 节 “限制访问某些服务端的服务”.
See
inetd(8),
inetd.conf(5),
protocols(5),
services(5),
tcpd(8),
hosts_access(5),
hosts_options(5),
rpcinfo(8),
portmap(8),
and "/usr/share/doc/portmap/portmapper.txt.gz
".
The system message can be customized by
"/etc/default/rsyslog
" and
"/etc/rsyslog.conf
" for both the log file and on-screen
display. See
rsyslogd(8)
and
rsyslog.conf(5).
See also 第 9.2.2 节 “日志分析”.
The kernel message can be customized by
"/etc/default/klogd
" for both the log file and on-screen
display. Set "KLOGD='-c 3'
" in this file and run
"/etc/init.d/klogd restart
". See
klogd(8).
You may directly change the error message level by the following.
# 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 级别的信息 |
For Linux kernel 2.6 and newer, the udev system provides mechanism for the automatic hardware discovery and initialization (see udev(7)). Upon discovery of each device by the kernel, the udev system starts a user process which uses information from the sysfs filesystem (see 第 1.2.12 节 “procfs 和 sysfs”), loads required kernel modules supporting it using the modprobe(8) program (see 第 3.3.1 节 “内核模块初始化”), and creates corresponding device nodes.
![]() |
提示 |
---|---|
If " |
The name of device nodes can be configured by udev rule files in
"/etc/udev/rules.d/
". Current default rules tend to
create dynamically generated names resulting non-static device names except
for cd and network devices. By adding your custom rules similar to what cd
and network devices do, you can generate static device names for other
devices such as USB memory sticks, too. See "Writing udev rules" or
"/usr/share/doc/udev/writing_udev_rules/index.html
".
Since the udev system is somewhat a moving target, I leave details to other documentations and describe the minimum information here.
![]() |
提示 |
---|---|
For mounting rules in " |
The modprobe(8) program enables us to configure running Linux kernel from user process by adding and removing kernel modules. The udev system (see 第 3.3 节 “udev 系统”) automates its invocation to help the kernel module initialization.
There are non-hardware modules and special hardware driver modules as the
following which need to be pre-loaded by listing them in the
"/etc/modules
" file (see
modules(5)).
TUN/TAP modules providing virtual Point-to-Point network device (TUN) and virtual Ethernet network device (TAP),
netfilter modules providing netfilter firewall capabilities (iptables(8), 第 5.9 节 “Netfilter 网络过滤框架”), and
watchdog timer driver modules.
The configuration files for the
modprobe(8)
program are located under the "/etc/modprobes.d/
"
directory as explained in
modprobe.conf(5).
(If you want to avoid some kernel modules to be auto-loaded, consider to
blacklist them in the "/etc/modprobes.d/blacklist
" file.)
The "/lib/modules/<version>/modules.dep
" file
generated by the
depmod(8)
program describes module dependencies used by the
modprobe(8)
program.
![]() |
注意 |
---|---|
If you experience module loading issues with boot time module loading or
with
modprobe(8),
" |
The modinfo(8) program shows information about a Linux kernel module.
The
lsmod(8)
program nicely formats the contents of the
"/proc/modules
", showing what kernel modules are
currently loaded.
![]() |
提示 |
---|---|
You can identify exact hardware on your system. See 第 9.4.3 节 “硬件识别”. |
![]() |
提示 |
---|---|
You may configure hardware at boot time to activate expected hardware features. See 第 9.4.4 节 “硬件配置”. |
![]() |
提示 |
---|---|
You can probably add support for your special device by recompiling the kernel. See 第 9.9 节 “内核”. |