浅析 Linux 初始化 init 系统,第 1 部分: sysvinit
近年來,Linux 系統(tǒng)的 init 進程經(jīng)歷了兩次重大的演進,傳統(tǒng)的 sysvinit 已經(jīng)淡出歷史舞臺,新的 init 系統(tǒng) UpStart 和 systemd 各有特點,而越來越多的 Linux 發(fā)行版采納了 systemd。本文簡要介紹了這三種 init 系統(tǒng)的使用和原理,每個 Linux 系統(tǒng)管理員和系統(tǒng)軟件開發(fā)者都應(yīng)該了解它們,以便更好地管理系統(tǒng)和開發(fā)應(yīng)用。本文是系列的第一部分,主要講述 sysvinit 的特點和使用。
什么是 Init 系統(tǒng),init 系統(tǒng)的歷史和現(xiàn)狀
Linux 操作系統(tǒng)的啟動首先從 BIOS 開始,接下來進入 boot loader,由 bootloader 載入內(nèi)核,進行內(nèi)核初始化。內(nèi)核初始化的最后一步就是啟動 pid 為 1 的 init 進程。這個進程是系統(tǒng)的第一個進程。它負責(zé)產(chǎn)生其他所有用戶進程。
init 以守護進程方式存在,是所有其他進程的祖先。init 進程非常獨特,能夠完成其他進程無法完成的任務(wù)。
Init 系統(tǒng)能夠定義、管理和控制 init 進程的行為。它負責(zé)組織和運行許多獨立的或相關(guān)的始化工作(因此被稱為 init 系統(tǒng)),從而讓計算機系統(tǒng)進入某種用戶預(yù)訂的運行模式。
僅僅將內(nèi)核運行起來是毫無實際用途的,必須由 init 系統(tǒng)將系統(tǒng)代入可操作狀態(tài)。比如啟動外殼 shell 后,便有了人機交互,這樣就可以讓計算機執(zhí)行一些預(yù)訂程序完成有實際意義的任務(wù)。或者啟動 X 圖形系統(tǒng)以便提供更佳的人機界面,更加高效的完成任務(wù)。這里,字符界面的 shell 或者 X 系統(tǒng)都是一種預(yù)設(shè)的運行模式。
大多數(shù) Linux 發(fā)行版的 init 系統(tǒng)是和 System V 相兼容的,被稱為 sysvinit。這是人們最熟悉的 init 系統(tǒng)。一些發(fā)行版如 Slackware 采用的是 BSD 風(fēng)格 Init 系統(tǒng),這種風(fēng)格使用較少,本文不再涉及。其他的發(fā)行版如 Gentoo 是自己定制的。Ubuntu 和 RHEL 采用 upstart 替代了傳統(tǒng)的 sysvinit。而 Fedora 從版本 15 開始使用了一個被稱為 systemd 的新 init 系統(tǒng)。
可以看到不同的發(fā)行版采用了不同的 init 實現(xiàn),本系列文章就是打算講述三個主要的 Init 系統(tǒng):sysvinit,UpStart 和 systemd。了解它們各自的設(shè)計特點,并簡要介紹它們的使用。
在 Linux 主要應(yīng)用于服務(wù)器和 PC 機的時代,SysVinit 運行非常良好,概念簡單清晰。它主要依賴于 Shell 腳本,這就決定了它的最大弱點:啟動太慢。在很少重新啟動的 Server 上,這個缺點并不重要。而當(dāng) Linux 被應(yīng)用到移動終端設(shè)備的時候,啟動慢就成了一個大問題。為了更快地啟動,人們開始改進 sysvinit,先后出現(xiàn)了 upstart 和 systemd 這兩個主要的新一代 init 系統(tǒng)。Upstart 已經(jīng)開發(fā)了 8 年多,在不少系統(tǒng)中已經(jīng)替換 sysvinit。Systemd 出現(xiàn)較晚,但發(fā)展更快,大有取代 upstart 的趨勢。
本文的第一部分先簡要介紹 sysvinit。
Sysvinit 概況
sysvinit 就是 system V 風(fēng)格的 init 系統(tǒng),顧名思義,它源于 System V 系列 UNIX。它提供了比 BSD 風(fēng)格 init 系統(tǒng)更高的靈活性。是已經(jīng)風(fēng)行了幾十年的 UNIX init 系統(tǒng),一直被各類 Linux 發(fā)行版所采用。
運行級別
Sysvinit 用術(shù)語 runlevel 來定義"預(yù)訂的運行模式"。Sysvinit 檢查 '/etc/inittab' 文件中是否含有 'initdefault' 項。 這告訴 init 系統(tǒng)是否有一個默認運行模式。如果沒有默認的運行模式,那么用戶將進入系統(tǒng)控制臺,手動決定進入何種運行模式。
sysvinit 中運行模式描述了系統(tǒng)各種預(yù)訂的運行模式。通常會有 8 種運行模式,即運行模式 0 到 6 和 S 或者 s。
每種 Linux 發(fā)行版對運行模式的定義都不太一樣。但 0,1,6 卻得到了大家的一致贊同:
- 0 關(guān)機
- 1 單用戶模式
- 6 重啟
通常在 /etc/inittab 文件中定義了各種運行模式的工作范圍。比如 RedHat 定義了 runlevel 3 和 5。運行模式 3 將系統(tǒng)初始化為字符界面的 shell 模式;運行模式 5 將系統(tǒng)初始化為 GUI 模式。無論是命令行界面還是 GUI,運行模式 3 和 5 相對于其他運行模式而言都是完整的正式的運行狀態(tài),計算機可以完成用戶需要的任務(wù)。而模式 1,S 等往往用于系統(tǒng)故障之后的排錯和恢復(fù)。
很顯然,這些不同的運行模式下系統(tǒng)需要初始化運行的進程和需要進行的初始化準(zhǔn)備都是不同的。比如運行模式 3 不需要啟動 X 系統(tǒng)。用戶只需要指定需要進入哪種模式,sysvinit 將負責(zé)執(zhí)行所有該模式所必須的初始化工作。
sysvinit 運行順序
Sysvinit 巧妙地用腳本,文件命名規(guī)則和軟鏈接來實現(xiàn)不同的 runlevel。首先,sysvinit 需要讀取/etc/inittab 文件。分析這個文件的內(nèi)容,它獲得以下一些配置信息:
- 系統(tǒng)需要進入的 runlevel
- 捕獲組合鍵的定義
- 定義電源 fail/restore 腳本
- 啟動 getty 和虛擬控制臺
得到配置信息后,sysvinit 順序地執(zhí)行以下這些步驟,從而將系統(tǒng)初始化為預(yù)訂的 runlevel X。
- /etc/rc.d/rc.sysinit
- /etc/rc.d/rc 和/etc/rc.d/rcX.d/ (X 代表運行級別 0-6)
- /etc/rc.d/rc.local
- X Display Manager(如果需要的話)
首先,運行 rc.sysinit 以便執(zhí)行一些重要的系統(tǒng)初始化任務(wù)。在 RedHat 公司的 RHEL5 中(RHEL6 已經(jīng)使用 upstart 了),rc.sysinit 主要完成以下這些工作。
- 激活 udev 和 selinux
- 設(shè)置定義在/etc/sysctl.conf 中的內(nèi)核參數(shù)
- 設(shè)置系統(tǒng)時鐘
- 加載 keymaps
- 使能交換分區(qū)
- 設(shè)置主機名(hostname)
- 根分區(qū)檢查和 remount
- 激活 RAID 和 LVM 設(shè)備
- 開啟磁盤配額
- 檢查并掛載所有文件系統(tǒng)
- 清除過期的 locks 和 PID 文件
完成了以上這些工作之后,sysvinit 開始運行/etc/rc.d/rc 腳本。根據(jù)不同的 runlevel,rc 腳本將打開對應(yīng)該 runlevel 的 rcX.d 目錄(X 就是 runlevel),找到并運行存放在該目錄下的所有啟動腳本。每個 runlevel X 都有一個這樣的目錄,目錄名為/etc/rc.d/rcX.d。
在這些目錄下存放著很多不同的腳本。文件名以 S 開頭的腳本就是啟動時應(yīng)該運行的腳本,S 后面跟的數(shù)字定義了這些腳本的執(zhí)行順序。在/etc/rc.d/rcX.d 目錄下的腳本其實都是一些軟鏈接文件,真實的腳本文件存放在/etc/init.d 目錄下。如下所示:
清單 1.rc5.d 目錄下的腳本
[root@www ~]# ll /etc/rc5.d/ lrwxrwxrwx 1 root root 16 Sep 4 2008 K02dhcdbd -> ../init.d/dhcdbd ....(中間省略).... lrwxrwxrwx 1 root root 14 Sep 4 2008 K91capi -> ../init.d/capi lrwxrwxrwx 1 root root 23 Sep 4 2008 S00microcode_ctl -> ../init.d/microcode_ctl lrwxrwxrwx 1 root root 22 Sep 4 2008 S02lvm2-monitor -> ../init.d/lvm2-monitor ....(中間省略).... lrwxrwxrwx 1 root root 17 Sep 4 2008 S10network -> ../init.d/network ....(中間省略).... lrwxrwxrwx 1 root root 11 Sep 4 2008 S99local -> ../rc.local lrwxrwxrwx 1 root root 16 Sep 4 2008 S99smartd -> ../init.d/smartd ....(底下省略)....當(dāng)所有的初始化腳本執(zhí)行完畢。Sysvinit 運行/etc/rc.d/rc.local 腳本。
rc.local 是 Linux 留給用戶進行個性化設(shè)置的地方。您可以把自己私人想設(shè)置和啟動的東西放到這里,一臺 Linux Server 的用戶一般不止一個,所以才有這樣的考慮。
Sysvinit 和系統(tǒng)關(guān)閉
Sysvinit 不僅需要負責(zé)初始化系統(tǒng),還需要負責(zé)關(guān)閉系統(tǒng)。在系統(tǒng)關(guān)閉時,為了保證數(shù)據(jù)的一致性,需要小心地按順序進行結(jié)束和清理工作。
比如應(yīng)該先停止對文件系統(tǒng)有讀寫操作的服務(wù),然后再 umount 文件系統(tǒng)。否則數(shù)據(jù)就會丟失。
這種順序的控制這也是依靠/etc/rc.d/rcX.d/目錄下所有腳本的命名規(guī)則來控制的,在該目錄下所有以 K 開頭的腳本都將在關(guān)閉系統(tǒng)時調(diào)用,字母 K 之后的數(shù)字定義了它們的執(zhí)行順序。
這些腳本負責(zé)安全地停止服務(wù)或者其他的關(guān)閉工作。
Sysvinit 的管理和控制功能
此外,在系統(tǒng)啟動之后,管理員還需要對已經(jīng)啟動的進程進行管理和控制。原始的 sysvinit 軟件包包含了一系列的控制啟動,運行和關(guān)閉所有其他程序的工具。
halt
停止系統(tǒng)。
init
這個就是 sysvinit 本身的 init 進程實體,以 pid1 身份運行,是所有用戶進程的父進程。最主要的作用是在啟動過程中使用/etc/inittab 文件創(chuàng)建進程。
killall5
就是 SystemV 的 killall 命令。向除自己的會話(session)進程之外的其它進程發(fā)出信號,所以不能殺死當(dāng)前使用的 shell。
last
回溯/var/log/wtmp 文件(或者-f 選項指定的文件),顯示自從這個文件建立以來,所有用戶的登錄情況。
lastb
作用和 last 差不多,默認情況下使用/var/log/btmp 文件,顯示所有失敗登錄企圖。
mesg
控制其它用戶對用戶終端的訪問。
pidof
找出程序的進程識別號(pid),輸出到標(biāo)準(zhǔn)輸出設(shè)備。
poweroff
等于 shutdown -h –p,或者 telinit 0。關(guān)閉系統(tǒng)并切斷電源。
reboot
等于 shutdown –r 或者 telinit 6。重啟系統(tǒng)。
runlevel
讀取系統(tǒng)的登錄記錄文件(一般是/var/run/utmp)把以前和當(dāng)前的系統(tǒng)運行級輸出到標(biāo)準(zhǔn)輸出設(shè)備。
shutdown
以一種安全的方式終止系統(tǒng),所有正在登錄的用戶都會收到系統(tǒng)將要終止通知,并且不準(zhǔn)新的登錄。
sulogin
當(dāng)系統(tǒng)進入單用戶模式時,被 init 調(diào)用。當(dāng)接收到啟動加載程序傳遞的-b 選項時,init 也會調(diào)用 sulogin。
telinit
實際是 init 的一個連接,用來向 init 傳送單字符參數(shù)和信號。
utmpdump
以一種用戶友好的格式向標(biāo)準(zhǔn)輸出設(shè)備顯示/var/run/utmp 文件的內(nèi)容。
wall
向所有有信息權(quán)限的登錄用戶發(fā)送消息。
不同的 Linux 發(fā)行版在這些 sysvinit 的基本工具基礎(chǔ)上又開發(fā)了一些輔助工具用來簡化 init 系統(tǒng)的管理工作。比如 RedHat 的 RHEL 在 sysvinit 的基礎(chǔ)上開發(fā)了 initscripts 軟件包,包含了大量的啟動腳本 (如 rc.sysinit) ,還提供了 service,chkconfig 等命令行工具,甚至一套圖形化界面來管理 init 系統(tǒng)。其他的 Linux 發(fā)行版也有各自的 initscript 或其他名字的 init 軟件包來簡化 sysvinit 的管理。
只要您理解了 sysvinit 的機制,在一個最簡的僅有 sysvinit 的系統(tǒng)下,您也可以直接調(diào)用腳本啟動和停止服務(wù),手動創(chuàng)建 inittab 和創(chuàng)建軟連接來完成這些任務(wù)。因此理解 sysvinit 的基本原理和命令是最重要的。您甚至也可以開發(fā)自己的一套管理工具。
Sysvinit 的小結(jié)
Sysvinit 的優(yōu)點是概念簡單。Service 開發(fā)人員只需要編寫啟動和停止腳本,概念非常清楚;將 service 添加/刪除到某個 runlevel 時,只需要執(zhí)行一些創(chuàng)建/刪除軟連接文件的基本操作;這些都不需要學(xué)習(xí)額外的知識或特殊的定義語法(UpStart 和 Systemd 都需要用戶學(xué)習(xí)新的定義系統(tǒng)初始化行為的語言)。
其次,sysvinit 的另一個重要優(yōu)點是確定的執(zhí)行順序:腳本嚴格按照啟動數(shù)字的大小順序執(zhí)行,一個執(zhí)行完畢再執(zhí)行下一個,這非常有益于錯誤排查。UpStart 和 systemd 支持并發(fā)啟動,導(dǎo)致沒有人可以確定地了解具體的啟動順序,排錯不易。
但是串行地執(zhí)行腳本導(dǎo)致 sysvinit 運行效率較慢,在新的 IT 環(huán)境下,啟動快慢成為一個重要問題。此外動態(tài)設(shè)備加載等 Linux 新特性也暴露出 sysvinit 設(shè)計的一些問題。針對這些問題,人們開始想辦法改進 sysvinit,以便加快啟動時間,并解決 sysvinit 自身的設(shè)計問題。
Upstart 是第一個被廣泛應(yīng)用的新一代 init 系統(tǒng)。我們在接下來的第二部分介紹 UpStart。
總結(jié)
以上是生活随笔為你收集整理的浅析 Linux 初始化 init 系统,第 1 部分: sysvinit的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Oracle PL SQL 精萃pdf
- 下一篇: linux 其他常用命令