什么是LSB
LSB,即Linux標准規范(英語:Linux Standard Base)是一個在Linux基金會結構下對Linux發行版的聯合項目,使Linux操作系統符合軟件系統架構,或文件系統架構標准的規范及標准。LSB基於POSIX,統一UNIX規范及其他開放標准,共在某些領域擴展它們。詳細情況請參考相關鏈接。
LSB腳本動作
由LSB應用程序提供的腳本應該需要接受一個指示其動作(action)的參數,目前包括:
- start 啟動服務
- stop 停止服務
- restart 如果服務在運行,則先停止,再啟動,否則啟動服務
- try-restart 如果服務正在運行,重啟服務
- reload 不通過重啟服務的方式重新加載配置文件
- force-reload 如果服務支持的話,重新加載配置文件,否則重啟服務
- status 打印服務的當前狀態
start,stop,restart,force-reload 和status是所有lsb腳本必須支持的;reload和try-restart是可選的。當然自己也可以定義別的一些動作。
在下列情況下,lsb腳本要求確保對其接受的動作(action)有其明確且合理的行為
- 服務已經啟動,然后調用start
- 服務已經停止,然后調用stop
對於這些行為,為了滿足其一致性,最好使用/lib/lsb/init-functions腳本(后面分析)
在主流的Linux發行版版本中,一個軟件包卸載(remove)時,並不會講一些腳本,配置文件同時刪除,除非你強制指定為清除(purge).因此,在你的lsb腳本最前面應該包括一個判斷真正的可執行文件是否存在,類似於下面這個樣子:
[ -x /usr/sbin/ifconfig ] || exit 5
如果調用status動作,lsb腳本應該根據其狀態返回下面的值:
- 0 程序正在運行,或者服務正常
- 1 程序已死,但/var/run/下的pid文件還存在(或者在別的位置)
- 2 程序已死,但/var/lock/下的鎖文件還存在(或者在別的位置)
- 3 程序沒有運行
- 4 程序或者服務狀態未知
- 5-99 LSB為擴展保留
- 100-149 為發行版本使用保留
- 150-199 為應用程序使用保留
- 200-254 保留
除status動作外,指定其他動作,lsb腳本必須返回狀態值(exit $?),如果完成動作其他的結果,返回為0,否則應該根據動作情況,返回下列值之一:
- 1 通用(generic)錯誤或者非規范化錯誤
- 2 無效參數,或者參數過多
- 3 未實現的特性(比如reload)
- 4 用戶權限不夠
- 5 程序沒有安裝
- 6 程序沒有配置
- 7 程序沒有運行
- 8-99 LSB為擴展保留
- 100-149 為發行版本保留
- 150-199 為應用程序使用保留
- 200-254 保留
錯誤和狀態消息應該通過日志函數來輸出,比如lsb提供的log_failure_msg。
因為lsb腳本有可能是由系統管理員在非標准的環境下手工運行,比如沒有PATH,USER,LOGNAME等環境變量.因此lsb腳本不能依賴環境變量,它需要自己設定自己需要的變量或者使用缺省值.
LSB腳本注釋約定
在init.d目錄的lsb腳本,其腳本描述信息應該用### BEGIN INIT INFO 和 ### INIT INFO來分隔。分隔行可以包行尾部空白,腳本會忽略它。在分隔行之間包圍區域其描述信息需要遵循這樣的格式: # {keyword}: [arg1] [arg2] ...。,在#和keyword之間只能而且必須有一個空格,類似下面的例子:
1 2 3 4 5 6 7 8 9 |
# Provides: boot_facility_1 [ boot_facility_2 ...] # Required-Start: boot_facility_1 [ boot_facility_2 ...] # Required-Stop: boot_facility_1 [ boot_facility_2 ...] # Should-Start: boot_facility_1 [ boot_facility_2 ...] # Should-Stop: boot_facility_1 [ boot_facility_2 ...] # Default-Start: run_level_1 [ run_level_2 ...] # Default-Stop: run_level_1 [ run_level_2 ...] # Short-Description: short_description # Description: multiline_description |
init.d下的lsb腳本可以用Required-Start關鍵字來申明在運行該腳本之前應該需要先運行哪些腳本,這些信息一般是由安裝程序或者啟動腳本工具根據相互依賴關系來生成其正確的順序(比如所有依賴網絡的服務都應該應該在network腳本啟動之后運行)。當lsb腳本帶start參數運行時,在Provides指定的設施(facility)應該存在,而且lsb腳本也要求這些設施能夠正確運行.
類似的,Required-Stop里定義的啟動設施應該在該腳本停止時都有效.
Should-Start關鍵字和Should-Stop關鍵字的概念和Required-Start及Required-Stop類似,只是對其后面定義的設施是希望而不是必須。
Default-Start和Default-Stop 定義了缺省情況下該腳本在哪些運行級別下啟動和停止,它可以通過init腳本來控制。
Short-Description和Description關鍵字是描述該腳本的行為,如關鍵字說描述的那樣,Short-Description希望是簡潔的介紹該腳本,而Description則可以更詳細一點。如果描述信息多余一行,從描述信息的第二行起,每一行都必須以#符號開頭,然后接一個tab鍵,或者至少兩個空格。
安裝和移除(removal)init.d腳本
通過將腳本拷貝到init.d目錄或者符號鏈接到該目錄,就完成了腳本的安裝工作,在執行安裝包的postinstall腳本階段(RPM包管理),/usr/lib/lsb/install_initd程序調用安裝程序的init.d腳本文件來安裝/usr/lib/lsb/inistall_initd程序可以帶一個參數,類似如下:
/usr/lib/lsb/install_initd /etc/init.d/foo
如果腳本已經安裝或者安裝程序,該程序均返回為0,其他情況返回為非0值。
卸載軟件包時,通過preuninstall腳本來調用/usr/lib/lsb/remove_initd程序來移走init.d目錄對應的文件,類似如下:
/usr/lib/lsb/remove_initd /etc/init.d/foo
如果腳本已經移除或者移除成功,則返回為0,否則返回為非0值。
系統發行版本應該提供一個有效的工具(比如紅帽的chkconfig)來提供給系統管理員來管理多運行級別下,腳本的啟動停止控制。
運行級別
絕大部分通用Linux發行版都提供了多種啟動級別,前面說到的Default-Start,Default-Stop也表明了這點。系統init腳本通過調用對應運行級別目錄(rc?.d)下的腳本(符號鏈接)來控制哪些腳本應該在該級別啟動和停止。/usr/lib/lsb/inistall_initd程序通過查詢腳本的Default-Start和Default-Stop的定義來創建對應運行級別目錄的符號鏈接。系統啟動級別及描述如下:
- 0 停機
- 1 單用戶模式
- 2 多用戶無網絡模式(很少使用)
- 3 完整的多用戶終端模式(無圖形界面)
- 4 保留
- 5 多用戶帶GUI模式
- 6 重啟
設施(facility)名稱
啟動設施用來指示init腳本之間的依賴性。以$符號開頭設施名都是系統設施,它由LSB定義,發行版吧必須提供。符合LSB規范的應用程序不能提供以$開頭的設施名稱。 當前LSB定義下面的幾種設施名稱:
- $local_fs 所有的本地文件系統已經掛載
- $network 底層網絡已經有效(指網卡,IP地址,PCMCI之類的)
- named 域名解析后台服務(DNS)正在運行
- portmap 提供SunRPC/ONCRPC端口映射的服務(如果存在的話)正在運行
- remote_fs 所有遠程文件系統已經掛載
- syslog 系統日志服務可用
- time 系統時鍾已經設置
其他(非系統)的設施可以由LSB應用程序來定義,這些設施名稱應該采取腳本名同名的命名約定,通常情況下,發行版版本都是如此.
腳本名稱
所有的init腳本都在同一個目錄,因此名字不能沖突,LSB規范提供了三種有效命名空間方式:
-
Assigned namespace 這種命令只能由[a-z0-9]類的字符組成(沒有大寫字母).為了避免名字沖突,應該去Linux Assigned Names and Numbers Authority(LANANA)去申請你需要的名字.
-
Hierarchical namespace 這種命名空間由類似[hier1]-[hier2]-...-[name]組成,其中name由[a-z0-9]內的字符組成.[hier-n]可以有一個或者多個,[hier1]的名字要不是LANANA分配給LSB的名字,要不就是腳本擁有者的DNS小寫名稱,至少包含一個.符號,比如debian.org,kingbase.com. LSB提供的名字只能由[a-z0-9]內的ASCII碼組成.
-
Reserved namespace 這種命令空間以_符號開頭,僅提供給版本發行商使用,而且這種命令空間也應該只用在核心軟件包上.其他軟件包絕不推薦這種命名方式.
init腳本函數
每一個LSB兼容的init.d腳本必須包含/lib/lsb/init-functions,使用方式如下: source /lib/lsb/init-functions LSB自帶的腳本應該僅僅依賴/bin/sh(/bin/sh並不總是符號鏈接到/bin/bash)
-
start_daemon [-f] [-n nicelevel] [-p pidfile] pathname [args] 將指定的程序運行為守護進程(daemon).start_daemon會檢查對應的程序是否已經在運行,如果是,它不會再運行一次,除非使用-f參數.如果使用-n參數指定了nicelevel(參考nice(1)),start_daemon 應該返回LSB定義的退出代碼. 如果程序運行成功,該函數返回為0,否則返回為非0.
-
killproc [-p pidfile] pathname [signal] 停止指定的程序.該程序應該通過pidofproc函數找到(下面描述).如果指定了signal,則通過給kill指令傳遞-signal_name或-signal_number參數來終止程序,如果沒有,則先使用SIGTERM信號,如果無法終止,再使用SIGKILL信號.LSB兼容的應用程序可以使用basename而不一定是pathname. killproc應該返回LSB預定義的退出碼.調用時,如果沒有使用signal參數,該函數返回為0,假如程序已經停止,否則返回為非0.如果指定了signal參數,只有在程序還在運行的情況下,函數返回為0.
-
pidofproc [-p pidfile] pathname 該函數返回特定守護進程的一個活多個pid號.如果能找到/var/run/basename.pid文件,則返回該文件的值.如果-p參數指定,則返回該參數指定文件的內容. LSB兼容的程序可以使用basename而不非得是pathname.pidofproc應該返回LSB預定義的的退出碼,以便給status動作使用.如果程序正在運行,他應該返回為0,否則為非0.
-
log_success_msg "message" 打印一條成功消息,消息長度最好控制在60個字符內
-
log_failure_msg "mesage" 打印一條失敗消息,消息長度最好控制在60個字符內
-
log_warning_msg "message" 打印一條警告消息,消息長度最好控制在60個字符內
chkconfig
為了使得chkconfig能識別並能管理init腳本,需要在腳本第二行(第一行是#!/bin/bash)其增加下面這樣幾行:
# # chkconfig: 35 80 5 # description: some description about this script # processname: foo
檢測LSB兼容性
-
服務沒有啟動時,執行start操作 /etc/init.d/some_service start; echo $? 預期結果服務啟動;start操作的返回值為0。
-
服務已經啟動,執行status操作 /etc/init.d/some_server status; echo $? 預期結果服務仍在運行,status操作顯示服務正在運行並且返回值為0。
-
服務已經啟動,執行start操作 /etc/init.d/some_service start; echo $? 預期結果服務仍在運行,start操作返回值為0。
-
服務已經啟動,執行stop操作 /etc/init.d/some_service stop; echo $? 預期結果服務停止,stop操作的返回值為0。
-
服務已經停止,執行status操作 /etc/init.d/some_service status; echo $? 預期結果服務保持停止,status操作顯示服務已經停止並且返回值為3。
-
服務已經停止,執行stop操作 /etc/init.d/some_service stop; echo $? 預期結果服務保持停止,stop操作返回值為0。
-
加載內核 執行init程序
/etc/rc.d/rc.sysinit # 由init執行的第一個腳本
/etc/rc.d/rc $RUNLEVEL # $RUNLEVEL為缺省的運行模式
/etc/rc.d/rc.local #相應級別服務啟動之后、在執行該文件(其實也可以把需要執行的命令寫到該文件中) /sbin/mingetty # 等待用戶登錄
在Redhat中,/etc/rc.d/rc.sysinit主要做在各個運行模式中相同的初始化工作,包括: 調入keymap以及系統字體 啟動swapping 設置主機名 設置NIS域名
檢查(fsck)並mount文件系統打開quota 裝載聲卡模塊設置系統時鍾等等。
/etc/rc.d/rc則根據其參數指定的運行模式(運行級別,你在inittab文件中可以設置)來執行相應目錄下的腳本。
凡是以Kxx開頭的 ,都以stop為參數來調用;凡是以Sxx開頭的,都以start為參數來調用。
調用的順序按xx 從小到大來執行。
(其中xx是數字、表示的是啟動順序)例如,假設缺省的運行模式是3,/etc/rc.d/rc就會按上述方式調用
/etc/rc.d/rc3.d/下的腳本。
值得一提的是,Redhat中的運行模式2、3、5都把/etc/rc.d/rc.local做為初始化腳本中
的最后一個,所以用戶可以自己在這個文件中添加一些需要在其他初始化工作之后,登錄之前執行的命令。 init在等待/etc/rc.d/rc執行完畢之后(因為在/etc/inittab中/etc/rc.d/rc的
action是wait),將在指定的各個虛擬終端上運行/sbin/mingetty,等待用戶的登錄。 至此,LINUX的啟動結束。
2)init運行級別及指令 一、什么是INIT:
init是Linux系統操作中不可缺少的程序之一。
所謂的init進程,它是一個由內核啟動的用戶級進程。
內核自行啟動(已經被載入內存,開始運行,並已初始化所有的設備驅動程序和數據結構等)之后,就通過啟動一個用戶級程序init的方式,完成引導進程。所以,init始終是第一個進程(其進程編號始終為1)。
內核會在過去曾使用過init的幾個地方查找它,它的正確位置(對Linux系統來說)是/sbin/init。如果內核找不到init,它就會試着運行/bin/sh,如果運行失敗,系統的啟動也會失敗。
二、運行級別
那么,到底什么是運行級呢?
簡單的說,運行級就是操作系統當前正在運行的功能級別。
這個級別從1到6 ,具有不同的功能。 不同的運行級定義如下
# 0 -停機(千萬不能把initdefault 設置為0 )
# 1 -單用戶模式 # s init s = init 1
# 2 -多用戶,沒有 NFS
# 3 -完全多用戶模式(標准的運行級)
# 4 -沒有用到
# 5 -X11 多用戶圖形模式(xwindow)
# 6 -重新啟動 (千萬不要把initdefault 設置為6 )
這些級別在/etc/inittab 文件里指定。
這個文件是init 程序尋找的主要文件,最先運行的服務是放
在/etc/rc.d 目錄下的文件。
在大多數的Linux 發行版本中,啟動腳本都是位於 /etc/rc.d/init.d中的。
這些腳本被用ln 命令連接到 /etc/rc.d/rcn.d 目錄。(這里的n 就是運行級0-6) 3):
---------------------------
chkconfig命令主要用來更新(啟動或停止)和查詢系統服務的運行級信息。謹記chkconfig不是立即自動禁止或激活一個服務,它只是簡單的改變了符號連接。
使用語法:
chkconfig [--add][--del][--list][系統服務] 或 chkconfig [--level <等級代號>][系統服務][on/off/reset]
chkconfig在沒有參數運行時,顯示用法。如果加上服務名,那么就檢查這個服務是否在當前運行級啟動。如果是,返回true,否則返回false。如果在服務名后面指定了on,off或者reset,那么chkconfi 會改變指定服務的啟動信息。on和off分別指服務被啟動和停止,reset指重置服務的啟動信息,無論有問題的初始化腳本指定了什么。on和off開關,系統默認只對運行級3,4,5有效,但是reset可以對所有運行級有效。
參數用法:
--add 增加所指定的系統服務,讓chkconfig指令得以管理它,並同時在系統啟動的敘述文件內增加相關數據。
--del 刪除所指定的系統服務,不再由chkconfig指令管理,並同時在系統啟動的敘述文件內刪除相關數據。
--level<等級代號> 指定讀系統服務要在哪一個執行等級中開啟或關畢。
等級0表示:表示關機
等級1表示:單用戶模式
等級2表示:無網絡連接的多用戶命令行模式
等級3表示:有網絡連接的多用戶命令行模式
等級4表示:不可用
等級5表示:帶圖形界面的多用戶模式
等級6表示:重新啟動
需要說明的是,level選項可以指定要查看的運行級而不一定是當前運行級。對於每個運行級,只能有一個啟動腳本或者停止腳本。當切換運行級時,init不會重新啟動已經啟動的服務,也不會再次去停止已經停止的服務。
chkconfig --list [name]:顯示所有運行級系統服務的運行狀態信息(on或off)。如果指定了name,那么只顯示指定的服務在不同運行級的狀態。
chkconfig --add name:增加一項新的服務。chkconfig確保每個運行級有一項啟動(S)或者殺死(K)入口。如有缺少,則會從缺省的init腳本自動建立。
chkconfig --del name:刪除服務,並把相關符號連接從/etc/rc[0-6].d刪除。
chkconfig [--level levels] name:設置某一服務在指定的運行級是被啟動,停止還是重置。
運行級文件:
每個被chkconfig管理的服務需要在對應的init.d下的腳本加上兩行或者更多行的注釋。第一行告訴chkconfig缺省啟動的運行級以及啟動和停止的優先級。如果某服務缺省不在任何運行級啟動,那么使用 - 代替運行級。第二行對服務進行描述,可以用 跨行注釋。
例如,random.init包含三行:
# chkconfig: 2345 20 80
# description: Saves and restores system entropy pool for
# higher quality random number generation.
使用范例:
chkconfig --list #列出所有的系統服務
chkconfig --add httpd #增加httpd服務
chkconfig --del httpd #刪除httpd服務
chkconfig --level httpd 2345 on #設置httpd在運行級別為2、3、4、5的情況下都是on(開啟)的狀態
chkconfig --list #列出系統所有的服務啟動情況
chkconfig --list mysqld #列出mysqld服務設置情況
chkconfig --level 35 mysqld on #設定mysqld在等級3和5為開機運行服務,--level 35表示操作只在等級3和5執行,on表示啟動,off表示關閉
chkconfig mysqld on #設定mysqld在各等級為on,“各等級”包括2、3、4、5等級
如何增加一個服務:
1.服務腳本必須存放在/etc/ini.d/目錄下;
2.chkconfig --add servicename
在chkconfig工具服務列表中增加此服務,此時服務會被在/etc/rc.d/rcN.d中賦予K/S入口了;
3.chkconfig --level 35 mysqld on
修改服務的默認啟動等級。
(第一位(X):是指定該腳本在哪個系統啟動級別下運行(關於linux啟動級別將在別的博文中介紹),比如你需要在3,4,5上運行,那么第二位就設置成345,我這里用的是”-”,代表在2,3,4,5上都運行。
第二位(Y):系統啟動時,服務啟動順序。(需要注意的是,有的程序依賴與別的程序的話,啟動順序就要注意了,比如A程序的啟動依賴於B程序的啟動,那么A程序的這個值一定要比B程序大。)
第三位(Z):系統終止時,服務終止順序。)