從 sysvinit 到 systemd
近年來,Linux 系統(tǒng)的 init 進(jìn)程經(jīng)歷了兩次重大的演進(jìn),傳統(tǒng)的 sysvinit 已經(jīng)淡出歷史舞臺(tái),新的 init 系統(tǒng) UpStart 和 systemd 各有特點(diǎn),而越來越多的 Linux 發(fā)行版采納了 systemd。本文簡要介紹了這三種 init 系統(tǒng)的使用和原理,每個(gè) Linux 系統(tǒng)管理員和系統(tǒng)軟件開發(fā)者都應(yīng)該了解它們,以便更好地管理系統(tǒng)和開發(fā)應(yīng)用。本文是系列的第一部分,主要講述 sysvinit 的特點(diǎn)和使用。
劉 明, 軟件工程師, 上海交通大學(xué)通信與電子工程系
Linux 操作系統(tǒng)的啟動(dòng)首先從 BIOS 開始,接下來進(jìn)入 boot loader,由 bootloader 載入內(nèi)核,進(jìn)行內(nèi)核初始化。內(nèi)核初始化的最后一步就是啟動(dòng) pid 為 1 的 init 進(jìn)程。這個(gè)進(jìn)程是系統(tǒng)的第一個(gè)進(jìn)程。它負(fù)責(zé)產(chǎn)生其他所有用戶進(jìn)程。
init 以守護(hù)進(jìn)程方式存在,是所有其他進(jìn)程的祖先。init 進(jìn)程非常獨(dú)特,能夠完成其他進(jìn)程無法完成的任務(wù)。
Init 系統(tǒng)能夠定義、管理和控制 init 進(jìn)程的行為。它負(fù)責(zé)組織和運(yùn)行許多獨(dú)立的或相關(guān)的始化工作(因此被稱為 init 系統(tǒng)),從而讓計(jì)算機(jī)系統(tǒng)進(jìn)入某種用戶預(yù)訂的運(yùn)行模式。
僅僅將內(nèi)核運(yùn)行起來是毫無實(shí)際用途的,必須由 init 系統(tǒng)將系統(tǒng)代入可操作狀態(tài)。比如啟動(dòng)外殼 shell 后,便有了人機(jī)交互,這樣就可以讓計(jì)算機(jī)執(zhí)行一些預(yù)訂程序完成有實(shí)際意義的任務(wù)。或者啟動(dòng) X 圖形系統(tǒng)以便提供更佳的人機(jī)界面,更加高效的完成任務(wù)。這里,字符界面的 shell 或者 X 系統(tǒng)都是一種預(yù)設(shè)的運(yùn)行模式。
大多數(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 開始使用了一個(gè)被稱為 systemd 的新 init 系統(tǒng)。
可以看到不同的發(fā)行版采用了不同的 init 實(shí)現(xiàn),本系列文章就是打算講述三個(gè)主要的 Init 系統(tǒng):sysvinit,UpStart 和 systemd。了解它們各自的設(shè)計(jì)特點(diǎn),并簡要介紹它們的使用。
在 Linux 主要應(yīng)用于服務(wù)器和 PC 機(jī)的時(shí)代,SysVinit 運(yùn)行非常良好,概念簡單清晰。它主要依賴于 Shell 腳本,這就決定了它的最大弱點(diǎn):啟動(dòng)太慢。在很少重新啟動(dòng)的 Server 上,這個(gè)缺點(diǎn)并不重要。而當(dāng) Linux 被應(yīng)用到移動(dòng)終端設(shè)備的時(shí)候,啟動(dòng)慢就成了一個(gè)大問題。為了更快地啟動(dòng),人們開始改進(jìn) sysvinit,先后出現(xiàn)了 upstart 和 systemd 這兩個(gè)主要的新一代 init 系統(tǒng)。Upstart 已經(jīng)開發(fā)了 8 年多,在不少系統(tǒng)中已經(jīng)替換 sysvinit。Systemd 出現(xiàn)較晚,但發(fā)展更快,大有取代 upstart 的趨勢。
本文的第一部分先簡要介紹 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ù)訂的運(yùn)行模式"。Sysvinit 檢查 '/etc/inittab' 文件中是否含有 'initdefault' 項(xiàng)。 這告訴 init 系統(tǒng)是否有一個(gè)默認(rèn)運(yùn)行模式。如果沒有默認(rèn)的運(yùn)行模式,那么用戶將進(jìn)入系統(tǒng)控制臺(tái),手動(dòng)決定進(jìn)入何種運(yùn)行模式。
sysvinit 中運(yùn)行模式描述了系統(tǒng)各種預(yù)訂的運(yùn)行模式。通常會(huì)有 8 種運(yùn)行模式,即運(yùn)行模式 0 到 6 和 S 或者 s。
每種 Linux 發(fā)行版對(duì)運(yùn)行模式的定義都不太一樣。但 0,1,6 卻得到了大家的一致贊同:
通常在 /etc/inittab 文件中定義了各種運(yùn)行模式的工作范圍。比如 RedHat 定義了 runlevel 3 和 5。運(yùn)行模式 3 將系統(tǒng)初始化為字符界面的 shell 模式;運(yùn)行模式 5 將系統(tǒng)初始化為 GUI 模式。無論是命令行界面還是 GUI,運(yùn)行模式 3 和 5 相對(duì)于其他運(yùn)行模式而言都是完整的正式的運(yùn)行狀態(tài),計(jì)算機(jī)可以完成用戶需要的任務(wù)。而模式 1,S 等往往用于系統(tǒng)故障之后的排錯(cuò)和恢復(fù)。
很顯然,這些不同的運(yùn)行模式下系統(tǒng)需要初始化運(yùn)行的進(jìn)程和需要進(jìn)行的初始化準(zhǔn)備都是不同的。比如運(yùn)行模式 3 不需要啟動(dòng) X 系統(tǒng)。用戶只需要指定需要進(jìn)入哪種模式,sysvinit 將負(fù)責(zé)執(zhí)行所有該模式所必須的初始化工作。
Sysvinit 巧妙地用腳本,文件命名規(guī)則和軟鏈接來實(shí)現(xiàn)不同的 runlevel。首先,sysvinit 需要讀取/etc/inittab 文件。分析這個(gè)文件的內(nèi)容,它獲得以下一些配置信息:
得到配置信息后,sysvinit 順序地執(zhí)行以下這些步驟,從而將系統(tǒng)初始化為預(yù)訂的 runlevel X。
首先,運(yùn)行 rc.sysinit 以便執(zhí)行一些重要的系統(tǒng)初始化任務(wù)。在 RedHat 公司的 RHEL5 中(RHEL6 已經(jīng)使用 upstart 了),rc.sysinit 主要完成以下這些工作。
完成了以上這些工作之后,sysvinit 開始運(yùn)行/etc/rc.d/rc 腳本。根據(jù)不同的 runlevel,rc 腳本將打開對(duì)應(yīng)該 runlevel 的 rcX.d 目錄(X 就是 runlevel),找到并運(yùn)行存放在該目錄下的所有啟動(dòng)腳本。每個(gè) runlevel X 都有一個(gè)這樣的目錄,目錄名為/etc/rc.d/rcX.d。
在這些目錄下存放著很多不同的腳本。文件名以 S 開頭的腳本就是啟動(dòng)時(shí)應(yīng)該運(yùn)行的腳本,S 后面跟的數(shù)字定義了這些腳本的執(zhí)行順序。在/etc/rc.d/rcX.d 目錄下的腳本其實(shí)都是一些軟鏈接文件,真實(shí)的腳本文件存放在/etc/init.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/capilrwxrwxrwx 1 root root 23 Sep 4 2008 S00microcode_ctl -> ../init.d/microcode_ctllrwxrwxrwx 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.locallrwxrwxrwx 1 root root 16 Sep 4 2008 S99smartd -> ../init.d/smartd....(底下省略)....
當(dāng)所有的初始化腳本執(zhí)行完畢。Sysvinit 運(yùn)行/etc/rc.d/rc.local 腳本。
rc.local 是 Linux 留給用戶進(jìn)行個(gè)性化設(shè)置的地方。您可以把自己私人想設(shè)置和啟動(dòng)的東西放到這里,一臺(tái) Linux Server 的用戶一般不止一個(gè),所以才有這樣的考慮。
Sysvinit 不僅需要負(fù)責(zé)初始化系統(tǒng),還需要負(fù)責(zé)關(guān)閉系統(tǒng)。在系統(tǒng)關(guān)閉時(shí),為了保證數(shù)據(jù)的一致性,需要小心地按順序進(jìn)行結(jié)束和清理工作。
比如應(yīng)該先停止對(duì)文件系統(tǒng)有讀寫操作的服務(wù),然后再 umount 文件系統(tǒng)。否則數(shù)據(jù)就會(huì)丟失。
這種順序的控制這也是依靠/etc/rc.d/rcX.d/目錄下所有腳本的命名規(guī)則來控制的,在該目錄下所有以 K 開頭的腳本都將在關(guān)閉系統(tǒng)時(shí)調(diào)用,字母 K 之后的數(shù)字定義了它們的執(zhí)行順序。
這些腳本負(fù)責(zé)安全地停止服務(wù)或者其他的關(guān)閉工作。
此外,在系統(tǒng)啟動(dòng)之后,管理員還需要對(duì)已經(jīng)啟動(dòng)的進(jìn)程進(jìn)行管理和控制。原始的 sysvinit 軟件包包含了一系列的控制啟動(dòng),運(yùn)行和關(guān)閉所有其他程序的工具。
halt
停止系統(tǒng)。
init
這個(gè)就是 sysvinit 本身的 init 進(jìn)程實(shí)體,以 pid1 身份運(yùn)行,是所有用戶進(jìn)程的父進(jìn)程。最主要的作用是在啟動(dòng)過程中使用/etc/inittab 文件創(chuàng)建進(jìn)程。
killall5
就是 SystemV 的 killall 命令。向除自己的會(huì)話(session)進(jìn)程之外的其它進(jìn)程發(fā)出信號(hào),所以不能殺死當(dāng)前使用的 shell。
last
回溯/var/log/wtmp 文件(或者-f 選項(xiàng)指定的文件),顯示自從這個(gè)文件建立以來,所有用戶的登錄情況。
lastb
作用和 last 差不多,默認(rèn)情況下使用/var/log/btmp 文件,顯示所有失敗登錄企圖。
mesg
控制其它用戶對(duì)用戶終端的訪問。
pidof
找出程序的進(jìn)程識(shí)別號(hào)(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)運(yùn)行級(jí)輸出到標(biāo)準(zhǔn)輸出設(shè)備。
shutdown
以一種安全的方式終止系統(tǒng),所有正在登錄的用戶都會(huì)收到系統(tǒng)將要終止通知,并且不準(zhǔn)新的登錄。
sulogin
當(dāng)系統(tǒng)進(jìn)入單用戶模式時(shí),被 init 調(diào)用。當(dāng)接收到啟動(dòng)加載程序傳遞的-b 選項(xiàng)時(shí),init 也會(huì)調(diào)用 sulogin。
telinit
實(shí)際是 init 的一個(gè)連接,用來向 init 傳送單字符參數(shù)和信號(hào)。
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 軟件包,包含了大量的啟動(dòng)腳本 (如 rc.sysinit) ,還提供了 service,chkconfig 等命令行工具,甚至一套圖形化界面來管理 init 系統(tǒng)。其他的 Linux 發(fā)行版也有各自的 initscript 或其他名字的 init 軟件包來簡化 sysvinit 的管理。
只要您理解了 sysvinit 的機(jī)制,在一個(gè)最簡的僅有 sysvinit 的系統(tǒng)下,您也可以直接調(diào)用腳本啟動(dòng)和停止服務(wù),手動(dòng)創(chuàng)建 inittab 和創(chuàng)建軟連接來完成這些任務(wù)。因此理解 sysvinit 的基本原理和命令是最重要的。您甚至也可以開發(fā)自己的一套管理工具。
Sysvinit 的優(yōu)點(diǎn)是概念簡單。Service 開發(fā)人員只需要編寫啟動(dòng)和停止腳本,概念非常清楚;將 service 添加/刪除到某個(gè) runlevel 時(shí),只需要執(zhí)行一些創(chuàng)建/刪除軟連接文件的基本操作;這些都不需要學(xué)習(xí)額外的知識(shí)或特殊的定義語法(UpStart 和 Systemd 都需要用戶學(xué)習(xí)新的定義系統(tǒng)初始化行為的語言)。
其次,sysvinit 的另一個(gè)重要優(yōu)點(diǎn)是確定的執(zhí)行順序:腳本嚴(yán)格按照啟動(dòng)數(shù)字的大小順序執(zhí)行,一個(gè)執(zhí)行完畢再執(zhí)行下一個(gè),這非常有益于錯(cuò)誤排查。UpStart 和 systemd 支持并發(fā)啟動(dòng),導(dǎo)致沒有人可以確定地了解具體的啟動(dòng)順序,排錯(cuò)不易。
但是串行地執(zhí)行腳本導(dǎo)致 sysvinit 運(yùn)行效率較慢,在新的 IT 環(huán)境下,啟動(dòng)快慢成為一個(gè)重要問題。此外動(dòng)態(tài)設(shè)備加載等 Linux 新特性也暴露出 sysvinit 設(shè)計(jì)的一些問題。針對(duì)這些問題,人們開始想辦法改進(jìn) sysvinit,以便加快啟動(dòng)時(shí)間,并解決 sysvinit 自身的設(shè)計(jì)問題。
Upstart 是第一個(gè)被廣泛應(yīng)用的新一代 init 系統(tǒng)。我們在接下來的第二部分介紹 UpStart。
從 sysvinit 到 systemd
近年來,Linux 系統(tǒng)的 init 進(jìn)程經(jīng)歷了兩次重大的演進(jìn),傳統(tǒng)的 sysvinit 已經(jīng)淡出歷史舞臺(tái),新系統(tǒng) UpStart 和 systemd 各有特點(diǎn),而越來越多的 Linux 發(fā)行版采納了 systemd。本文簡要介紹了這三種 init 系統(tǒng)的使用和原理,每個(gè) Linux 系統(tǒng)管理員和系統(tǒng)軟件開發(fā)者都應(yīng)該了解它們,以便更好地管理系統(tǒng)和開發(fā)應(yīng)用。本文是系列的第二部分,主要講述 UpStart 的特點(diǎn)和使用。
假如您使用的 Linux 發(fā)行版是 Ubuntu,很可能會(huì)發(fā)現(xiàn)在您的計(jì)算機(jī)上找不到/etc/inittab 文件了,這是因?yàn)?Ubuntu 使用了一種被稱為 upstart 的新型 init 系統(tǒng)。
大約在 2006 年或者更早的時(shí)候, Ubuntu 開發(fā)人員試圖將 Linux 安裝在筆記本電腦上。在這期間技術(shù)人員發(fā)現(xiàn)經(jīng)典的 sysvinit 存在一些問題:它不適合筆記本環(huán)境。這促使程序員 Scott James Remnant 著手開發(fā) upstart。
當(dāng) Linux 內(nèi)核進(jìn)入 2.6 時(shí)代時(shí),內(nèi)核功能有了很多新的更新。新特性使得 Linux 不僅是一款優(yōu)秀的服務(wù)器操作系統(tǒng),也可以被用于桌面系統(tǒng),甚至嵌入式設(shè)備。桌面系統(tǒng)或便攜式設(shè)備的一個(gè)特點(diǎn)是經(jīng)常重啟,而且要頻繁地使用硬件熱插拔技術(shù)。在現(xiàn)代計(jì)算機(jī)系統(tǒng)中,硬件繁多、接口有限,人們并非將所有設(shè)備都始終連接在計(jì)算機(jī)上,比如 U 盤平時(shí)并不連接電腦,使用時(shí)才插入 USB 插口。因此,當(dāng)系統(tǒng)上電啟動(dòng)時(shí),一些外設(shè)可能并沒有連接。而是在啟動(dòng)后當(dāng)需要的時(shí)候才連接這些設(shè)備。在 2.6 內(nèi)核支持下,一旦新外設(shè)連接到系統(tǒng),內(nèi)核便可以自動(dòng)實(shí)時(shí)地發(fā)現(xiàn)它們,并初始化這些設(shè)備,進(jìn)而使用它們。這為便攜式設(shè)備用戶提供了很大的靈活性。
可是這些特性為 sysvinit 帶來了一些挑戰(zhàn)。當(dāng)系統(tǒng)初始化時(shí),需要被初始化的設(shè)備并沒有連接到系統(tǒng)上;比如打印機(jī)。為了管理打印任務(wù),系統(tǒng)需要啟動(dòng) CUPS 等服務(wù),而如果打印機(jī)沒有接入系統(tǒng)的情況下,啟動(dòng)這些服務(wù)就是一種浪費(fèi)。Sysvinit 沒有辦法處理這類需求,它必須一次性把所有可能用到的服務(wù)都啟動(dòng)起來,即使打印機(jī)并沒有連接到系統(tǒng),CUPS 服務(wù)也必須啟動(dòng)。
還有網(wǎng)絡(luò)共享盤的掛載問題。在/etc/fstab 中,可以指定系統(tǒng)自動(dòng)掛載一個(gè)網(wǎng)絡(luò)盤,比如 NFS,或者 iSCSI 設(shè)備。在本文的第一部分 sysvinit 的簡介中可以看到,sysvinit 分析/etc/fstab 掛載文件系統(tǒng)這個(gè)步驟是在網(wǎng)絡(luò)啟動(dòng)之前??墒侨绻W(wǎng)絡(luò)沒有啟動(dòng),NFS 或者 iSCSI 都不可訪問,當(dāng)然也無法進(jìn)行掛載操作。Sysvinit 采用 netdev 的方式來解決這個(gè)問題,即/etc/fstab 發(fā)現(xiàn) netdev 屬性掛載點(diǎn)的時(shí)候,不嘗試掛載它,在網(wǎng)絡(luò)初始化并使能之后,還有一個(gè)專門的 netfs 服務(wù)來掛載所有這些網(wǎng)絡(luò)盤。這是一個(gè)不得已的補(bǔ)救方法,給管理員帶來不便。部分新手管理員甚至從來也沒有聽說過 netdev 選項(xiàng),因此經(jīng)常成為系統(tǒng)管理的一個(gè)陷阱。
針對(duì)以上種種情況,Ubuntu 開發(fā)人員在評(píng)估了當(dāng)時(shí)的幾個(gè)可選 init 系統(tǒng)之后,決定重新設(shè)計(jì)和開發(fā)一個(gè)全新的 init 系統(tǒng),即 UpStart。UpStart 基于事件機(jī)制,比如 U 盤插入 USB 接口后,udev 得到內(nèi)核通知,發(fā)現(xiàn)該設(shè)備,這就是一個(gè)新的事件。UpStart 在感知到該事件之后觸發(fā)相應(yīng)的等待任務(wù),比如處理/etc/fstab 中存在的掛載點(diǎn)。采用這種事件驅(qū)動(dòng)的模式,upstart 完美地解決了即插即用設(shè)備帶來的新問題。
此外,采用事件驅(qū)動(dòng)機(jī)制也帶來了一些其它有益的變化,比如加快了系統(tǒng)啟動(dòng)時(shí)間。sysvinit 運(yùn)行時(shí)是同步阻塞的。一個(gè)腳本運(yùn)行的時(shí)候,后續(xù)腳本必須等待。這意味著所有的初始化步驟都是串行執(zhí)行的,而實(shí)際上很多服務(wù)彼此并不相關(guān),完全可以并行啟動(dòng),從而減小系統(tǒng)的啟動(dòng)時(shí)間。在 Linux 大量應(yīng)用于服務(wù)器的時(shí)代,系統(tǒng)啟動(dòng)時(shí)間也許還不那么重要;然而對(duì)于桌面系統(tǒng)和便攜式設(shè)備,啟動(dòng)時(shí)間的長短對(duì)用戶體驗(yàn)影響很大。此外云計(jì)算等新的 Server 端技術(shù)也往往需要單個(gè)設(shè)備可以更加快速地啟動(dòng)。
UpStart 滿足了這些需求,目前不僅桌面系統(tǒng) Ubuntu 采用了 UpStart,甚至企業(yè)級(jí)服務(wù)器級(jí)的 RHEL 也默認(rèn)采用 UpStart 來替換 sysvinit 作為 init 系統(tǒng)。
UpStart 解決了之前提到的 sysvinit 的缺點(diǎn)。采用事件驅(qū)動(dòng)模型,UpStart 可以:
這些特點(diǎn)使得 UpStart 可以很好地應(yīng)用在桌面或者便攜式系統(tǒng)中,處理這些系統(tǒng)中的動(dòng)態(tài)硬件插拔特性。
Upstart 的基本概念和設(shè)計(jì)清晰明確。UpStart 主要的概念是 job 和 event。Job 就是一個(gè)工作單元,用來完成一件工作,比如啟動(dòng)一個(gè)后臺(tái)服務(wù),或者運(yùn)行一個(gè)配置命令。每個(gè) Job 都等待一個(gè)或多個(gè)事件,一旦事件發(fā)生,upstart 就觸發(fā)該 job 完成相應(yīng)的工作。
Job 就是一個(gè)工作的單元,一個(gè)任務(wù)或者一個(gè)服務(wù)。可以理解為 sysvinit 中的一個(gè)服務(wù)腳本。有三種類型的工作:
task job 代表在一定時(shí)間內(nèi)會(huì)執(zhí)行完畢的任務(wù),比如刪除一個(gè)文件;
service job 代表后臺(tái)服務(wù)進(jìn)程,比如 apache httpd。這里進(jìn)程一般不會(huì)退出,一旦開始運(yùn)行就成為一個(gè)后臺(tái)精靈進(jìn)程,由 init 進(jìn)程管理,如果這類進(jìn)程退出,由 init 進(jìn)程重新啟動(dòng),它們只能由 init 進(jìn)程發(fā)送信號(hào)停止。它們的停止一般也是由于所依賴的停止事件而觸發(fā)的,不過 upstart 也提供命令行工具,讓管理人員手動(dòng)停止某個(gè)服務(wù);
Abstract job 僅由 upstart 內(nèi)部使用,僅對(duì)理解 upstart 內(nèi)部機(jī)理有所幫助。我們不用關(guān)心它。
除了以上的分類之外,還有另一種工作(Job)分類方法。Upstart 不僅可以用來為整個(gè)系統(tǒng)的初始化服務(wù),也可以為每個(gè)用戶會(huì)話(session)的初始化服務(wù)。系統(tǒng)的初始化任務(wù)就叫做 system job,比如掛載文件系統(tǒng)的任務(wù)就是一個(gè) system job;用戶會(huì)話的初始化服務(wù)就叫做 session job。
Upstart 為每個(gè)工作都維護(hù)一個(gè)生命周期。一般來說,工作有開始,運(yùn)行和結(jié)束這幾種狀態(tài)。為了更精細(xì)地描述工作的變化,Upstart 還引入了一些其它的狀態(tài)。比如開始就有開始之前(pre-start),即將開始(starting)和已經(jīng)開始了(started)幾種不同的狀態(tài),這樣可以更加精確地描述工作的當(dāng)前狀態(tài)。
工作從某種初始狀態(tài)開始,逐漸變化,或許要經(jīng)歷其它幾種不同的狀態(tài),最終進(jìn)入另外一種狀態(tài),形成一個(gè)狀態(tài)機(jī)。在這個(gè)過程中,當(dāng)工作的狀態(tài)即將發(fā)生變化的時(shí)候,init 進(jìn)程會(huì)發(fā)出相應(yīng)的事件(event)。
狀態(tài)名 | 含義 |
---|---|
Waiting | 初始狀態(tài) |
Starting | Job 即將開始 |
pre-start | 執(zhí)行 pre-start 段,即任務(wù)開始前應(yīng)該完成的工作 |
Spawned | 準(zhǔn)備執(zhí)行 script 或者 exec 段 |
post-start | 執(zhí)行 post-start 動(dòng)作 |
Running | interim state set after post-start section processed denoting job is running (But it may have no associated PID!) |
pre-stop | 執(zhí)行 pre-stop 段 |
Stopping | interim state set after pre-stop section processed |
Killed | 任務(wù)即將被停止 |
post-stop | 執(zhí)行 post-stop 段 |
圖 1 展示了 Job 的狀態(tài)機(jī)。
其中有四個(gè)狀態(tài)會(huì)引起 init 進(jìn)程發(fā)送相應(yīng)的事件,表明該工作的相應(yīng)變化:
而其它的狀態(tài)變化不會(huì)發(fā)出事件。那么我們接下來就來看看事件的詳細(xì)含義吧。
顧名思義,Event 就是一個(gè)事件。事件在 upstart 中以通知消息的形式具體存在。一旦某個(gè)事件發(fā)生了,Upstart 就向整個(gè)系統(tǒng)發(fā)送一個(gè)消息。沒有任何手段阻止事件消息被 upstart 的其它部分知曉,也就是說,事件一旦發(fā)生,整個(gè) upstart 系統(tǒng)中所有工作和其它的事件都會(huì)得到通知。
Event 可以分為三類: signal,methods 或者 hooks。
Signals
Signal 事件是非阻塞的,異步的。發(fā)送一個(gè)信號(hào)之后控制權(quán)立即返回。
Methods
Methods 事件是阻塞的,同步的。
Hooks
Hooks 事件是阻塞的,同步的。它介于 Signals 和 Methods 之間,調(diào)用發(fā)出 Hooks 事件的進(jìn)程必須等待事件完成才可以得到控制權(quán),但不檢查事件是否成功。
事件是個(gè)非常抽象的概念,下面我羅列出一些常見的事件,希望可以幫助您進(jìn)一步了解事件的含義:
不同的 Linux 發(fā)行版對(duì) upstart 有不同的定制和實(shí)現(xiàn),實(shí)現(xiàn)和支持的事件也有所不同,可以用man 7 upstart-events
來查看事件列表。
Upstart 就是由事件觸發(fā)工作運(yùn)行的一個(gè)系統(tǒng),每一個(gè)程序的運(yùn)行都由其依賴的事件發(fā)生而觸發(fā)的。
系統(tǒng)初始化的過程是在工作和事件的相互協(xié)作下完成的,可以大致描述如下:系統(tǒng)初始化時(shí),init 進(jìn)程開始運(yùn)行,init 進(jìn)程自身會(huì)發(fā)出不同的事件,這些最初的事件會(huì)觸發(fā)一些工作運(yùn)行。每個(gè)工作運(yùn)行過程中會(huì)釋放不同的事件,這些事件又將觸發(fā)新的工作運(yùn)行。如此反復(fù),直到整個(gè)系統(tǒng)正常運(yùn)行起來。
究竟哪些事件會(huì)觸發(fā)某個(gè)工作的運(yùn)行?這是由工作配置文件定義的。
任何一個(gè)工作都是由一個(gè)工作配置文件(Job Configuration File)定義的。這個(gè)文件是一個(gè)文本文件,包含一個(gè)或者多個(gè)小節(jié)(stanza)。每個(gè)小節(jié)是一個(gè)完整的定義模塊,定義了工作的一個(gè)方面,比如 author 小節(jié)定義了工作的作者。工作配置文件存放在/etc/init 下面,是以.conf 作為文件后綴的文件。
#This is a simple demo of Job Configure file#This line is comment, start with ##Stanza 1, The authorauthor “Liu Ming”#Stanza 2, Descriptiondescription “This job only has author and description, so no use, just a demo”
上面的例子不會(huì)產(chǎn)生任何作用,一個(gè)真正的工作配置文件會(huì)包含很多小節(jié),其中比較重要的小節(jié)有以下幾個(gè):
"expect" Stanza
Upstart 除了負(fù)責(zé)系統(tǒng)的啟動(dòng)過程之外,和 SysVinit 一樣,Upstart 還提供一系列的管理工具。當(dāng)系統(tǒng)啟動(dòng)之后,管理員可能還需要進(jìn)行維護(hù)和調(diào)整,比如啟動(dòng)或者停止某項(xiàng)系統(tǒng)服務(wù)。或者將系統(tǒng)切換到其它的工作狀態(tài),比如改變運(yùn)行級(jí)別。本文后續(xù)將詳細(xì)介紹 Upstart 的管理工具的使用。
為了啟動(dòng),停止,重啟和查詢某個(gè)系統(tǒng)服務(wù)。Upstart 需要跟蹤該服務(wù)所對(duì)應(yīng)的進(jìn)程。比如 httpd 服務(wù)的進(jìn)程 PID 為 1000。當(dāng)用戶需要查詢 httpd 服務(wù)是否正常運(yùn)行時(shí),Upstart 就可以利用 ps 命令查詢進(jìn)程 1000,假如它還在正常運(yùn)行,則表明服務(wù)正常。當(dāng)用戶需要停止 httpd 服務(wù)時(shí),Upstart 就使用 kill 命令終止該進(jìn)程。為此,Upstart 必須跟蹤服務(wù)進(jìn)程的進(jìn)程號(hào)。
部分服務(wù)進(jìn)程為了將自己變成后臺(tái)精靈進(jìn)程(daemon),會(huì)采用兩次派生(fork)的技術(shù),另外一些服務(wù)則不會(huì)這樣做。假如一個(gè)服務(wù)派生了兩次,那么 UpStart 必須采用第二個(gè)派生出來的進(jìn)程號(hào)作為服務(wù)的 PID。但是,UpStart 本身無法判斷服務(wù)進(jìn)程是否會(huì)派生兩次,為此在定義該服務(wù)的工作配置文件中必須寫明 expect 小節(jié),告訴 UpStart 進(jìn)程是否會(huì)派生兩次。
Expect 有兩種,"expect fork"表示進(jìn)程只會(huì) fork 一次;"expect daemonize"表示進(jìn)程會(huì) fork 兩次。
"exec" Stanza 和"script" Stanza
一個(gè) UpStart 工作一定需要做些什么,可能是運(yùn)行一條 shell 命令,或者運(yùn)行一段腳本。用"exec"關(guān)鍵字配置工作需要運(yùn)行的命令;用"script"關(guān)鍵字定義需要運(yùn)行的腳本。
清單 2 顯示了 exec 和 script 的用法:
# mountall.confdescription “Mount filesystems on boot”start on startupstop on starting rcS...script . /etc/default/rcS [ -f /forcefsck ] && force_fsck=”--force-fsck” [ “$FSCKFIX”=”yes” ] && fsck_fix=”--fsck-fix” ... exec mountall –daemon $force_fsck $fsck_fixend script...
這是 mountall 的例子,該工作在系統(tǒng)啟動(dòng)時(shí)運(yùn)行,負(fù)責(zé)掛載所有的文件系統(tǒng)。該工作需要執(zhí)行復(fù)雜的腳本,由"script"關(guān)鍵字定義;在腳本中,使用了 exec 來執(zhí)行 mountall 命令。
"start on" Stanza 和"stop on" Stanza
"start on"定義了觸發(fā)工作的所有事件。"start on"的語法很簡單,如下所示:
start on EVENT [[KEY=]VALUE]... [and|or...]
EVENT 表示事件的名字,可以在 start on 中指定多個(gè)事件,表示該工作的開始需要依賴多個(gè)事件發(fā)生。多個(gè)事件之間可以用 and 或者 or 組合,"表示全部都必須發(fā)生"或者"其中之一發(fā)生即可"等不同的依賴條件。除了事件發(fā)生之外,工作的啟動(dòng)還可以依賴特定的條件,因此在 start on 的 EVENT 之后,可以用 KEY=VALUE 來表示額外的條件,一般是某個(gè)環(huán)境變量(KEY)和特定值(VALUE)進(jìn)行比較。如果只有一個(gè)變量,或者變量的順序已知,則 KEY 可以省略。
"stop on"和"start on"非常類似,只不過是定義工作在什么情況下需要停止。
代碼清單 3 是"start on"和"stop on"的一個(gè)例子。
#dbus.confdescription “D-Bus system message bus”start on local-filesystemsstop on deconfiguring-networking…
D-Bus 是一個(gè)系統(tǒng)消息服務(wù),上面的配置文件表明當(dāng)系統(tǒng)發(fā)出 local-filesystems 事件時(shí)啟動(dòng) D-Bus;當(dāng)系統(tǒng)發(fā)出 deconfiguring-networking 事件時(shí),停止 D-Bus 服務(wù)。
UpStart 還可以用于管理用戶會(huì)話的初始化。在我寫這篇文章的今天,多數(shù) Linux 發(fā)行版還沒有使用 UpStart 管理會(huì)話。只有在 Ubuntu Raring 版本中,使用 UpStart 管理用戶會(huì)話的初始化過程。
首先讓我們了解一下 Session 的概念。Session 就是一個(gè)用戶會(huì)話,即用戶從遠(yuǎn)程或者本地登入系統(tǒng)開始工作,直到用戶退出。這整個(gè)過程就構(gòu)成一個(gè)會(huì)話。
每個(gè)用戶的使用習(xí)慣和使用方法都不相同,因此用戶往往需要為自己的會(huì)話做一個(gè)定制,比如添加特定的命令別名,啟動(dòng)特殊的應(yīng)用程序或者服務(wù),等等。這些工作都屬于對(duì)特定會(huì)話的初始化操作,因此可以被稱為 Session Init。
用戶使用 Linux 可以有兩種模式:字符模式和圖形界面。在字符模式下,會(huì)話初始化相對(duì)簡單。用戶登錄后只能啟動(dòng)一個(gè) Shell,通過 shell 命令使用系統(tǒng)。各種 shell 程序都支持一個(gè)自動(dòng)運(yùn)行的啟動(dòng)腳本,比如~/.bashrc。用戶在這些腳本中加入需要運(yùn)行的定制化命令。字符會(huì)話需求簡單,因此這種現(xiàn)有的機(jī)制工作的很好。
在圖形界面下,事情就變得復(fù)雜一些。用戶登錄后看到的并不是一個(gè) shell 提示符,而是一個(gè)桌面。一個(gè)完整的桌面環(huán)境由很多組件組成。
一個(gè)桌面環(huán)境包括 window manager,panel 以及其它一些定義在/usr/share/gnome-session/sessions/下面的基本組件;此外還有一些輔助的應(yīng)用程序,共同幫助構(gòu)成一個(gè)完整的方便的桌面,比如 system monitors,panel applets,NetworkManager,Bluetooth,printers 等。當(dāng)用戶登錄之后,這些組件都需要被初始化,這個(gè)過程比字符界面要復(fù)雜的多。目前啟動(dòng)各種圖形組件和應(yīng)用的工作由 gnome-session 完成。過程如下:
以 Ubuntu 為例,當(dāng)用戶登錄 Ubuntu 圖形界面后,顯示管理器(Display Manager)lightDM 啟動(dòng) Xsession。Xsession 接著啟動(dòng) gnome-session,gnome-session 負(fù)責(zé)其它的初始化工作,然后就開始了一個(gè) desktop session。
init |- lightdm | |- Xorg | |- lightdm ---session-child | |- gnome-session --session=ubuntu | |- compiz | |- gwibber | |- nautilus | |- nm-applet | : | : | |- dbus-daemon --session | : :
這個(gè)過程有一些缺點(diǎn)(和 sysVInit 類似)。一些應(yīng)用和組件其實(shí)并不需要在會(huì)話初始化過程中啟動(dòng),更好的選擇是在需要它們的時(shí)候才啟動(dòng)。比如 update-notifier 服務(wù),該服務(wù)不停地監(jiān)測幾個(gè)文件系統(tǒng)路徑,一旦這些路徑上發(fā)現(xiàn)可以更新的軟件包,就提醒用戶。這些文件系統(tǒng)路徑包括新插入的 DVD 盤等。Update-notifier 由 gnome-session 啟動(dòng)并一直運(yùn)行著,在多數(shù)情況下,用戶并不會(huì)插入新的 DVD,此時(shí) update-notifier 服務(wù)一直在后臺(tái)運(yùn)行并消耗系統(tǒng)資源。更好的模式是當(dāng)用戶插入 DVD 的時(shí)候再運(yùn)行 update-notifier。這樣可以加快啟動(dòng)時(shí)間,減小系統(tǒng)運(yùn)行過程中的內(nèi)存等系統(tǒng)資源的開銷。對(duì)于移動(dòng),嵌入式等設(shè)備等這還意味著省電。除了 Update-notifier 服務(wù)之外,還有其它一些類似的服務(wù)。比如 Network Manager,一天之內(nèi)用戶很少切換網(wǎng)絡(luò)設(shè)備,所以大部分時(shí)間 Network Manager 服務(wù)僅僅是在浪費(fèi)系統(tǒng)資源;再比如 backup manager 等其它常駐內(nèi)存,后臺(tái)不間斷運(yùn)行卻很少真正被使用的服務(wù)。
用 UpStart 的基于事件的按需啟動(dòng)的模式就可以很好地解決這些問題,比如用戶插入網(wǎng)線的時(shí)候才啟動(dòng) Network Manager,因?yàn)橛脩舨迦刖W(wǎng)線表明需要使用網(wǎng)絡(luò),這可以被稱為按需啟動(dòng)。
下圖描述了采用 UpStart 之后的會(huì)話初始化過程。
init |- lightdm | |- Xorg | |- lightdm ---session-child | |- session-init # <-- upstart running as normal user | |- dbus-daemon --session | |- gnome-session --session=ubuntu | |- compiz | |- gwibber | |- nautilus | |- nm-applet | : | : : :
有兩種人員需要了解 Upstart 的使用。第一類是系統(tǒng)開發(fā)人員,比如 MySQL 的開發(fā)人員。它們需要了解如何編寫工作配置文件,以便用 UpStart 來管理服務(wù)。比如啟動(dòng),停止 MySQL 服務(wù)。
另外一種情況是系統(tǒng)管理員,它們需要掌握 Upstart 的管理命令以便配置和管理系統(tǒng)的初始化,管理系統(tǒng)服務(wù)。
系統(tǒng)開發(fā)人員不僅需要掌握工作配置文件的寫法,還需要了解一些針對(duì)服務(wù)進(jìn)程編程上的要求。本文僅列出了少數(shù)工作配置文件的語法。要全面掌握工作配置文件的寫法,需要詳細(xì)閱讀 Upstart 的手冊。這里讓我們來分析一下如何用 Upstart 來實(shí)現(xiàn)傳統(tǒng)的運(yùn)行級(jí)別,進(jìn)而了解如何靈活使用工作配置文件。
Upstart 系統(tǒng)中的運(yùn)行級(jí)別
Upstart 的運(yùn)作完全是基于工作和事件的。工作的狀態(tài)變化和運(yùn)行會(huì)引起事件,進(jìn)而觸發(fā)其它工作和事件。
而傳統(tǒng)的 Linux 系統(tǒng)初始化是基于運(yùn)行級(jí)別的,即 SysVInit。因?yàn)闅v史的原因,Linux 上的多數(shù)軟件還是采用傳統(tǒng)的 SysVInit 腳本啟動(dòng)方式,并沒有為 UpStart 開發(fā)新的啟動(dòng)腳本,因此即便在 Debian 和 Ubuntu 系統(tǒng)上,還是必須模擬老的 SysVInit 的運(yùn)行級(jí)別模式,以便和多數(shù)現(xiàn)有軟件兼容。
雖然 Upstart 本身并沒有運(yùn)行級(jí)別的概念,但完全可以用 UpStart 的工作模擬出來。讓我們完整地考察一下 UpStart 機(jī)制下的系統(tǒng)啟動(dòng)過程。
系統(tǒng)啟動(dòng)過程
下圖描述了 UpStart 的啟動(dòng)過程。
系統(tǒng)上電后運(yùn)行 GRUB 載入內(nèi)核。內(nèi)核執(zhí)行硬件初始化和內(nèi)核自身初始化。在內(nèi)核初始化的最后,內(nèi)核將啟動(dòng) pid 為 1 的 init 進(jìn)程,即 UpStart 進(jìn)程。
Upstart 進(jìn)程在執(zhí)行了一些自身的初始化工作后,立即發(fā)出"startup"事件。上圖中用紅色方框加紅色箭頭表示事件,可以在左上方看到"startup"事件。
所有依賴于"startup"事件的工作被觸發(fā),其中最重要的是 mountall。mountall 任務(wù)負(fù)責(zé)掛載系統(tǒng)中需要使用的文件系統(tǒng),完成相應(yīng)工作后,mountall 任務(wù)會(huì)發(fā)出以下事件:local-filesystem,virtual-filesystem,all-swaps,
其中 virtual-filesystem 事件觸發(fā) udev 任務(wù)開始工作。任務(wù) udev 觸發(fā) upstart-udev-bridge 的工作。Upstart-udev-bridge 會(huì)發(fā)出 net-device-up IFACE=lo 事件,表示本地回環(huán) IP 網(wǎng)絡(luò)已經(jīng)準(zhǔn)備就緒。同時(shí),任務(wù) mountall 繼續(xù)執(zhí)行,最終會(huì)發(fā)出 filesystem 事件。
此時(shí),任務(wù) rc-sysinit 會(huì)被觸發(fā),因?yàn)?rc-sysinit 的 start on 條件如下:
start on filesystem and net-device-up IFACE=lo
任務(wù) rc-sysinit 調(diào)用 telinit。Telinit 任務(wù)會(huì)發(fā)出 runlevel 事件,觸發(fā)執(zhí)行/etc/init/rc.conf。
rc.conf 執(zhí)行/etc/rc$.d/目錄下的所有腳本,和 SysVInit 非常類似,讀者可以參考本文第一部分的描述。
程序開發(fā)時(shí)需要注意的事項(xiàng)
作為程序開發(fā)人員,在編寫系統(tǒng)服務(wù)時(shí),需要了解 UpStart 的一些特殊要求。只有符合這些要求的軟件才可以被 UpStart 管理。
規(guī)則一,派生次數(shù)需聲明。
很多 Linux 后臺(tái)服務(wù)都通過派生兩次的技巧將自己變成后臺(tái)服務(wù)程序。如果您編寫的服務(wù)也采用了這個(gè)技術(shù),就必須通過文檔或其它的某種方式明確地讓 UpStart 的維護(hù)人員知道這一點(diǎn),這將影響 UpStart 的 expect stanza,我們在前面已經(jīng)詳細(xì)介紹過這個(gè) stanza 的含義。
規(guī)則二,派生后即可用。
后臺(tái)程序在完成第二次派生的時(shí)候,必須保證服務(wù)已經(jīng)可用。因?yàn)?UpStart 通過派生計(jì)數(shù)來決定服務(wù)是否處于就緒狀態(tài)。
規(guī)則三,遵守 SIGHUP 的要求。
UpStart 會(huì)給精靈進(jìn)程發(fā)送 SIGHUP 信號(hào),此時(shí),UpStart 希望該精靈進(jìn)程做以下這些響應(yīng)工作:
·完成所有必要的重新初始化工作,比如重新讀取配置文件。這是因?yàn)?UpStart 的命令"initctl reload"被設(shè)計(jì)為可以讓服務(wù)在不重啟的情況下更新配置。
·精靈進(jìn)程必須繼續(xù)使用現(xiàn)有的 PID,即收到 SIGHUP 時(shí)不能調(diào)用 fork。如果服務(wù)必須在這里調(diào)用 fork,則等同于派生兩次,參考上面的規(guī)則一的處理。這個(gè)規(guī)則保證了 UpStart 可以繼續(xù)使用 PID 管理本服務(wù)。
規(guī)則四,收到 SIGTEM 即 shutdown。
·當(dāng)收到 SIGTERM 信號(hào)后,UpStart 希望精靈進(jìn)程進(jìn)程立即干凈地退出,釋放所有資源。如果一個(gè)進(jìn)程在收到 SIGTERM 信號(hào)后不退出,Upstart 將對(duì)其發(fā)送 SIGKILL 信號(hào)。
作為系統(tǒng)管理員,一個(gè)重要的職責(zé)就是管理系統(tǒng)服務(wù)。比如系統(tǒng)服務(wù)的監(jiān)控,啟動(dòng),停止和配置。UpStart 提供了一系列的命令來完成這些工作。其中的核心是initctl,這是一個(gè)帶子命令風(fēng)格的命令行工具。
比如可以用 initctl list 來查看所有工作的概況:
$initctl listalsa-mixer-save stop/waitingavahi-daemon start/running, process 690mountall-net stop/waitingrc stop/waitingrsyslog start/running, process 482screen-cleanup stop/waitingtty4 start/running, process 859udev start/running, process 334upstart-udev-bridge start/running, process 304ureadahead-other stop/waiting
這是在 Ubuntu10.10 系統(tǒng)上的輸出,其它的 Linux 發(fā)行版上的輸出會(huì)有所不同。第一列是工作名,比如 rsyslog。第二列是工作的目標(biāo);第三列是工作的狀態(tài)。
此外還可以用 initctl stop 停止一個(gè)正在運(yùn)行的工作;用 initctl start 開始一個(gè)工作;還可以用 initctl status 來查看一個(gè)工作的狀態(tài);initctl restart 重啟一個(gè)工作;initctl reload 可以讓一個(gè)正在運(yùn)行的服務(wù)重新載入配置文件。這些命令和傳統(tǒng)的 service 命令十分相似。
Service 命令 | UpStart initctl 命令 |
---|---|
service start | initctl start |
service stop | initctl stop |
service restart | initctl restart |
service reload | initctl reload |
很多情況下管理員并不喜歡子命令風(fēng)格,因?yàn)樾枰謩?dòng)鍵入的字符太多。UpStart 還提供了一些快捷命令來簡化 initctl,實(shí)際上這些命令只是在內(nèi)部調(diào)用相應(yīng)的 initctl 命令。比如 reload,restart,start,stop 等等。啟動(dòng)一個(gè)服務(wù)可以簡單地調(diào)用
start <job>
這和執(zhí)行 initctl start <job>是一樣的效果。
一些命令是為了兼容其它系統(tǒng)(主要是 sysvinit),比如顯示 runlevel 用/sbin/runlevel 命令:
$runlevelN 2
這個(gè)輸出說明當(dāng)前系統(tǒng)的運(yùn)行級(jí)別為 2。而且系統(tǒng)沒有之前的運(yùn)行級(jí)別,也就是說在系統(tǒng)上電啟動(dòng)進(jìn)入預(yù)定運(yùn)行級(jí)別之后沒有再修改過運(yùn)行級(jí)別。
那么如何修改系統(tǒng)上電之后的默認(rèn)運(yùn)行級(jí)別呢?
在 Upstart 系統(tǒng)中,需要修改/etc/init/rc-sysinti.conf 中的 DEFAULT_RUNLEVEL 這個(gè)參數(shù),以便修改默認(rèn)啟動(dòng)運(yùn)行級(jí)別。這一點(diǎn)和 sysvinit 的習(xí)慣有所不同,大家需要格外留意。
還有一些隨 UpStart 發(fā)布的小工具,用來幫助開發(fā) UpStart 或者診斷 UpStart 的問題。比如 init-checkconf 和 upstart-monitor
還可以使用 initctl 的 emit 命令從命令行發(fā)送一個(gè)事件。
#initctl emit <event>
這一般是用于 UpStart 本身的排錯(cuò)。
可以看到,UpStart 的設(shè)計(jì)比 SysVInit 更加先進(jìn)。多數(shù) Linux 發(fā)行版上已經(jīng)不再使用 SysVInit,一部分發(fā)行版采用了 UpStart,比如 Ubuntu;而另外一些比如 Fedora,采用了一種被稱為 systemd 的 init 系統(tǒng)。Systemd 出現(xiàn)的比 UpStart 更晚,但發(fā)展迅速,雖然 UpStart 也還在積極開發(fā)并被越來越多地應(yīng)用,但 systemd 似乎發(fā)展更快,我將在下一篇文章中再介紹 systemd。
聯(lián)系客服