Linux 系统初始化
正如标题所示,我将以某种形式讨论 Linux 系统初始化是如何工作的。系统初始化从内核启动结束后开始。我打算解释的主题包括 Slackware 风格的系统初始化——一种 BSD(伯克利软件发行版)的仿制品——以及 Red Hat、Caldera、Debian 等风格的 System V(五)初始化,并指出它们之间的差异。您很快就会看到,尽管表面上看起来相反,但这些系统实际上比它们的不同之处更相似。我还将介绍在启动过程中通过 LILO 将开关传递给 init——这主要用于紧急情况。
我不会讨论(为了简洁起见)Red Hat、Caldera 或其他初始化脚本中的一些细节,特别是 /etc/sysconfig 或 /etc/modules 目录中找到的配置信息。对于这些细节,您需要自行研究。此外,这些细节更容易在不同的版本之间发生变化。
早在 UNIX 年轻的时候,许多大学获得了操作系统(OS)的“免费”副本,并进行了改进和增强。其中之一是加州大学伯克利分校。这所学校对操作系统做出了重大贡献,后来被其他大学采用。一个并行的发展始于更商业化的环境,并最终演变成现在的 System V。虽然这两个并行系统共享一个共同的内核和传承,但它们演变成了相互竞争的系统。差异可以在初始化、许多常用命令使用的开关(例如 ps:在 BSD 下,ps aux 等同于 System V 的 ps -ef)、进程间通信(IPC)、打印和流中找到。虽然 Linux 在大多数发行版中采用了 System V init,但 BSD 命令语法仍然占主导地位。至于 IPC,两者在 Linux 发行版中都可用且普遍使用。Linux 还使用 BSD 风格的打印能力,并且缺乏对流的支持。
在初始化方面,两者(BSD 和 System V)之间最大的区别在于 init 脚本的使用。System V 使用运行级别和独立的独立初始化脚本。脚本根据运行级别(也称为系统状态)运行以启动和停止守护进程,每个守护进程或进程子系统一个脚本。System V 状态默认从 0 到 6 运行,每个运行级别对应于不同的操作模式;通常,即使是这几个状态也并非全部使用。BSD 只有两种模式(相当于 System V 的运行级别):单用户模式(有时称为维护模式)和多用户模式。所有守护进程基本上都由两个(实际上更像是四到六个)脚本启动——一个通用系统脚本,分别是单用户模式或多用户模式的 rc.K 或 rc.M,一个本地脚本和几个特殊脚本,rc.inet 和 rc.inet2。系统脚本通常由发行版创建者提供;本地脚本由系统管理员编辑,并根据特定系统进行定制。BSD 风格的脚本不是独立的,而是按顺序调用的。(对于来自 DOS 世界的人来说,BSD 初始化将是最熟悉的。)这两个主要脚本可以与 config.sys 和 autoexec.bat 相比较,顺便说一句,它们会调用一两个其他脚本。然而,相似之处仅止于此。只有这几个脚本来启动一切,并不能提供 System V 所带来的那种灵活性(或者有些人这么说)。然而,它确实使事情更容易找到。在 System V 圈子里(但仅在 System V 圈子里),BSD 初始化被认为是过时的——但他们又知道什么呢?就像一双舒适的鞋子一样,它不会在很长一段时间内被丢弃,如果会的话。
回想一下,我之前说过 Slackware 做了一个 BSD 仿制品,但它仍然使用 rc.S/rc.M 等脚本。这是因为 inittab(我们稍后会看到)使用相同的运行级别引用,并使用这些(非常 System V 的)运行级别来决定运行哪些脚本。事实上,我所看过的所有发行版都使用相同的 init 二进制文件,因此 Slackware 和 Red Hat 或 Debian 之间的差异实际上比表面上看起来要小,完全不像旧的 BSD 系统那样只引用模式“S”或“M”。
一旦内核启动,我们就拥有了一个运行中的 Linux 系统。它不是很可用,因为内核不允许与“用户空间”直接交互。因此,系统运行一个程序:init。这个程序负责其他一切,被认为是所有进程的父进程。然后,内核退居其作为系统管理器处理“内核空间”的应有位置。首先,init 读取从命令行传递给它的任何参数。此命令行是您在系统开始启动内核之前看到的 LILO 提示符。如果您有多个内核可供选择,您可以按名称选择它,并可能在行中添加一些其他启动参数。内核不需要的任何参数都将传递给 init。这些命令行选项会覆盖 init 配置文件中包含的任何选项。正如对实际情况的良好检查将告诉您的那样,运行级别只是一种通过软件将“进程包”分组在一起的便捷方式。它们对内核没有任何特殊的意义。
当 init 启动时,它从一个名为 inittab 的文件读取其配置,该文件代表初始化表。如果 inittab 中的任何默认值在命令行中被覆盖,则会被丢弃。inittab 文件告诉 init 如何设置系统。本文稍后包含 Slackware、Red Hat 和 Debian 的 inittab 示例。
读取 inittab 时,我们将跳过以“#”开头的任何行,因为这些是注释,init 会忽略它们。其余行可以轻松读取,就像许多其他典型的类 UNIX 配置文件表一样,即每列由“:”分隔(id:运行级别:动作:进程),可以按如下方式读取
id:第一列是该行其余部分的唯一标识符。在较新的 Linux 系统上,它可以长达四个字母数字字符,但通常限制为两个。较旧的系统有两个字符的限制,并且大多数发行版都没有改变这种习惯。
运行级别:第二列指示此行有效的运行级别。此列可以为空,也可以包含任意数量的有效运行级别。
动作:这可以是几个不同的事物,最常见的是 respawn,但也可是以下任何一项:once、sysinit、boot、bootwait、wait、off、ondemand、initdefault、powerwait、powerfail、powerokwait、ctrlaltdel 或 kbrequest。
进程:这是要运行的特定进程或程序。
inittab 中的每一行都有一个特定的唯一标识符。通常,您希望它是容易与执行的特定操作关联的东西。例如,如果您想在第一个串口上放置一个 getty,您可以使用标识符 s1。当我执行 w 以查看正在运行的进程时,我可以更容易地识别谁通过 com1 上的调制解调器登录,当该用户被识别为在 s1 上时。
运行级别默认标识为 0 到 6 和 A 到 C。运行级别 0、1 和 6 是特殊的,不应随意更改。这些分别对应于系统停止、维护模式和系统重启。例如,更改运行级别 1 可能会产生深远的影响。请注意,要进入维护模式(状态 1),您可以将参数 1 传递给 init(通过 telinit2)。或者,您可以使用 S 或 s 表示维护模式。如果您更改状态 1 的操作,则当传递 S 或 s 时,相同的更改将适用。但是,运行级别 2 到 5 可以根据需要进行自定义。
许多系统都有命令 runlevel(通常在 /sbin 中找到)。执行此命令将输出先前的运行级别和当前的运行级别,如下所示:N 2。N 表示没有先前的运行级别。如果您进行更改,例如更改为状态 3,然后重新发出 runlevel 命令,您将看到 2 3。
由于一个好的演示将比仅仅告诉您更好,请在您的系统上尝试一下。(请注意,我已在 Debian 1.3 和其他一些系统(例如较旧的 Red Hat [可能是 3.0])上成功完成此操作,但在其他系统上没有成功,因此您的结果可能会有所不同。)以 root 用户身份(只有 root 用户可以告诉 init 更改状态)发出 init 命令。您应该看到一条用法消息,告诉您向 init 传递一个参数,该参数由 0 到 6 的数字、字母 A 到 C 或 S 或 Q 组成。小写字母在语法上与其大写字母相同。如果您向 init 传递除合法值以外的任何内容,您应该会收到相同的用法消息。现在向 init 传递参数 8,例如 init 8(或 telinit 8,如果您愿意)。如果没有任何反应,请不要担心。现在再次键入 runlevel,您应该看到 2 8。如果您的系统上没有 runlevel,请尝试 ps ax | grep init,您可能会看到 init [8]。您可能会也可能不会在方括号中看到列出的运行级别。一旦您确认您实际上已更改为运行级别 8,请更改回您之前的运行级别。请注意,如果您的 getty 死了,它们不会在此运行级别重新生成,因此您可能在注销后再次登录时遇到问题。如果您不确定您的默认运行级别是什么,请在 inittab 的顶部附近查找第一列为 id 且第三列为 initdefault 的行。此行中的第二列是默认运行级别。示例行如下所示
id:3:initdefault
此演示旨在向您展示,虽然运行级别 7 到 9 未记录在案,但如果您需要它们,它们实际上是可用的。(稍后我将解释为什么当您更改状态时没有任何反应)。它们没有被使用仅仅是因为这不是习惯。Linux 的可自定义状态(2 到 5)通常对任何人来说都足够了。
当您想要生成 inittab 中列出的守护进程并让此“运行级别”指定为一次性(按需)时,使用字母 A 到 C。因此,告诉 init 更改为状态 C 不会更改运行级别,它只是执行在运行级别列为 C 的行上列出的操作。也许您想在端口上放置一个 getty 以接收呼叫,但仅在首先收到语音呼叫后(不是每次)。让我们进一步假设您想准备好接收数据呼叫或传真呼叫,当您收到语音消息时,您将知道您想要哪个。您可以在 inittab 中放置两行,每行都有自己的 ID,并且每个都有一个运行级别,例如 A 表示数据,B 表示传真。当您知道您需要哪个时,您只需从命令行生成适当的一个:telinit A 或 telinit B。适当的 getty 将一直放在线上,直到收到第一个呼叫。一旦呼叫者终止连接,getty 将会掉线,因为根据定义,按需进程不会重新生成。
另外两个字母 S 和 Q 是特殊的。正如我之前指出的,S 会将您的系统带入维护模式,这与将状态更改为运行级别 1 相同。Q 是告诉 init 重新读取 inittab 所必需的。inittab 可以根据需要经常更改,但只有在某些情况下才会读取:它的一个进程死亡(我们需要重新生成另一个吗?),来自电源守护进程(或命令行)的电源故障信号,或者当被 telinit 告知更改状态时。因此,Q 参数将告诉 init,“我已经更改了一些东西,请重新读取 inittab。”
在深入研究按发行版分组的部分之前,我想强调它们不是独立的。以下每个部分都将补充其他部分。
让我们看一下 列表 1 中的 Slackware inittab 示例。我已经为行编号以便于参考。这些数字不会出现在您的 inittab 中——您的 inittab 将从行号右侧的两个空格开始。在 inittab 文件中,以“#”符号开头的行被禁用,并保留为解释性备注或可能的未来用途示例。请务必通读所有注释;它们被插入以帮助您,并可能给您提示如何更好地自定义您自己的 inittab。大多数程序(例如 mgetty 或 efax)旨在从 inittab 运行,都附带了如何实现它们的示例。
由于您已经知道如何读取行(id:运行级别(s):动作:进程),我将仅介绍一些特别感兴趣的行。
正如我已经提到的,Slackware 不是旧式真正的 BSD 系统。它实际上使用运行级别 3 作为其默认运行级别,而不是只有单用户模式和多用户模式。它首先运行系统初始化脚本 rc.S。此脚本旨在仅在启动时运行一次。然后它运行 rc.M。它跳过带有 rc.K 的行,除非系统操作员干预并故意更改为该状态。当在单用户模式和多用户模式之间更改状态时,会调用相应的脚本。(请参阅列表 1,第 15、18 和 21 行。)
rc.0 和 rc.6 也是在系统关闭时运行的文件。(请参阅列表 1,第 27 和 30 行。)
您将看到脚本中处理的电源管理(UPS 电源管理)以及 ctrl-alt-del 键序列。(请参阅列表 1,第 24、33、36 和 39 行。)
您应该注意到的关于此 inittab 的一些奇怪之处(它是直接从发行版 CD 中提取的):虽然默认的 init 运行级别是 3,但如果电源守护进程向系统发出关闭信号,然后电源恢复,则关闭被取消,系统在运行级别 5 重新启动。但是,由于运行级别 3 和 5 本质上是相同的(它们运行相同的 rc 脚本),因此在这种情况下没有区别。
现在我们来谈谈所有 inittab 专门设计用于处理的标准部分:初始化和重新生成 getty。在 UNIX 年轻的时候,哑终端挂在串行端口上。这些哑终端被称为电传打字机终端或简称为 TTY。因此,将登录屏幕发送到 tty 的程序被称为 getty,即“get TTY”。今天的 getty 执行相同的基本功能,尽管今天的 TTY 不太可能是那么哑的。添加和删除虚拟终端就像在 inittab 中添加或删除行一样容易;您最多可以有 255 个。
接下来,您将看到一行,允许在运行级别 4 中重新生成 X Display Manager (XDM)。
我唯一没有提到的是,在 Slackware 系统上完成所有工作的脚本都位于 /etc/rc.d 中。仔细查看它们。Slackware 使用最少数量的脚本来启动后台进程。inittab 特别引用的是 rc.S、rc.K、rc.M、rc.0 和 rc.6。由脚本(例如 rc.M)调用,但不由 init 调用的是 rc.inet、rc.inet2、rc.local、rc.serial 等。
看一下 Red Hat inittab (列表 2)。此文件中很好地解释了 Red Hat 如何使用运行级别。我在这里不再赘述。请注意,Red Hat 选择使用的运行级别只是一种约定,并不表示所有 System V UNIX 系统,甚至不是其他 Linux System V 初始化。
正如您所看到的,Red Hat 默认为运行级别 3,但是一旦您正确配置了 X 服务器,就可以将其更改为 5。(请参阅列表 2,第 18 和 56 行。)考虑到 Red Hat 整合了如此多的图形工具,您可能会认为他们会鼓励使用运行级别 5,但是将此作为开箱即用的默认设置会在 X 未首先正确配置的情况下引起麻烦。
在默认运行级别下方,您将看到系统初始化脚本(列表 2,第 21 行)。这会在系统启动时运行一次。然后 init 跳转到(在本例中)第 13 行(列表 2,第 26 行)。第 10 行到第 12 行和第 14 行到第 16 行被跳过,因为我们的默认运行级别是 3。
请注意,ud、ca、pf 和 pr 的运行与运行级别无关。当运行级别列为空时,进程将在每个运行级别中运行。
getty 行应该让您感到熟悉。不要因为 Red Hat 选择 mingetty 而不是 getty 而感到困扰。它们都做同样的事情:向 tty 发送登录横幅。
最后,运行级别 5 生成 XDM(X 显示管理器)。
在 Red Hat 下,您将在 /etc/rc.d 中找到所有系统初始化脚本。此子目录甚至有更多子目录——每个运行级别一个:rc0.d 到 rc6.d 和 init.d。在 /etc/rc.d/rc#.d 子目录(其中 # 由单个数字替换)中,是指向存储在 /etc/rc.d/init.d 中的主脚本的链接。init.d 中的脚本接受 start 或 stop 参数,有时接受 reload 或 restart。
/etc/rc.d/rc#.d 目录中的链接都以 S 或 K 开头,分别表示启动或停止,一个数字表示脚本的相对顺序,以及脚本名称——通常与 init.d 中找到的链接到的主脚本名称相同。例如,S20lpd 将使用参数 start 运行 init.d 中的脚本 lpd,这将启动行式打印机守护进程。也可以从命令行调用脚本
/etc/rc.d/init.d/lpd start
System V 初始化的优点在于,root 用户可以轻松地从命令行启动、停止、重新启动或重新加载守护进程或进程子系统,只需使用参数 start、stop、reload 或 restart 调用 init.d 中的相应脚本即可。
当未从带有参数的命令行调用时,rc 脚本会解析命令行。如果它正在运行 K20lpd,它将使用 stop 参数运行 lpd init 脚本。当 init 遵循 inittab 中到 rc.d/rc3.d 的链接时,它首先按数字顺序从最低到最高运行所有以 K 开头的脚本,然后对于 S 脚本也是如此。这确保了正确的守护进程在每个运行级别中运行,并以正确的顺序停止和启动。例如,您不能在启动网络之前启动 sendmail 或 bind/named(伯克利 DNS 或域名服务守护进程)。BSD 风格的脚本 Slackware 使用的脚本将在 rc.M 脚本的早期启动网络,但您在修改 Slackware 启动脚本时必须始终注意顺序。还记得我们上面更改为运行级别 8 并且没有任何反应吗?由于不存在子目录 rc8.d,因此也没有 kill 或 start 脚本,因此当我们更改状态时,没有运行任何脚本。如果我们直接从启动进入运行级别 8,我们将遇到问题。只有内核、init 和那些通过 inittab 中的 sysinit、boot 或 bootwait 命令启动的守护进程才会运行。我将让您自己查看 ../init.d/ 目录中的脚本,但是 列表 3 中显示了 Slackware 系统的示例。
对于那些发现编辑链接以在任何特定运行级别中添加或删除脚本是一项繁琐的任务,或者只是不习惯这样做的人,Red Hat 发行了一个名为 tksysv 的程序。此程序使用图形界面(使用 Tcl/Tk)读取 /etc/rc.d/init.d 中的脚本名称,并在应用程序框的最左侧显示它们。如果您的系统在不同的位置有 init.d,您可以安装符号链接(对于每个 rc#.d 目录),它将正常运行,或者破解脚本并根据您的系统进行自定义。该系统还会读取每个 rc#.d 子目录中的链接,并从左到右为每个运行级别显示它们,启动脚本在上方,kill 脚本在下方。(见图 1。)您可以根据需要添加、删除甚至更改执行顺序。
现在看一下 Debian inittab 示例。虽然与 Red Hat 的 inittab 相似,但它也有一些差异。首先,您会注意到,虽然 Red Hat 使用运行级别 3 表示非图形模式,运行级别 5 表示图形模式,但 Debian 对两者都使用运行级别 2(参见 列表 4,第 5 行)。区别在于 Debian 对 XDM 的启动/kill 脚本的使用。
我还想提请您注意一个非常特殊的行,第 12 行。该行以“~~”(两个波浪号)开头。请注意,在单用户模式(状态 1 或 S)下,调用了 sulogin。这可以防止有人只是启动系统并成为 root 用户。虽然它不能阻止使用其他技巧“后门”进入系统,并且不能替代系统的物理安全,但它确实可以防止普通用户通过简单地重新启动来获得 root 访问权限。命令的使用
boot from c: only, vice boot a: then c:
结合 BIOS 设置屏幕的密码保护,以及机箱上的锁以防止有人重置主板上的 BIOS,最后将 LILO 设置为 0 秒,计算机几乎有 50% 的安全性免受未经授权的篡改。(您可以从系统本身获得几乎另外 45% 的安全性,但请注意,最后的 5% 实际上是遥不可及的。)
在每个运行级别的脚本调用下方是另一行,用于在运行级别 6 中为 root 用户设置登录屏幕。这仅用于紧急情况,以防运行级别 6 中的 kill 脚本出现问题并且系统无法正常停止。它永远不应该运行。(请参阅列表 3,第 22 至 30 行)。
Debian inittab 还包括一些示例,用于在调制解调器和串行线路上启用 getty,如果您发现它们有用的话。但是,调用 mgetty 的行显然无法工作,除非您已安装 mgetty 软件包。
在正常启动期间,通过启动逻辑,init 知道它将在状态 2 中运行。有了这些信息,并且在启动期间没有被覆盖,init 首先运行 /etc/init.d/boot 脚本。一旦此脚本运行,init 然后执行 /etc/init.d/rc,参数为 2。init 还运行与 ca、kb、pf、pn 和 po 关联的命令。如果您阅读 powerfail,您会发现除非电源发生变化,否则不会发生任何事情。接下来,我们看到 init 在虚拟终端上生成 getty。在本例中(运行级别 2),它将生成六个(请参阅列表 4,第 50-55 行)。其余行被注释掉,未使用。
查看 /etc/init.d/rc 脚本,您可以看到它如何确定要运行什么以实现状态更改或将系统带入初始状态。
编辑 inittab 或任何 rc 脚本都需要一定程度的谨慎。即使是最好的测试也无法模拟完整的系统重启,脚本在系统初始化后可能看起来运行正常,但在系统初始化期间可能会失败。原因多种多样,但通常涉及使事情顺序颠倒。
在 Caldera 的 Network Desktop 中,它在 1.2.13 内核上运行并使用模块,我修改了一个脚本以在启动序列的早期启动 kerneld 进程。当我将系统升级到 Caldera 的 OpenLinux v1.0 时,它运行 2.0.25 内核,我对同一个脚本进行了完全相同的更改,对其进行了测试,当我确信一切正常后,我重新启动了。令我沮丧的是,启动过程挂起了,猜猜在哪里——是的,加载 kerneld。我发现,在较新的内核中,kerneld 需要知道计算机的主机名,而主机名尚不可用。这类事情可能发生在任何人身上。像键入错误的键或忘记给出文件的完整路径名这样简单的事情都可能让您陷入困境。
幸运的是,您可以将启动时参数传递给 init。当系统启动并且您看到:LILO: 时,您可以按 shift 键,然后按 tab 键以查看可用于启动的内核标签。然后,您可以添加内核标签,并在其后添加任何必需的参数以启动系统。内核需要的任何参数都会被使用并丢弃。例如,如果您的 RAM 超过 64MB,则需要以 mem=96MB 的形式将该信息传递给内核。如果您传递 -b 开关,内核将不会使用它,但会将其传递给 init。任何个位数数字或字母 S 或 Q(大写或小写)也是如此。
通过将任何数字或字母传递给 init,我们正在覆盖 inittab 中的默认值,正如我之前所说。大多数这些数字或字母的功能与从正在运行的系统上的命令行传递时完全相同。但是,-b 是特殊的:它是紧急启动参数。此参数告诉 init 读取 inittab,但对于某些特殊例外情况,不执行任何命令,只需进入维护模式即可。因此,不会执行任何 rc 脚本。您可以以读写方式挂载系统并修复它。不执行任何 inittab 命令的一个例外是进程 ID ~~,其进程应为 sulogin。这将为您提供 root 用户密码的提示,以便未经授权的人员无法更改系统文件,例如 /etc/passwd 或 /etc/shadow。
如果您在 inittab 文件中犯了错误怎么办?系统可以被拯救吗?是的,但我必须警告您,除非绝对必要,否则不要这样做。内核中编码了在完全加载并进入内存后启动 init 的指令。如果 /etc/inittab 已损坏到 init 无法运行的程度,即使使用 -b 开关也不行(我个人从未见过这种情况),也可以告诉 Linux 内核在启动时运行不同的程序而不是 init。代替发出 -b 开关,在内核名称后替换 init=/bin/sh。这将导致内核运行 bash shell,您将以 root 用户身份登录。请在此处小心,因为没有任何其他程序在运行,例如,系统日志记录或更新守护进程。这不是系统的正常运行模式。修复任何必要的内容并重新启动。
现在我已经解释了 Linux 系统初始化工作原理的很大一部分,我将告诉您 Linux 与我使用过的一些系统的比较。
对于 BSD 风格的系统,当我第一次看到 Slackware 时,我对它在启动时与我在一些 DEC-5000 上使用的 Ultrix 的相似性感到惊讶——它具有相同的结构,rc 脚本在 /etc/rc.d 中,并且名称相同。如果 Slackware 使用任何系统作为模式,Ultrix 可能是其中之一。我没有使用过任何较新的 BSD 风格的系统,因此我无法进一步评论。
对于 System V,我可以将各种 Linux 发行版与其他几个发行版进行比较。最相似的一个似乎是 Sun Solaris,它使用与 Debian 相同的结构,但使用运行级别 3 作为其默认值,并像 Debian 一样实现 XDM 启动。此外,运行级别 5 用于系统关闭,并且 rc 脚本被移动到 /sbin。HP-UX 10.20 也类似,但 HP 将 init.d、rc.d 和其他运行级别目录放在 /sbin 下。IBM 的 AIX 使用 System V 风格的初始化,但其大部分子进程的单独脚本直接从其 inittab 中调用。最后,SCO OpenServer 使用类似于 Debian 的系统进行启动时初始化,但不使用指向 init.d 的符号链接。相反,所有启动-kill 脚本都位于 rc2.d 中。
最新的 Linux 文件系统层次结构标准 (FHS) v2.0,日期为 1997 年 10 月 26 日,声明 BSD 或 System V 风格的初始化都是可接受的。然而,它没有详细说明 rc 脚本的具体位置,只是说它们会在 /etc 目录下,并且该标准的未来修订版可能会提供进一步的指导。 我认为这不太可能,因为红帽和 Debian 这两个非常流行的发行版在这方面做得略有不同。 我个人没有特别的偏好,事实上,我的系统有符号链接,使得每个系统看起来都像另一个系统,以防安装过程对我的系统配置做出无效的假设。 我要告诉你的是,因为我比较懒,所以启动和停止守护进程的输入越少越好,因此我更倾向于 /etc/init.d/。
虽然这篇文章绝非包罗万象,但希望您已经对您的 Linux 系统在启动期间如何初始化有了一些了解。所有这些表格和脚本都是简单的 ASCII 文本文件,可以使用 vi 或您选择的任何文本编辑器轻松修改。 只需阅读它们并遵循它们的逻辑。我已经向您展示了如何阅读和解释 /etc/inittab,并为您提供了关于 init 工作原理的基本信息。
我还向您展示了如何恢复,以防您设法创建了一个脚本,该脚本会挂起启动过程或阻止 init 启动。查看您的 inittab 和它运行的脚本,以便更好地了解您的系统并为您自己的用途进行优化。
本文中提到的所有列表都可以通过匿名下载文件 ftp://ftp.linuxjournal.com/pub/lj/listings/issue56/3016.tgz 获取。
