本文将把/etc/inittab作为研究起点,向外扩展辐射相关系统知识并一一进行说明。
在Linux系统中,/etc/inittab配置文件用来设置系统的默认运行级别。什么是系统的运行级别?且看下文。
一、Linux系统的运行级别
1、7个运行级别
Linux系统有7个运行级别(runlevel),它们分别是:
运行级别0:系统停机状态,系统默认运行级别不能设为0,否则不能正常启动;
运行级别1:单用户工作状态,root权限,用于系统维护,禁止运程登陆 ;
运行级别2:多用户状态(没有NFS);
运行级别3:完全的多用户状态(有NFS),登陆后进入控制台命令行模式;
运行级别4:系统未使用,保留;
运行级别5:X11控制台,登陆后进入图形GUI模式;
运动级别6:系统正常关闭并重启,默认运行级别不能设为6,否则不能正常启动。
2、运行级别的原理
(1)在目录/etc/rc.d/init.d中有许多服务脚本,一般称为服务(service)。这里要说明一下,/etc/rc.d/init.d这个目录并不是固定的,由于后续各子系统开发过程中的调整,这个目录也可能为/etc/init.d或其它目录。另外,在这个服务脚本目录中可以设置服务自启动;
(2)在/etc/rc.d(或/etc/)下有7个名为rcN.d的目录,对应系统的7个运行级别;
(3)rcN.d目录下都是一些链接文件,这些文件都链接到init.d目录下的service脚本,它的命名规则是K+nn+服务名或S+nn+服务名,其中nn为两位数字;
(4)系统会根据指定的运行级别进入到相应的rcN.d目录,并按照文件名顺序检索目录下手链接文件:对于以K开头的文件,系统将终止对应的服务,对于以S开头的文件,系统将启动对应的服务;
(5)查看当前运行级别的命令:runlevel;
(6)进入其他运行级别的命令:init N
(7)init0为关机,init 6为重启系统。
二、inittab文件
1、作用及使用流程
Linux内核启动完成后,内核通过启动第一个用户进程(init进程)来启动其他用户的进程或服务,因此init是Linux系统中所有进程的父进程。
init进程将解析inittab文件,运行操作系统的配置脚本,对Linux系统进行初始化。这个解析与运行过程如下:
2、格式分析
inittab是一个不可执行的文本文件,它被要求按照固定的格式书写,从而便于init进程识别。inittab的每一行都是一个登记项,它的结构如下:
identifier:run_level:action:process
(1)identifier
identifier是每个登记项的标识符,最多为4个字符,用于唯一标识每个登记项,不能重复
(2)run_level
run_level是系统运行级别,用于指定相应的登记项在哪个运行级别中处理。如果该字段为空, 那么相应的登记项将适用于所有的运行级别。在该字段中,可以同时指定一个或多个运行级别,其中各运行级别分别以数字0.1.2.3.4.5.6表示,且无需对其进行分隔。
(3)action
表示对应登记项的process在一定条件下所要执行的动作:
动作 | 作用 |
---|---|
respawn | init应该监视这个进程,即使它结束也应该被重新启动 |
wait | init应该运行这个进程一次,并等待其结束后再进行下一步操作 |
once | init只运行一次该进程 |
boot | 系统地运行该进程 |
bootwait | 在系统启动时运行,init等待进程完成 |
ctrlaltdel | 当Ctrl+Alt+Del三个键同时按下时运行,把SIGINT信号发送给init |
sysinit | 在运行boot或bootwait进程之前运行 |
powerfail | 当init收到SIGWR信号时运行 |
powerokwait | 当收到SIGWD信号且/etc/文中 的电源状态包含OK时运行 |
powerwait | 当收到SIGPWD信号,并且init等待进程结束时运行。 |
(4)process
pocess表示所要执行的shell命令。任何合法的shell语法都适用于该字段。
3、举例
以之前使用qemu模拟开发板中的inittab为例进行说明:
# /etc/inittab
::sysinit:/etc/init.d/rcS #系统开机或重新启动时执行rcS文件
console::askfirst:-/bin/sh #系统启动后,运行登陆程序
::ctrlaltdel:/sbin/reboot #按下组合键“Ctrl+Alt+Del”,重启Linux系统
::shutdown:/bin/umount -a -r #系统关机时,卸载所有文件系统
::restart:/sbin/init #重启init进程
#所有的runlevel都为空,因此适用于所有runlevel
需要说明:“-/bin/sh”中的“-”是有用处的,加上这个“-”,那么 会在登陆终端之后调用/etc/目录下的profile文件,而不加“-”则不会执行这个脚本。
三、为什么没有/etc/inittab
在旧式的System V initialization中,/etc/inittab可是个相当重要的文件。init进程启动后第一时间找的就是它!inittab负责初始化系 统,设置系统runlevel及进 入各runlevel对应要执行的命令。假设当前inittab中设置的默认runlevle是5,则init会运行/etc/init.d/rc 5命令,该命令会依据系统服务的依赖关系遍历执行/etc/rc5.d中的脚本/程序。进入/etc/rc5.d目录可以发现里面的文件都是到/etc /init.d/下对应的脚本/程序的软链接。以S开头的为启动的意思,以K开头的为停止。并且S/K后面的两位数数字代表了服务的启动顺序(由服务依赖 关系决定)。
那么Upstart job是怎么样的呢?我们知道,System V initializaiton是以runlevel为核心,依据服务间依赖关系的init方式,但在Upstart job,runlevel虽说对于服务的启动也有影响但已不是关键所在。Upstart job是事件驱动的,系统服务的启动、停止等等均是由事件决定的,反过来,系统服务的启动、停止也可以作为事件源触发其他服务。并且事件并不一定得由系统内部产生, 用户可以手工的键入start/stop [Service]产生事件来启动/终止服务。man upstart-evnets查看upstart job所定义的事件,可以发现,runlevel也被当作事件来对待(因runlevel的改变而产生的事件),诸如此类还有其他如 startup,started,filesystem等等。那么系统服务又是如何知道自己应该什么时候启动,什么时候终止的呢?答案就在 于/etc /init中(有的distros可能是在/etc/event.d)。进入/etc/init目录下一看,均是系统服务的配置文件,或者说,是job definition files。(实际上Upstart init只需要/etc/init这么一个目录,不像System V init,“拐弯抹脚”转好多圈才到达目的地,在性能上不如前者)。
Ubuntu采用的就是Upstart job,它的init并不会直接奔着/etc/init.d或者/etc/rc${runlevel}.d/而去,它采用了折衷的办法,通过 /etc/init下的某些配置文件调用/etc/rc${runlevel}.d/中的脚本以启动采用旧式System V-style的服务。(这是精髓)