Linux的引导过程,运行级别以及/etc/rc.d/ 与/etc/rc.d/init.d目录分析
Linux的引导过程,运行级别以及/etc/rc.d/ 与/etc/rc.d/init.d目录分析
一、 Linux的引导过程
系统启动之后,在进入init.d之前,我们先来看看系统都做了什么工作
我们从比较高的角度去看开始引导的整个过程,比较清晰明了。系统加电之后,首先进行的硬件自检,然后是bootloader对系统的初始化,加载内核。
内核被加载到内存中之后,就开始执行了。一旦内核启动运行,对硬件的检测就会决定需要对哪些设备驱动程序进行初始化。从这里开始,内核就能够挂装根文件系统(这个过程类似于Windows识别并存取C盘的过程)。内核挂装了根文件系统,并已初始化所有的设备驱动程序和数据结构等之后,就通过启动一个叫init的用户级程序,完成引导进程。
【很重要亚强】我们在这里总结一下linux系统引导,从系统加电,到根据运行级别启动对应服务的整个过程:
a:继续上面的叙述,启动init用户级程序后,init首先从/etc/inittab文件中读取当前系统的默认启动级别,如该文件中有行id:3:initdefault:,代表默认启动级别为3。
b:接着init引导进程根据默认启动级别3,到/etc/rc.d/rc3.d/目录(启动级别为*,那么从/etc/rc.d/rc*.d/目录下查询)下查询在启动级别3的的时候,应该启动的服务。该/etc/rc.d/rc3.d/目录下是一些软链接,目的地址为/etc/rc.d/init.d/,这些软链接执行时候会传递stop或start参数到/etc/rc.d/init.d/目录下的脚本文件,从而确定是否运行对应服务。依次执行/etc/rc.d/rc3.d/文件下的软链接,从而依次执行当前运行级别下应该启动的服务。关于服务的启动先后顺序等参见本页面后面讲述的《三、 /etc/rc.d/与/etc/rc.d/init.d的关系》部分。
二、 运行级别(run level)
Init进程是系统启动之后的第一个用户进程,所以它的pid(进程编号)始终为1。init进程上来首先做的事是去读取初始化运行级别文件/etc/inittab文件中initdefault id值(该文件有行“id:3:initdefault:”,代表初始化系统以运行级别3加载相关服务),这个值称为运行级别(run-level)。它决定了系统启动之后运行于什么级别。运行级别决定了系统启动的绝大部分行为和目的。这个级别从0到6 ,具有不同的功能。不同的运行级定义如下:
# 0 - 停机(千万别把initdefault设置为0,否则系统永远无法启动)
# 1 - 单用户模式
# 2 - 多用户,没有 NFS
# 3 - 完全多用户模式(标准的运行级)
# 4 – 系统保留的
# 5 - X11 (x window)
# 6 - 重新启动 (千万不要把initdefault 设置为6,否则将一直在重启 )
三、 /etc/rc.d/与/etc/rc.d/init.d的关系
/etc/rc.d/init.d/目录下的脚本(cenos6.4为shell脚本文件)就类似与windows中的注册表,在系统启动的时候某些指定脚本将被执行。
写到这里,应该差不多要进入init.d了,可是我觉得单写/etc/rc.d/init.d的话不一定能说得清楚明白,就拿它跟/etc/rc.d这个它上一级的目录一起来讨论,可能比较合适一些,因为他们之间有着千丝万缕的关系。
在这里先解释一下init.d里面放的都是什么东西。这个目录存放的是一些脚本,一般是linux以rpm包安装时设定的一些服务的启动脚本。系统在安装时装了好多rpm包,这里面就有很多对应的脚本(亚强备注:这里rpm包与yum安装包类似,比如我们要安装postfix邮件服务,我们执行命令yum install postfix,我们使用rpm -ql postfix 会发现,该yum安装命令执行后,会增加一个postfix邮件服务的shell脚本启动文件/etc/rc.d/init.d/postfix,这个文件就是postfix邮件服务的启动脚本文件)。执行这些脚本可以用来启动,停止,重启这些服务。
前面说到,/etc/rc.d/init.d这个目录下的脚本就类似于windows中的注册表,在系统启动的时候执行。程序运行到这里(init进程从/etc/inittab文件读取运行级别为*,然后从/etc/rc.d/rc*.d读取了该运行级别下启动哪些具体服务),接着运行init.d里的脚本了,但是并不是直接运行,而是根据/etc/rc.d/rc*.d中的软连接文件有选择的执行一些服务。
那么,系统是如何选择哪些需要启动哪些不要呢?这时刚才说的运行级别就起作用了。
在决定了系统启动的run level之后,/etc/rc.d/rc这个脚本先执行。在RH9(红帽linux系统)和FC7的源码中它都是一上来就check_runlevel()(虽然实现的代码不一样,也大同小异),检测到运行级别之后,对于每一个运行级别,在rc.d下都有一个子目录分别是rc0.d,rc1.d ….. rc6.d。每个目录下都是到init.d目录的一部分脚本一些链接。每个级别要执行哪些服务就在相对应的目录下,比如级别5要启动的服务就都放在rc5.d下,但是放在这个rc5.d下的都是一些链接文件,链接到init.d中相对应的文件,真正干活到init.d里的脚本。
1、这些链接文件前面为什么会带一个Kxx或者Sxx呢?是这样的,带K的表示停止(Kill)一个服务,S表示开启(Start)的意思
2、K和S后面带的数字呢?干什么用的
这个我开始的时候还以为是排列起来好看或者数数用呢。后来发现不是的。它的作用是用来排序,就是决定这些脚本执行的顺序,数值小的先执行,数值大的后执行。很多时候这些执行顺序是很重要的,比如要启动Apache服务,就必须先配置网络接口(即首先启动网络接口相关服务,然后再启动apache相关服务),不然一个没有IP的机子来启动http服务那岂不是很搞笑,这些数字是如何确定的呢,是根据某个服务的/etc/rc.d/init.d/postfix启动脚本中内容确定的,如该postfix邮件服务脚本中有
行# chkconfig: 2345 80 30,那么启动对应服务软链接命名为S80postfix,不启动对应服务软链接命名为K30postfix,可见第二组数字80为启动软链接命名的一部分,第三组数字30为不启动软链接命名的一部分。
3、无意中我发现同一个服务带S的和带K的链接到init.d之后是同一个脚本。我就纳闷了,为什么会是执行同一个脚本呢?
这个时候真是S和K的妙用了,原来S和K并不止是用来看起来分的清楚而已。S给和K还分别给init.d下面的脚本传递了start和stop的参数。哦,是这样的(恍然大悟的样子,呵呵)!这时我才想起来原来曾经无数用过的/etc/rc.d/init.d/network restart命令。原来传S时相当于执行了/etc/rc.d/init.d/xxx start这条命令,当然K就相当于/etc/rc.d/init.d/xxx stop了
四、/etc/rc.d/init.d目录shell启动脚本的书写
/etc/rc.d/init.d:该目录存放着linux系统所有的服务引导文件,实际上这些文件是一些shell脚本文件。
/etc/rc.d/rc*.d:其中,*为0到6共计7个自然数。该目录存放着7个运行级别需要启动或不启动的软链接,该链接指向/etc/rc.d/init.d目录下的服务引导文件。
我们以该目录下的crond计划任务服务引导文件为例说明这些运行级文件的内容部分:
#!/bin/sh
#
# crond Start/Stop the cron clock daemon.
#
# chkconfig: 2345 90 60
# description: cron is a standard UNIX program that runs user-specified \
# programs at periodic scheduled times. vixie cron adds a \
# number of features to the basic UNIX cron, including better \
# security and more powerful configuration options.
亚强分析:
第一行#!/bin/sh:表明当前shell文件通过/bin/sh这个shell引擎解析执行。
第五行# chkconfig: 2345 90 60:表明crond服务安装后,默认的运行级别为2345启动,90与60作用不详。这里是默认的启动级别。
其他案例:
#chkconfig: - 64 36,其中-代表默认任何启动级别都不启动。
# chkconfig: 2345 64 36,默认在2345启动级别启动当前服务(即执行当前shell启动脚本)。
注意该文件该行仅仅代表你刚刚安装当前服务的时候,默认的启动级别。即比如你使用yum install postfix;之后,那么默认启动级别为2345。一般情况下系统会自动根据该启动级别,将启动软链接写入到/etc/rc.d/rc*.d(*为从0到6)共计7个目录中。当你加电接通linux服务器启动系统时候,系统引导程序init是从/etc/rc.d/rc*.d中查询具体启动的服务,而不是根据该init.d中确定的启动级别。通常我们会使用chkconfig命令来管理各个服务的启动级别,chkconfig修改重写的是/etc/rc.d/rc*.d目录中的软连接的命名,而不是直接去修改重写/etc/rc.d/init.d下的shell启动脚本。只有当我们执行chkconfig --add postfix命令来添加某个服务,或当我们执行chkconfig postfix reset来重置某个服务安装时的默认启动级别时,才会直接读取/etc/rc.d/init.d/postfix启动脚本,从而根据启动脚本中默认的启动级别来确定如何将启动软链接写入到/etc/rc.d/rc*.d(*为从0到6)目录中,从而从实际上确定了某个服务的默认启动级别。
第六行:对当前服务crond的介绍性文字。
五、/etc/rc.d/init.d目录下shell启动脚本的执行
方法一:直接通过路径找到当前脚本按下enter直接执行。
如:操作postfix邮件服务
[root@iZ25ja2kaemZ ~]# /etc/rc.d/init.d/postfix status #查看服务
master (pid 19600) is running...
[root@iZ25ja2kaemZ ~]# /etc/rc.d/init.d/postfix stop #停止postfix服务
Shutting down postfix: [ OK ]
[root@iZ25ja2kaemZ ~]# /etc/rc.d/init.d/postfix start #开启postfix服务
Starting postfix: [ OK ]
[root@iZ25ja2kaemZ ~]# /etc/rc.d/init.d/postfix reload #重新加载服务配置文件
Reloading postfix: [ OK ]
[root@iZ25ja2kaemZ ~]# /etc/rc.d/init.d/postfix restart #重启postfix服务
Shutting down postfix: [ OK ]
Starting postfix: [ OK ]
方法二:通过service命令执行,有些系统默认不支持service命令,因此建议直接使用方法一。
如:操作postfix邮件服务,注释省略,参见方法一。
[root@iZ25ja2kaemZ ~]# service postfix status
master (pid 6198) is running...
[root@iZ25ja2kaemZ ~]# service postfix stop
Shutting down postfix: [ OK ]
[root@iZ25ja2kaemZ ~]# service postfix start
Starting postfix: [ OK ]
[root@iZ25ja2kaemZ ~]# service postfix restart
Shutting down postfix: [ OK ]
Starting postfix: [ OK ]
[root@iZ25ja2kaemZ ~]# service postfix reload
Reloading postfix: [ OK ]
方法三:系统初始化自动执行部分服务脚本
系统自动执行,即系统进行接通电源后,进行系统引导,检测硬件,加载内核,加载驱动以及数据结构,然后启动用户级进程init,init首先读取/etc/inittab文件,确定系统启动的默认启动级别,然后根据默认启动级别确定启动哪些服务。比如/etc/inittab文件中有“id:3:initdefault:”行,即以第3用户级别,即完全多用户模式(支持NFS)启动,然后去/etc/rc.d/rc3.d(如果运行级别为n,那么在/etc/rc.d/rcn.d目录下寻找,n为从0到6之间的自然数)目录下的文件,执行所有以S开头的文件(这些文件都是软链接,全部指向/etc/rc.d/init.d/目录下的shell启动脚本文件)。相关资料详细信息参见本页面的运行级别等部分资料。
六:更改默认的系统启动运行级别
用vi编辑/etc/inittab
定位到 id:X:initdefault
X表示你要修改的模式,除了0和6,其他的都可以填的,
案例:
设置默认启动级别为3(完整的多用户文本模式,有NFS,登陆后进入控制台命令行模式):
id:3:initdefault:
七、chkconfig相关命令参数,对/etc/rc.d/目录文件的修改,添加,删除操作。
1.添加某个服务到某个运行级别自动启动或不启动:chkconfig --add postfix,运行该命令后,我们可以用chkconfig的各种参数来控制操作该服务的运行级别。
注意:一般来讲,你用yum等命令安装某个服务后,那么会自动运行一遍chkconfig --add postfix命令。只有将某个服务加入到/etc/rc.d/rc*.d目录下,那么该服务才会在对应级别运行,否则不会自动启动。
注意:该命令行执行的前提条件是,在/etc/rc.d/init.d/目录下存在以相应服务的名字命名的服务,比如要添加postfix服务,那么必须存在/etc/rc.d/init.d/postfix启动脚本(通常yum install postfix邮件服务后,那么该yum命令会自动添加该服务启动脚本到/etc/rc.d/init.d/目录),否则--add命令执行失败。
根据/etc/rc.d/init.d/postfix启动脚本中定义的启动级别,将创建7个软链接分别写入到/etc/rc.d/rc*.d(*为从0到6)共计7个目录中,并根据软链的命名确定某个目录(每个目录代表一个启动级别需要启动哪些服务)下是启动postfix服务还是不启动postfix服务。一般以软链接命名为标记,如软链以S开头,那么代表当前启动级别启动该服务,如果以K开头,那么表明当前启动级别不启动当前服务。
比如:/etc/rc.d/init.d/postfix中文件中有行# chkconfig: 2345 80 30,即安装postfix服务后,默认启动级别为2345
我们执行chkconfig --add postfix
命令效果为:读取/etc/rc.d/init.d/postfix文件的默认启动级别为2345,在/etc/rc.d/rc2.d,/etc/rc.d/rc3.d,/etc/rc.d/rc3.d,/etc/rc.d/rc4.d目录下写入软链接文件S80postfix,在/etc/rc.d/rc0.d,/etc/rc.d/rc1.d,/etc/rc.d/rc6.d,写入K30postfix。
我们执行下面的命令看看效果:
[root@iZ25ja2kaemZ rc.d]# find ./ -name '*postfix*' | sort -n
./init.d/postfix
[root@iZ25ja2kaemZ rc.d]# chkconfig --add postfix
[root@iZ25ja2kaemZ rc.d]# find ./ -name '*postfix*' | sort -n
./init.d/postfix
./rc0.d/K30postfix
./rc1.d/K30postfix
./rc2.d/S80postfix
./rc3.d/S80postfix
./rc4.d/S80postfix
./rc5.d/S80postfix
./rc6.d/K30postfix
[root@iZ25ja2kaemZ rc.d]#
2从运行级别目录/etc/rc.d/rc*.d删除某个服务:chkconfig --del postfix,执行该命令后该服务的启动级别将不能再被chkconfig命令来进行修改。
执行效果为:将/etc/rc.d/rc*.d下关于该指定服务的所有软链接全部删除,但是不会删除位于/etc/rc.d/init.d/目录下的该服务的启动脚本文件。参见下面的代码:
[root@iZ25ja2kaemZ rc.d]# chkconfig --list postfix
postfix 0:off 1:off 2:off 3:off 4:off 5:off 6:off
[root@iZ25ja2kaemZ rc.d]# find ./ -name '*postfix*' | sort -n
./init.d/postfix
./rc0.d/K30postfix
./rc1.d/K30postfix
./rc2.d/K30postfix
./rc3.d/K30postfix
./rc4.d/K30postfix
./rc5.d/K30postfix
./rc6.d/K30postfix
[root@iZ25ja2kaemZ rc.d]# chkconfig --del postfix
[root@iZ25ja2kaemZ rc.d]# find ./ -name '*postfix*' | sort -n
./init.d/postfix
[root@iZ25ja2kaemZ rc.d]# chkconfig --list postfix
service postfix supports chkconfig, but is not referenced in any runlevel (run 'chkconfig --add postfix')
[root@iZ25ja2kaemZ rc.d]# chkconfig --add postfix
[root@iZ25ja2kaemZ rc.d]# chkconfig --list postfix #亚强,可以看到这里加载的是/etc/rc.d/init.d/postfix启动脚本中的默认级别,而不是前面删除该启动脚本时候的运行级别,
postfix 0:off 1:off 2:on 3:on 4:on 5:on 6:off
[root@iZ25ja2kaemZ rc.d]# find ./ -name '*postfix*' | sort -n
./init.d/postfix
./rc0.d/K30postfix
./rc1.d/K30postfix
./rc2.d/S80postfix
./rc3.d/S80postfix
./rc4.d/S80postfix
./rc5.d/S80postfix
./rc6.d/K30postfix
[root@iZ25ja2kaemZ rc.d]#
3 重置某个服务的运行级别为安装该服务时,默认的运行级别。chkconfig postfix reset
效果:从/etc/rc.d/init.d/postfx文件中的# chkconfig: 2345 80 30行,读取postfix服务安装时的运行级别。
分2步骤,第一首先将/etc/rc.d/rc*.d中有关该服务postfix邮件服务的所有软链接全部删除。第二:将rc2.d,rc3.d,rc4.d,rc5.d目录中写入到S80postfix,在rc0.d,rc1.d,rc6.d中写入K30postfix.d.可以看到reset是对全部7个运行级别目录进行重写,文件/etc/rc.d/init.d/postfx启动脚本中标记为启动的写入启动软链接到指定运行级别目录,其他运行级目录写入不启动软链接。
案例:
[root@iZ25ja2kaemZ rc.d]# find ./ -name '*postfix*' | sort -n
./init.d/postfix
./rc0.d/S80postfix
./rc1.d/S80postfix
./rc2.d/S80postfix
./rc3.d/S80postfix
./rc4.d/S80postfix
./rc5.d/S80postfix
./rc6.d/S80postfix
[root@iZ25ja2kaemZ rc.d]# chkconfig postfix reset
[root@iZ25ja2kaemZ rc.d]# find ./ -name '*postfix*' | sort -n
./init.d/postfix
./rc0.d/K30postfix
./rc1.d/K30postfix
./rc2.d/S80postfix
./rc3.d/S80postfix
./rc4.d/S80postfix
./rc5.d/S80postfix
./rc6.d/K30postfix
[root@iZ25ja2kaemZ rc.d]#
4修改某个服务的启动级别。chkconfig --level 23 postfix on/off;如果省略--level参数,那么该参数值在centos6下默认为2345。即chkconfig --level 2345 postfix on/off等价于chkconfig postfix on/off;
该level参数仅仅对涉及到的运行级别有效,不影响其他运行级别。
如:
chkconfig --level 23 postfix on #将postfix服务的23启动级别设置为自动启动,01456启动级别不受到该命令的任何影响。与reset不同,reset会重置所有的7个级别为安装服务时的默认值(/etc/rc.d/init.d/postfix文件中有记录该值# chkconfig: 2345 80 30),即仅仅对设计到的rc2.d,rc3.d运行级目录将postfix服务的相关软链删除,然后重新写入S80postfix软链接。
chkconfig --level 23 postfix off #将postfix服务的23启动级别设置为不自动启动,01456启动级别不受到该命令的任何影响。与reset不同,reset会重置所有的7个级别为安装服务时的默认值(/etc/rc.d/init.d/postfix文件中有记录该值# chkconfig: 2345 80 30)),即仅仅对设计到的rc2.d,rc3.d运行级目录将postfix服务的相关软链删除,然后重新写入K30postfix软链接。。
案例:
[root@iZ25ja2kaemZ rc.d]# find ./ -name '*postfix*' | sort -n
./init.d/postfix
./rc0.d/K30postfix
./rc1.d/K30postfix
./rc2.d/K30postfix
./rc3.d/K30postfix
./rc4.d/K30postfix
./rc5.d/K30postfix
./rc6.d/K30postfix
[root@iZ25ja2kaemZ rc.d]# chkconfig --level 23 postfix on
[root@iZ25ja2kaemZ rc.d]# find ./ -name '*postfix*' | sort -n
./init.d/postfix
./rc0.d/K30postfix
./rc1.d/K30postfix
./rc2.d/S80postfix
./rc3.d/S80postfix
./rc4.d/K30postfix
./rc5.d/K30postfix
./rc6.d/K30postfix
[root@iZ25ja2kaemZ rc.d]#