初探FreeBSD與Linux的預處理機制

/*FreeBSD下的預處理機制*/

FreeBSD和system V還是一些不大一樣的,在rc(Resource Configuration)的使用機制上可以略見一斑了..
..rc系列的系統文件在FreeBSD中是非常常見的,這裡我們可以find一下...
alex# find /etc -name "rc*" -print;find /usr/local/etc -name "rc*" -print
/etc/defaults/rc.conf
/etc/rc.d
/etc/rc.d/rcconf.sh
/etc/rc
/etc/rc.firewall
/etc/rc.firewall6
/etc/rc.sendmail
/etc/rc.shutdown
/etc/rc.subr
/etc/rc.suspend
/etc/rc.resume
/etc/rc.conf
/usr/local/etc/rc.d
可以說掌握了它們的原理你就可以很快地熟悉FreeBSD系統的一些基本配置了。在初學者的角度來說我們需要
掌握的是:
/etc/rc.conf----------------系統主配置文件
/etc/defaults/rc.conf----默認系統配置文件
/etc/rc.d-------------------預處理目錄
/usr/local/etc/rc.d-------用戶級別預處理目錄
/etc/rc.local---------------系統預處理SHELL腳本
剩下的都是rc.conf的輔助文件了。

/etc/rc.conf大家可能不會陌生了(PS:如果以前有看過我的筆記的話),以前我把網關的rc.conf改成:
sendmail_enable="NONE"
sshd_enable="NO"
gateway_enable="YES"
hostname="alex.demon"
ifconfig_rl0="inet 192.168.1.1 netmask 255.255.255.0"
natd_enable="YES"
natd_interface="tun0"
ppp_enable="YES"
ppp_nat="YES"
ppp_mode="ddial"
ppp_profile="gzDSL"
上面的意思看上去好像誰都懂,但如何是一個空白的文件,現在要你"touch"一個rc.conf,要你"cat>>"一個出
來又如何呢?...對,這裡就涉及到一個'語法'與'關鍵字'的問題了...你知道哪個關鍵字是代表哪個服務
的嗎(看了上面的部分你可能會猜到一些,如何不看呢?又或者是沒看過的部分呢?)?另外,這些關鍵字所
對應的值究竟是BOOL值(這裡指的是"YES"或者"NO")又或者是字符串值呢?....問了上面的問題後可能你會
想答案可能會非常的複雜,其實只要你會E文就可以知道答案了...
alex# cat /etc/defaults/rc.conf|less
因為有N頁紙,所以我就挑出其中的一部分吧
pccard_enable="NO"   # Set to YES if you want to configure PCCARD devices.
pccard_mem="DEFAULT"  # If pccard_enable=YES, this is card memory address.
pccard_beep="2"     # pccard beep type.
pccard_ifconfig="NO"  # Specialized pccard ethernet configuration (or NO).
pccardd_flags="-z"   # Additional flags for pccardd.
pccard_conf="/etc/defaults/pccard.conf" # pccardd(8) config file
pccard_ether_delay="5" # Delay before trying to start dhclient in pccard_ether
#
ipfilter_enable="NO"      # Set to YES to enable ipfilter functionality
ipfilter_program="/sbin/ipf"  # where the ipfilter program lives
ipfilter_rules="/etc/ipf.rules" # rules definition file for ipfilter, see
                # /usr/src/contrib/ipfilter/rules for examples
ipfilter_flags=""        # additional flags for ipfilter
ipnat_enable="NO"        # Set to YES to enable ipnat functionality
ipnat_program="/sbin/ipnat"   # where the ipnat program lives
ipnat_rules="/etc/ipnat.rules" # rules definition file for ipnat
ipnat_flags=""         # additional flags for ipnat
ipmon_enable="NO"        # Set to YES for ipmon; needs ipfilter or ipnat
ipmon_program="/sbin/ipmon"   # where the ipfilter monitor program lives
ipmon_flags="-Ds"        # typically "-Ds" or "-D /var/log/ipflog"
看到右邊有註釋了吧?如果你想要更詳細的說明可以man rc.conf(PS:現在知道為什麼IT人都要學E文了...
)...上面我從/etc/defaults/rc.conf中節選了兩個部分,第一個部分是PC卡的控制段,第二部分是ipfilte
r系列的控制段,看出它們有什麼共通點了嗎?是的,它們各自的段都有相同的關鍵字:*_enable和*_flags。
它們是什麼關係呢?*_enable關鍵字是擊活這個段的開關(或者說是擊活這種功能的開關),它的值是BOOL
值(字符串YES或者NO);*_flags則是執行這個功能所附帶的參數,它的值是一串等同於在SHELL下執行該Da
emon時所使用的參數字符串。另外還有一個是非常常用的關鍵字(但它不是一定有的,具體哪個控制段有哪
個控制段沒有可以參看/etc/defaults/rc.conf),名為*_program,它是用來定位這個要執行的Daemon的程
序的執行文件位置的。舉個例子,如何你在/etc/rc.conf裡添加內容為:
ipmon_enable="YES"
ipmon_program="/sbin/ipmon"
ipmon_flags="-Ds"
其實就等同於系統在啟動時在SHELL下自動幫你執行:
alex# /sbin/ipmon -Ds
上面的例子為什麼是在/etc/rc.conf裡添加,而不是在/etc/defaults/rc.conf裡添加呢?這裡又引入這兩個
文件之間的關係這個概念了。/etc/defaults/rc.conf是系統的默認rc.conf,當/etc/rc.conf不存在時系統
也會正常地讀取rc.conf,讀取的部分就是/etc/defaults/rc.conf了;若/etc/rc.conf存在,則系統讀取該
文件的內容,當該文件中沒有提及的其他部分的設置系統將按/etc/defaults/rc.conf來制定,也就是說/etc
/rc.conf的優先級別比/etc/defaults/rc.conf高(這就是為什麼/etc/defaults/rc.conf中每個段的開關關
鍵字的值都為"NO"的緣故了)。上面提及的是rc.conf文件的優先問題,下面說說rc.conf中段設置的優先問
題。上面我曾說過rc.conf中每個段結構都有一個開關關鍵字*_enable的,當/etc/rc.conf設置啟用了該段所
代表的Daemon,則系統就會向/etc/rc.conf讀取下面的參數關鍵字,若某些關鍵字不存在,系統也會向/etc/
defaults/rc.conf讀取參數關鍵字;若/etc/rc.conf設置某Daemon段的開關關鍵字值為"NO",則就算/etc/de
faults/rc.conf設置該開關關鍵字的值為"YES",系統既不會啟動該Daemon也不會再向任何一個文件讀取關於
該Daemon下的參數關鍵字的值的。還有一點是需要注意的:就是/etc/rc.conf裡是可以寫進SHELL腳本的(但
不推崇那麼做)。

關於/etc/rc.d與/usr/local/etc/rc.d這兩個目錄文件的使用方法大致是相同的。在它們裡面的預處理文件
必須滿足三個條件:
1)都是以.sh結尾的SHELL腳本文件
2)文件的mask都有x(執行權限)
3)必須有'start'這個啟動程序的參數存在
滿足上面三點的話,系統在啟動時會自動將這兩個目錄下的SHELL腳本執行以start參數形式運行。至於這個
兩目錄文件的不同點就是:/etc/rc.d主要用於存放操作系統級別的Daemon控制腳本,而/usr/local/etc/rc.
d則用於存放用戶級別的Daemon控制腳本。所以如果是我們自己寫的*.sh最好還是放在/usr/local/etc/rc.d
裡。

至於最後一個介紹的文件/etc/rc.local通常是系統的預處理中最後被調用出來的,它的內容完全沒什麼限制
,只要是能執行SHELL腳本就可以了。
////////////////////////////////////////////////////////////////////////////////////////////////
/*Linux下的預處理機制*/

linux下與FREEBSD並不完全一樣,它的主要特點是它對runlevel有非常明確的定義的。下面我就自己的LINUX
(FEDORA 2)對此發表一下自己的看法(PS:當然,不同的發行版之間是有一定的差別的)。一台PC引導LIN
UX系統的步驟應該是(下面純粹是我個人的見解):

PC從BIOS ROM中找到硬引導設備-》從引導設備中找到MBR-》載入並初始化內核-》檢測硬件設備-》建立必要
的系統進程-》(必要的手工干預)-》預處理[DAEMON等]-》多用戶操作

前5步都是與預處理機制無關的,在第6部是可選的(所以用括號括起來),一但第6步正常退出,「運作的主
線」還是會回到第7步的,第7步就是本文的重點。LINUX是如何完成預處理的呢?它通常是根據一種init的機
制(PS:前面也說了,它非常的注重runlevel),首先系統在這個步驟是進行一系列有「預謀」的固定SHELL
腳本集執行,然後再根據發行版的不同而進行一些其他的預處理。

就我目前用的FEDORA 2而言,它本身也是有一套順序的:首先執行/etc/sysconfig目錄的腳本集,然後進行i
nit機制工作,最後讀取一下為兼容BSD系統而設立的/etc/rc.local腳本文件(這個是可選的)。

關於/etc/sysconfig的腳本集這個是REDHAT特有的,而且它使用起來比較凌亂,所以大多是不需要大家掌握,
大家可以用相關的工具去完成這部分的操作,打個比方,在/etc/sysconfig/network-scripts下的ifcfg-*文
件是在系統啟動時給網絡接口定義值的腳本,我們並不需要去編輯它,而可以選擇Linuxconf又或者netconfi
g等程序去完成它的編輯(PS:這樣可讀性就提高了)。

這裡我們必須明確上面所說的init機制。首先系統會讀取/etc/inittab文件,這裡我截選一段主要的部分來
說明一下:

id:3:initdefault:     <-------這裡定義了系統默認使用哪一個runlevel

# System initialization.
si::sysinit:/etc/rc.d/rc.sysinit <-----系統初始化

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

# Trap CTRL-ALT-DELETE
ca::ctrlaltdel:/sbin/shutdown -t3 -r now  <--------當接收到「熱啟」信號時

# Run gettys in standard runlevels  <-------關於getty的定義
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

# Run xdm in runlevel 5     <-------當目前狀態時運行級別5(X窗口)時
x:5:respawn:/etc/X11/prefdm -nodaemon

從上面的例子大概可以看出每一條作用行(非註釋行)都是由下面的部分構成的:
ID號:運行級別:運行狀態:需要運行的命令行
「ID號」由最多兩個英文字符組成,它的組成字符是有特別意思的,如系統初始化(System initialization
)的ID號固定一定是si的,不過這一項大家是不用故意去記住它的,只要跟著它上一行的註釋就可以知道了。
「運行級別」這一項可以定義多個運行級別的值在該值中,如上面的「1:2345:respawn:/sbin/mingetty tty
1」定義中「運行級別」這個值就有允許「2345」這四個級別都囊括在其中了。「運行狀態」屬於是inittab
語法上的一種關鍵字,大家可以man inittab來看一下。「需要運行的命令行」這個就不用我多說了吧?

這裡又引出了新的工作模式了。首先inittab尋找「運行狀態」這個參數為「initdefault」的作用行,找到
它的默認運行級別的值(上例為3),然後跳到「ID號」為「l3」的作用行,作用行根據它的運行命令行部分
(上例是/etc/rc.d/rc3.d這個目錄)。現在我們打開/etc/rc.d/rc3.d這個目錄來看看其中的『奧妙’(下
面只是其中節選的一小部分)。
lrwxrwxrwx 1 root root 18 Jul 11 1997 K89netplugd -> ../init.d/netplugd
lrwxrwxrwx 1 root root 18 Feb 17 14:02 K92iptables -> ../init.d/iptables
lrwxrwxrwx 1 root root 16 Jan 19 14:16 K96pcmcia -> ../init.d/pcmcia
lrwxrwxrwx 1 root root 19 Jul 11 1997 K99readahead -> ../init.d/readahead
lrwxrwxrwx 1 root root 25 Jul 11 1997 K99readahead_early -> ../init.d/readahead_early
lrwxrwxrwx 1 root root 23 Jul 11 1997 S00microcode_ctl -> ../init.d/microcode_ctl
lrwxrwxrwx 1 root root 15 Jul 11 1997 S05kudzu -> ../init.d/kudzu
lrwxrwxrwx 1 root root 18 Jul 11 1997 S06cpuspeed -> ../init.d/cpuspeed
lrwxrwxrwx 1 root root 14 Jul 11 1997 S09isdn -> ../init.d/isdn
lrwxrwxrwx 1 root root 17 Jul 11 1997 S10network -> ../init.d/network
lrwxrwxrwx 1 root root 16 Jul 11 1997 S12syslog -> ../init.d/syslog
lrwxrwxrwx 1 root root 20 Jul 11 1997 S13irqbalance -> ../init.d/irqbalance
可以看出所有文件都是鏈接到/etc/rc.d/init.d/下的SHELL腳本文件的。
[root@demonalex2 root]# cd /etc/rc.d/init.d
[root@demonalex2 init.d]# file syslog
sshd: Bourne-Again shell script text executable
至於這些SHELL腳本有什麼要求嘛,有執行權限(x)、有參數start。在系統執行到這個rcX.d目錄時它會通
過文件的特徵字符去辨別應該如何執行的。目錄裡每個文件的開頭都只有兩種可能S/K,當進入該運行級別時
系統會執行文件名為S開頭的SHELL腳本(調用start參數),當系統離開該運行級別時將執行該目錄下所有文
件名以K開頭的腳本(調用stop參數);S/K字符後緊跟著一個自然數值,它是系統用來辨別程序執行順序的,
順序是從小到大開始執行的;最後剩下的字符串代表程序的名稱。

現在讓我們再回到/etc/inittab文件裡頭看看,默認在「initdefault」下面還有一個「運行狀態」為「sysi
nit」的功能行,在它的命令執行部分定義了/etc/rc.d/rc.sysinit這個腳本,它是一個定義全局環境的SHEL
L腳本來的(它只會在系統引導時工作一次),有能力的朋友可以適當地編輯一下它來「改善一下生活」喏。

最後REDHAT的開發者可能是良心發現,留了系統中最後一個執行預處理的機會給一個兼容於BSD的執行腳本--
---/etc/rc.d/rc.local(存放的位置與BSD有些不同,BSD是在/etc/rc.local的),大家也可以用它來編輯
自己的SHELL處理了。
arrow
arrow
    全站熱搜

    Bluelove1968 發表在 痞客邦 留言(0) 人氣()