Linux就這個範兒 第10章 生死與共的兄弟

Linux就這個範兒 第10章 生死與共的兄弟html

 

就說Linux系統的開機。必須通過加載BIOS、讀取MBR、Boot Loader、加載內核、啓
動init進程並肯定運行等級、執行初始化腳本、啓動內核模塊、執行對應運行等級的初始化
腳本、個性化設置、進入登陸狀態這十個步驟。怎麼樣?服氣吧!若是以爲還不夠直觀,那
麼看一下圖10.1 Linux系統啓動流程吧。node

LVS的IPVS模塊也是採用動態加載的方式mysql


圖10.1 Linux系統啓動流程
那關機是否是會省點事兒呢?不是!Linux的關機會涉及4個命令和4個按鍵。其中的4個命令就是shutdown、halt、reboot和lnit,而且每一個命令所執行的步驟還不盡相同。至於4個按鍵應該不多有人不知道,其中三個就是Ctrl+Alt+Del組合鍵,另一個就是電源鍵。4個按鍵跟4個命令同樣,執行的步驟也不盡相同。可見Linux關機的這點破事兒是要多亂有多亂,還斬不斷。關機這事兒就跟死亡和交稅同樣,永遠都避免不了。
因此,做爲Linux,出來混這麼久了,在這「生」、「死」關頭,道兒上要是沒幾個好兄弟,早被人砍成七塊八塊的了。接下來要講的就是那些與Linux生死與共的兄弟們的事兒了。有的伴隨着「生」,有的伴隨着「死」,有的「生」、「死」相伴……順便提醒一下某位哲人曾經說過:「兄弟就是拿來利用的!」linux

 

 

10.1 死心眼兒的BIOS
記得好久之前的一本書上說:「至今的全部PC機都預裝了比爾·蓋茨編寫的BASIC程序。」做爲比爾粉絲的我確定是不會放過要在本身的運行着Win95的電腦中找找看滴,卻始終不得其鑰匙(如今想一想以爲那本書就不是給這個「世紀」的人寫的)。後來在另一本書上發現了一個名詞「Basic Input Output System」,簡稱是BIOS,便覺得這就是比爾的傑做。雖然讓我找到了,卻始終搞不清楚怎麼用它來寫程序。畢竟本身水平很凹,時間久了也就把這件事擱下了。直到高中畢業,時間忽然多得花不完,在萬般聊賴之時又翻到了「Basic Input Output System」這玩意。學過英語不少年的我瞬間被融化了:基本輸入輸出系統,跟BASIC沒有半毛錢關係啊。沒文化真可怕。
我想絕大多數人如今使用的電腦跟我當年用的在體系結構上也不會有什麼太大變化。別跟我說你用的是蘋果機,那玩意兒早就改intel體系了。若是不是,您仍是當古董珍藏起來比較合適。因此當你按下電源按鈕,就開始有奇蹟發生!會有什麼奇蹟呢?來看看。
此時此刻,無論你內存有多麼高端,裏面內容都是亂的。別說沒有Linux,連毛線都沒有。不過很快就發生變化了。有一個特殊電路,它會「敲打」一下CPU的被稱做reset的腳(別問我這隻腳在那裏,好幾百只呢,我也搞不定!知道有這麼回事兒就好了)。而後CPU就開始起變化了。一些寄存器,好比cs(從CPU外殼上是看不到滴)、eip憑空會出現一些固定的內容。cs足OxFFFF,eip是Ox0000。這就是告訴CPU從物理內存地址OxFFFFO處開始執行代碼。那裏有什麼代碼呢?就一條,讓CPU跳轉。告訴CPU:跳吧!跳吧!跳下去,你就會融化在BIOS裏!
BIOS是咱們電腦最開始執行的程序。它會讀取CMOS中的信息來了解硬件狀況,好比CPU的總線時鐘、啓動設備的搜索順序、硬盤大小與型號、系統時間、即插即用設備、各設備的I/O地址、中斷請求等。以後BIOS開始作開機自檢,好比肯定可用的內存(有時候還要測試一下)、肯定時鐘速度等。若是測試成功,會發出「畔」的一聲告訴你沒問題(有問題會狂叫)。接着開始對硬件進行初始化、設定即插即用設備、肯定啓動設備……最後從啓動設備中讀取MBR,並將控制權交給MBR中的程序。
BIOS這東西兒乎是全部PC的標配,歷史甚爲久遠,不過由此上溯至1842年仍是不必的,追溯到1984年是沒人站出來不一樣意的。怎麼看也算是個老革命了吧!但是它倒是個咧執的死心眼兒。甭管你是什麼操做系統,它歷來不買帳,必定要從MBR作入口。因此做爲操做系統,不跟MBR打好交道,就別期望能在電腦上過得好。這也致使了好多操做系統在這個地方爭得不可開交,甚至鬥得頭破血流。不過死心眼也有它的好處,就是BIOS會始終默默無聞地堅守着它那沒有繁花似錦卻硝煙瀰漫的崗位,心中默唱:我願鋪起,一條五彩的路。讓操做系統去迎接黎明迎接歡樂。心甘情願地作着雨花石。sql

 

10.2 小肚雞腸的MBR(主引導記錄)
MBR是Master Boot Record的縮寫。中國人……哦不……應該是咱們國家的人都叫它主引導記錄。這是一個老革命(BIOS)認準了的主兒,地位天然不容小覷。不過這但是一個小肚雞腸的主兒。shell


10.2.1 MBR的結構
好多人將Boot Sector(引導扇區)與MBR混淆在一塊兒說。express

嚴格上講應該是Boot Sector 引導扇區是由MBR、DPT(Disk Partition Table,磁盤分區表)和BRID(Boot Record ID,引導記錄標識)三部分組成的。ubuntu

 

Boot Sector在硬盤上也就512字節,還不是MBR獨佔。知道有多小肚雞腸了吧?
BIOS讀MBR是無論什麼DPT的,會將Boot Sector的所有內容讀到內存中。讀到什麼位置呢?反正無論有多少愛能夠胡來,BIOS是不會胡來的,老是會將它們讀到地址是Ox7c00的內存位置,而後跳轉到那裏,將控制權交給MBR。這也就決定了MBR -定是在Boot Sector最前面,不然BIOS就將控制權交給DPT了。c#

 

BIOS-》啓動設備-》boot sector引導扇區512字節(MBR446字節+DPT64字節+BRID2字節)-》grub-》內核centos

 

實際狀況是,DPT要佔用64個字節,Boot RecordID要佔用2個字節,因此留給MBR的只有446個字節。

 

從個頭上看是MBR>DPT>BRID的,實際上也是這麼排隊的。
這個Boot Sector就是硬盤(嚴格說是全部的可引導的存儲介質)上的第一個扇區。可見BIOS的最後那麼一抖,就是讀在CMOS中被設爲啓動設備的第一個扇區,並將控制權交給它。BIOS雖然死心眼,可也不傻。不是在「第一扇區」的它都認,必需要駿明正身才行。BIOS要檢查是否有BRID這東西,也就是Boot Sector的最後兩個字節。看它是否是「Ox55AA」這樣的內容。不是就玩死機,是就交權。至於交權後MBR都幹了什麼,BIOS還真挺放心的。

 

 

10.2.2磁盤分區表
到這取你呵能會問:剛纔說磁盤分區表DPT只有64個了:節,那個人一塊2T硬盤,分了10個區了,64個字節夠用嗎?夠用,絕對夠用。我還要告訴你,一個分區須要16個字節來描述
估計你如今會在想,我小學數學是語文老師教的吧。其實還真是。我上小學時,班主任負責教語文和數學。可是這不影響個人算數成績。由於硬盤分區表只能描述4個分區。至於你怎麼分了10個區,那是個技巧問題。固然那不是你的技巧。爲了說明這個問題,咱們先看一個表來描述一下DPT表項的結構,見表10-1 DPT表項的結構。

 

表10-1 DPT表項的結構

偏移量

長度(字節)

  定  義

Ox00

1

分區狀態:Ox00非活動分區;Ox80活動分區;

其餘數值沒啥意義      

Ox01  

1

分區起始磁頭號  

Ox02

2

分區起始扇區號,Ox02的0~5位

分區起始柱面號,Ox02的6~7位和Ox03的所有8位

Ox04

1

文件系統標識位,Ox83就是Linux分區

Ox05

1

分區結束磁頭號 擴展分區

Ox06

2

分區結束扇區號,Ox06的O~5位

分區結束柱面號,Ox06的6~7位和Ox07的所有8位

Ox08

4

分區起始相對扇區號

OxOC

4

分區總的扇區數


注意表10-1中的最後一行,分區的總扇區數是4個字節,32位。也就是說,最多能表示4294967295這麼大昀數。既然一個扇區是512字節,那麼一個分區的大小就被限制成4294967295x512=2T這麼大。能夠描述4個分區,頂天了就能支持8T大小的硬盤。再大就沒轍了嗎?有辦法,使用GPT,叫GUID分區表(GUID PARTITION TABLE)。這玩意單個分區支持18EB。牛啊,那得多少塊硬盤拼啊?我想,大部分人短時間內見不到,我也就少廢話了。反正Linux支持,遇到了本身問google吧。
咱們仍是回到10個分區怎麼分出來的問題上。注意DPT表項的Ox04偏移量的位置,文件系統標識位。表上說明Ox83是Linux分區。還有一個標識是Ox05,表上沒說,這裏說明一下。這表明擴展分區。擴展分區也有相似DPT的東西,來描述邏輯分區,並且沒有什麼大小限制,能夠分出任意多個邏輯分區。顯然分10個是不算什麼的。只是無論邏輯分區有多少,總和不能超過2T。
既然引出了擴展分區,又引出了邏輯分區,那麼在DPT中剩下的三個叫啥?答:主分區。其實擴展分區也是主分區的一種,只是由於能夠包含邏輯分區才這麼命名的。並且擴展分區不能直接用,必須至少包含一個邏輯分區。並且Linux才無論是主分區仍是什麼邏輯分區,都能容身。不過Linux對待主分區和邏輯分區仍是有差異的。全部sdal~sda4都分配給主分區,無論你有沒有分配;邏輯分區的分區號都是5開始的。因此在Linux上看一下分區所對應的設備文件名,就能知道是主分區仍是邏輯分區了。

 

 

 

10.2.3 MBR的功能
東拉西扯一直不着邊,就沒說到正題上。正題應該是MBR。這東西小肚雞腸的就446個字節的心胸,並且也不是什麼東西,就是一段空間。這麼小的空間就別期望能利用它做出什麼驚天地泣鬼神的事情了,固然病毒除外。正事兒就很簡單,以它爲跳板,找其餘體量大的兄弟交權了事兒。


10.3和事佬GRUB(牛B的統一引導加載器)
BIOS死心眼,MBR小肚雞腸。惹得操做系統們是打得你死我活、人仰馬翻!事情到了這份田地,結果就有人看不下去了。因而請出了和事佬,幾面調停,終於擺平了這場禍端。


10.3.1 Bootloader
當今公認的和事佬非GRUB莫屬。GRUB是Grand Unified Bootloader的簡稱,翻譯過來就是「牛B的統一引導加載器」。牛B是了不超的,由於牛B是要有真材實料的,沒料的就是裝13。幾乎全部的Linux發行版都使用它。並且還能驅使一直仰着高貴的頭的Solaris從10 1/06版開始也低下頭採用GRUB做爲它的引導加載器。在類UNIX這個世界裏,GRUB是絕對的老大,頗有領袖的範兒!天然是作和事佬的絕佳人選。
其實究竟是牛B仍是裝13都是不重要的,由於那些都是形容詞。重要的是名詞,即BootloadeI-引導加載器,這是個什麼玩意兒?Bootloader是在操做系統內核運行以前運行的一小段程序。它負責將操做系統內核裝入內存,而後將電腦控制權交給操做系統。它還會蒐集電腦的硬件信息、初始化硬件設備、安排內存佈局,從而將電腦的軟硬件環境整理得窗明几淨、層次分明,爲操做系統的內核佈置了一張溫暖的大牀。
其實這並非最重要的功能,由於這些BIOS都能幹。因爲死心眼的BIOS是始終堅決不移地去讀取MBR並跳轉。而小肚雞腸的MBR也沒什麼能耐。哪一個操做系統佔了,這臺電腦就是哪一個操做系統說了算。生活在萬惡的資本主義社會的電腦工程師們哪能容許這種獨裁統治?因此制訂了「多啓動規範」這部「憲法」,容許用戶自由選擇該由誰來管理他/她的電腦。不少Bootloader孰是這部「憲法」下的產物。
原本Linux也是擁有一顆獨裁的心的,內核中早就備有具有這個能耐的代碼的。本想與BIOS唱天仙配的,結果如今也只能隔GRUB遙相望了。何況某些內容一旦放入內核就很難改了(加入內核啓動參數)。畢竟人的需求老是千奇百怪的,很難保證適合全部人的胃口。並且這個世界上,先知是沒有的,問題老是要等到出現了纔去想辦法解決。因此,Linux內核自備的那些啓動加載代碼就先一邊兒涼快兒去吧。

 

 

10.3.2 GRUB的功能
在早期的Linux發行版上,廣泛採用的遵照多啓動規範的Bootloader是LILO。據官方稱LILO是Linux Loader的縮寫。可是我怎麼看都是「Logln LogOut」的縮寫。你這一進一出的,吃偉哥也堅持不了多久啊!結果沒幾年,就被GRUB幹掉了。
GRUB是個很牛B的Bootloader,主要表如今如下幾點:
1. GRUB是動態可配置的。它在啓動時讀取配置信息,且容許啓動時修改。
2. GRUB提供菜單供用戶選擇要啓動的操做系統。經過向配置文件中添加相關信息,
GRUB能夠控制150個甚至更多的菜單選項。在啓動時可經過鍵盤的方向鍵,甚至
鼠標進行選擇。
3.GRUB支持的操做系統很是普遍。它可以支持多種可執行格式。不但可以啓動支持
多啓動規範的操做系統,還能經過鏈式啓動功能支持諸如Windows和OS/2之類的
不支持多啓動規範的操做系統。不但支持全部Linux酌文件系統,還支持Windows
的FAT、NTFS,更支持LBA模式。甚至容許用戶查看它所支持的文件系統裏的文
件內容。
4. GRUB具備多種形式的用戶界面。多數Linux發行版利用GRUB的圖形界面,提
供帶有漂亮背景的啓動菜單。甚至還能支持鼠標操做。若是使用文本界面,還能利
用串口實現遠程終端啓動。
5. GRUB擁有豐富的控制檯命令與用戶交互。載入操做系統以前,在GRUB的交互
菜單界面下,按c鍵能夠進入控制檯。這個控制檯與Linux的控制檯很類似,提供相似shell的功能。經過命令,能夠查看硬盤分區的細節,甚至修改分區設置。不但能夠修改本身的配置信息,還能查看其所支持的文件系統中其餘Bootloader的配置信息。即使在GRUB的配置文件丟失的時候,依然能夠進入這個控制檯,手工啓動操做系統。
6. GRUB能夠從鏡像文件中啓動操做系統。GRUB能夠在它所支持的文件系統中找到
操做系統的鏡像文件(Linux內核映像),並啓動這個操做系統。甚至能夠經過網絡下載操做系統鏡像,
所以它能夠支持無盤工做站。
7. GRUB支持鏈式啓動。所謂鏈式啓動就是一個Bootloader能夠啓動另外一個Bootloader。經過這種方式就能夠肩動如DOS、Windows、OS/2等系統。GRUB4DOS
8. GRUB支持多種語言。這其中包括中文,所以能夠設計很是友好的啓動界面。
上面我只是羅列了一部分功能,顯然是已經很是了不得了。我對GRUB的開發者們的敬佩之情真可謂是有如滔滔江水,連綿不絕。我很是懷疑,這個世界上是否有哪位牛人就直接拿GRUB當操做系統使用了。

 

 

10.3.3 GRUB的工做流程
目前GRUB所使用的GRUB的全稱應該是GNU GRUB。也就是GNU組織山寨出來的。並且這個纔是真正牛B的GRUB,以前說的功能都是它的。真的GRUB已經不知道去哪裏涼快去了。可見山寨貨不都是次品。如今的GRUB已經更新到第二代了(版本1.98)。第一代也很流行,因此也不能放過。
第一代的GRUB使用三段式引導啓動stage1-》stage1.5-》stage2。
第一階段是佔MBR的坑,這是對付死心眼兒的BIOS的惟一方法。可是GRUB要發揮功能,在MBR的那點地盤上折騰不起來,只能叫個大的兄弟上。編譯好的GRUB對應這個階段會產生一個名爲stage1的文件,大小必定是512。(gnu grub軟件也要編譯)
因爲第一階段太挫了,因此第二階段只能放在緊接在MBR後面的固定位置,由於放別的地方會找不到。這裏有大概30K左右的代碼。主要是文件系統的驅動程序(/boot分區)目的就是爲了可以找到名爲stage2的文件。這個文件的內容是GRUB的主功能代碼。那既然MBR的代碼是stagel,主功能代碼是stage2,顯然沒有第二階段啊!還真是.官方歷來不叫第二階段,這只是個人理解。對應這一階段編譯出來的文件名是stagel_5,因此官方說這是1.5階段。設置這一階段是爲了stage2能夠亂放。但是30K左右的代碼並不能支持全部文件系統啊。因此這階段的代碼是不肯定的。stage2放在什麼文件系統上,這部分就是什麼文件系統的驅動
因爲stage2受文件系統管理,因此在空問上基本上就沒什麼障礙了。那就:駿馬,奔馳在遼闊的草原上吧!什麼功能都能提供了。這就是我說的第三階段,提供一切可以提供的功能。
第二代的GRUB是最近開始流行起來的。既然是二代了,確定是進步不小的最主要的是不用手工編寫配置複雜的配置文件了,可是讓玩Linux的不寫配置文件那是不現實的事情,因此只能是極大地簡化。簡化到只須要提供幾個參數,或者回答yes or no就好了
其實所謂的第二代GRUB,官方開始時是不認可的,只是說的人多了也就這樣了。廣泛意義上認爲的第二代是GRUB 1.98版之後的。不過這不影響人們對它的稱呼,說GRUB2沒人會以爲你2。
GRUB2改變了引導啓動流程,同時在架構上也有很是大的變化。
GRUB2使用四個階段。並且採用了比較霸道的方式,即必須提供IM酌空白空間,來放置它的核心代碼。這IM的空間放在哪兒無所謂,但必須放在2T之內,不然找不到。因此有大硬盤的朋友要萬分注意這個問題。
GRUB2的第一階段與GRUBI相同,也是佔MBR的坑。這階段的代碼更名了,叫boot.img。更貼切一些了。固然大小是亙古不變的512。它不去找什麼stagel_5了。而是去那1M的空間中找diskboot.img。
這個diskboot.img就是第二階段的代碼,大小也是512。是GRUB核心文件core.img的第一個扇區。這階段的代碼就是繼續將core.img文件餘下的部分讀到內存中,而後繼續執行。
第三階段比較有趣,開始加載內核模塊。注意這不是Linux的內核模塊,是GRUB的內核模塊。這樣設計的好處是core.img能夠作得很小,可配置性和擴展性很是高。
第四階段纔是啓動操做界面,供用戶選擇要啓動的操做系統。

grub2 :boot.img512字節-》diskboot.img1M-》core.img

grub2:第一階段(boot.img512字節)-》 第二階段(diskboot.img1M )-》  第三階段(core.img)-》第四階段啓動操做界面選擇要啓動的內核

grub1要三個階段

grub2要四個階段


說來講去,無論GRUB是一代仍是二代,都脫離不了MBR。其實這個不是絕對的。徹底不必跟死心眼兒的BIOS較勁。GRUB的第一階段代碼是能夠安裝到別的地方的。無論是主分區仍是邏輯分區,固然必須是第一個扇區,並且要求所安裝的分區是活動分區(df查看/boot分區所在分區有* 活動分區)。微軟其實是一個很大公無私的企業。當年在設計DOS的分區管理程序時,並無爲我獨尊的想法,即使到如今也仍是個好人!被DOS或Windows管理的MBR中並無與操做系統相關的引導程序。它只是掃描並讀取隨後的分區表,找到相應的活動分區,讀取相應活動分區的第一個扇區的程序並交權。因此徹底不用抱若MBR的大腿不放。並且將GRUB的第一階段代碼安裝到其餘地方,還能夠防止有人利用DOS的fdisk /mbr命令的破壞。何樂而不爲呢?

/boot/grub/device.map文件

cat /boot/grub/device.map
(hd0) /dev/hda

grub使用的設備名稱和Linux的不太同樣,這是一張映射表。

(hd0,2)對應/dev/hda3;(hd0,4)對應/dev/hda5

 

 

10.4脣齒相依的內核啓動參數
終於要說到內核了,可是還要注意一點,在這個世界上,每個運行着的Linux系統,均可以有一顆不同凡響的內核。那是由於,每個運行着的Linux系統,均可以有不一樣的內核啓動參數組合。


10.4.1 什麼是內核啓動參數
學習代數的中學生們開始知道方程式是有參數的:電腦用久了的「小白領」們也會知道不少軟件是有參數的;軟件工程師們確定知道不少函數是有參數的。這個世界怎麼這麼多參數?人們在這個世界極度缺乏「先知」這種珍惜資源的狀況下,只能用試錯這種方法來解決遇到的問題。長此以往就發明了參數這個東西。因此參數是能夠亂變的,錯了就變,直到對了爲止。既然Linux的開發者們跟咱們是一個世界裏的人,身在五行中就跳不出三界外,也沒法保證Linux內核能夠解決全部問題。因此讓Linux內核支持啓動參數,是最英明神武的決策
所謂內核啓動參數,就必定是在Linux內核啓動的時候傳給它的參數。不然就是內核運行時參數①了。其主要目的是,當內核沒法識別某些硬件導敢不能設置硬件參數時,或者不但願內核更改某些參數值時,抑或但願內核表現某些特性時,讓Linux內核具有人工干預的途徑。這也是必須選擇GRUB等Bootloader去啓動Linux的具備絕對殺傷力的理由。由於直接讓BIOS加載Linux內核將沒法傳遞任何啓動參數。

 

 ①Linux 是具有內核運行時參數的,咱們後面會講到。

 

10.4.2 內核啓動參數的格式
Linux的內核啓動參數是以空格分開的一個字符串列表,通常的格式以下:
name[=value_l][,value_2]…[,value一10]
「name」就是具體的參數名,內核根據這個名稱來決定應該把參數值交給誰來處理。若是某個參數名找不到主兒,內核也不會輕易地把它丟掉,而是會傳遞給後面咱們要講解的init進程來處理。每一個參數名所對應的值的數量是有限制的,最多10個,最少能夠沒有。但若你必定要跟這個數量上的限制較勁也不怕,能夠重複使用同一個參數名來傳遞任意多個值①。
內核的參數名是大小寫敏感的,好比mem和Mem是不一樣的參數。並且命名也是有規則可尋的。首先,參數只能由26個英文字母的大小寫加上「.」和「」這些符號組成。其次,若是在參數名中出現「.」則代表這是傳遞給某一個內核可加載模塊的,若是對應的模塊沒有加載,其實是不起做用的。這個時候參數名的格式以下:
module_name. parameter_name
例如:acpi.debug_level=l這個啓動參數是給acpi②模塊傳遞debug_level參數,其值是1。

①好比:abc=0,1,2,3.4.5.6,7,8.9 abc=10,11,12.13.14.15,16.17,18,19。
②高級配置和電源管理接口( Advanced Configuration and Power Interface)。

 

內核配置文件  深度實踐KVM P49

/boot/config-2.6.32-504.el6.x86_64
CONFIG_CRC7=m
CONFIG_LIBCRC32C=m
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=m
CONFIG_LZO_COMPRESS=m
CONFIG_LZO_DECOMPRESS=m
CONFIG_DECOMPRESS_GZIP=y
CONFIG_DECOMPRESS_BZIP2=y
CONFIG_DECOMPRESS_LZMA=y
CONFIG_GENERIC_ALLOCATOR=y
CONFIG_REED_SOLOMON=m
CONFIG_REED_SOLOMON_DEC16=y
CONFIG_TEXTSEARCH=y
CONFIG_TEXTSEARCH_KMP=m
CONFIG_TEXTSEARCH_BM=m
CONFIG_TEXTSEARCH_FSM=m
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
CONFIG_HAS_DMA=y
CONFIG_CHECK_SIGNATURE=y
CONFIG_CPUMASK_OFFSTACK=y
CONFIG_CPU_RMAP=y
CONFIG_NLATTR=y
CONFIG_AVERAGE=y

 

10.4.3經常使用的內核啓動參數
最多見的內核啓動參數有以下這麼幾個:
●init=……:設置init進程的位置。若是沒有明確給出這個參數,內核會按照
/etc/init、/bin/init、/sbin/init、/bin/sh這個順序來搜索,若是沒找到,Linux就會宕機。
root---…:該參數告訴內核啓動時使用哪一個磁盤分區做爲根文件系統。好比能夠
指定根文件系統爲/dev/sda5:root=/dev/hda8。這個參數必須指定,不然Linux將沒法正常工做,甚至由於找不到init進程而宕機。
● ro和rw:該參數告訴內核啓動時如何掛接根文件系統。ro參數告訴內核以只讀方
式掛接根文件系統,這樣能夠有效防止根文件系統被破壞。另外,若是在啓動時需
要對根文件系統進行fsck,則必須以只讀方式掛接。rw正好與ro相反,:容許讀寫
根文件系統的內容。若是不指定這個參數,則默認是ro。
● mem=……:限制或設定內核使用的內存數量。我就曾經遇到早期Linux版本沒法
正確識別我p4電腦內存大小的狀況,致使沒法啓動。使用mem參數指定正確內存
大小後問題解決。
●initrd=……:指定內核初始化用ramdisk的位置。這個功能很是有用,後面咱們

● rhgb:這個參數只能在RetHat系的Linux發行版中看到。表示啓動RedHat Graphics
Boot功能,就是讓啓動界面好看點。用圖片或動畫代替啓動過程當中顯示的文本信息。

● enforcing=……:啓動了SElinux致使進不了系統,這時候能夠設置enforcing=0關閉SElinux來進入系統
● quiet: quiet參數是讓內核採用靜默方式肩動,即儘可能少輸出啓動信息。
● nosmp和maxcpus=N:這兩個參數只有在擁有多顆CPU的時候才起做用。nosmp
參數用來禁止開啓支持多個CPU的功能。maxcpus則是限制最多支持的CPU個數。
如今人們都恨不得使用smp技術來提升運算速度,提供這種參數的人是否是蛋疼
呢?不要忘了存在就是道理這個重要的哲學觀點。當Linux運行在虛擬機上的時候
常常會出現計時不許確的狀況,這兩個參數就能解決這個問題。
因爲Linux的內核啓動參數太多,舉不勝舉,有這麼多也差很少夠了。爲啥提了10個卻寫了8條呢?中國人喜歡8這個數字嘛,我也喜歡!何況十全十美的東西是不存在的。
不知道你們注意沒有,我所列舉的這些內核啓動參數都是必須是在內核啓動以前就應該指定的,不然就會沒法啓動,或者得不到預想的效果。這不正好說明它們是內核啓動參數而不是內核運行時參數了嗎?正所詔脣齒相依,Linux內核是齒,則內核啓動參數就是脣。若是內核啓動參數設定不當,內核也很難正常工做。脣亡且有齒不寒之理?
至於這些參數放在什麼地方、內核怎麼處理、如何處理、什麼時候處理等問題已經超出本書的範圍,有興趣的能夠看看內核代碼(我相信,若是你能徹底掌握並融會貫通本書所涉及的內容,是有能力讀懂絕大部份內核代碼的)。內核源代碼中附帶的Documentation/kemel-
parameters.txt文件詳細介紹了官方內核所提供的大部份內核啓動參數。

 

 

10.5 自力更生的Linux內核  內核解壓-》startup_32  -》start—kemel-》kernel init
BIOS把路已經鋪穩了,GRUB藉着MBR的地兒也把牀給烘暖能夠就枕了,內核啓動參數全都弄準了。到了這個時候,Linux內核你再不自力更生的確有點對不起追你的粉了。接下來就是內核初始化的過程,看看它是怎麼自立更生的吧。


10.5.1 內核引導協議
在這個時候Linux內核給Bootloader們兩個選擇。

第一是回到實模式①,讓內核本身從新來過;

第二是Bootloader在保護模式②下直接交權給內核,內核繼續接下來的工做。GRUB選擇了後者。

無論Bootloader們做出了何種選擇,都必須將內核須要的數據按照特定格式準備好,並且還專門制定了一個規範。這就是Linux的引導協議(Boot Protocol),有興趣的可

以查閱內核源代碼中附帶的Documentation/x86/boot.txt文件。

①x86系列CPU的默認工做模式,16位字長,20位尋址,最高支持1MB內存。
②x86系列CPU的經常使用工做模式,32位字長,32位尋址,支持多任務,最高支持4GB內存。

包含模式:Linux就這個範兒P545 七種武器 ,實現虛擬內存技術主要有兩種方案:段式內存和頁式內存管理。這兩種方案的目的只有一個,就是讓多任務操做系統可以將

多個進程的地址空間保護起來,讓它們互相隔離,使得它們不會互相打架。保護模式的叫法也來源於此。

 

 

10.5.2 內核爲何要壓縮
無論怎樣,內核想繼續工做,都必須對本身進行解壓縮。至於爲何要對內核進行壓縮,這是一個由來已久的問題。因爲最先的Linux是在x86平臺上開發完成的,而這個平臺的一個最大毛病就是開機時處於實模式下工做,最多隻能訪問1M內存,並且還有一大部分被BIOS佔去了,因此就有了年長一點的人都瞭解的DOS 640 K①的問題。早期的Linux比較小巧,就幾十K的樣子,因此也不是個問題。並且那個時候大多數人都認爲640K足夠用了,也沒人心這個問題。到後來Linux的功能愈來愈豐富,內核大小很快就超過了這個限制。可是再回頭解決這個問題就有些來不及了。那怎麼辦呢?壓縮吧!這個時候就有個zlmage這個內核文件格式,最大能夠支持512K的壓縮內核鏡像。同時又引入了可加載模塊技術,內核鏡像可控制的很小,人們覺得這下能夠高枕無憂了。但好事不長。Linux爲了與Windows等主流操做系統爭奪市場,不得不繼續豐富自身的功能。很快人們就發現即使利用可加載模塊技術也很難將zlmage格式的內核鏡像文件控制在512K以內,就又發明了bzlmage這個格式。其實這才足高枕無憂的開始bzlmage格式的內核鏡像要求Bootloader將它讀到1MB以上的內存空間。而這個時候就要求Bootloader必須進入保護模式才能完成這個操做。所以也就有了前面所說的Bootloader們的兩種選擇。這個時候內核開發者們可沒有大意,一直保持了內核鏡像是壓縮的。並且因爲Linux的普遍應用,不少嵌入式設備也開始採用Linux做爲操做系統,壓縮過的內核鏡像能夠給這些嵌入式系統節省不少存儲成本。因此,對Linux內核鏡像進行壓縮就被看成一個優良的傳統給保留下來了。固然不是全部硬件體系的內核鏡像都是壓縮的,好比PowerPC②上就不用壓縮。由於將Linux系統移植過去的時候人家原本就不存在640K這個問題,何況也不多有嵌入式系統應用這種架構的CPU。

 

①DOS留給用戶的最多隻有640K的用戶空間,要想使用更多的內存,須要不少特別的技術。好比頁而映射。將大於1MB的內存空間的一小塊映射到640K之內。用完了再從新映射。
⑦由1BM設計的精簡指令集架構的CPU,Mac電腦曾經使用過。當前咱們最容易見到的是在各類遊戲機上的應用。好比XBOX360、PS3和WII。

 

 

10.5.3 startup_32  它表明Linux的第一個進程——process 0的開始
內核自解壓完畢以後將跳轉到startup_32這個函數繼續執行。這個函數是徹底用匯編語言寫的。內核源碼中叫startup_32的函數有兩個。第一個是在內核解壓縮以前,調用內核白解壓縮代碼用的。這裏要說的是第二個,是內核解壓縮後的。比較有趣的是,這兩個同名的函數都是用匯編寫的,並且都在名爲head。S的文件中定義。固然也是兩個不一樣的文件,相同的只是名稱和語言。不用擔憂會由衝突,致使內核亂執行。畢竟一個是壓縮前的,一個是壓縮後的。何況名稱都是給人看的,電腦看的是地址。
這個startup_32對於整個Linux系統來講意義是非同小可的,它表明Linux的第一個進程——process 0的開始。這裏,決定了Linux的內存佈局;這裏,Linux瞭解了本身將要與什麼樣的CPU在一塊兒;這裏,會把由BIOS提供和Bootloader們整理的資料放入內存的第一個分頁裏;這裏,爲之後要發生的中斷請求作好準備①;這裏,若是是64位系統,將把長模式②開啓;這裏,將跳往Linux內核的主函數-start kernel,開啓Linux內核真正的生命之旅。

 

10.5.4 start kernel  Linux內核的入口main函數:start—kemel
每個C語言寫的程序,都有入口函數叫main。Linux內核也有這樣的函數,叫start—kemel。它就靜靜地躺在內核源代碼的init/main.c這個文件中。其實這個函數跟你們想像的不太同樣,它跟具體的硬件關係不大。大部分時間都是在爲Linux內核準備必要的數據結構。好比:用於內存管理的那些數據結構,用於任務調度的那些數據結構,用於處理多任務同步的數據結構,用於處理中斷的數據結構,用於文件系統管理的數據結構等。反正通過對這些數據結構的初始化,Linux此時已經具有一個操做系統應該具有的功能,各類子模塊均可以良好運行。在這以後,start—kemel會建立一個名爲kernel init的內核線程,而後進入本身的最終歸宿-cpu_idle函數,進入無休止的循壞當中
這個cpu_idle函數就是咱們常見的CPU佔用率常常是99%的進程。進程的pid是0。只要你看到它對CPU的佔用率還在80%以上,就說明你的系統還很閒。雖然這只是一個死循環,並且優先級很低,可是功能不可小覷。它會一直調用CPU的idle指令,讓CPU降溫③且省電。


①x86系列CPU的中斷描述符表在這裏初始化,目前所有置0。
②最新的x86_64系列CPU的一種新的運行模式,相對於32位的保護模式,長模式是64位的,兼容32位程序。可是內存的尋址方式,AMD和Intel兩家有不一樣看法。
③不少所謂給CPU降溫的工具,其實就是強制執行idle指令。
④因爲Linux的內核是一個總體,在它內部產生的多任務分支都叫內核線程。內核線程在被映射到用戶空間時,不少都是咱們一般所認識的進程。

kthreadd進程的pid是2,ppid是0,kthreadd是全部內核線程的祖先

ps axjf|grep kthreadd

USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
0        2        0       0 ?     -1 S       0                    0:00 [kthreadd]

 

10.5.5 kernel init
若是你查看的是較老的內核源代碼,或許找不到kemel init線程所對應的函數。不要緊,這是由於較新的內核才這麼叫。老的內核都叫init內核線程。不過在我看來新的稱呼更加貼切。由於kemel—init內核線程其實是Linux系統最爲重要的init進程的內核部分。新的稱呼更能體現它是在內核中這個特性。這個是Linux系統的第二個進程④,這也是init進程的pid -定是1的由來。並且在最新的內核代碼中,因爲必須在建立kemel init以前建立另一個內核線程來作一些重要的事情,則不得不先建立kernel init,並把它鎖起來。而後再建立新的內核線程,而後kemel_ init等到它執行完後解鎖繼續執行。若是不這麼作,init進程的pid就會是2。那樣的話,接下來全部的程序均可能會變的很2了。
Kemel_init內核進程比較重要的工做就是讓Linux內核開始與外面進行溝通。好比:尋找用戶指定的根文件系統(initramfs來作,先有根文件系統纔有後續的加載硬件驅動程序)、給硬件加載驅動程序、初始化網絡堆棧、在多CPU的系統中讓其餘CPU開始工做等。當一切都穩妥以後,kemel init會調用用戶空間的第一個進程-init程序。這個時候,內核的初始化工做就完成了,Linux系統向用戶空間開啓了大門。

 

10.6 及時雨initramfs
歷經千辛萬苦的自力更生以後,Linux系統終於要與廣大粉絲們見面了。等等!恰恰就在這個時候Linux也開始犯BIOS死心眼兒的毛病了。跟粉絲見面就必定要經init進程的介紹!若是內核找不到init進程腫麼辦捏?粉絲們,拜拜……


10.6.1 尋找init的問題
粉絲們通常會把init進程放在根文件系統中。若是Linux找不到根文件系統就沒戲了。一般,可用的文件系統都會羅列在/etc/fstab文件中,因此mount命令能夠找到它們。可是/etc/fstab既然是文件,就必須呆在文件系統中。這樣,Linux找根文件系統的過程就成了雞生蛋蛋生雞的問題。爲了解決它,內核的開發者們提供了「root=」這個內核啓動參數,來指定哪一個設備做爲Linux的根文件系統。不過,這要是穿越到十幾年前仍是個不錯的主意,也就是軟盤或硬盤的差異。到現在可謂是技術百花齊放的年代。什麼SCSI啊、SATA啊、RAID啊,五花八門舉不勝舉。並且位置都開始不固定了。好比U盤,一個電腦上好多USB扎,插哪兒了只有誰用誰知道,有的還帶加密的。這你讓Linux內核情何以堪啊?有人就建議,讓內核帶上所有驅動就好了。雖然是個餿主意,但總比沒有強。但是這年頭不但技術多,山寨的也多不是。某些山寨爲了表示本身不山寨,還會採用特別的技術手段,好比改改某些參數什麼的,並美其名日自主創新。這麼折騰,Linux內核傷不起啊!好在及時雨initramfs的來到,給Linux和它的粉絲們撐起了一片廣闊的天空,讓山寨們折騰去吧!

10.6.2 較早的initrd
initramfs也算是個新人,不過也只能算是個相對的了。以前它有一個同行的老大哥,叫initrd。我在介紹內核啓動參數的時候就提過一句。如今咱們就來詳細瞭解一下。
initramfs和initrd乾的工做是同樣的,只是機制不一樣罷了。initrd實際上就是在內存中開闢了一塊模擬的磁盤空間。在Linux內核啓動以後,先將這個模擬的磁盤看成根文件系統,並執行initrd當中的/linuxrc文件。linuxrc文件就是一個腳本程序,負責加載那些內核要訪問的真正的根文件系統所必須的驅動和掛接真正的根文件系統。initrd對於Linux發行版和LiveCD是非帶有好處的。好比做爲發行版就要儘量多的適應硬件環境。可是作一個超大內核顯然是會被人噴的。這個時候就能夠請initrd來幫忙。在系統安裝階段,檢測用戶的硬件特性並找到用於做爲根文件系統的設備的驅動,並將這些放入initrd中。若是在安裝過程當中發現沒有附帶合適的驅動時,還能請求用戶拿出設備驅動程序盤來安裝。這樣就基本不怕找不到init進程了。若是用戶拿不出合適的驅動,還能夠人性化地告訴用戶:您的電腦不適合安裝Linux。「科技以人爲本」是亙古不能違反的真理!


10.6.3爲何選擇initramfs
前面說過initramfs和initrd乾的是同樣的活,那要它來做甚?緣由就在於機制的不一樣。initrd是一個ramdisk,ramdisk必須是某種文件系統,好比ext2。若是Linux要訪問initrd,就必須帶有相應的文件系統驅動。initramfs是一個使用gzip壓縮的cpio打包文件。Linux內核會將它的內容裝入一個tmpfs,這就不須要附帶任何文件系統驅動就能工做。並且ramdisk大小必須固定,tmpfs卻能夠動態擴展。固然,這些都是一些小的技術差異。比較大的差異就是如何對待init進程這個問題。如今的Linux開發者們有了一個十分大膽的設想,就是儘早進入用戶空間( Early Userspace),盡最大努力把全部能在用戶空間完成的工做都不用內核去作。使用inirrd就必須在內核空間完成磁盤的掛接工做,這顯然是能夠在用戶空間完成的。因而在繼LVM、Udev等以後,開始動起了initrd的主意。因而就有了initramfs這玩意兒
initramfs再也不須要linuxrc這個文件了,取而代之的是直接啓動init進程。initramfs由Bootloader準備好,告訴內核它在什麼位置。內核知道了以後在kernel—init內核線程中也不掛接什麼根文件系統,直接啓動initramfs中的init進程。接下來去找根文件系統的活兒就都交給init進程。這下永遠都不怕找不到init進程了。因此initramfs是個真正的及時雨,畢竟它比initrd要先走好幾步呢!
或許不少人會問,那如今根分區中的init程序是幹嗎的?這是個備份,若是沒有initramfs,內核就會本身去掛接分區去找它。何況用戶還須要使用init程序給init進程發送消息來切換運行級別呢!如今Linux依然提供「root=」和「initrd=」這兩個內核啓動參數。由於initrd並無徹底地退出歷史舞臺。

 

10.7 「生」、「死」永相伴的init進程
當Linux內核啓動init進程以後,便「陷入」了人民羣衆的汪洋大海,開始了其真正的生命之旅。不過這個旅程並不孤單,永遠有init進程與它相伴,一同去經歷那六道輪迴之苦。


10.7.1 名存實亡
若是非要給Linux系統的初始化設定一個期限的語,我想是從開機到屏幕出現登陸界面爲止。既然Linux認準了init,並且從名字上一眼就能看出它就是用於初始化的,並且它也的確這麼作了。init進程會根據用戶設定的一個叫運行級別的指標來對Linux系統進行一系列的初始化過程。好比:啓動對應運行級別的服務進程、配置網絡、繼續爲某些硬件加載驅動、運行相關軟件等。不過你要是認爲init進程就幹這些事情那就大錯特錯了。
init進程會接受用戶的「CtrI+Alt+Del」三鍵大法,責令Linux系統從新啓動;即使Linux系統已經運行於某個級別之上,用戶還能夠經過init切換到刖的運行級;當用戶要關掉Linux系統,init進程會默默地將尚未來得及保存的文件保存好;若有用戶但願某個程序須要一直運行respawn,能夠告訴init進程,那就誰都kill不掉這個進程例如mingetty;init進程還會認養全部孤兒進程,若是某個程序要判斷父進程是否死掉了,能夠經過確認當前的父進程是不是init進程來判斷。等等。因此init進程是名存實亡的,它不僅僅是作初始化,幾乎就是Linux系統的守護神。按照Linux的命名規範,我我的認爲叫systemd是最合適不過的了
要說systemd,還真有這麼一個玩意兒,跟init進程作的事兒還差很少。並且在Linux這個無比自由的世界中,init並非某個特定程序的名稱。它只是表明一個過程。只要一個程序,甚至是一組程序,可以完成這一過程,在Linux的眼裏,它們都是init。並且還有「init=」這個內核啓動參數,誰還會在乎完成這個過程的程序叫什麼名字呢?因此在不一樣的發行版中就有可能使用不一樣的程序來完成這個過程。好比:最古老的Slackware使用的是sysvinit;Ubuntu,RHEL和Fedora使用的是Upstart;而最新的Ubuntu和Fedora又開始使用systemd了。自由的世界是一個混亂的世界,但這混亂中卻充滿了競爭。init這個名字掩蓋了那背後各類實現策略的博弈,也讓咱們有所從有所不從。至於誰能在這混亂的競爭中勝出,或永久消亡,只能讓歷史去作個見證。而Linux要執行init過程的這個機制就像真理同樣,歷來沒有改變過。

淺析 Linux 初始化 init 系統,第 1 部分: sysvinit 第 2 部分: UpStart 第 3 部分: Systemd
http://www.cnblogs.com/MYSQLZOUQI/p/5250336.html

 

10.7.2運行級別
運行級別(run level)這個稱呼聽起來確實很唬人,給人極其神祕又科技味兒十足的感受。說白了就是mit用數字作的命令選項,並且mit自己也沒定義這些數字的含義是什麼。就像阿扁①在監獄內只是1020號罷了,誰在意他是否是前「總統」呢?
運行級別這個概念源自System V②。這東西幾乎是當前全部Unix和類Unix系統的祖宗了,當初給它設計的系統啓動機制也被Linux所延續下來。因此對init的正確稱呼就應該是System V init或SysV init。由於是在系統初始化時的行爲,不一樣的運行級別會致使系統以不一樣的方式被初始化。這樣的結果就致使了系統啓動後對於用戶會有不一樣的外在表現行爲。這種設計不但被Linux這祥的類Unix系統所延續,Windows也借鑑了不少,好比常常會跑出來的「安全模式」。
運行級別大多數狀況都是用數字來表示,從0~9共有10個。有些時候也用「S」來代
表某個運行級別。雖然是用數字來描述,但同一時刻一個Linux系統只能處於一個運行級別,
千萬不要認爲這是按順序逐一執行的。

 

①陳水扁,前臺灣地區最高領導人,於2010年11月ll日因貪腐案入獄。
②System V是衆多UNIX操做系統版本中的一支,最初由AT&T開發,在1983年第一次發佈。一共發行了4個主要版本一、二、三、4。System V Release 4,或者RVR4,是最成功的版本,成爲一些UNIX共同特性的源頭。

 


Linux系統一共定義了7個運行級別,分別是:

0 - halt,關閉系統,不能做爲默認運行級別
1 - single user mode,單用戶模式,相似安全模式,用於故障維護
2 - Multiuser, without NFS,與3相似,可是沒有聯網能力
3 - Full multiuser mode,全功能的多用戶模式
4 - unused,保留,沒有使用
5 – Xll,帶有圖形用戶界面的全功能多用戶模式
6 - reboot,從新啓動,不能做爲默認運行級別,不然會有靈異事件
注意,這個定義只是建議性的,不是全部Linux發行版都會遵守這個約定。0、l和6這三個運行級別在任何UNIX和類UNIX系統中都是同樣的,Linux固然不能例外。其餘運行級別會有差異,好比:Slackware的運行級別5是保留的,而4跟建議的5是相同的。絕大多數發行版中運行級別3的定義都是按照這個建議執行的,至少我沒有見過其餘狀況
System V的init是經過讀取/etc/inittab這個文件來確認默認執行什麼運行級別的。大多數Linux發行版所採用的init也是這麼作的,可是systemd放棄了這個策略。使用systemd的發行版,就不會有這個文件。即便有,也只是起到了一今提示做用。
不一樣的運行級別會有不一樣的啓動腳本程序和配置文件。在System V中,這些與運行級別相關的啓動腳本和配置文件也是由inittab來指定的。好比咱們打開使用sysvinit的Linux發行版的inittab文件,會看到相似這樣的內容:

id : 5 : initdefault :

si : : sysinit : /etc/rc . d/rc . Sysinit

10:0:wait:/etc/rc.d/rc 0
11:1:wait:/etc/rc.d/rc 1
12:2:wait:/etc/rc.d/rc 2
13:3:wait:/etc/rc.d/rc 3
14:4:wait:/etc/rc.d/rc 4
15:5:wait:/etc/rc.d/rc 5
16:6:wait:/etc/rc.d/rc 6
ca : : ctrlaltdel : /sbin/shutdown -t3 -r now
pf : :powerfail:/sbin/shutdown -f -h +2 " Power Failure;System Shutting Down"
pr : 12345 :powerokwait:/sbin/shutdovm -c" Power Restored; Shutdown Cancelled"
1 : 2345 : respawn : /sbin/mingetty ttyl
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
x:5: respawn: /etc/Xll/prefdm -nodaemon

 

看起來挺變態的,其實格式是很嚴整的。任何一行都是按照:

id:runlevels:action選項:process 命令

這樣一個固定的格式編寫的。不過只給出格式仍是讓人很暈的,因此我解釋一下:
● id是一個任意指定的四個字符之內的序列標號。在這個文件內必須是惟一的,因此
就當它是個索引好了。
● runlevels表示這一行適用於哪些或是哪一個運行級別。若是忽略它,就代表適用於任
何運行級別。
● action表示在進入對應runlevels所指定的運行級別時,iit如何執行process字段的
命令的方式。具體的設定參考表10-2所示。
● process就是具體應該執行的程序了。這也代表在退出相應運行級別時要終止運行
的程序。

表10-2常見的action值

action值

說  明

respawn

表示irut監視的進程,即便其結束也應詼被從新啓動

wait

init應該運行這個進程一次,並等待它結束才繼續

once

init僅運行這個進程一次    

boot

隨系統啓動運行,全部runlevels值對它沒用

bootwait

隨系統啓動運行,而且init黴它結束。行有runlevels無效

off

沒有任何意義

initdefault

系統啓動後的默認運行級別。出於進入相應的運行級別會激活對應級別的進程,因此對其指定process字段沒有任何意義。若是inittab文件內不存在這一條記錄,系統啓動時會在控制檯詢問要進入的運行級別

sysinit

系統啓動時準備運行的命令

powerwait

容許init在電源被切斷時關閉系統。不過你得有UPS~和監視UPS並能通知init電源已被切斷的軟件  

 

                

① 不間斷電源。當斷電後,UPS會利用本身的電池電腦共電。可以提供多久的供電能力取決於電池容量。我在購買第一臺電腦時就配備了UPS,所以在尚未養成隨時保存文件的好習慣的時候,UPS挽救了我好多重要的工做內容。玩遊戲時也很給力

(續)

action值

說  明

powerfail

同powerfail,但init不會等待正在運行的程序結束  

powerokwait

當電源監視軟件報告「供電恢復」時,init要執行的操做

powerfailnow

監測到UPS電源即將耗盡時,init要執行的操做

ctrlaltdel

規定init在用戶執行「CrtI+Alt+Del」三鍵人法時要執行的操做

 

當你看到這裏的時候,我強烈建議你再回頭看看我所給出的inittab文件的例子。注意init是不必定按照順序來解析inittab文件的。優先級是:sysinit最高、boot和bootwait次之、其餘的最低,有些仍是事件觸發的。
可是目前使用最多的Upstart甚本上不多碰inittab文件。它使用了一套傘新的配置腳本①來實現與inittab文件差很少的功能。這些配置腳本在/etc/init/目錄下能夠找到。當你翻閱這些配置腳本的時候,會發現與單獨的inittab沒什麼特別本質的區別。只能說採用配置腳本將inittab模塊化了。至於systemd,實在太過於激進了,就留大家本身去研究它吧。

 

10.7.3進入運行級別以前
無論謾定了何種運行級別,在init進程剛剛被肩動的時候,Linux系統仍是不健全的,光禿禿的只有內核。爲了讓Linux系統可以被人使用,也爲了Linux可以恰當地運行於某一運行級別之上,必需要進行一系列的初始化操做才行。這個初始化的過程一般會由一個腳本程序來完成。但並無規定具體的文件名是什麼。在我給出的inittab文件的例子中是/etc/rc.d/rc.sysinit腳本。這個腳本也是在Linux衆多的發行版中最爲常見的
rc.syslmt這樣的腳本都幹了些什麼呢?很難徹底說清楚,不一樣發行版處理的方式有一些差異。因此我總結了一些共性羅列給你們。大致上都是要幹這麼兒件事的:
1. 確認主機名,主要是搞清楚本身是誰這個哲學問題
2. 掛接/proc和/sys等重要的特種文件系統
3. 設置控制檯界面的默認字體
4. 輸出版權信息,炫耀一下本身的出身
5. 啓動udev,這時候才真正具有硬件管理的能力/sbin/start_udev
6. 初始化硬件,加載驅動,設置時鐘
7. 設置鍵盤佈局
8. 設置主機名,「我是誰」這個問題永遠很重要
9. 設置ACPI
10.檢測磁盤,執行fsck
11.掛接/etc/fstab中設置的其餘文件系統,不包含/proc和NFS
12.初始化僞隨機數生成器  /dev/urandom  系統剛啓動噪音較少
13.清理/tmp和/var目錄
14.啓動交換空間  swap -a -e
15.初始化串口
16.將全部執行的操做寫入/var/log/dmesg文件
實際上rc.syslnlt這樣的腳本所執行的操做遠不止這些,有不少發行版本身設計的特性操做。若是想看看本身的系統在這個過程當中都執行了那些操做,more -下/var/log/dmesg文件就行了。
經過列舉的這些項目能夠很明顯地看出,執行完這個腳本以後,Linux才長出頭、五官、四肢和手腳,成爲一個可以被人使用的操做系統,爲接下來執行運行級別相關的腳本打下基礎。

 

10.7.4進入運行級別
若是將進入運行級別以前所做的初始化認爲是系統的通用初始化階段,則進入運行級別
時還要進行鍼對運行級別的個性初始化。
個性初始化的目的就是爲了啓動不一樣的軟件集,從而讓不一樣運行級別可以有不一樣的外在
表現。從inittab文件的例子中能夠發現/etc/rc.d/rc這個腳本是作這個事情的。不一樣的運行級別會有不一樣的數字參數傳遞給它,這樣能夠保證它在不一樣的運行級別上能夠有不一樣的行爲表現。
既然是個性化,就應該容許用戶可配置。可是若是用戶想本身針對某個運行級別進行個性化配置的時候,就必須修改rc這個腳本才行。顯然門檻有點高,通用性也不好。那麼這個時候就須要有一種方法,既能夠配置,又沒有高門檻,還能很通用就是一個好方法。SystemV就提供了這樣一個好方法。Linux的設計者們也就懶得去想了,直接將它的方法繼承下來。
這個方法是將個性初始化腳本在功能上進行了細粒度的劃分,基本上一個程序對應一個初始化腳本,甚至一個程序會對應幾個初始化腳本。將這些初始化腳本統一放到/etc/init.d或/etc/rc.d/init.d目錄下。而後準備一些形如/etc/rc[N].d或/etc/rc.d/rc[N].d的目錄,其中[N]與運行級別對應。在這些目錄下創建到init.d目錄下某些啓動腳本的符號鏈接。創建了對哪些腳本的鏈接,就代表在進行個性初始化的時候要執行哪些鏈接。這樣運行級別所須要啓動的軟件集也就被啓動了這些腳本誰去調用呢?交給rc這個腳本好了。讓它根據給定的參數執行不一樣目錄的全部腳本就好了。並且參數是數字的,正好能夠和[N]對應,rc腳本能夠很簡單。
這樣作的好處孰是:
● 若是用戶想在某個級別中啓動一個本來沒有配置的軟件,如今只須要創建一個鏈接
就好,門檻下降了不少。
● 若是某個程序想在某些運行級別下被自動啓動,將本身的啓動腳本放入init.d目錄
下,而後在相應的rc[n].d目錄下創建符號鏈接便可。甚至這個啓動腳本均可以不
用放在init.d目錄下,通用性問題獲得很好的解決。
不一樣的運行級可能要啓動某些共同的程序,這樣用符號鏈接時就沒必要將啓動腳本拷
來拷去了。不但有很好的複用性,還節省磁盤空間。
● rc腳本能夠作得很是精巧簡單,簡單就表明穩定嘛!
爲了可以更好地說明這種方法,我拿一個實際的例子來講。在我所使用的發行版中,
/etc/rc/rc3.d目錄下有這些內容:

K01certmonger K75ntpdate Sllportreserve S25netfs
K01smartd K75quota_nld S12 rsyslog S26acpid
K020ddj obd K80sssd S13cpuspeed S26haldaemon
K10psacct K86cgred S13irqbalance S26udev-post
K10saslauthd K87restorecond S13 rpcbind S28autofs
K15httpd K89rdisc S14nfslock S55sshd
K20tomcat6 K95cgconfig S15mdmonitor S80postfix
K36mysqld S01sysstat S18rpcidmapd S82abrtd
K50netconsole S02lvm2-monitor S19rpcgssd S90crond
K60nfs S08ip6tables S20kdump S95atd
K69rpcsvcgssd S08iptables S22messagebus S99libvirt-guests
K73ypbind S10network S24avahi-daemon S99local
K74ntpd S11auditd S25cups


你會發現這些都是符號鏈接,大多數都是鏈接到/etc/rc/init.d目錄下某個文件的。
不過這裏全部符號鏈接的名稱有點怪異,都是K??*或S??*這樣的。其實這只是利用名稱耍的花招。首先要明白的一個簡單道理就是:開機啓動的程序,關機的時候得關閉。固然,這個不是絕對的。由於有些程序啓動以後很快就本身退出了,關機的時候不用理它。還有些開機時不用啓動,可是關機的時候須要啓動某些程序來收拾一下爛攤子。那麼S就表明start(啓動),K就表明kill(殺死或中止)。因此經過名稱就能看出來哪些是開機的時候執行,哪些是關機的時候會執行。
那麼後面的數字是幹什麼的呢?序號!就是程序啓動或關閉須要一個茼後順序。由於程序之間有時候會有一些「莫名其妙」的依賴關係,因此排好隊很重要。爲了能允許某些後來的程序能夠加塞,序號都是跳着來的。
細心的人在查看本身系統的時候,會發現K和S開頭的符號鏈接實際上鍊接的是同一個腳本程序。可是前面說過rc腳本只是執行它們,怎麼處理啓動和關閉呢?原來rc腳本會根據K或S來判斷給這些啓動腳本傳遞什麼樣的參數。若是以S開頭,就傳遞start;若是以K開頭就傳遞stop。守護進程不就是這樣啓動和中止的嗎?
在不少發行版中,在rc2.d、rc3.d、rc4.d和rc5.d這四個目錄中會發現S99local這樣一個符號鏈接。都會鏈接到一個rc.local文件上。這個文件並不在init.d目錄下,通常會是/etc/rc.local或/etc/rc.d/rc.local。這個是專門爲用戶準備的一個設定開機自動啓動程序的地方。

按照慣例,凡是能放入init.d目錄的都應該是守護進程。因此對於非守護進程且還須要開機自動啓動的程序,這裏是一個很是好的設定地點。
大多數狀況下rc.local是最後一個被執行的腳本。當它執行完畢後,系統就完成了所有
初始化任務,開始爲用戶提供服務了。

rc.local裏面的執行順序在6和7都是同樣的,自己就是個腳本,確定從上往下執行。
centos6和centos7惟一區別是6是串行的最後一個,而7是並行的,若是rc.local裏啓動的某個程序依賴了一些服務,那麼可能致使這個程序起不來
解決辦法有3個:
(1) 在rc.local最開始增長sleep多等待一會;
(2)手動修改rc-local.service,配置依賴關係;
(3)不要用rc.local

 

 

10.7.5轉換運行級別
在一個運行中的Linux系統的運行級別並非保持不變的,由於具備最高控制權的root
用戶是能夠隨時切換運行級別的。固然,若是遇到一個不負責任的root,常常來切換運行級
別那將會是一件很可怕的事情。由於切換運行級別會致使當前正在運行的好多程序被關閉
其實Linux系統的關機和從新啓動就是靠切換運行級別實現的。運行級別O和6就是爲
此而設置的。目前所提供的那些關機和重啓命令都是基於這種運行級別假設的。這也是經歷
了這麼多年,一直沒有人打這兩個運行級別主意的主要緣由。
做爲root用戶,切換運行級別很簡單。執行init命令附帶一個運行級別參數便可。例如:

# inti 3


切換到運行級別3。固然,init命令是很簡單粗暴的,會當即執行切換操做。不少時候
這種行爲會形成沒法挽回的結果。因此Linux還提供了另一個命令telinit(tell you init 告訴你進行運行級別切換),它帶有一個一t參數能夠指定多少秒以後去切換運行級別。例如:

#telinit -t 120 3


這條命令要求2分鐘以後切換到運行級別3。顯然給人以時間上的準備。在一個大型多
人使用的系統中,若是不少人不爲管理員發出的切換運行級別警告所動,依然自覺得是地作
着本身的工做。管理員徹底能夠利用telinit命令設定好在一段時間以後切換,而後就告訴那些正在使用系統的人:我已經作完了,留給你的時間就那麼點兒,你本身看着辦吧!顯然這時候系統管理員再也不會受到人情世故所惱了。
深刻理解System V init和其引入的運行級別機制,就能夠從容不迫地應對那些系統在啓動和關閉時候所要解決的一切煩人的事情了。init進程不愧爲可以與Linux生死與共的真朋摯友。

 

10.8幕後英雄們
當系統初始化完畢以後,Linux系統就能夠給人使用了。可是讓人如何使用倒是一個仁
者見仁的問題了。Linux系統提供不少種方法,好比:提供一個相似DOS的文本界面讓用戶
經過各類命令來使用:或者提供一個圖形界面,讓用戶只須要經過鼠標就能完成大部分工做;
甚至還可讓多個用戶經過telnet或ssh鏈接進來,你們一塊兒使用。這些使用方法都是與Linux同生共死的init來提供的嗎?不是!提供這麼多種使用方法的是一羣幕後的英雄們。


10.8.1 終端
在開始介紹這些幕後英雄以前,須要先講清楚一個概念,那就是——終端。
話說在電腦的遠古時期,UNIX出現了。這是一個多用戶、多任務的分時操做系統。當
時可以運行UNIX的電腦都很貴,人們在使用的時候都是使用一個廉價的設備鏈接到這臺電
腦上共享使用的。UNIX會讓使用者覺得這個廉價設備就是那臺昂貴的電腦。這個廉價設備
被稱爲終端。
Linux是一種類UNIX系統,它很天然地繼承了UNIX經過終端來使用的特質。可是Linux
誕生的年代,電腦已經很便宜了。便宜到比當年的終端還便宜。顯然Linux再要求人們用終
端去使用它就有點不知好歹了。可是沒有終端義不像UNIX。怎麼辦呢?僞裝吧!僞裝鍵盤
就是終端的輸入,僞裝顯示器就是終端的輸出。但是對別人說你什麼都是假的,顯然你再有
能力也沒人信了。因此出於信譽第一的考慮,假終端被美其名日虛擬終端。自從Linux有了
虛擬終端,原來須要從終端獲取的輸入,鍵盤就搞定了;原來須要終端展示的輸出,顯示器
就搞定了。早期的UNIX程序全都能移植過來了。並且Linux爲了充分展示這個假的一點不
比真的差,甚至比真還的好,一下僞裝了不少個。因此你孰發現能夠經過CtrI+Alt+F[1 -6]組合鍵切換控制檯。切換控制檯就是在切換虛擬終端。
在Linux上,鍵盤的輸入和屏幕的輸出都是經過虛擬終端來完成的。一個虛擬終端被看
做是一個設備。在/dev目錄下能夠查看到這些設備所映射到的文件。全部以tty[0-9]*方式命名的文件就表明着虛擬終端。好比你在文本界面控制檯直接登陸系統,那麼你當前使用的虛擬終端對應的設備應該是/dev/tty1。使用CtrI+Alt+F[1-6]組合鍵所切換的虛擬終端會分別與功能鍵對應,好比F2就對應着/dev/tty2。可是有兩個比較特殊的虛擬終端設備,就是/det/tty和/dev/tty0。tty表明當前你正在使用的終端。tty0表明當前被激活的全部虛擬終端。好多時候這個很難區分,由於你使用的就是當前被激活的。固然要試驗它們的差異仍是有的,我後面會說。還有一個特殊的虛擬終端是/dev/console。這個表明的是「UNIX時代」本機的顯示器和鍵盤。在「Linux時代」實際上不少時候表明的是/dev/tty1。在Linux上,全部tty設備都被稱爲進程控制終端,console被稱爲系統控制終端。進程和系統的差剮就是:全部程序輸出的內容,都會輸出到進程控制終端;全部內核輸出的內容,都會輸出到系統控制終端。
當前絕大多數Linux發行版默認會提供6個虛擬終端供用戶使用。固然,虛擬終端的數
量是沒有限制的。若是你足夠狠,能夠弄出幾百個來,前提是你的鍵盤能支持

物理終端 /dev/console

虛擬終端 /dev/tty -》login程序

模擬終端 /dev/pts -》sshd程序

 

 

10.8.2 getty系列命令
根據Linux須要虛擬終端來處理絕大多數程序的輸入輸出這一事實,init在完成系統的
初始化以後,就必然要開啓虛擬終端。那就讓咱們作一個小穿越,回到「10.7.2運行級別」
一節中給出的那個inittab文件的例子。其中就有關這方面的設定。那些全部process字段都帶有「/sbin/mingetty」命令的條目就是幹這個的。
mingetty命令是getty命令的一個變種。getty命令的變種還有好多,最多見的有agetty、
mingetty、fbgetty、fgetty和rungetty。有這些變種的出現就是由於getty命令自己很是複雜,並且伸縮能力有限。若是直接使用getty,Linux系統要提供圖形用戶界面就有可能遇到麻煩,好比程序無端退出、X Server死鎖等問題。這些變種都很好地解決了這些問題。同時也簡化了使用上的複雜度。就好比mingetty命令,只須要給定參數是ttyl就可以啓動ttyl表明的虛擬終端。
getty系列命令不僅是開啓虛擬終端。它要乾的一個比較重要的事情是調用login程序。
login程序比較簡單,就是問你要用戶名和密碼。你輸入正確的用戶名和密碼後,就能夠開
始使用Linux了。
從inittab文件的例子中能夠看到,mingetty命令被respawn所修飾。這代表init會堅守着它不會被kill掉。因此無論你採用何種方式,都沒法越過輸入用戶名和密碼的這道關卡。也正由於這個緣由,纔將getty系列命令交給init直接調用,而不是讓rc腳本(還記得前面講過嗎?)去處理它。
細心的人會發現,當登入Linux系統後,使用「top」或「ps -ax」,甚至「ptree」命令都是找不到與所使用虛擬終端對應的mingetty的蹤跡的。這是爲何?原來getty系列命令在啓動login程序時,是與login融爲一體被login取代了,即便用相同的進程號①。那麼init並不會認爲getty已經退出了。而使用「ps」等命令查看進程時,看到的大可能是程序自己的名字。因此可以看到login,卻看不到getty。當kill掉login後,就會被init發現,從新將getty啓動,讓你輸入用戶名和密碼。雖然咱們看不到getty,可是這一切都是getty在起做用,也許這就是幕後英雄的悲劇吧。

使用exec系統調用就有這個效果

 

10.8.3 Display Manager
Linux的另外一個幕後英雄是Display Manager。翻譯過來就是顯示管理器,能夠簡稱DM。
用途就是提供圖形界面的登陸窗口。當前有好多種DM。好比:GNOME的GDM、KDE的KDM、獨立的LightDM等。每種DM都有本身的特性,天然也就會獲得不一樣人羣的喜愛。因此大多數Linux發行版會提供多種DM供用戶選擇。也正由於如此,仵inittab申每每是指
定一個腳原本調用DM們。
圖形界面也要使用虛擬終端的。不過它通常不與文本界面爭虛擬終端的資源。大多數Linux發行版將tty7分配給圖形界面。這樣也就使得即便開啓了圖形界面登陸,也能夠經過
CtrI+Alt+F[1-6]來切換到文本界面,保持總體風格的一致。要切換回圖形界面就按CtrI+Alt+F7便可。不過也有例外,就是有一些發行版將圖形界面分配給ttyl。這些發行版的考慮是認爲用戶開啓圖形界面,就應該是一直使用,那麼就應該將默認的虛擬終端提供給用戶。
圖形界面使用哪個虛擬終端,由DM說了算。只是大多數DM不像getty那些變種那
麼簡單。規定它使用哪一個虛擬終端通常須要用配置文件來指定。因爲DM的種類繁多,我就
不列舉了。想了解的話能夠去問google。
DM與getty相同的地方就是都被init給respawn了。這樣誰都殺不死它,因此也就不能跳過輸入用戶名和密碼的關卡。並且在登陸以後,DM也與getty -樣,消失了。

 

文本界面 6個tty

圖形界面 6個tty+1個圖形tty

 

10.8.4僞終端
在經過網絡鏈接,使用telnet或ssh多人共享一個Linux系統時,就再也不使用虛擬終端
了。可是因爲傳統程序們都是要使用虛擬終端的,因此就只能「假上加假」了。既然不能告
訴人們虛擬終端是假的,天然不能提假上加假這事兒。但人類的智慧是無窮的,語言更是豐
富多彩的。因此就發明了僞終端這個名詞。
無論是否是假上加假,它好歹也是個設備。因此在/dev/曰錄下也是有名號的。不過這假
的就是假的,名號很是混亂。並且不少時候會不經意地發現多出來幾個,一眨眼又少了幾個。
連蹤跡都難肯定。不過要識別它仍是有辦法的,就是它們的名稱都是以「pty」開頭的。更
有熱心的Linux發行版,將它們統一放到/dev/pts曰錄下,只要在這裏的就必定都是僞終端。
Linux系統對僞終端的控制是比較隨意的,init也不去管它們。那怎麼保障安全,讓每
個經過網絡登陸的用戶都必須輸入用戶名和密碼呢?這個是交給普通程序來處理的。好比使
用ssh來登陸,那麼相應的ssh服務器程序-sshd要負責向系統申請僞終端資源,並要求用戶輸入用戶名和密碼。因此若是sshd不安全,使用sshd的Linux系統也就不安全。幸虧sshd的表現還不錯。它的哥哥telnet就沒有這麼幸運,因爲安全性的問題基本上快要退出歷史舞臺了。
無論怎麼樣,僞終端都算是一個幕後英雄。由於人們不多關心它。可是它卻解決了人們
經過網絡共享使用Linux的問題。即使是假上加假,也一樣可以贏得人們對它的喝彩。

 

ps aux|grep pts

sshd :root@pts/0    #pts目錄下文件名爲0的文件

 

10.8.5配置文件
對於Linux這種高度可配置的操做系統來講,在任什麼時候候配置文件都是功不可沒的。尤
其是那些涉及系統初始化的配置文件們,決定了系統將來的命運走向,地位更不容忽視。比
較遺憾的是:各大發行版都在執行着各自的設計策略,我沒法提取出具有共性的東西。這個
地方只能留給大家本身去研究。
不管如何,這些配置文件們都是幕後英雄。甚至連名字都沒法讓人們去牢記。可是每一
介Linux的使用者都會由於它們的存在而受益不淺。可以掌握某個經常使用發行版的配置文件,
才能真正馴服這個系統,讓它對你再無祕密可言。


10.9結束語
咱們如今再來回顧一下Linux系統從開機到關機這個過程當中所出現的那些角色。死心眼
的BIOS、小肚雞腸的MBR、和事佬GRUB、脣齒相依的內核啓動參數、自力更生的Linux內核、及時雨initramfs、生死永相伴的init,以及那些不爲人知的幕後英雄們。這些都是與Linux生死與共的兄弟。那兄弟究竟是來幹什麼的?答:兄弟是拿來利用的

 

 

 

centos5使用sysvinit
centos6使用ubuntu的UpStart
centos7使用systemd

 

 

在 RedHat 公司的 RHEL5 中(RHEL6 已經使用 upstart 了),rc.sysinit 主要完成如下這些工做。設置定義在/etc/sysctl.conf 中的內核參數
# Apply sysctl settings, including files in /etc/sysctl.d
apply_sysctl() {
sysctl -e -p /etc/sysctl.conf >/dev/null 2>&1
for file in /etc/sysctl.d/* ; do
is_ignored_file "$file" && continue
test -f "$file" && sysctl -e -p "$file" >/dev/null 2>&1
done
}

 


cat /boot/grub/grub.conf
# grub.conf generated by anaconda
#
# Note that you do not have to rerun grub after making changes to this file
# NOTICE: You have a /boot partition. This means that
# all kernel and initrd paths are relative to /boot/, eg.
# root (hd0,0)
# kernel /vmlinuz-version ro root=/dev/mapper/VolGroup-lv_root
# initrd /initrd-[generic-]version.img
#boot=/dev/sda
default=0
timeout=5
splashimage=(hd0,0)/grub/splash.xpm.gz
hiddenmenu
title CentOS (2.6.32-504.8.1.el6.x86_64)
root (hd0,0)
kernel /vmlinuz-2.6.32-504.8.1.el6.x86_64 ro root=/dev/mapper/VolGroup-lv_root rd_NO_LUKS LANG=en_US.UTF-8 rd_NO_MD rd_LVM_LV=VolGroup/lv_swap SYSFONT=latarcyrheb-sun16 crashkernel=auto rd_LVM_LV=VolGroup/lv_root KEYBOARDTYPE=pc KEYTABLE=us rd_NO_DM
initrd /initramfs-2.6.32-504.8.1.el6.x86_64.img
title CentOS (2.6.32-358.el6.x86_64)
root (hd0,0)
kernel /vmlinuz-2.6.32-358.el6.x86_64 ro root=/dev/mapper/VolGroup-lv_root rd_NO_LUKS LANG=en_US.UTF-8 rd_NO_MD rd_LVM_LV=VolGroup/lv_swap SYSFONT=latarcyrheb-sun16 crashkernel=auto rd_LVM_LV=VolGroup/lv_root KEYBOARDTYPE=pc KEYTABLE=us rd_NO_DM rhgb quiet
initrd /initramfs-2.6.32-358.el6.x86_64.img


# pwd
/boot
# ll
總用量 48200
-rw-r--r--. 1 root root 104081 2月 22 2013 config-2.6.32-358.el6.x86_64
-rw-r--r-- 1 root root 106312 1月 29 2015 config-2.6.32-504.8.1.el6.x86_64
drwxr-xr-x. 3 root root 1024 1月 26 2015 efi
drwxr-xr-x. 2 root root 1024 12月 4 03:06 grub
-rw-r--r--. 1 root root 16218612 1月 26 2015 initramfs-2.6.32-358.el6.x86_64.img
-rw------- 1 root root 19364509 3月 10 2015 initramfs-2.6.32-504.8.1.el6.x86_64.img
drwx------. 2 root root 12288 1月 26 2015 lost+found
-rw-r--r--. 1 root root 185734 2月 22 2013 symvers-2.6.32-358.el6.x86_64.gz
-rw-r--r-- 1 root root 200245 1月 29 2015 symvers-2.6.32-504.8.1.el6.x86_64.gz
-rw-r--r--. 1 root root 2407466 2月 22 2013 System.map-2.6.32-358.el6.x86_64
-rw-r--r-- 1 root root 2544888 1月 29 2015 System.map-2.6.32-504.8.1.el6.x86_64
-rwxr-xr-x. 1 root root 4043888 2月 22 2013 vmlinuz-2.6.32-358.el6.x86_64
-rwxr-xr-x 1 root root 4153008 1月 29 2015 vmlinuz-2.6.32-504.8.1.el6.x86_64

 

http://mp.weixin.qq.com/s?__biz=MjM5NTU2MTQwNA==&mid=401882005&idx=2&sn=ef58771798e24992a355441e311489b4&scene=0#wechat_redirect

除此以外,還須要一個Linux啓動內核的映像文件。在 RedHat linux 6.0光盤的 images/目錄下有這個文件——vmlinuz。  

/boot/vmlinuz-2.6.32-504.el6.x86_64

 


cat /etc/inittab

http://www.ibm.com/developerworks/cn/linux/1407_liuming_init2/

爲何/etc/inittab文件的內容這麼少,書上的/etc/inittab文件的內容都沒有,是由於書上是按照centos5來講的,centos6使用ubuntu的UpStart,而UpStart沒有運行級別的概念,他只是模擬運行級別,因此/etc/inittab文件只保留了一句話

id:3:initdefault:

 


# inittab is only used by upstart for the default runlevel.
#
# ADDING OTHER CONFIGURATION HERE WILL HAVE NO EFFECT ON YOUR SYSTEM.
#
# System initialization is started by /etc/init/rcS.conf
#
# Individual runlevels are started by /etc/init/rc.conf
#
# Ctrl-Alt-Delete is handled by /etc/init/control-alt-delete.conf
#
# Terminal gettys are handled by /etc/init/tty.conf and /etc/init/serial.conf,
# with configuration in /etc/sysconfig/init.
#
# For information on how to write upstart event handlers, or how
# upstart works, see init(5), init(8), and initctl(8).
#
# Default runlevel. The runlevels used 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)
#
id:3:initdefault:


cat rc.sysinit
#!/bin/bash
#
# /etc/rc.d/rc.sysinit - run once at boot time
#
# Taken in part from Miquel van Smoorenburg's bcheckrc.
#

HOSTNAME=$(/bin/hostname)

set -m

if [ -f /etc/sysconfig/network ]; then
. /etc/sysconfig/network
fi
if [ -z "$HOSTNAME" -o "$HOSTNAME" = "(none)" ]; then
HOSTNAME=localhost
fi

if [ ! -e /proc/mounts ]; then
mount -n -t proc /proc /proc
mount -n -t sysfs /sys /sys >/dev/null 2>&1
fi
if [ ! -d /proc/bus/usb ]; then
modprobe usbcore >/dev/null 2>&1 && mount -n -t usbfs /proc/bus/usb /proc/bus/usb
else
mount -n -t usbfs /proc/bus/usb /proc/bus/usb
fi

#remount /dev/shm to set attributes from fstab #669700
mount -n -o remount /dev/shm >/dev/null 2>&1
#remount /proc to set attributes from fstab #984003
mount -n -o remount /proc >/dev/null 2>&1

. /etc/init.d/functions

PLYMOUTH=
[ -x /bin/plymouth ] && PLYMOUTH=yes

# Check SELinux status
SELINUX_STATE=
if [ -e "/selinux/enforce" ] && [ "$(cat /proc/self/attr/current)" != "kernel" ]; then
if [ -r "/selinux/enforce" ] ; then
SELINUX_STATE=$(cat "/selinux/enforce")
else
# assume enforcing if you can't read it
SELINUX_STATE=1
fi
fi

if [ -n "$SELINUX_STATE" -a -x /sbin/restorecon ] && __fgrep " /dev " /proc/mounts >/dev/null 2>&1 ; then
/sbin/restorecon -R -F /dev 2>/dev/null
fi

disable_selinux() {
echo $"*** Warning -- SELinux is active"
echo $"*** Disabling security enforcement for system recovery."
echo $"*** Run 'setenforce 1' to reenable."
echo "0" > "/selinux/enforce"
}

relabel_selinux() {
# if /sbin/init is not labeled correctly this process is running in the
# wrong context, so a reboot will be required after relabel
AUTORELABEL=
. /etc/selinux/config
echo "0" > /selinux/enforce
[ -n "$PLYMOUTH" ] && plymouth --hide-splash

if [ "$AUTORELABEL" = "0" ]; then
echo
echo $"*** Warning -- SELinux ${SELINUXTYPE} policy relabel is required. "
echo $"*** /etc/selinux/config indicates you want to manually fix labeling"
echo $"*** problems. Dropping you to a shell; the system will reboot"
echo $"*** when you leave the shell."
start rcS-emergency

else
echo
echo $"*** Warning -- SELinux ${SELINUXTYPE} policy relabel is required."
echo $"*** Relabeling could take a very long time, depending on file"
echo $"*** system size and speed of hard drives."

/sbin/fixfiles -F restore > /dev/null 2>&1
fi
rm -f /.autorelabel
echo $"Unmounting file systems"
umount -a
mount -n -o remount,ro /
echo $"Automatic reboot in progress."
reboot -f
}

# Print a text banner.
echo -en $"\t\tWelcome to "
read -r system_release < /etc/system-release
if [[ "$system_release" == *"Red Hat"* ]]; then
[ "$BOOTUP" = "color" ] && echo -en "\\033[0;31m"
echo -en "Red Hat"
[ "$BOOTUP" = "color" ] && echo -en "\\033[0;39m"
PRODUCT=$(sed "s/Red Hat \(.*\) release.*/\1/" /etc/system-release)
echo " $PRODUCT"
elif [[ "$system_release" == *Fedora* ]]; then
[ "$BOOTUP" = "color" ] && echo -en "\\033[0;34m"
echo -en "Fedora"
[ "$BOOTUP" = "color" ] && echo -en "\\033[0;39m"
PRODUCT=$(sed "s/Fedora \(.*\) \?release.*/\1/" /etc/system-release)
echo " $PRODUCT"
elif [[ "$system_release" =~ "CentOS" ]]; then
[ "$BOOTUP" = "color" ] && echo -en "\\033[0;36m"
echo -en "CentOS"
[ "$BOOTUP" = "color" ] && echo -en "\\033[0;39m"
PRODUCT=$(sed "s/CentOS \(.*\) \?release.*/\1/" /etc/system-release)
echo " $PRODUCT"
else
PRODUCT=$(sed "s/ release.*//g" /etc/system-release)
echo "$PRODUCT"
fi

# Only read this once.
cmdline=$(cat /proc/cmdline)

# Initialize hardware
if [ -f /proc/sys/kernel/modprobe ]; then
if ! strstr "$cmdline" nomodules && [ -f /proc/modules ] ; then
sysctl -w kernel.modprobe="/sbin/modprobe" >/dev/null 2>&1
else
# We used to set this to NULL, but that causes 'failed to exec' messages"
sysctl -w kernel.modprobe="/bin/true" >/dev/null 2>&1
fi
fi

touch /dev/.in_sysinit >/dev/null 2>&1

# Set default affinity
if [ -x /bin/taskset ]; then
if strstr "$cmdline" default_affinity= ; then
for arg in $cmdline ; do
if [ "${arg##default_affinity=}" != "${arg}" ]; then
/bin/taskset -p ${arg##default_affinity=} 1
fi
done
fi
fi

nashpid=$(pidof nash 2>/dev/null)
[ -n "$nashpid" ] && kill $nashpid >/dev/null 2>&1
unset nashpid

apply_sysctl

/sbin/start_udev

# Load other user-defined modules
for file in /etc/sysconfig/modules/*.modules ; do
[ -x $file ] && $file
done

# Load modules (for backward compatibility with VARs)
if [ -f /etc/rc.modules ]; then
/etc/rc.modules
fi

mount -n /dev/pts >/dev/null 2>&1
[ -n "$SELINUX_STATE" ] && restorecon -F /dev/pts >/dev/null 2>&1

# Configure kernel parameters
update_boot_stage RCkernelparam
apply_sysctl

# Set the hostname.
update_boot_stage RChostname
action $"Setting hostname ${HOSTNAME}: " hostname ${HOSTNAME}
[ -n "${NISDOMAIN}" ] && domainname ${NISDOMAIN}

# Sync waiting for storage.
{ rmmod scsi_wait_scan ; modprobe scsi_wait_scan ; rmmod scsi_wait_scan ; } >/dev/null 2>&1

# Device mapper & related initialization
if ! __fgrep "device-mapper" /proc/devices >/dev/null 2>&1 ; then
modprobe dm-mod >/dev/null 2>&1
fi

if [ -f /etc/crypttab ]; then
init_crypto 0
fi

if ! strstr "$cmdline" nompath && [ -f /etc/multipath.conf -a \
-x /sbin/multipath ]; then
modprobe dm-multipath > /dev/null 2>&1
/sbin/multipath -v 0
if [ -x /sbin/kpartx ]; then
/sbin/dmsetup ls --target multipath --exec "/sbin/kpartx -a -p p" >/dev/null
fi
fi

if ! strstr "$cmdline" nodmraid && [ -x /sbin/dmraid ]; then
modprobe dm-mirror >/dev/null 2>&1
dmraidsets=$(LC_ALL=C /sbin/dmraid -s -c -i)
if [ "$?" = "0" ]; then
for dmname in $dmraidsets; do
if [[ "$dmname" == isw_* ]] && \
! strstr "$cmdline" noiswmd; then
continue
fi
/sbin/dmraid -ay -i --rm_partitions -p "$dmname" >/dev/null 2>&1
/sbin/kpartx -a -p p "/dev/mapper/$dmname"
done
fi
fi

# Start any MD RAID arrays that haven't been started yet
[ -r /proc/mdstat -a -r /dev/md/md-device-map ] && /sbin/mdadm -IRs

if [ -x /sbin/lvm ]; then
if [ ! -f /.nolvm ] && ! strstr "$cmdline" nolvm ; then
action $"Setting up Logical Volume Management:" /sbin/lvm vgchange -a ay --sysinit --ignoreskippedcluster
else
echo $"Logical Volume Management disabled at boot."
fi
fi

if [ -f /etc/crypttab ]; then
init_crypto 0
fi

if [ -f /fastboot ] || strstr "$cmdline" fastboot ; then
fastboot=yes
fi

if [ -f /fsckoptions ]; then
fsckoptions=$(cat /fsckoptions)
fi

if [ -f /forcefsck ] || strstr "$cmdline" forcefsck ; then
fsckoptions="-f $fsckoptions"
elif [ -f /.autofsck ]; then
[ -f /etc/sysconfig/autofsck ] && . /etc/sysconfig/autofsck
if [ "$AUTOFSCK_DEF_CHECK" = "yes" ]; then
AUTOFSCK_OPT="$AUTOFSCK_OPT -f"
fi
if [ -n "$AUTOFSCK_SINGLEUSER" ]; then
[ -n "$PLYMOUTH" ] && plymouth --hide-splash
echo
echo $"*** Warning -- the system did not shut down cleanly. "
echo $"*** Dropping you to a shell; the system will continue"
echo $"*** when you leave the shell."
[ -n "$SELINUX_STATE" ] && echo "0" > /selinux/enforce
start rcS-emergency
[ -n "$SELINUX_STATE" ] && echo "1" > /selinux/enforce
[ -n "$PLYMOUTH" ] && plymouth --show-splash
fi
fsckoptions="$AUTOFSCK_OPT $fsckoptions"
fi

if [ "$BOOTUP" = "color" ]; then
fsckoptions="-C $fsckoptions"
else
fsckoptions="-V $fsckoptions"
fi

READONLY=
if [ -f /etc/sysconfig/readonly-root ]; then
. /etc/sysconfig/readonly-root
fi
if strstr "$cmdline" readonlyroot ; then
READONLY=yes
[ -z "$RW_MOUNT" ] && RW_MOUNT=/var/lib/stateless/writable
[ -z "$STATE_MOUNT" ] && STATE_MOUNT=/var/lib/stateless/state
fi
if strstr "$cmdline" noreadonlyroot ; then
READONLY=no
fi

if [ "$READONLY" = "yes" -o "$TEMPORARY_STATE" = "yes" ]; then

mount_empty() {
if [ -e "$1" ]; then
echo "$1" | cpio -p -vd "$RW_MOUNT" &>/dev/null
mount -n --bind "$RW_MOUNT$1" "$1"
fi
}

mount_dirs() {
if [ -e "$1" ]; then
mkdir -p "$RW_MOUNT$1"
find "$1" -type d -print0 | cpio -p -0vd "$RW_MOUNT" &>/dev/null
mount -n --bind "$RW_MOUNT$1" "$1"
fi
}

mount_files() {
if [ -e "$1" ]; then
cp -a --parents "$1" "$RW_MOUNT"
mount -n --bind "$RW_MOUNT$1" "$1"
fi
}

# Common mount options for scratch space regardless of
# type of backing store
mountopts=

# Scan partitions for local scratch storage
rw_mount_dev=$(blkid -t LABEL="$RW_LABEL" -l -o device)

# First try to mount scratch storage from /etc/fstab, then any
# partition with the proper label. If either succeeds, be sure
# to wipe the scratch storage clean. If both fail, then mount
# scratch storage via tmpfs.
if mount $mountopts "$RW_MOUNT" > /dev/null 2>&1 ; then
rm -rf "$RW_MOUNT" > /dev/null 2>&1
elif [ x$rw_mount_dev != x ] && mount $rw_mount_dev $mountopts "$RW_MOUNT" > /dev/null 2>&1; then
rm -rf "$RW_MOUNT" > /dev/null 2>&1
else
mount -n -t tmpfs $RW_OPTIONS $mountopts none "$RW_MOUNT"
fi

for file in /etc/rwtab /etc/rwtab.d/* /dev/.initramfs/rwtab ; do
is_ignored_file "$file" && continue
[ -f $file ] && cat $file | while read type path ; do
case "$type" in
empty)
mount_empty $path
;;
files)
mount_files $path
;;
dirs)
mount_dirs $path
;;
*)
;;
esac
[ -n "$SELINUX_STATE" -a -e "$path" ] && restorecon -R "$path"
done
done

# Use any state passed by initramfs
[ -d /dev/.initramfs/state ] && cp -a /dev/.initramfs/state/* $RW_MOUNT

# In theory there should be no more than one network interface active
# this early in the boot process -- the one we're booting from.
# Use the network address to set the hostname of the client. This
# must be done even if we have local storage.
ipaddr=
if [ "$HOSTNAME" = "localhost" -o "$HOSTNAME" = "localhost.localdomain" ]; then
ipaddr=$(ip addr show to 0.0.0.0/0 scope global | awk '/[[:space:]]inet / { print gensub("/.*","","g",$2) }')
for ip in $ipaddr ; do
HOSTNAME=
eval $(ipcalc -h $ip 2>/dev/null)
[ -n "$HOSTNAME" ] && { hostname ${HOSTNAME} ; break; }
done
fi

# Clients with read-only root filesystems may be provided with a
# place where they can place minimal amounts of persistent
# state. SSH keys or puppet certificates for example.
#
# Ideally we'll use puppet to manage the state directory and to
# create the bind mounts. However, until that's all ready this
# is sufficient to build a working system.

# First try to mount persistent data from /etc/fstab, then any
# partition with the proper label, then fallback to NFS
state_mount_dev=$(blkid -t LABEL="$STATE_LABEL" -l -o device)
if mount $mountopts $STATE_OPTIONS "$STATE_MOUNT" > /dev/null 2>&1 ; then
/bin/true
elif [ x$state_mount_dev != x ] && mount $state_mount_dev $mountopts "$STATE_MOUNT" > /dev/null 2>&1; then
/bin/true
elif [ ! -z "$CLIENTSTATE" ]; then
# No local storage was found. Make a final attempt to find
# state on an NFS server.

mount -t nfs $CLIENTSTATE/$HOSTNAME $STATE_MOUNT -o rw,nolock
fi

if [ -w "$STATE_MOUNT" ]; then

mount_state() {
if [ -e "$1" ]; then
[ ! -e "$STATE_MOUNT$1" ] && cp -a --parents "$1" "$STATE_MOUNT"
mount -n --bind "$STATE_MOUNT$1" "$1"
fi
}

for file in /etc/statetab /etc/statetab.d/* ; do
is_ignored_file "$file" && continue
[ ! -f "$file" ] && continue

if [ -f "$STATE_MOUNT/$file" ] ; then
mount -n --bind "$STATE_MOUNT/$file" "$file"
fi

for path in $(grep -v "^#" "$file" 2>/dev/null); do
mount_state "$path"
[ -n "$SELINUX_STATE" -a -e "$path" ] && restorecon -R "$path"
done
done

if [ -f "$STATE_MOUNT/files" ] ; then
for path in $(grep -v "^#" "$STATE_MOUNT/files" 2>/dev/null); do
mount_state "$path"
[ -n "$SELINUX_STATE" -a -e "$path" ] && restorecon -R "$path"
done
fi
fi

if mount | grep -q /var/lib/nfs/rpc_pipefs ; then
mount -t rpc_pipefs sunrpc /var/lib/nfs/rpc_pipefs && service rpcidmapd restart
fi
fi

if [[ " $fsckoptions" != *" -y"* ]]; then
fsckoptions="-a $fsckoptions"
fi

_RUN_QUOTACHECK=0
if [ -f /forcequotacheck ] || strstr "$cmdline" forcequotacheck ; then
_RUN_QUOTACHECK=1
fi
if [ -z "$fastboot" -a "$READONLY" != "yes" ]; then

STRING=$"Checking filesystems"
echo $STRING
fsck -T -t noopts=_netdev -A $fsckoptions
rc=$?

if [ "$rc" -eq "0" ]; then
success "$STRING"
echo
elif [ "$rc" -eq "1" ]; then
passed "$STRING"
echo
elif [ "$rc" -eq "2" -o "$rc" -eq "3" ]; then
echo $"Unmounting file systems"
umount -a
mount -n -o remount,ro /
echo $"Automatic reboot in progress."
reboot -f
fi

# A return of 4 or higher means there were serious problems.
if [ $rc -gt 1 ]; then
[ -n "$PLYMOUTH" ] && plymouth --hide-splash

failure "$STRING"
echo
echo
echo $"*** An error occurred during the file system check."
echo $"*** Dropping you to a shell; the system will reboot"
echo $"*** when you leave the shell."

str=$"(Repair filesystem)"
PS1="$str \# # "; export PS1
[ "$SELINUX_STATE" = "1" ] && disable_selinux
start rcS-emergency

echo $"Unmounting file systems"
umount -a
mount -n -o remount,ro /
echo $"Automatic reboot in progress."
reboot -f
elif [ "$rc" -eq "1" ]; then
_RUN_QUOTACHECK=1
fi
fi

remount_needed() {
local state oldifs
[ "$READONLY" = "yes" ] && return 1
state=$(LC_ALL=C awk '/ \/ / && ($3 !~ /rootfs/) { print $4 }' /proc/mounts)
oldifs=$IFS
IFS=","
for opt in $state ; do
if [ "$opt" = "rw" ]; then
IFS=$oldifs
return 1
fi
done
IFS=$oldifs
return 0
}

# Remount the root filesystem read-write.
update_boot_stage RCmountfs
if remount_needed ; then
action $"Remounting root filesystem in read-write mode: " mount -n -o remount,rw /
fi

# Clean up SELinux labels
if [ -n "$SELINUX_STATE" ]; then
restorecon /etc/mtab /etc/ld.so.cache /etc/blkid/blkid.tab /etc/resolv.conf >/dev/null 2>&1
fi

# If relabeling, relabel mount points.
if [ -n "$SELINUX_STATE" -a "$READONLY" != "yes" ]; then
if [ -f /.autorelabel ] || strstr "$cmdline" autorelabel ; then
restorecon $(awk '!/^#/ && $4 !~ /noauto/ && $2 ~ /^\// { print $2 }' /etc/fstab) >/dev/null 2>&1
fi
fi

if [ "$READONLY" != "yes" ] ; then
# Clear mtab
(> /etc/mtab) &> /dev/null

# Remove stale backups
rm -f /etc/mtab~ /etc/mtab~~

# Enter mounted filesystems into /etc/mtab
mount -f /
mount -f /proc >/dev/null 2>&1
mount -f /sys >/dev/null 2>&1
mount -f /dev/pts >/dev/null 2>&1
mount -f /dev/shm >/dev/null 2>&1
mount -f /proc/bus/usb >/dev/null 2>&1
fi

# Mount all other filesystems (except for NFS and /proc, which is already
# mounted). Contrary to standard usage,
# filesystems are NOT unmounted in single user mode.
# The 'no' applies to all listed filesystem types. See mount(8).
if [ "$READONLY" != "yes" ] ; then
action $"Mounting local filesystems: " mount -a -t nonfs,nfs4,smbfs,ncpfs,cifs,gfs,gfs2,glusterfs -O no_netdev
else
action $"Mounting local filesystems: " mount -a -n -t nonfs,nfs4,smbfs,ncpfs,cifs,gfs,gfs2i,glusterfs -O no_netdev
fi

# Update quotas if necessary
if [ X"$_RUN_QUOTACHECK" = X1 -a -x /sbin/quotacheck ]; then
action $"Checking local filesystem quotas: " /sbin/quotacheck -anug
fi

if [ -x /sbin/quotaon ]; then
action $"Enabling local filesystem quotas: " /sbin/quotaon -aug
fi

# Check to see if a full relabel is needed
if [ -n "$SELINUX_STATE" -a "$READONLY" != "yes" ]; then
if [ -f /.autorelabel ] || strstr "$cmdline" autorelabel ; then
relabel_selinux
fi
else
if [ -d /etc/selinux -a "$READONLY" != "yes" ]; then
[ -f /.autorelabel ] || touch /.autorelabel
fi
fi

# Initialize pseudo-random number generator
if [ -f "/var/lib/random-seed" ]; then
cat /var/lib/random-seed > /dev/urandom
else
[ "$READONLY" != "yes" ] && touch /var/lib/random-seed
fi
if [ "$READONLY" != "yes" ]; then
chmod 600 /var/lib/random-seed
dd if=/dev/urandom of=/var/lib/random-seed count=1 bs=4096 2>/dev/null
fi

if [ -f /etc/crypttab ]; then
init_crypto 1
fi

# Configure machine if necessary.
if [ -f /.unconfigured ]; then

if [ -x /bin/plymouth ]; then
/bin/plymouth quit
fi

if [ -x /usr/bin/system-config-keyboard ]; then
/usr/bin/system-config-keyboard
fi
if [ -x /usr/bin/passwd ]; then
/usr/bin/passwd root
fi
if [ -x /usr/sbin/system-config-network-tui ]; then
/usr/sbin/system-config-network-tui
fi
if [ -x /usr/sbin/timeconfig ]; then
/usr/sbin/timeconfig
fi
if [ -x /usr/sbin/authconfig-tui ]; then
/usr/sbin/authconfig-tui --nostart
fi
if [ -x /usr/sbin/ntsysv ]; then
/usr/sbin/ntsysv --level 35
fi

# Reread in network configuration data.
if [ -f /etc/sysconfig/network ]; then
. /etc/sysconfig/network

# Reset the hostname.
action $"Resetting hostname ${HOSTNAME}: " hostname ${HOSTNAME}
fi

rm -f /.unconfigured
fi

# Clean out /.
rm -f /fastboot /fsckoptions /forcefsck /.autofsck /forcequotacheck /halt \
/poweroff /.suspended &> /dev/null

# Do we need (w|u)tmpx files? We don't set them up, but the sysadmin might...
_NEED_XFILES=
[ -f /var/run/utmpx -o -f /var/log/wtmpx ] && _NEED_XFILES=1

# Clean up /var.
rm -rf /var/lock/cvs/* /var/run/screen/*
find /var/lock /var/run ! -type d -exec rm -f {} \;
rm -f /var/lib/rpm/__db* &> /dev/null
rm -f /var/gdm/.gdmfifo &> /dev/null

[ "$PROMPT" != no ] && plymouth watch-keystroke --command "touch /var/run/confirm" --keys=Ii &

# Clean up utmp/wtmp
> /var/run/utmp
touch /var/log/wtmp
chgrp utmp /var/run/utmp /var/log/wtmp
chmod 0664 /var/run/utmp /var/log/wtmp
if [ -n "$_NEED_XFILES" ]; then
> /var/run/utmpx
touch /var/log/wtmpx
chgrp utmp /var/run/utmpx /var/log/wtmpx
chmod 0664 /var/run/utmpx /var/log/wtmpx
fi
[ -n "$SELINUX_STATE" ] && restorecon /var/run/utmp* /var/log/wtmp* >/dev/null 2>&1

# Clean up various /tmp bits
[ -n "$SELINUX_STATE" ] && restorecon /tmp
rm -f /tmp/.X*-lock /tmp/.lock.* /tmp/.gdm_socket /tmp/.s.PGSQL.*
rm -rf /tmp/.X*-unix /tmp/.ICE-unix /tmp/.font-unix /tmp/hsperfdata_* \
/tmp/kde-* /tmp/ksocket-* /tmp/mc-* /tmp/mcop-* /tmp/orbit-* \
/tmp/scrollkeeper-* /tmp/ssh-* \
/dev/.in_sysinit

# Make ICE directory
mkdir -m 1777 -p /tmp/.ICE-unix >/dev/null 2>&1
chown root:root /tmp/.ICE-unix
[ -n "$SELINUX_STATE" ] && restorecon /tmp/.ICE-unix >/dev/null 2>&1

# Start up swapping.
update_boot_stage RCswap
action $"Enabling /etc/fstab swaps: " swapon -a -e
if [ "$AUTOSWAP" = "yes" ]; then
curswap=$(awk '/^\/dev/ { print $1 }' /proc/swaps | while read x; do get_numeric_dev dec $x ; echo -n " "; done)
swappartitions=$(blkid -t TYPE=swap -o device)
if [ x"$swappartitions" != x ]; then
for partition in $swappartitions ; do
[ ! -e $partition ] && continue
majmin=$(get_numeric_dev dec $partition)
echo $curswap | grep -qw "$majmin" || action $"Enabling local swap partitions: " swapon $partition
done
fi
fi

# Set up binfmt_misc
/bin/mount -t binfmt_misc none /proc/sys/fs/binfmt_misc > /dev/null 2>&1

# Boot time profiles. Yes, this should be somewhere else.
if [ -x /usr/sbin/system-config-network-cmd ]; then
if strstr "$cmdline" netprofile= ; then
for arg in $cmdline ; do
if [ "${arg##netprofile=}" != "${arg}" ]; then
/usr/sbin/system-config-network-cmd --profile ${arg##netprofile=}
fi
done
fi
fi

# Now that we have all of our basic modules loaded and the kernel going,
# let's dump the syslog ring somewhere so we can find it later
[ -f /var/log/dmesg ] && mv -f /var/log/dmesg /var/log/dmesg.old
dmesg -s 131072 > /var/log/dmesg

# create the crash indicator flag to warn on crashes, offer fsck with timeout
touch /.autofsck &> /dev/null

[ "$PROMPT" != no ] && plymouth --ignore-keystroke=Ii
if strstr "$cmdline" confirm ; then
touch /var/run/confirm
fi

# Let rhgb know that we're leaving rc.sysinit
if [ -x /bin/plymouth ]; then
/bin/plymouth --sysinit
fi


cat /etc/init.d/functions

# -*-Shell-script-*-
#
# functions This file contains functions to be used by most or all
# shell scripts in the /etc/init.d directory.
#

TEXTDOMAIN=initscripts

# Make sure umask is sane
umask 022

# Set up a default search path.
PATH="/sbin:/usr/sbin:/bin:/usr/bin"
export PATH

# Get a sane screen width
[ -z "${COLUMNS:-}" ] && COLUMNS=80

[ -z "${CONSOLETYPE:-}" ] && CONSOLETYPE="$(/sbin/consoletype)"

if [ -f /etc/sysconfig/i18n -a -z "${NOLOCALE:-}" -a -z "${LANGSH_SOURCED:-}" ] ; then
. /etc/profile.d/lang.sh 2>/dev/null
# avoid propagating LANGSH_SOURCED any further
unset LANGSH_SOURCED
fi

# Read in our configuration
if [ -z "${BOOTUP:-}" ]; then
if [ -f /etc/sysconfig/init ]; then
. /etc/sysconfig/init
else
# This all seem confusing? Look in /etc/sysconfig/init,
# or in /usr/doc/initscripts-*/sysconfig.txt
BOOTUP=color
RES_COL=60
MOVE_TO_COL="echo -en \\033[${RES_COL}G"
SETCOLOR_SUCCESS="echo -en \\033[1;32m"
SETCOLOR_FAILURE="echo -en \\033[1;31m"
SETCOLOR_WARNING="echo -en \\033[1;33m"
SETCOLOR_NORMAL="echo -en \\033[0;39m"
LOGLEVEL=1
fi
if [ "$CONSOLETYPE" = "serial" ]; then
BOOTUP=serial
MOVE_TO_COL=
SETCOLOR_SUCCESS=
SETCOLOR_FAILURE=
SETCOLOR_WARNING=
SETCOLOR_NORMAL=
fi
fi

# Interpret escape sequences in an fstab entry
fstab_decode_str() {
fstab-decode echo "$1"
}

# Check if any of $pid (could be plural) are running
checkpid() {
local i

for i in $* ; do
[ -d "/proc/$i" ] && return 0
done
return 1
}

__readlink() {
ls -bl "$@" 2>/dev/null| awk '{ print $NF }'
}

__fgrep() {
s=$1
f=$2
while read line; do
if strstr "$line" "$s"; then
echo $line
return 0
fi
done < $f
return 1
}

# __umount_loop awk_program fstab_file first_msg retry_msg retry_umount_args
# awk_program should process fstab_file and return a list of fstab-encoded
# paths; it doesn't have to handle comments in fstab_file.
__umount_loop() {
local remaining sig=
local retry=3 count

remaining=$(LC_ALL=C awk "/^#/ {next} $1" "$2" | sort -r)
while [ -n "$remaining" -a "$retry" -gt 0 ]; do
if [ "$retry" -eq 3 ]; then
action "$3" fstab-decode umount $remaining
else
action "$4" fstab-decode umount $5 $remaining
fi
count=4
remaining=$(LC_ALL=C awk "/^#/ {next} $1" "$2" | sort -r)
while [ "$count" -gt 0 ]; do
[ -z "$remaining" ] && break
count=$(($count-1))
usleep 500000
remaining=$(LC_ALL=C awk "/^#/ {next} $1" "$2" | sort -r)
done
[ -z "$remaining" ] && break
kill $sig $(fstab-decode /sbin/fuser -m $remaining 2>/dev/null | sed -e "s/\b$$\b//g") > /dev/null
sleep 3
retry=$(($retry -1))
sig=-9
done
}

# Similar to __umount loop above, specialized for loopback devices
__umount_loopback_loop() {
local remaining devremaining sig=
local retry=3

remaining=$(awk '$1 ~ /^\/dev\/loop/ && $2 != "/" {print $2}' /proc/mounts)
devremaining=$(awk '$1 ~ /^\/dev\/loop/ && $2 != "/" {print $1}' /proc/mounts)
while [ -n "$remaining" -a "$retry" -gt 0 ]; do
if [ "$retry" -eq 3 ]; then
action $"Unmounting loopback filesystems: " \
fstab-decode umount $remaining
else
action $"Unmounting loopback filesystems (retry):" \
fstab-decode umount $remaining
fi
for dev in $devremaining ; do
losetup $dev > /dev/null 2>&1 && \
action $"Detaching loopback device $dev: " \
losetup -d $dev
done
remaining=$(awk '$1 ~ /^\/dev\/loop/ && $2 != "/" {print $2}' /proc/mounts)
devremaining=$(awk '$1 ~ /^\/dev\/loop/ && $2 != "/" {print $1}' /proc/mounts)
[ -z "$remaining" ] && break
fstab-decode /sbin/fuser -k -m $sig $remaining >/dev/null
sleep 3
retry=$(($retry -1))
sig=-9
done
}

# __proc_pids {program} [pidfile]
# Set $pid to pids from /var/run* for {program}. $pid should be declared
# local in the caller.
# Returns LSB exit code for the 'status' action.
__pids_var_run() {
local base=${1##*/}
local pid_file=${2:-/var/run/$base.pid}
local pid_dir=$(/usr/bin/dirname $pid_file)
local binary=$3

[ -d "$pid_dir" -a ! -r "$pid_dir" ] && return 4

pid=
if [ -f "$pid_file" ] ; then
local line p

[ ! -r "$pid_file" ] && return 4 # "user had insufficient privilege"
while : ; do
read line
[ -z "$line" ] && break
for p in $line ; do
if [ -z "${p//[0-9]/}" -a -d "/proc/$p" ] ; then
if [ -n "$binary" ] ; then
local b=$(readlink /proc/$p/exe | sed -e 's/\s*(deleted)$//')
[ "$b" != "$binary" ] && continue
fi
pid="$pid $p"
fi
done
done < "$pid_file"

if [ -n "$pid" ]; then
return 0
fi
return 1 # "Program is dead and /var/run pid file exists"
fi
return 3 # "Program is not running"
}

# Output PIDs of matching processes, found using pidof
__pids_pidof() {
pidof -c -o $$ -o $PPID -o %PPID -x "$1" || \
pidof -c -o $$ -o $PPID -o %PPID -x "${1##*/}"
}


# A function to start a program.
daemon() {
# Test syntax.
local gotbase= force= nicelevel corelimit
local pid base= user= nice= bg= pid_file=
local cgroup=
nicelevel=0
while [ "$1" != "${1##[-+]}" ]; do
case $1 in
'') echo $"$0: Usage: daemon [+/-nicelevel] {program}"
return 1;;
--check)
base=$2
gotbase="yes"
shift 2
;;
--check=?*)
base=${1#--check=}
gotbase="yes"
shift
;;
--user)
user=$2
shift 2
;;
--user=?*)
user=${1#--user=}
shift
;;
--pidfile)
pid_file=$2
shift 2
;;
--pidfile=?*)
pid_file=${1#--pidfile=}
shift
;;
--force)
force="force"
shift
;;
[-+][0-9]*)
nice="nice -n $1"
shift
;;
*) echo $"$0: Usage: daemon [+/-nicelevel] {program}"
return 1;;
esac
done

# Save basename.
[ -z "$gotbase" ] && base=${1##*/}

# See if it's already running. Look *only* at the pid file.
__pids_var_run "$base" "$pid_file"

[ -n "$pid" -a -z "$force" ] && return

# make sure it doesn't core dump anywhere unless requested
corelimit="ulimit -S -c ${DAEMON_COREFILE_LIMIT:-0}"

# if they set NICELEVEL in /etc/sysconfig/foo, honor it
[ -n "${NICELEVEL:-}" ] && nice="nice -n $NICELEVEL"

# if they set CGROUP_DAEMON in /etc/sysconfig/foo, honor it
if [ -n "${CGROUP_DAEMON}" ]; then
if [ ! -x /bin/cgexec ]; then
echo -n "Cgroups not installed"; warning
echo
else
cgroup="/bin/cgexec";
for i in $CGROUP_DAEMON; do
cgroup="$cgroup -g $i";
done
fi
fi

# Echo daemon
[ "${BOOTUP:-}" = "verbose" -a -z "${LSB:-}" ] && echo -n " $base"

# And start it up.
if [ -z "$user" ]; then
$cgroup $nice /bin/bash -c "$corelimit >/dev/null 2>&1 ; $*"
else
$cgroup $nice runuser -s /bin/bash $user -c "$corelimit >/dev/null 2>&1 ; $*"
fi

[ "$?" -eq 0 ] && success $"$base startup" || failure $"$base startup"
}

# A function to stop a program.
killproc() {
local RC killlevel= base pid pid_file= delay try binary=

RC=0; delay=3; try=0
# Test syntax.
if [ "$#" -eq 0 ]; then
echo $"Usage: killproc [-p pidfile] [ -d delay] {program} [-signal]"
return 1
fi
if [ "$1" = "-p" ]; then
pid_file=$2
shift 2
fi
if [ "$1" = "-b" ]; then
if [ -z $pid_file ]; then
echo $"-b option can be used only with -p"
echo $"Usage: killproc -p pidfile -b binary program"
return 1
fi
binary=$2
shift 2
fi
if [ "$1" = "-d" ]; then
delay=$(echo $2 | awk -v RS=' ' -v IGNORECASE=1 '{if($1!~/^[0-9.]+[smhd]?$/) exit 1;d=$1~/s$|^[0-9.]*$/?1:$1~/m$/?60:$1~/h$/?60*60:$1~/d$/?24*60*60:-1;if(d==-1) exit 1;delay+=d*$1} END {printf("%d",delay+0.5)}')
if [ "$?" -eq 1 ]; then
echo $"Usage: killproc [-p pidfile] [ -d delay] {program} [-signal]"
return 1
fi
shift 2
fi

# check for second arg to be kill level
[ -n "${2:-}" ] && killlevel=$2

# Save basename.
base=${1##*/}

# Find pid.
__pids_var_run "$1" "$pid_file" "$binary"
RC=$?
if [ -z "$pid" ]; then
if [ -z "$pid_file" ]; then
pid="$(__pids_pidof "$1")"
else
[ "$RC" = "4" ] && { failure $"$base shutdown" ; return $RC ;}
fi
fi

# Kill it.
if [ -n "$pid" ] ; then
[ "$BOOTUP" = "verbose" -a -z "${LSB:-}" ] && echo -n "$base "
if [ -z "$killlevel" ] ; then
if checkpid $pid 2>&1; then
# TERM first, then KILL if not dead
kill -TERM $pid >/dev/null 2>&1
usleep 100000
if checkpid $pid ; then
try=0
while [ $try -lt $delay ] ; do
checkpid $pid || break
sleep 1
let try+=1
done
if checkpid $pid ; then
kill -KILL $pid >/dev/null 2>&1
usleep 100000
fi
fi
fi
checkpid $pid
RC=$?
[ "$RC" -eq 0 ] && failure $"$base shutdown" || success $"$base shutdown"
RC=$((! $RC))
# use specified level only
else
if checkpid $pid; then
kill $killlevel $pid >/dev/null 2>&1
RC=$?
[ "$RC" -eq 0 ] && success $"$base $killlevel" || failure $"$base $killlevel"
elif [ -n "${LSB:-}" ]; then
RC=7 # Program is not running
fi
fi
else
if [ -n "${LSB:-}" -a -n "$killlevel" ]; then
RC=7 # Program is not running
else
failure $"$base shutdown"
RC=0
fi
fi

# Remove pid file if any.
if [ -z "$killlevel" ]; then
rm -f "${pid_file:-/var/run/$base.pid}"
fi
return $RC
}

# A function to find the pid of a program. Looks *only* at the pidfile
pidfileofproc() {
local pid

# Test syntax.
if [ "$#" = 0 ] ; then
echo $"Usage: pidfileofproc {program}"
return 1
fi

__pids_var_run "$1"
[ -n "$pid" ] && echo $pid
return 0
}

# A function to find the pid of a program.
pidofproc() {
local RC pid pid_file=

# Test syntax.
if [ "$#" = 0 ]; then
echo $"Usage: pidofproc [-p pidfile] {program}"
return 1
fi
if [ "$1" = "-p" ]; then
pid_file=$2
shift 2
fi
fail_code=3 # "Program is not running"

# First try "/var/run/*.pid" files
__pids_var_run "$1" "$pid_file"
RC=$?
if [ -n "$pid" ]; then
echo $pid
return 0
fi

[ -n "$pid_file" ] && return $RC
__pids_pidof "$1" || return $RC
}

status() {
local base pid lock_file= pid_file= binary=

# Test syntax.
if [ "$#" = 0 ] ; then
echo $"Usage: status [-p pidfile] {program}"
return 1
fi
if [ "$1" = "-p" ]; then
pid_file=$2
shift 2
fi
if [ "$1" = "-l" ]; then
lock_file=$2
shift 2
fi
if [ "$1" = "-b" ]; then
if [ -z $pid_file ]; then
echo $"-b option can be used only with -p"
echo $"Usage: status -p pidfile -b binary program"
return 1
fi
binary=$2
shift 2
fi
base=${1##*/}

# First try "pidof"
__pids_var_run "$1" "$pid_file" "$binary"
RC=$?
if [ -z "$pid_file" -a -z "$pid" ]; then
pid="$(__pids_pidof "$1")"
fi
if [ -n "$pid" ]; then
echo $"${base} (pid $pid) is running..."
return 0
fi

case "$RC" in
0)
echo $"${base} (pid $pid) is running..."
return 0
;;
1)
echo $"${base} dead but pid file exists"
return 1
;;
4)
echo $"${base} status unknown due to insufficient privileges."
return 4
;;
esac
if [ -z "${lock_file}" ]; then
lock_file=${base}
fi
# See if /var/lock/subsys/${lock_file} exists
if [ -f /var/lock/subsys/${lock_file} ]; then
echo $"${base} dead but subsys locked"
return 2
fi
echo $"${base} is stopped"
return 3
}

echo_success() {
[ "$BOOTUP" = "color" ] && $MOVE_TO_COL
echo -n "["
[ "$BOOTUP" = "color" ] && $SETCOLOR_SUCCESS
echo -n $" OK "
[ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
echo -n "]"
echo -ne "\r"
return 0
}

echo_failure() {
[ "$BOOTUP" = "color" ] && $MOVE_TO_COL
echo -n "["
[ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
echo -n $"FAILED"
[ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
echo -n "]"
echo -ne "\r"
return 1
}

echo_passed() {
[ "$BOOTUP" = "color" ] && $MOVE_TO_COL
echo -n "["
[ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
echo -n $"PASSED"
[ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
echo -n "]"
echo -ne "\r"
return 1
}

echo_warning() {
[ "$BOOTUP" = "color" ] && $MOVE_TO_COL
echo -n "["
[ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
echo -n $"WARNING"
[ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
echo -n "]"
echo -ne "\r"
return 1
}

# Inform the graphical boot of our current state
update_boot_stage() {
if [ -x /bin/plymouth ]; then
/bin/plymouth --update="$1"
fi
return 0
}

# Log that something succeeded
success() {
[ "$BOOTUP" != "verbose" -a -z "${LSB:-}" ] && echo_success
return 0
}

# Log that something failed
failure() {
local rc=$?
[ "$BOOTUP" != "verbose" -a -z "${LSB:-}" ] && echo_failure
[ -x /bin/plymouth ] && /bin/plymouth --details
return $rc
}

# Log that something passed, but may have had errors. Useful for fsck
passed() {
local rc=$?
[ "$BOOTUP" != "verbose" -a -z "${LSB:-}" ] && echo_passed
return $rc
}

# Log a warning
warning() {
local rc=$?
[ "$BOOTUP" != "verbose" -a -z "${LSB:-}" ] && echo_warning
return $rc
}

# Run some action. Log its output.
action() {
local STRING rc

STRING=$1
echo -n "$STRING "
shift
"$@" && success $"$STRING" || failure $"$STRING"
rc=$?
echo
return $rc
}

# returns OK if $1 contains $2
strstr() {
[ "${1#*$2*}" = "$1" ] && return 1
return 0
}

# Confirm whether we really want to run this service
confirm() {
[ -x /bin/plymouth ] && /bin/plymouth --hide-splash
while : ; do
echo -n $"Start service $1 (Y)es/(N)o/(C)ontinue? [Y] "
read answer
if strstr $"yY" "$answer" || [ "$answer" = "" ] ; then
return 0
elif strstr $"cC" "$answer" ; then
rm -f /var/run/confirm
[ -x /bin/plymouth ] && /bin/plymouth --show-splash
return 2
elif strstr $"nN" "$answer" ; then
return 1
fi
done
}

# resolve a device node to its major:minor numbers in decimal or hex
get_numeric_dev() {
(
fmt="%d:%d"
if [ "$1" == "hex" ]; then
fmt="%x:%x"
fi
ls -lH "$2" | awk '{ sub(/,/, "", $5); printf("'"$fmt"'", $5, $6); }'
) 2>/dev/null
}

# Check whether file $1 is a backup or rpm-generated file and should be ignored
is_ignored_file() {
case "$1" in
*~ | *.bak | *.orig | *.rpmnew | *.rpmorig | *.rpmsave)
return 0
;;
esac
return 1
}

# Evaluate shvar-style booleans
is_true() {
case "$1" in
[tT] | [yY] | [yY][eE][sS] | [tT][rR][uU][eE])
return 0
;;
esac
return 1
}

# Evaluate shvar-style booleans
is_false() {
case "$1" in
[fF] | [nN] | [nN][oO] | [fF][aA][lL][sS][eE])
return 0
;;
esac
return 1
}

# Apply sysctl settings, including files in /etc/sysctl.d
apply_sysctl() {
sysctl -e -p /etc/sysctl.conf >/dev/null 2>&1
for file in /etc/sysctl.d/* ; do
is_ignored_file "$file" && continue
test -f "$file" && sysctl -e -p "$file" >/dev/null 2>&1
done
}

key_is_random() {
[ "$1" = "/dev/urandom" -o "$1" = "/dev/hw_random" \
-o "$1" = "/dev/random" ]
}

find_crypto_mount_point() {
local fs_spec fs_file fs_vfstype remaining_fields
local fs
while read fs_spec fs_file remaining_fields; do
if [ "$fs_spec" = "/dev/mapper/$1" ]; then
echo $fs_file
break;
fi
done < /etc/fstab
}

# Because of a chicken/egg problem, init_crypto must be run twice. /var may be
# encrypted but /var/lib/random-seed is needed to initialize swap.
init_crypto() {
local have_random dst src key opt mode owner params makeswap skip arg opt
local param value rc ret mke2fs mdir prompt mount_point

ret=0
have_random=$1
while read dst src key opt; do
[ -z "$dst" -o "${dst#\#}" != "$dst" ] && continue
[ -b "/dev/mapper/$dst" ] && continue;
if [ "$have_random" = 0 ] && key_is_random "$key"; then
continue
fi
if [ -n "$key" -a "x$key" != "xnone" ]; then
if test -e "$key" ; then
owner=$(ls -l $key | (read a b owner rest; echo $owner))
if ! key_is_random "$key"; then
mode=$(ls -l "$key" | cut -c 5-10)
if [ "$mode" != "------" ]; then
echo $"INSECURE MODE FOR $key"
fi
fi
if [ "$owner" != root ]; then
echo $"INSECURE OWNER FOR $key"
fi
else
echo $"Key file for $dst not found, skipping"
ret=1
continue
fi
else
key=""
fi
params=""
makeswap=""
mke2fs=""
skip=""
# Parse the src field for UUID= and convert to real device names
if [ "${src%%=*}" == "UUID" ]; then
src=$(/sbin/blkid -t "$src" -l -o device)
elif [ "${src/^\/dev\/disk\/by-uuid\/}" != "$src" ]; then
src=$(__readlink $src)
fi
# Is it a block device?
[ -b "$src" ] || continue
# Is it already a device mapper slave? (this is gross)
devesc=${src##/dev/}
devesc=${devesc//\//!}
for d in /sys/block/dm-*/slaves ; do
[ -e $d/$devesc ] && continue 2
done
# Parse the options field, convert to cryptsetup parameters and
# contruct the command line
while [ -n "$opt" ]; do
arg=${opt%%,*}
opt=${opt##$arg}
opt=${opt##,}
param=${arg%%=*}
value=${arg##$param=}

case "$param" in
cipher)
params="$params -c $value"
if [ -z "$value" ]; then
echo $"$dst: no value for cipher option, skipping"
skip="yes"
fi
;;
size)
params="$params -s $value"
if [ -z "$value" ]; then
echo $"$dst: no value for size option, skipping"
skip="yes"
fi
;;
hash)
params="$params -h $value"
if [ -z "$value" ]; then
echo $"$dst: no value for hash option, skipping"
skip="yes"
fi
;;
verify)
params="$params -y"
;;
swap)
makeswap=yes
;;
tmp)
mke2fs=yes
esac
done
if [ "$skip" = "yes" ]; then
ret=1
continue
fi
if [ -z "$makeswap" ] && cryptsetup isLuks "$src" 2>/dev/null ; then
if key_is_random "$key"; then
echo $"$dst: LUKS requires non-random key, skipping"
ret=1
continue
fi
if [ -n "$params" ]; then
echo "$dst: options are invalid for LUKS partitions," \
"ignoring them"
fi
if [ -n "$key" ]; then
/sbin/cryptsetup -d $key luksOpen "$src" "$dst" <&1 2>/dev/null && success || failure
rc=$?
else
mount_point="$(find_crypto_mount_point $dst)"
[ -n "$mount_point" ] || mount_point=${src##*/}
prompt=$(printf $"%s is password protected" "$mount_point")
plymouth ask-for-password --prompt "$prompt" --command="/sbin/cryptsetup luksOpen -T1 $src $dst" <&1
rc=$?
fi
else
[ -z "$key" ] && plymouth --hide-splash
/sbin/cryptsetup $params ${key:+-d $key} create "$dst" "$src" <&1 2>/dev/null && success || failure
rc=$?
[ -z "$key" ] && plymouth --show-splash
fi
if [ $rc -ne 0 ]; then
ret=1
continue
fi
if [ -b "/dev/mapper/$dst" ]; then
if [ "$makeswap" = "yes" ]; then
mkswap "/dev/mapper/$dst" 2>/dev/null >/dev/null
fi
if [ "$mke2fs" = "yes" ]; then
if mke2fs "/dev/mapper/$dst" 2>/dev/null >/dev/null \
&& mdir=$(mktemp -d /tmp/mountXXXXXX); then
mount "/dev/mapper/$dst" "$mdir" && chmod 1777 "$mdir"
umount "$mdir"
rmdir "$mdir"
fi
fi
fi
done < /etc/crypttab
return $ret
}

# A sed expression to filter out the files that is_ignored_file recognizes
__sed_discard_ignored_files='/\(~\|\.bak\|\.orig\|\.rpmnew\|\.rpmorig\|\.rpmsave\)$/d'


cat /etc/rc.d/rc

#! /bin/bash
#
# rc This file is responsible for starting/stopping
# services when the runlevel changes.
#
# Original Author:
# Miquel van Smoorenburg, <miquels@drinkel.nl.mugnet.org>
#

set -m

# check a file to be a correct runlevel script
check_runlevel ()
{
# Check if the file exists at all.
[ -x "$1" ] || return 1
is_ignored_file "$1" && return 1
return 0
}

# Now find out what the current and what the previous runlevel are.
argv1="$1"
set $(/sbin/runlevel)
runlevel=$2
previous=$1
export runlevel previous

. /etc/init.d/functions

export CONSOLETYPE
do_confirm="no"
if [ -f /var/run/confirm ]; then
do_confirm="yes"
fi
UPSTART=
[ -x /sbin/initctl ] && UPSTART=yes
# See if we want to be in user confirmation mode
if [ "$previous" = "N" ]; then
if [ "$do_confirm" = "yes" ]; then
echo $"Entering interactive startup"
else
echo $"Entering non-interactive startup"
fi
fi

# Get first argument. Set new runlevel to this argument.
[ -n "$argv1" ] && runlevel="$argv1"

# Is there an rc directory for this new runlevel?
[ -d /etc/rc$runlevel.d ] || exit 0

# Set language, vc settings once to avoid doing it for every init script
# through functions
if [ -f /etc/sysconfig/i18n -a -z "${NOLOCALE:-}" ] ; then
. /etc/profile.d/lang.sh 2>/dev/null
export LANGSH_SOURCED=1
fi

# First, run the KILL scripts.
for i in /etc/rc$runlevel.d/K* ; do

# Check if the subsystem is already up.
subsys=${i#/etc/rc$runlevel.d/K??}
[ -f /var/lock/subsys/$subsys -o -f /var/lock/subsys/$subsys.init ] || continue
check_runlevel "$i" || continue

# Bring the subsystem down.
[ -n "$UPSTART" ] && initctl emit --quiet stopping JOB=$subsys
$i stop
[ -n "$UPSTART" ] && initctl emit --quiet stopped JOB=$subsys
done

還能夠使用 initctl 的 emit 命令從命令行發送一個事件。
#initctl emit <event>
這通常是用於 UpStart 自己的排錯。

http://www.ibm.com/developerworks/cn/linux/1407_liuming_init2/

 

 

# Now run the START scripts.
for i in /etc/rc$runlevel.d/S* ; do

# Check if the subsystem is already up.
subsys=${i#/etc/rc$runlevel.d/S??}
[ -f /var/lock/subsys/$subsys ] && continue
[ -f /var/lock/subsys/$subsys.init ] && continue
check_runlevel "$i" || continue

# If we're in confirmation mode, get user confirmation
if [ "$do_confirm" = "yes" ]; then
confirm $subsys
rc=$?
if [ "$rc" = "1" ]; then
continue
elif [ "$rc" = "2" ]; then
do_confirm="no"
fi
fi

update_boot_stage "$subsys"
# Bring the subsystem up.
[ -n "$UPSTART" ] && initctl emit --quiet starting JOB=$subsys
if [ "$subsys" = "halt" -o "$subsys" = "reboot" ]; then
export LC_ALL=C
exec $i start
fi
$i start
[ -n "$UPSTART" ] && initctl emit --quiet started JOB=$subsys
done
[ "$do_confirm" = "yes" ] && rm -f /var/run/confirm
exit 0

 

 

[root@steven ~]# cat /sbin/service

#!/bin/sh

. /etc/init.d/functions

VERSION="$(basename $0) ver. 0.91"
USAGE="Usage: $(basename $0) < option > | --status-all | \
[ service_name [ command | --full-restart ] ]"
SERVICE=
SERVICEDIR="/etc/init.d"
OPTIONS=

if [ $# -eq 0 ]; then
echo "${USAGE}" >&2
exit 1
fi

cd /
while [ $# -gt 0 ]; do
case "${1}" in
--help | -h | --h* )
echo "${USAGE}" >&2
exit 0
;;
--version | -V )
echo "${VERSION}" >&2
exit 0
;;
*)
if [ -z "${SERVICE}" -a $# -eq 1 -a "${1}" = "--status-all" ]; then
cd ${SERVICEDIR}
for SERVICE in * ; do
case "${SERVICE}" in
functions | halt | killall | single| linuxconf| kudzu)
;;
*)
if ! is_ignored_file "${SERVICE}" \
&& [ -x "${SERVICEDIR}/${SERVICE}" ]; then
env -i PATH="$PATH" TERM="$TERM" "${SERVICEDIR}/${SERVICE}" status
fi
;;
esac
done
exit 0
elif [ $# -eq 2 -a "${2}" = "--full-restart" ]; then
SERVICE="${1}"
if [ -x "${SERVICEDIR}/${SERVICE}" ]; then
env -i PATH="$PATH" TERM="$TERM" "${SERVICEDIR}/${SERVICE}" stop
env -i PATH="$PATH" TERM="$TERM" "${SERVICEDIR}/${SERVICE}" start
exit $?
fi
elif [ -z "${SERVICE}" ]; then
SERVICE="${1}"
else
OPTIONS="${OPTIONS} ${1}"
fi
shift
;;
esac
done

if [ -f "${SERVICEDIR}/${SERVICE}" ]; then
env -i PATH="$PATH" TERM="$TERM" "${SERVICEDIR}/${SERVICE}" ${OPTIONS}  #env -i:開始一個新的空的環境;
else
echo $"${SERVICE}: unrecognized service" >&2
exit 1
fi

 

在一個新的空的環境中執行指令

$ echo $PATH
/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/home/steven/bin

echo $TERM
xterm

env -i PATH="$PATH" TERM="$TERM" "${SERVICEDIR}/${SERVICE}" stop
env -i PATH="$PATH" TERM="$TERM" "${SERVICEDIR}/${SERVICE}" start
env -i PATH="$PATH" TERM="$TERM" "${SERVICEDIR}/${SERVICE}" status


env命令
來自: http://man.linuxde.net/env
Shell內建命令 env命令用於顯示系統中已存在的環境變量,以及在定義的環境中執行指令。該命令只使用"-"做爲參數選項時,隱藏了選項"-i"的功能。若沒有設置任何選項和參數時,則直接顯示當前的環境變量。 若是使用env命令在新環境中執行指令時,會由於沒有定義環境變量"PATH"而提示錯誤信息"such file or directory"。此時,用戶能夠從新定義一個新的"PATH"或者使用絕對路徑。

 

選項

-i:開始一個新的空的環境;
-u<變量名>:從當前環境中刪除指定的變量。

參數

變量定義:定義在新的環境中變量,定義多個變量定義用空格隔開。格式爲「變量名=值」;
指定:指定要執行的指令和參數。

 

實例
[root@localhost ~]# env hostname=LinServ-1 TERM=linux SHELL=/bin/bash HISTSIZE=1000 SSH_CLIENT=192.168.2.111 2705 22 SSH_TTY=/dev/pts/0 USER=root LS_COLORS=no=00:fi=00:di=01;34:ln=01;36:pi=40;33:so=01;35:bd=40;33;01:cd=40;33;01:or=01;05;37;41:mi=01;05;37;41:ex=01;32:*.cmd=01;32:*.exe=01;32:*.com=01;32:*.btm=01;32:*.bat=01;32:*.sh=01;32:*.csh=01;32:*.tar=01;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.gz=01;31:*.bz2=01;31:*.bz=01;31:*.tz=01;31:*.rpm=01;31:*.cpio=01;31:*.jpg=01;35:*.gif=01;35:*.bmp=01;35:*.xbm=01;35:*.xpm=01;35:*.png=01;35:*.tif=01;35: mail=/var/spool/mail/root PATH=/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin INPUTRC=/etc/inputrc pwd=/root LANG=zh_CN.UTF-8 SHLVL=1 HOME=/root logname=root SSH_CONNECTION=192.168.2.111 2705 192.168.2.2 22 LESSOPEN=|/usr/bin/lesspipe.sh %s G_BROKEN_FILENAMES=1 _=/bin/env

 


[root@steven pts]# pwd
/dev/pts
[root@steven pts]# ll
crw--w---- 1 root tty 136, 0 1月 18 19:50 0
c--------- 1 root root 5, 2 1月 18 05:29 ptmx

查看當前shell在哪一個終端下運行
[root@steven pts]# tty
/dev/pts/0

# ll #每開一個pts 模擬終端,/dev/pts/目錄下就會多一個終端文件,從0開始 0,1,2,3,4。。。。。總用量 0crw--w---- 1 root tty 136, 0 1月 18 19:52 0crw--w---- 1 root tty 136, 1 1月 18 19:52 1c--------- 1 root root 5, 2 1月 18 05:29 ptmx

相關文章
相關標籤/搜索