3.4 运行机制介绍
Linux系统的运行机制,主要包括系统的运行级别,系统的启动、引导与修复,root密码重置及关机等过程,下面讲述Linux的具体运行机制。
3.4.1 系统运行级
所谓运行级别,简单来说,就是操作系统当前正在运行的功能级别。级别为0~6,分别具有不同的功能,这些级别定义保存在/etc/inittab文件中。这个文件是init程序寻找的主要文件,系统最先运行的服务是那些放在/ect/rc.d目录下的文件。
1.运行级别及原理
Linux下的7个运行级别如表3-2所示。
表3-2 /etc/inittab运行级别
各级别说明如下。
0:系统停机状态,系统默认运行级别不能设置为0,否则不能正常启动,机器关闭。
1:单用户工作模式,root权限,用于系统维护,禁止远程登录,就像Windows下的安全模式登录。
2:多用户模式,不支持NFS功能。
3:完整的多用户模式,有NFS支持,登录后进入控制台命令行模式。
4:系统保留,一般不用。在一些特殊情况下可以用它来做一些事情,例如在笔记本电脑的电池用尽时,可以切换到这个模式来做一些设置。
5:X11控制台,登录后进入图形GUI模式,X Window系统。
6:系统正常关闭并重启,默认运行级别不能设为6,否则系统不能正常启动。运行init6机器就会重启。
标准的Linux运行级别为3或5。
关于运行级别的补充说明如下:
在目录/etc/rc.d/init.d下有许多服务器脚本程序,一般称为服务(service)。
在/etc/rc.d下有7个名为rcN.d的目录,对应系统的7个运行级别。
rcN.d目录下都是一些符号链接文件,这些链接文件都指向init.d目录下的service脚本文件,命名规则为K+nn+服务名或S+nn+服务名,其中nn为两位数字。
系统会根据指定的运行级别进入到对应的rcN.d目录,并按照文件名顺序检索目录下的链接文件:对于以K(Kill)开头的文件,系统将终止对应的服务;对于以S(Start)开头的文件,系统将启动对应的服务。
查看运行级别可用runlevel。
进入其他运行级别可使用initN命令,例如运行init3则进入终端模式,运行init5则又登录到图形GUI模式。
标准的Linux运行级别为3或5,如果是3的话,系统就运行在多用户状态下;如果是5的话,则运行在X Window系统下。不同的运行级别有不同的用处,应该根据不同情形来设置。例如,如果丢失了root口令,那么可以让机器启动进入单用户状态来设置。在启动后的lilo提示符下输入:
init=/bin/shrw
这样就可以使机器进入运行级别1,并把root文件系统挂载为读写权限。它会跳过所有系统认证,让用户使用passwd程序来改变root口令,然后以一个新的运行级启动。
2.chkconfig用法
chkconfig命令可以用来检查、设置系统的各种服务,使用语法如下:
chkconfig[--add][--del][--list][系统服务]
或
chkconfig[--level<等级代号>][系统服务] [on/off/reset]
参数用法如下。
add 增加指定的系统服务,让chkconfig指令得以管理它,并同时在系统启动的叙述文件内增加相关数据。
del 删除指定的系统服务,不再由chkconfig指令来管理该任务,并同时在系统启动的叙述文件内删除相关数据。
level<等级代号> 指定读系统服务要在哪一个执行等级中开启或关闭。
使用范例:
chkconfig --list 列出所有的系统服务 chkconfig --add httpd 增加httpd服务 chkconfig --del httpd 删除httpd服务 chkconfig --level httpd 2345 on httpd在运行级别为2、3、4、5的情况下设置为on (开启)的状态。
chkconfig命令提供了一种简单的方式来设置一个服务的运行级别。例如,为了设置MySQL服务器在运行级别为3和4上运行,用户必须首先将MySQL添加为受chkconfig管理的服务:
chkconfig --add mysql
现在,假设用户在级别3和5上设定服务为“on”,可输入:
chkconfig --level 35 mysql on
在其他级别上设为“off”,可输入:
chkconfig --level 01246 mysql off
为了确认用户的配置被正确地修改了,可以列出服务将会运行的运行级别,输入代码如下所示。
chkconfig --list mysql
3.4.2 系统启动过程及GRUB文件
RHEL系统的启动按照如下步骤进行,其启动流程如图3-2所示。
图3-2 系统启动流程
(1)POST(加电自检):检测硬件
在CPU的控制下,将RAM芯片中的某个程序映射到ROM地址空间,并执行其中的指令,完成系统硬件健康状况的检查,例如存储设备、网卡、CPU、声卡等硬件设备是否完好。检查完成后,如果所有硬件或基本硬件、核心硬件没有问题时,则进入下一个启动流程启动BIOS。
(2)BIOS(Boot Sequence):决定启动介质
按照BIOS所设定的系统启动流程,根据引导次序(Boot Sequence)自上而下地寻找对应存储设备上操作系统的MBR(全称为Master Boot Record,即硬盘的主引导记录),如果MBR存在,则会读取MBR中的bootloader。
(3)MBR(bootloader):寻找grub,读取配置文件/etc/grub.conf,决定默认启动项
根据MBR所指引的活动分区,寻找系统分区中的bootloader。bootloader是一段程序,占据446字节。在bootloader中配置了所要引导操作系统的内核所在的位置,因此当BIOS被载入内存并实现将控制权限转交给bootloader以后,bootloader即接收整个系统的控制权限;而后根据用户的选择去读取相应操作系统的内核,并将内核装载到内存的某个空间位置,解压缩;这时kernel就可以在内存中开始工作,并根据kernel本身的功能在内存中搜索硬件,加载硬件驱动程序,完成内核初始化,bootloader会将控制权限转交给内核。
(4)kernel(初始化):内核会主动调用init进程,读取配置文件/etc/inittab,决定启动级别,运行初始化脚本/etc/rc.d/rc.sysinit。
步骤是探测硬件→加载驱动(initrd)→挂载根文件系统→rootfs(/sbin/init)。initrd是一个虚拟的文件系统,里面有/、lib、bin、sbin、usr、proc、sys、var、dev、boot等目录,我们称之为虚拟的根文件系统,作用是将kernel和真实的根文件系统建立关联关系,让kernel去initrd中加载根文件系统所需要的驱动程序,以读写的方式挂载根文件系统,并执行用户当中第一个进程init。
/etc/inittab
/sbin/init启动会用到/etc/inittab所定义的条目,如:默认登录级别为id:3:initdefault:,/etc/inittab有0~6个运行级别。
系统初始化(/etc/rc.d/rc.sysinit)
①检测,并以读写方式挂载根文件系统。
②设定主机名。
③检测并挂载/etc/fstab中的其他文件系统。
④启动swap分区。
⑤初始化外围硬件设备驱动。
⑥根据/etc/sysctl.conf设定内核参数。
⑦激活udev和seLinux。
⑧激活LVM和RAID设备。
⑨清理过期锁文件和PID文件。
⑩装载键映射(键盘上每个键的功能)。
GRUB配置文件/etc/grub.conf
/etc/grub.conf文件说明如图3-3、图3-4所示。
图3-3 /etc/grub.conf文件说明
图3-4 /etc/grub.conf文件说明
文件参数说明如下。
default=0:默认启动第一个系统,后面的每一个title对应一个系统,第一个title对应第一个系统,用0表示;第二个title对应第二个系统,用1表示。
timeout=5:默认启动选择界面时停留的时间,单位是秒。例如设置为5,表示等待5秒后会自动进入默认操作系统。
splashimage=(hd0,0)/grub/splash.xpm.gz:grub启动背景画面,配置文件中可以不包括此项内容。
hiddenmenu:隐藏菜单。只有按上、下键才会出现。
title Red Hat Enterprise Linux (2.6.32-279.el6.i686):title后面是系统在启动时显示的名字。
root (hd0,0):root指定内核所在的分区,hd0表示第一块硬盘设备,0表示第一个分区,也就是/boot所在的分区。
kernel...:内核所在位置和名字。ro表示只读,root用于指定根分区,rhgb用图形化方式显示启动过程,quiet表示用静默式方式启动,不显示dmesg信息。
initrd /initramfs-2.6.32-279.el6.i686.img:initrd内核镜像的名字。
rhgb:表示redhat graphics boot,就是用图片来代替启动过程中显示的文本信息。这些信息在启动后用dmesg可以看到。
quiet:表示在启动过程中只显示重要信息,类似硬件自检的消息则不会显示。
3.4.3 系统引导过程及修复
RHEL系统启动的引导过程如图3-5所示。
图3-5 RHEL系统启动引导过程
引导故障修复主要包含以下两种情况:grub.conf文件损坏和/boot分区损坏。下面详细说明这两种故障产生的原因及解决方法。
【例3-1】重启系统停留在如图3-6所示的界面,分析故障原因并说明解决方法。
图3-6 系统出错界面
故障原因:
GRUB找到不启动文件。
解决步骤:
(1)手动指定启动文件位置,运行root或者find /vmlinuz-2.6.32-279.e16.i686(可以使用Tab键补全),搜索vmlinuz所在分区,也就是/boot所在分区,如图3-7所示。
图3-7 指定启动文件位置
(2)指定Linux内核,执行kernel /vmlinuz-2.6.32-279.el6.i686 ro root=LABEL=/ rhgb quiet(结合Tab键),如图3-8所示。
图3-8 指定内核
(3)指定initrd文件,执行initrd /initrd-2.6.32-279.e16.i686.img,如图3-9所示。
图3-9 指定initrd文件
(4)执行boot,如图3-10所示。
图3-10 执行boot
(5)出现框中所标的Red Hat字样说明内核加载成功,如图3-11所示。
图3-11 内核加载成功
启动成功后需要在grub.conf中把刚才执行的三行命令加进去,否则下次启动时还是会出现系统出错界面。如果执行以上操作后还是无法正常进入系统,并提示内核恐慌等信息时,可以在第二步后面加上参数enforcing=0。
【例3-2】若经过以上操作仍无法正常进入系统,提示内核恐慌,如图3-12所示,试说明原因及解决方法。
图3-12 内核恐慌提示
故障原因:
提示无法找到root的参数,也就是使用root=LABEL=/这个参数后无效。
解决步骤:
(1)使用安装盘,以救援模式rescue启动,使用chroot命令切换到硬盘系统,修改根目录的LABEL名称,如图3-13所示。
图3-13 内核恐慌解决方案
(2)再重复上面修复的过程即可,如果以上还是无法修复,可以尝试在【例3-1】中解决方法的第二步指定内核kernel /vmlinuz-2.6.32-279.el6.i686 ro root=LABEL=/ rhgb quiet后面增加参数enforcing=0。
【例3-3】若/boot分区损坏重启后出现的界面和上面介绍的grub文件损坏时的一样,如何判断是grub损坏,还是/boot分区损坏?在指定内核时无法找到参数应如何解决?
在【例3-1】中指定内核时发现找不到内核参数,此时,应按照如下方法解决:
(1)放入安装盘从光盘启动,进入救援模式,执行步骤如图3-14所示。
图3-14 进入救援模式
(2)当前boot目录下一个文件也没有(boot下面应主要包含grub和kernel),因此这里需要安装这两部分内容。先挂载安装盘,命令为mount/dev/cdrom/mnt/cd/,如图3-15所示。
图3-15 挂载安装grub
(3)然后安装kernel,命令为:rpm -ivh -force/mnt/cd/Packages/kernel-2.6.32-279. e16.i686.rpm,如图3-16所示。
图3-16 挂载安装kernel
(4)安装好kernel后还需要安装grub,命令为grub-install/dev/sda,如图3-17所示。
图3-17 安装grub
(5)新安装的grub没有配置文件,需要手动添加,如图3-18所示。
图3-18 添加grub配置文件
(6)输入两次exit后退出重启,重启后会检测磁盘,如图3-19所示。该过程可能会有点长。
图3-19 退出重启
3.4.4 root密码重置
恢复root密码需要在单用户模式下对root账户进行初始化,对root账户重新设置密码的步骤如下。
(1)出现如图3-20所示的界面时,立即按字母键E,之后出现如图3-21所示的界面。
图3-20 系统启动按字母键E界面
图3-21 按字母键E后出现的界面
(2)在出现图3-21所示界面后,再按字母键E,进入如图3-22所示的界面。
图3-22 再按字母键E后的界面
(3)在图3-22所示界面中选中第二行(kernel /vm...)后,再按字母键E进入如图3-23所示的界面。
图3-23 选中第二行再按字母键E后的界面
(4)在图3-23所示界面中输入空格和数字1,如图3-24所示。
图3-24 输入空格和1后的界面
(5)按Enter键后进入如图3-25所示界面。
图3-25 按回车键后的界面
(6)在图3-25所示界面中按字母键B,进入如图3-26所示界面,然后修改需要修改的账户密码。
图3-26 按字母键B后的界面
(7)重启后即可用修改后的密码来登录。
3.4.5 系统关机过程
在了解Linux系统关机过程之前,有必要先学习Linux一些常用的关机命令。在Linux下,常用的关机/重启命令有shutdown、halt、reboot和init等,它们都可以达到关机重启系统的目的,但是每一个命令的内部工作过程却是不同的。通过学习这些可以更加灵活地运用各种关机命令,并进一步详细了解Linux系统的安全关机过程。
1.shutdown,停止系统的妥善方式
shutdown命令可安全地将系统关机。有些用户会使用直接断掉电源的方式来关闭Linux,这种方法是十分危险的。因为Linux与Windows不同,其后台运行着许多进程,所以强制关机可能会导致进程的数据丢失,使系统处于不稳定的状态,甚至在有的系统中会损坏硬件设备。而在系统关机前使用shutdown命令,系统管理员会通知所有登录的用户系统将要关闭。并且loginm命令会被冻结,即新的用户不能登录。直接关机、延迟一定的时间关机或者重启都是可能,这是由所有进程收到系统所送达的信号决定的。这让像vi之类的程序有时间来储存目前正在编辑的文档,而像处理邮件和新闻的程序则可以正常地离开等。
shutdown的任务是送信号给init程序,要求它改变runlevel。runlevel 0用来停机,runlevel 6用来重新激活系统,而runlevel 1则是用来让系统进入运行管理状态。要想了解在停机或者重新开机过程中做了哪些动作,可以在/etc/inittab文件里查看runlevels的相关资料。
shutdown的参数说明如下:
[-t]在改变到其他runlevel之前,告诉init多久以后关机。
[-r]重启计算机。
[-k]并不真正关机,只是发送警告信号给每位登录的用户(login)。
[-h]关机后关闭电源(halt)。
[-n]不用init,而是用户自己来关机。不鼓励使用这个选,该选项所产生的后果往往不是预料得到的。
[-c] cancel current process取消目前正在执行的关机程序。这个选项没有时间参数,但是可以输入一个用来解释的信息,该信息将会发送到每位登录的用户。
[-f]在重启计算机(reboot)时忽略fsck命令。
[-F]在重启计算机(reboot)时强制执行fsck命令。
[-time]设定关机(shutdown)前的时间。
【例3-4】立即关机重启。
命令如下:
shutdown –r now
【例3-5】立即关机。
命令如下:
shutdown –h now
【例3-6】设定10分钟后关机,同时发出警告信息给其他登录的用户。
命令如下:
shutdown +10 "system will shut down after 10 minutes"
2.halt,关闭系统更简单的方式
halt是最简单的关机命令,其实halt调用的就是shutdown -h。执行halt时,会杀死应用进程,执行sync系统调用,文件系统写操作完成后就会停止内核的工作。
halt的参数说明如下:
[-n]防止sync系统调用。它用在使用fsck修补根分区之后,以阻止内核用老版本的超级块(superblock)来覆盖修补过的超级块。
[-w]并不是真正的重启或关机,只是写wtmp(/var/log/wtmp)记录。
[-d]不写wtmp记录(已包含在选项[-n]中)。
[-f]不调用shutdown而强制关机或重启。
[-i]关机(或重启)前,关掉所有的网络接口。
[-p]该选项为缺省选项,就是关机时调用poweroff。
3.reboot,快速重新启动
reboot的工作过程和参数都与halt相差不多,不过它用于主机重启,而halt是关机。
4.telinit,改变init的运行级
init是所有进程的祖先,它的进程号始终为1,所以发送TERM信号给init会终止所有的用户进程、守护进程等,shutdown使用的就是这种机制。init定义了8个运行级别(runlevel),其中init 0为关机,init 1为重启。telinit命令可以改变init的运行级别,比如,telinit -iS可使系统进入单用户模式。在使用telinit命令的时候,不会得到像shutdown那样友好的警告信息,也得不到使用shutdown时的信息和等待时间,所以很少使用。不过对于执行测试inittab文件的修改效果来说,使用该命令还是比较方便的。
5.poweroff,关闭电源
poweroff命令等价于halt,不同之处在于,Linux关闭后poweroff可以向电源管理系统(在支持这项功能的系统上)发送一则请求来关闭系统的主电源,这项功能易于实现远程关机。Linux的文件系统缓冲一般在内存中变化,只是偶尔才把它们写回磁盘。这种方案使得磁盘I/O速度更快,但是当系统被粗暴地中止时,这种方式也更容易使文件系统丢失数据。传统的装有Unix和Linux系统的计算机要非常小心地处理关机方式才行,虽然现在的系统已经变得强壮了(尤其是使用ext3这样强健的文件系统时),但是妥善关机总是一个好习惯。
关闭或者重新引导系统有许多种方法,比如关闭电源,但即使是在桌面系统上,关闭电源也不是关闭系统的一个好办法,这样做有可能丢失数据和破坏文件系统。许多计算机有一个软电源开关,当用户按下电源按钮时,计算机实际上是在运行一串命令来执行关闭系统的正确操作。不过,这种情况也是相对的,当发生紧急情况时,如果没有足够的时间来妥善关机,那么关闭电源也是可以的。当然,Linux系统下的关机操作更为常用是使用上述shutdown命令、halt或者reboot命令、以telinit命令改变init运行级别及poweroff命令关闭系统电源等方法。