運(yùn)行級(jí)的概念來(lái)自System V,運(yùn)行級(jí)別將啟動(dòng)過(guò)程分成不同的集合,每個(gè)集合包含一
組腳本,當(dāng)init程序“切換運(yùn)行級(jí)”到對(duì)應(yīng)的級(jí)別時(shí),相應(yīng)的腳本就被觸發(fā),切換運(yùn)行
級(jí)可以通過(guò)執(zhí)行init [級(jí)別號(hào)]完成。(比如,在Linux中,run level 6代表reboot,所
以執(zhí)行init 6就會(huì)引起系統(tǒng)重新啟動(dòng))
運(yùn)行級(jí)別的定義每種System V都不完全一樣,只能通過(guò)直接讀/etc/inittab來(lái)確定,
下面是一個(gè)標(biāo)準(zhǔn)的Linux的/etc/inittab,注意這里解釋的內(nèi)容來(lái)自redhat,但是其他的
版本也大同小異。我們將它分成若干段來(lái)解釋,如同一般情況那樣,用#開始的行是注釋
,而非注釋行的語(yǔ)法是:
標(biāo)號(hào):運(yùn)行級(jí)別:操作方式:命令
標(biāo)號(hào)是這一行的標(biāo)簽,運(yùn)行級(jí)別用于定義這一行應(yīng)該用于那些級(jí)別,如果為空就定義
為所有級(jí)別,操作方式可以是一些確定的字符串,代表如何執(zhí)行后面的命令,而命令則
給處在進(jìn)入這一級(jí)別時(shí)執(zhí)行的程序。
下面是它的內(nèi)容:
# Default runlevel. The runlevels used by RHS are:
# 0 - halt (Do NOT set initdefault to this)
# 1 - Single user mode
# 2 - Multiuser, without NFS (The same as 3, if you do not have networking)
# 3 - Full multiuser mode
# 4 - unused
# 5 - X11
# 6 - reboot (Do NOT set initdefault to this)
#
上面的幾行解釋了缺省的運(yùn)行級(jí)別定義:
停機(jī),系統(tǒng)進(jìn)入這一級(jí)別后關(guān)機(jī);
單用戶模式,在這個(gè)模式中只能從控制臺(tái)操作計(jì)算機(jī),網(wǎng)絡(luò)和終端不啟動(dòng),許多文件
系統(tǒng)也沒有連結(jié);
多用戶模式,但關(guān)閉了網(wǎng)絡(luò)服務(wù)支持
完全的多用戶模式,就是我們一般使用的模式
無(wú)定義
圖形界面模式,系統(tǒng)切入這一運(yùn)行級(jí)后自動(dòng)啟動(dòng)X Window系統(tǒng)
重新啟動(dòng)
這些級(jí)別的定義是任意的,然而你最好不要修改它,尤其是level 0,1和6,因?yàn)樵S多
程序都使用init 0之類的方式實(shí)現(xiàn)對(duì)系統(tǒng)的控制,其他的Linux發(fā)行版本可能會(huì)更改2-5
的定義,你需要參考/etc/inittab才能判斷到底那個(gè)級(jí)別是什么意思,不過(guò)一般來(lái)說(shuō)0,
1和6總是上面的定義。
下面開始才是真正的內(nèi)容,首先系統(tǒng)必須定義缺省的運(yùn)行級(jí)別:
id:3:initdefault:
initdefault關(guān)鍵字決定了缺省的運(yùn)行級(jí)別,在這里是3,也就是在執(zhí)行了公共的系統(tǒng)
啟動(dòng)腳本之后,系統(tǒng)將會(huì)執(zhí)行與級(jí)別3對(duì)應(yīng)的那些行
# System initialization.
si::sysinit:/etc/rc.d/rc.sysinit
這里的sysinit關(guān)鍵字定義了公共的“系統(tǒng)初始化”腳本,在相應(yīng)于運(yùn)行級(jí)的地方是空
,表示適用于所有運(yùn)行級(jí)別。注意它將在系統(tǒng)進(jìn)入任何運(yùn)行級(jí)別以前完成,一會(huì)我們?cè)?BR>研究這個(gè)腳本的內(nèi)容。
l0:0:wait:/etc/rc.d/rc 0
l1:1:wait:/etc/rc.d/rc 1
l2:2:wait:/etc/rc.d/rc 2
l3:3:wait:/etc/rc.d/rc 3
l4:4:wait:/etc/rc.d/rc 4
l5:5:wait:/etc/rc.d/rc 5
l6:6:wait:/etc/rc.d/rc 6
這里開出了六個(gè)運(yùn)行級(jí)別的定義,運(yùn)行級(jí)0就去執(zhí)行命令/etc/rc.d/rc 0,運(yùn)行級(jí)1是
/etc/rc.d/rc 1,.....諸如此類。wait關(guān)鍵字表示系統(tǒng)必須等待此命令執(zhí)行完才能開始
下一步工作。
# Things to run in every runlevel.
ud::once:/sbin/update
這又是一個(gè)適用于所有級(jí)別的命令。update命令實(shí)際是去啟動(dòng)updated守護(hù)進(jìn)程,以便
定期刷新內(nèi)存中的超級(jí)塊表。Once關(guān)鍵字說(shuō)明這個(gè)項(xiàng)只被執(zhí)行一次。
# Trap CTRL-ALT-DELETE
ca::ctrlaltdel:/sbin/shutdown -t3 -r now
ctrlaltdel定義當(dāng)熱啟動(dòng)組合鍵被觸發(fā)時(shí)系統(tǒng)的行為,這里定義所有的運(yùn)行級(jí)別對(duì)它
的響應(yīng)都是重新啟動(dòng)(shutdown –r)
pf::powerfail:/sbin/shutdown -f -h +2 "Power Failure; System Shutting Down
"
pr:12345:powerokwait:/sbin/shutdown -c "Power Restored; Shutdown Cancelled
"
這兩行定義如何響應(yīng)ups信息,如果系統(tǒng)掉電(powerfail),執(zhí)行兩分鐘后關(guān)機(jī)的指令
;如果關(guān)機(jī)之前電源恢復(fù),取消關(guān)機(jī)操作。
# Run gettys in standard runlevels
1:2345:respawn:/sbin/mingetty tty1
2:2345:respawn:/sbin/mingetty tty2
3:2345:respawn:/sbin/mingetty tty3
4:2345:respawn:/sbin/mingetty tty4
5:2345:respawn:/sbin/mingetty tty5
6:2345:respawn:/sbin/mingetty tty6
2,3,4,5都是多用戶級(jí)別,為系統(tǒng)開出6個(gè)虛擬屏幕(就是用Alt+Fn即獲得虛擬屏幕)
,respawn關(guān)鍵字表示這個(gè)動(dòng)作在每次進(jìn)入相應(yīng)運(yùn)行級(jí)別時(shí)都會(huì)執(zhí)行。
# Run xdm in runlevel 5
# xdm is now a separate service
x:5:respawn:/etc/X11/prefdm -nodaemon
對(duì)于級(jí)別5,啟動(dòng)圖形界面。
歸納一下,系統(tǒng)在讀入inittab以后要做什么?設(shè)置Ctrl+Alt+Del響應(yīng),設(shè)置好對(duì)UPS
的支持,然后應(yīng)該執(zhí)行/etc/rc.d/rc.sysinit,然后是/etc/rc.d/rc 3,最后是update
和啟動(dòng)虛擬屏幕。顯然,系統(tǒng)的主要初始化命令應(yīng)該在/etc/rc.d/rc.sysinit和/etc/r
c.d/rc 3中完成。
rc.d下的基本腳本
下面我們來(lái)研究啟動(dòng)腳本,這里的腳本來(lái)自redhat 6.1,因?yàn)檫@是個(gè)最為廣泛使用的
版本,其他的版本的特有問(wèn)題將在下一節(jié)討論。
首先,系統(tǒng)將執(zhí)行/etc/rc.d/rc.sysinit,這是個(gè)shell腳本,你可以用普通的文本編
輯工具對(duì)它進(jìn)行處理,為了簡(jiǎn)便,我們只研究其中較為重要的部分或者較為典型的段落
:
#!/bin/sh
#
# /etc/rc.d/rc.sysinit - run once at boot time
#
# Taken in part from Miquel van Smoorenburg's bcheckrc.
#
# Rerun ourselves through initlog
if [ -z "$IN_INITLOG" ]; then
[ -f /sbin/initlog ] && exec /sbin/initlog $INITLOG_ARGS -r /etc/rc.d/rc.
sysinit
fi
首先,確定系統(tǒng)中是否存在/sbin/initlog文件,如果存在,那么需要記錄初始化信息
。
# Set the path
PATH=/bin:/sbin:/usr/bin:/usr/sbin
export PATH
設(shè)置缺省路徑。
# Read in config data.
if [ -f /etc/sysconfig/network ]; then
. /etc/sysconfig/network
else
NETWORKING=no
HOSTNAME=localhost
fi
這一段是網(wǎng)絡(luò)的參數(shù)設(shè)置,/etc/sysconfig/network的內(nèi)容是這樣:
NETWORKING=yes
FORWARD_IPV4="yes"
HOSTNAME="openlab.asnc.edu.cn"
GATEWAY=""
GATEWAYDEV=""
顯然,如果這個(gè)文件存在,那么設(shè)置網(wǎng)絡(luò)的運(yùn)行參數(shù),如域名,網(wǎng)關(guān)等等,這個(gè)文件
中可以包含很多的東西。詳細(xì)的內(nèi)容我們?cè)谠O(shè)置網(wǎng)絡(luò)的部分介紹
# Source functions
. /etc/rc.d/init.d/functions
/etc/rc.d/init.d是所有的服務(wù)腳本存放的地方,而functions是各種服務(wù)腳本需要的
一些參數(shù)的設(shè)置。有興趣的話你可以看一看,不看也不影響什么。
以下有一段是設(shè)置一些顯示信息,接下來(lái)是這樣的內(nèi)容:
# Mount /proc (done here so volume labels can work with fsck)
action "Mounting proc filesystem" mount -n -t proc /proc /proc
連結(jié)/proc文件系統(tǒng),應(yīng)該記得/proc是用來(lái)顯示系統(tǒng)狀態(tài)的虛擬文件系統(tǒng),注意acti
on命令的語(yǔ)法,它顯示一段提示信息,然后去執(zhí)行相應(yīng)的命令。
然后的段落有一點(diǎn)意思:
# Turn off sysrq
#if [ "$MAGIC_SYSRQ" = "no" ]; then
# echo "0" > /proc/sys/kernel/sysrq
#fi
$MAGIC_SYSRQ=no意味著你決定不使用內(nèi)核調(diào)試,腳本必須把系統(tǒng)的內(nèi)核調(diào)試功能關(guān)閉
,注意接下來(lái)的處理方法,在/proc/sys/kernel下建立一個(gè)名叫sysrq的文件,并且設(shè)置
其內(nèi)容為"0",就關(guān)閉了這項(xiàng)功能,這也是在運(yùn)行中打開或者關(guān)閉內(nèi)核的某個(gè)功能的標(biāo)準(zhǔn)
方法,以后我們會(huì)經(jīng)常看到這樣的例子。
接下來(lái)要設(shè)置時(shí)鐘和鍵盤映射表,裝入系統(tǒng)字體,又是一段冗長(zhǎng)的代碼,這里將它省
略,反正你總可以在自己的系統(tǒng)上看到他們。
# Start up swapping.
action "Activating swap partitions" swapon -a
swapon –a 將讀/etc/fstab文件,這個(gè)文件中包含有系統(tǒng)中存在的應(yīng)該自動(dòng)掛接的各
種文件系統(tǒng)的列表,同時(shí)也包含了關(guān)于交換分區(qū)的知識(shí),swapon –a將啟動(dòng)其中標(biāo)注的
所有交換分區(qū)。
# Set the hostname.
action "Setting hostname ${HOSTNAME}" hostname ${HOSTNAME}
# Set the NIS domain name
if [ -n "$NISDOMAIN" ]; then
action "Setting NIS domain name $NISDOMAIN" domainname $NISDOMAIN
else
domainname ""
fi
這兩段設(shè)置系統(tǒng)名字,我們應(yīng)該記得$HOSTNAME已經(jīng)在/etc/sysconfig/network文件中
設(shè)置過(guò),所以這里的action被執(zhí)行,而$NISDOMAIN現(xiàn)在是空字符串,所以執(zhí)行后hostna
me被設(shè)置而NIS域名不存在。
if [ -f /fsckoptions ]; then
fsckoptions=`cat /fsckoptions`
else
fsckoptions=
fi
if [ -f /forcefsck ]; then
fsckoptions="-f $fsckoptions"
fi
這里是與管理員相關(guān)的行了。如果系統(tǒng)的/下將存在/forcefsck文件,于是系統(tǒng)自動(dòng)啟
動(dòng)fsck程序去檢查文件系統(tǒng)是否有錯(cuò)誤。接下來(lái)是一段關(guān)于是否存在/fastboot文件的判
斷,與其大同小異,然后系統(tǒng)將會(huì)決定是否啟用PNP,方法和處理MAGIC_SYSRQ是類似的
,這兩段我們不討論了,你可以自己看一下。
# Remount the root filesystem read-write.
action "Remounting root filesystem in read-write mode" mount -n -o remount
,rw /
# Add /proc to /etc/mtab
mount -f -t proc /proc /proc
檢測(cè)根文件系統(tǒng)完畢后,系統(tǒng)重新將/連結(jié)成讀寫方式,并且將/proc加入到/etc/mta
b中。下面是非常重要的一步,如果系統(tǒng)內(nèi)核支持可裝載模塊,需要把$USEMODULES變量
設(shè)置成"y"并且設(shè)置模塊的缺省路徑,參數(shù)等等,然后,系統(tǒng)開始裝入模塊:
# load sound modules
if [ -n "$USEMODULES" ]; then
if grep -s -q "^alias sound " /etc/conf.modules ; then
action "Loading sound module" modprobe sound
fi
.........
fi
...........
當(dāng)這些直接裝入的模塊結(jié)束后,為了和以前的方式兼容,也為了管理員的方便,這個(gè)
腳本試圖去尋找/etc/rc.d/rc.modules,如果存在就執(zhí)行它:
# Load modules (for backward compatibility with VARs)
if [ -f /etc/rc.d/rc.modules ]; then
/etc/rc.d/rc.modules
fi
顯然,你可以將自己的模塊初始化命令加入/etc/rc.d/rc.modules使它在啟動(dòng)時(shí)得到
運(yùn)行。
完成主要模塊的裝入后,系統(tǒng)將開始一系列日常工作,如檢測(cè)有問(wèn)題的文件系統(tǒng),連
結(jié)所有本地文件系統(tǒng),啟動(dòng)磁盤限額等等,如果系統(tǒng)還沒有被配置,那么將啟動(dòng)配置腳
本,設(shè)置網(wǎng)絡(luò),超級(jí)用戶口令等等,否則,對(duì)于已經(jīng)配置好的系統(tǒng),清理記賬文件,準(zhǔn)
備進(jìn)行系統(tǒng)工作。
當(dāng)一切都完成之后,系統(tǒng)按照inittab的設(shè)定,進(jìn)入運(yùn)行級(jí)3,執(zhí)行/etc/rc.d/rc 3。
/etc/rc.d/rc是一個(gè)很有意思的程序,它是一個(gè)shell腳本,其行為是這樣:根據(jù)提供
給它的參數(shù),它去尋找相應(yīng)的目錄rc${arg1}.d,例如,在/etc/rc.d/rc 3執(zhí)行時(shí),它去
查詢/etc/rc.d/rc3.d下的所有文件,試圖執(zhí)行那些所有用S或K打頭的腳本,凡是用S開
頭的腳本,它給加上一個(gè)start參數(shù),凡是用K打頭的腳本,加上一個(gè)stop參數(shù)。執(zhí)行次
序是按照S或K后跟的數(shù)值順序。
例如,在現(xiàn)在的例子中,/etc/rc.d/rc 3下存在一個(gè)S50inet的腳本,于是 rc 腳本去
執(zhí)行S50inet start。而S50inet其實(shí)是到/etc/rc.d/init.d/inet的一個(gè)符號(hào)連結(jié),其內(nèi)
容是(這里只給出了部分內(nèi)容):
. /etc/rc.d/init.d/functions
. /etc/sysconfig/network
if [ ${NETWORKING} = "no" ]
then
exit 0
fi
[ -f /usr/sbin/inetd ] || exit 0
RETVAL=0
# See how we were called.
case "$1" in
start)
echo -n "Starting INET services: "
daemon inetd
RETVAL=$?
echo
[ $RETVAL -eq 0 ] && touch /var/lock/subsys/inet
;;
stop)
echo -n "Stopping INET services: "
killproc inetd
RETVAL=$?
echo
[ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/inet
;;
*)
echo "Usage: inet {start|stop|status|restart|reload}"
exit 1
esac
exit $REVAL
daemon和killproc是在/etc/rc.d/init.d/functions里面定義的函數(shù),daemon將命令
當(dāng)成守護(hù)進(jìn)程執(zhí)行,killproc則殺掉對(duì)應(yīng)進(jìn)程。顯然,S50inet start的結(jié)果是inetd程
序被啟動(dòng)為一個(gè)守護(hù)進(jìn)程。
這里的方法是啟動(dòng)服務(wù)進(jìn)程的標(biāo)準(zhǔn)模式,例如你要設(shè)置某個(gè)服務(wù)在runlevel 3被啟動(dòng)
,那么你可以自己寫一個(gè)腳本,比如說(shuō)mydaemon,讓mydaemon start啟動(dòng)服務(wù),mydaem
on stop停止服務(wù),然后將這個(gè)腳本復(fù)制到/etc/rc.d/init.d中,接著在/etc/rc.d/rc?
.d中建立連接,在rc3.d中連結(jié)為S65mydaemon,而在其他目錄中為K65mydaemon,這樣你
的腳本就會(huì)在進(jìn)入和退出運(yùn)行級(jí)3時(shí)自動(dòng)處理了。
除此與run level相關(guān)的啟動(dòng)指令之外,Linux還從BSD中引入了另外一些配置文件,其
中最重要的是/etc/rc.d/rc.local,通常它在執(zhí)行了全部運(yùn)行級(jí)腳本以后運(yùn)行,你可以
在這里定制自己的設(shè)置,如歡迎信息等等。
版本之間的區(qū)別
如同我們看到的那樣,Redhat的啟動(dòng)腳本看上去井井有條,要尋找某個(gè)功能很容易,
但是要尋找某個(gè)命令在何處啟動(dòng)就顯得比較困難,經(jīng)常需要從/etc/inittab開始。
Turbo Linux和Red-Flag的腳本和Redhat頗為相似,尤其是紅旗幾乎就是RedHat的中文
版,它們的配置也相當(dāng)近似。
Slackware的啟動(dòng)腳本使用另外一種風(fēng)格,實(shí)際上,看上去很象BSD系列。啟動(dòng)腳本也
在/etc/rc.d下面,但是它把一些在大部分運(yùn)行級(jí)別必須使用的腳本做在了一起,冠以r
c.modules,rc.inet1,rc.inet2等等的名字,這樣對(duì)于手工配置系統(tǒng)確實(shí)簡(jiǎn)單的多,不
過(guò)這些文件都相當(dāng)大,看起來(lái)需要耐心。對(duì)于這個(gè)系統(tǒng),你只要看一遍/etc/inittab就
能掌握它的配置文件位置了。
Debian/Corel使用一種有趣的方式,看上去頗像Sun的Solaris。實(shí)際上,它和RedHat
的方式幾乎是一樣的,但是啟動(dòng)腳本不是在/etc/rc.d,而是直接位于/etc下,例如/et
c/rc1.d,/etc/rc2.d等等,知道了這一點(diǎn)之后,配置debian就不會(huì)感到困難了。
關(guān)于Corel Linux我們應(yīng)該特別地說(shuō)一句,它的配置文件組織看起來(lái)要比RedHat簡(jiǎn)單一
些,但是它沒有類似于rc.modules的設(shè)定,等價(jià)于rc.sysinit的文件是/etc/init.d/rc
S。它的運(yùn)行級(jí)別定義也比較怪異,好像Run Level 2是正常的圖形模式,要配置Corel,
最好是從/etc/inittab直接開始。無(wú)論如何,我們不會(huì)建議一個(gè)新手使用corel Linux。