Initscripts (简体中文)
| 摘要 |
|---|
| 一个按照时间顺序对 Arch 启动过程的概览。 |
| 概览 |
| 为了启动 Arch Linux,一个与 Linux 兼容的启动引导程序,如 GRUB, GRUB2, LILO, 或者 Syslinux 必须被安装到主引导记录(MBR), 或者GUID 分区表(GPT)。启动引导程序的任务是初始化 Arch 启动过程,然后加载内核以及初始化内存盘。 |
| 相关页面 |
| fstab (简体中文) |
| rc.conf (简体中文) |
| Arch Boot Process (简体中文) |
| Autostarting |
本文按照时间顺序介绍 Initscripts 的启动过程以及使用的相关系统文件和进程,同时提供相关的 wiki 文章的链接。与常见的 SysV 启动架构不同,Initscripts 沿用了 BSD init 传统。系统默认设置成不同的 runlevel 运行相同的模块,不同的 runlevel 之间没有区别。优点是用户可以更简单地配置启动过程 (参见 rc.conf);缺点是一些 SysV 提供的精细调整好的配置选项没有了。Adding Runlevels 介绍如何把 SysV-like 的功能容纳到 Arch 中的方法。Wikipedia:init 包含了 SysV 和 BSD style 之间区别的更多信息。
Contents |
init: The Arch boot scripts
Arch主要的启动过程是由init完成的,他通过克隆出其他的进程(以及这些进程克隆出的进程),使系统进入一个可用的状态。正如前文中提到的,Arch使用的是一种BSD风格的引导脚本。具体来说,init程序会首先读取/etc/inittab这个配置文件,inittab通常像这样:
/etc/inittab
... # Boot to console id:3:initdefault: # Boot to X11 #id:5:initdefault: rc::sysinit:/etc/rc.sysinit rs:S1:wait:/etc/rc.single rm:2345:wait:/etc/rc.multi rh:06:wait:/etc/rc.shutdown su:S:wait:/sbin/sulogin ...
根据这个文件的第一个未被注释掉的行可知,系统默认的启动级别为3(启动器(bootloader)通常可以给内核传递系统的运行级别,如果没有传递,系统运行级别就采用这里的默认值),当内核调用init时:
- 首先,运行主初始化脚本
/etc/rc.sysinit,这是个Bash脚本。 - 如果系统处于单用户模式(运行级别为1或者S),系统就会接着运行
/etc/rc.single脚本。否者,如果系统处于2~5之间的运行级别,系统就会接着运行/etc/rc.multi脚本。 - 最后运行的脚本是
/etc/rc.local,这个脚本默认什么都没有。
/etc/rc.sysinit
rc.sysinit是一个很大的启动脚本。它通过一系列的初始化任务,完成所有的硬件配置。当你看到屏幕打印出下面这些行时,代表它开始运行了:
Arch Linux https://www.archlinux.org
rc.sysinit 的任务是:
- 导入
/etc/rc.conf文件 - 导入
/etc/rc.d/functions文件 - 显示欢迎信息
- 挂载各种各样的虚拟文件系统(proc、sysfs之类的)
- 保证 rootfs 挂载为只读
- 启动 bootlogd
- 显示过期警告
- 配置硬件时钟
- 启动 udev,从 rc.conf 定义的
MODULES数组装入文件等待 udev 处理完冷启动事件 - 启动回环(loopback)接口
- 配置RAID、btrfs 和加密文件系统映射
- 运行fsck检查相应分区的完整性
- 根据 /etc/fstab 中的配置重新挂载 rootfs
- 挂载本地文件系统(由于网络未加载,网络设备不会挂载)
- 启动 lvm 组的监视
- 激活交换分区
- 配置时区
- 初始化随机种子
- 移除leftover/temporary文件中的临时变量和文件,比如
/tmp/* - 根据
rc.conf中的配置,设置主机名、locale、系统时钟 - 配置本地化、终端、键盘映射
- 设置终端字体
- 输出dmesg中输出的信息到
/var/log/dmesg.log中
/etc/rc.sysinit是一个脚本。他本身并不包含任何的配置信息,而是通过导入rc.conf来读取配置信息。就连他内部使用的很多实现彩色输出(比如右对齐的busy、done字符串)的函数,也是定义在/etc/rc.d/functions中。通常情况下不需要编辑这个文件。 升级时会被覆盖,要进行定制,请使用下面的钩子。
/etc/rc.single
单用户(Single)模式通常在无法正常启动时使用,他会直接以root用户启动。除了最基本的syslog-ng和udev外,不会启动任何服务。单用户模式在修复系统时,需要避免远程用户操作导致数据丢失时很有用。单用户模式下可以直接在提示符后输入'exit'进入到多用户模式。
/etc/rc.multi
/etc/rc.multi通常在多用户模式(运行级别为2~5)下执行。通常情况,从rc.sysinit切换到rc.multi时,用户不太能感觉到。因为两者使用的函数类似,导致输出的提示信息也差不多。这个脚本主要执行以下任务:
- 首先,会根据
/etc/sysctl.conf的设置,运行sysctl以在运行时修改内核参数,Arch除了网络配置外,通常很少用这么干。 - 然后,会根据
rc.conf文件中的DAEMONS变量,执行非常重要的——服务(守护进程)启动任务。 - 最后,会执行
/etc/rc.local脚本
/etc/rc.local
/etc/rc.local 是本地多用户启动脚本,默认是空的。可以讲启动最后需要运行的程序放在这里。大部分系统配置任务(例如模块装入、字体修改、设备启动等) 都有固定的设置位置。为了避免混淆,请保证加入的命令不适合放在其他地方,例如 /etc/profile.d。
编辑时请记得其中的命令会在大部分设置完成后以 root 用户运行,不管 X 有没有启动。下面例子中,rc.local 脚本开启 ALSA 声音设置:
/etc/rc.local
#!/bin/bash # /etc/rc.local: Local multi-user startup script. amixer sset 'Master Mono' 50% unmute &> /dev/null amixer sset 'Master' 50% unmute &> /dev/null amixer sset 'PCM' 75% unmute &> /dev/null
自定义钩子
钩子可以在 rc.* 脚本的不同位置加入自定义指令.
| 脚本名 | 执行位置 |
|---|---|
| sysinit_start | rc.sysinit 启动开始 |
| sysinit_udevlaunched | udev 被 rc.sysinit 启动之后 |
| sysinit_udevsettled | uevents 被 rc.sysinit 处理后 |
| sysinit_prefsck | rc.sysinit 运行 fsck 前 |
| sysinit_postfsck | rc.sysinit 运行 fsck 后 |
| sysinit_premount | rc.sysinit 将 root 被挂载成读写模式后,本地文件系统挂载前 |
| sysinit_end | rc.sysinit 结束 |
| multi_start | rc.multi 执行前 |
| multi_end | rc.multi 结束时 |
| single_start | rc.single 开始 |
| single_prekillall | rc.single 停止所有进程前 |
| single_postkillall | rc.single 停止所有进程后 |
| single_udevlaunched | rc.single 执行 udev 后 |
| single_udevsettled | rc.single 处理 uevents 后 |
| single_end | rc.single 结束时 |
| shutdown_start | rc.shutdown 开始时 |
| shutdown_prekillall | rc.shutdown 停止所有进程前 |
| shutdown_postkillall | rc.shutdown 停止所有进程后 |
| shutdown_preumount | 所有文件系统写结束后,卸载文件前。 |
| shutdown_postumount | 所有文件系统卸载后 |
| shutdown_poweroff | rc.shutdown 关闭系统前 |
要创建钩子,在/etc/rc.d/functions.d 中创建文件:
function_name() {
...
}
add_hook hook_name function_name
/etc/rc.d/functions 会引入/etc/rc.d/functions.d 中的所有文件。.
可以同时注册多个钩子,或者在多个钩子中注册同一函数。不要再这些文件中使用 add_hook 或 run_hook 作为函数名,这两个函数在 /etc/rc.d/functions 中有定义。
示例
如下钩子会在所有 daemon 启动前禁用硬盘的回写缓存 (可以优化包含 MySQL InnoDB 文件的硬盘)。
/etc/rc.d/functions.d/hd_settings
hd_settings() {
/usr/bin/hdparm -W0 /dev/sdb
}
add_hook sysinit_udevsettled hd_settings
add_hook single_udevsettled hd_settings
先定义函数 hd_settings,然后注册到 single_udevsettled 和 sysinit_udevsettled hooks。函数会在 /etc/rc.d/rc.sysinit 或 /etc/rc.d/rc.single 处理完 uevent 消息后立即执行。
init: 登录
默认情况下,Arch启动过程完成后,agetty程序就会启动,并提示用户输入用户名。在输入用户名后agetty调用login,提示用户输入登录密码。
最后,在成功登录后login会启动用户的默认会话终端(shell)。默认终端和环境变量在/etc/profile下定义。还有一些别的配置在/etc目录下的文件中定义。用户也可以在自己的家目录下通过~/.bashrc这类的文件重新定义。如果两部分的定义冲突,那么将会优先采用主目录下的定义。
mingetty提供了一些选项,可以实现自动登录的功能。rungetty 也提供了一些用户登陆时自动运行程序的功能。
大多数用户可能希望启动图形界面,这个时候可以安装一个KDM、GDM之类的显示管理器(参考显示管理器)。