淺析Linux初始化init系統,第2部分: UpStart

Upstart 簡介

假如您使用的 Linux 發行版是 Ubuntu,極可能會發如今您的計算機上找不到/etc/inittab 文件了,這是由於 Ubuntu 使用了一種被稱爲 upstart 的新型 init 系統。html

開發 Upstart 的原因

大約在 2006 年或者更早的時候, Ubuntu 開發人員試圖將 Linux 安裝在筆記本電腦上。在這期間技術人員發現經典的 sysvinit 存在一些問題:它不適合筆記本環境。這促使程序員 Scott James Remnant 着手開發 upstart。linux

當 Linux 內核進入 2.6 時代時,內核功能有了不少新的更新。新特性使得 Linux 不只是一款優秀的服務器操做系統,也能夠被用於桌面系統,甚至嵌入式設備。桌面系統或便攜式設備的一個特色是常常重啓,並且要頻繁地使用硬件熱插拔技術。在現代計算機系統中,硬件繁多、接口有限,人們並不是將全部設備都始終鏈接在計算機上,好比 U 盤平時並不鏈接電腦,使用時才插入 USB 插口。所以,當系統上電啓動時,一些外設可能並無鏈接。而是在啓動後當須要的時候才鏈接這些設備。在 2.6 內核支持下,一旦新外設鏈接到系統,內核即可以自動實時地發現它們,並初始化這些設備,進而使用它們。這爲便攜式設備用戶提供了很大的靈活性。程序員

但是這些特性爲 sysvinit 帶來了一些挑戰。當系統初始化時,須要被初始化的設備並無鏈接到系統上;好比打印機。爲了管理打印任務,系統須要啓動 CUPS 等服務,而若是打印機沒有接入系統的狀況下,啓動這些服務就是一種浪費。Sysvinit 沒有辦法處理這類需求,它必須一次性把全部可能用到的服務都啓動起來,即便打印機並無鏈接到系統,CUPS 服務也必須啓動。shell

還有網絡共享盤的掛載問題。在/etc/fstab 中,能夠指定系統自動掛載一個網絡盤,好比 NFS,或者 iSCSI 設備。在本文的第一部分 sysvinit 的簡介中能夠看到,sysvinit 分析/etc/fstab 掛載文件系統這個步驟是在網絡啓動以前。但是若是網絡沒有啓動,NFS 或者 iSCSI 都不可訪問,固然也沒法進行掛載操做。Sysvinit 採用 netdev 的方式來解決這個問題,即/etc/fstab 發現 netdev 屬性掛載點的時候,不嘗試掛載它,在網絡初始化並使能以後,還有一個專門的 netfs 服務來掛載全部這些網絡盤。這是一個不得已的補救方法,給管理員帶來不便。部分新手管理員甚至歷來也沒有據說過 netdev 選項,所以常常成爲系統管理的一個陷阱。apache

針對以上種種狀況,Ubuntu 開發人員在評估了當時的幾個可選 init 系統以後,決定從新設計和開發一個全新的 init 系統,即 UpStart。UpStart 基於事件機制,好比 U 盤插入 USB 接口後,udev 獲得內核通知,發現該設備,這就是一個新的事件。UpStart 在感知到該事件以後觸發相應的等待任務,好比處理/etc/fstab 中存在的掛載點。採用這種事件驅動的模式,upstart 完美地解決了即插即用設備帶來的新問題。編程

此外,採用事件驅動機制也帶來了一些其它有益的變化,好比加快了系統啓動時間。sysvinit 運行時是同步阻塞的。一個腳本運行的時候,後續腳本必須等待。這意味着全部的初始化步驟都是串行執行的,而實際上不少服務彼此並不相關,徹底能夠並行啓動,從而減少系統的啓動時間。在 Linux 大量應用於服務器的時代,系統啓動時間也許還不那麼重要;然而對於桌面系統和便攜式設備,啓動時間的長短對用戶體驗影響很大。此外雲計算等新的 Server 端技術也每每須要單個設備能夠更加快速地啓動。ubuntu

UpStart 知足了這些需求,目前不只桌面系統 Ubuntu 採用了 UpStart,甚至企業級服務器級的 RHEL 也默認採用 UpStart 來替換 sysvinit 做爲 init 系統。bash

Upstart 的特色

UpStart 解決了以前提到的 sysvinit 的缺點。採用事件驅動模型,UpStart 能夠:服務器

  • 更快地啓動系統網絡

  • 當新硬件被發現時動態啓動服務

  • 硬件被拔除時動態中止服務

這些特色使得 UpStart 能夠很好地應用在桌面或者便攜式系統中,處理這些系統中的動態硬件插拔特性。

Upstart 概念和術語

Upstart 的基本概念和設計清晰明確。UpStart 主要的概念是 job 和 event。Job 就是一個工做單元,用來完成一件工做,好比啓動一個後臺服務,或者運行一個配置命令。每一個 Job 都等待一個或多個事件,一旦事件發生,upstart 就觸發該 job 完成相應的工做。

Job

Job 就是一個工做的單元,一個任務或者一個服務。能夠理解爲 sysvinit 中的一個服務腳本。有三種類型的工做:

  • task job;

  • service job;

  • abstract job;

task job 表明在必定時間內會執行完畢的任務,好比刪除一個文件;

service job 表明後臺服務進程,好比 apache httpd。這裏進程通常不會退出,一旦開始運行就成爲一個後臺精靈進程,由 init 進程管理,若是這類進程退出,由 init 進程從新啓動,它們只能由 init 進程發送信號中止。它們的中止通常也是因爲所依賴的中止事件而觸發的,不過 upstart 也提供命令行工具,讓管理人員手動中止某個服務;

Abstract job 僅由 upstart 內部使用,僅對理解 upstart 內部機理有所幫助。咱們不用關心它。

除了以上的分類以外,還有另外一種工做(Job)分類方法。Upstart 不只能夠用來爲整個系統的初始化服務,也能夠爲每一個用戶會話(session)的初始化服務。系統的初始化任務就叫作 system job,好比掛載文件系統的任務就是一個 system job;用戶會話的初始化服務就叫作 session job。

Job 生命週期

Upstart 爲每一個工做都維護一個生命週期。通常來講,工做有開始,運行和結束這幾種狀態。爲了更精細地描述工做的變化,Upstart 還引入了一些其它的狀態。好比開始就有開始以前(pre-start),即將開始(starting)和已經開始了(started)幾種不一樣的狀態,這樣能夠更加精確地描述工做的當前狀態。

工做從某種初始狀態開始,逐漸變化,或許要經歷其它幾種不一樣的狀態,最終進入另一種狀態,造成一個狀態機。在這個過程當中,當工做的狀態即將發生變化的時候,init 進程會發出相應的事件(event)。

wKiom1aE0kTgB_xMAAA6SsFkzjU781.png

圖 1 展現了 Job 的狀態機。

圖 1. Job’s life cycle


Job’s life cycle

其中有四個狀態會引發 init 進程發送相應的事件,代表該工做的相應變化:

  • Starting

  • Started

  • Stopping

  • Stopped

而其它的狀態變化不會發出事件。那麼咱們接下來就來看看事件的詳細含義吧。

事件 Event

顧名思義,Event 就是一個事件。事件在 upstart 中以通知消息的形式具體存在。一旦某個事件發生了,Upstart 就向整個系統發送一個消息。沒有任何手段阻止事件消息被 upstart 的其它部分知曉,也就是說,事件一旦發生,整個 upstart 系統中全部工做和其它的事件都會獲得通知。

Event 能夠分爲三類: signal,methods 或者 hooks。

Signals

Signal 事件是非阻塞的,異步的。發送一個信號以後控制權當即返回。

Methods

Methods 事件是阻塞的,同步的。

Hooks

Hooks 事件是阻塞的,同步的。它介於 Signals 和 Methods 之間,調用發出 Hooks 事件的進程必須等待事件完成才能夠獲得控制權,但不檢查事件是否成功。

事件是個很是抽象的概念,下面我羅列出一些常見的事件,但願能夠幫助您進一步瞭解事件的含義:

  • 系統上電啓動,init 進程會發送"start"事件

  • 根文件系統可寫時,相應 job 會發送文件系統就緒的事件

  • 一個塊設備被發現並初始化完成,發送相應的事件

  • 某個文件系統被掛載,發送相應的事件

  • 相似 atd 和 cron,能夠在某個時間點,或者週期的時間點發送事件

  • 另一個 job 開始或結束時,發送相應的事件

  • 一個磁盤文件被修改時,能夠發出相應的事件

  • 一個網絡設備被發現時,能夠發出相應的事件

  • 缺省路由被添加或刪除時,能夠發出相應的事件

不一樣的 Linux 發行版對 upstart 有不一樣的定製和實現,實現和支持的事件也有所不一樣,能夠用man 7 upstart-events來查看事件列表。

Job 和 Event 的相互協做

Upstart 就是由事件觸發工做運行的一個系統,每個程序的運行都由其依賴的事件發生而觸發的。

系統初始化的過程是在工做和事件的相互協做下完成的,能夠大體描述以下:系統初始化時,init 進程開始運行,init 進程自身會發出不一樣的事件,這些最初的事件會觸發一些工做運行。每一個工做運行過程當中會釋放不一樣的事件,這些事件又將觸發新的工做運行。如此反覆,直到整個系統正常運行起來。

究竟哪些事件會觸發某個工做的運行?這是由工做配置文件定義的。

工做配置文件

任何一個工做都是由一個工做配置文件(Job Configuration File)定義的。這個文件是一個文本文件,包含一個或者多個小節(stanza)。每一個小節是一個完整的定義模塊,定義了工做的一個方面,好比 author 小節定義了工做的做者。工做配置文件存放在/etc/init 下面,是以.conf 做爲文件後綴的文件。

清單 1. 一個最簡單的工做配置文件


清單 1. 一個最簡單的工做配置文件
#This is a simple demo of Job Configure file
#This line is comment, start with #

#Stanza 1, The author
author 「Liu Ming」

#Stanza 2, Description
description 「This job only has author and description, so no use, just a demo」

上面的例子不會產生任何做用,一個真正的工做配置文件會包含不少小節,其中比較重要的小節有如下幾個:

"expect" Stanza

Upstart 除了負責系統的啓動過程以外,和 SysVinit 同樣,Upstart 還提供一系列的管理工具。當系統啓動以後,管理員可能還須要進行維護和調整,好比啓動或者中止某項系統服務。或者將系統切換到其它的工做狀態,好比改變運行級別。本文後續將詳細介紹 Upstart 的管理工具的使用。

爲了啓動,中止,重啓和查詢某個系統服務。Upstart 須要跟蹤該服務所對應的進程。好比 httpd 服務的進程 PID 爲 1000。當用戶須要查詢 httpd 服務是否正常運行時,Upstart 就能夠利用 ps 命令查詢進程 1000,假如它還在正常運行,則代表服務正常。當用戶須要中止 httpd 服務時,Upstart 就使用 kill 命令終止該進程。爲此,Upstart 必須跟蹤服務進程的進程號。

部分服務進程爲了將本身變成後臺精靈進程(daemon),會採用兩次派生(fork)的技術,另一些服務則不會這樣作。假如一個服務派生了兩次,那麼 UpStart 必須採用第二個派生出來的進程號做爲服務的 PID。可是,UpStart 自己沒法判斷服務進程是否會派生兩次,爲此在定義該服務的工做配置文件中必須寫明 expect 小節,告訴 UpStart 進程是否會派生兩次。

Expect 有兩種,"expect fork"表示進程只會 fork 一次;"expect daemonize"表示進程會 fork 兩次。

"exec" Stanza 和"script" Stanza

一個 UpStart 工做必定須要作些什麼,多是運行一條 shell 命令,或者運行一段腳本。用"exec"關鍵字配置工做須要運行的命令;用"script"關鍵字定義須要運行的腳本。

清單 2 顯示了 exec 和 script 的用法:

清單 2.script 例子
# mountall.conf
description 「Mount filesystems on boot」
start on startup
stop 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_fix
end script
...

這是 mountall 的例子,該工做在系統啓動時運行,負責掛載全部的文件系統。該工做須要執行復雜的腳本,由"script"關鍵字定義;在腳本中,使用了 exec 來執行 mountall 命令。

"start on" Stanza 和"stop on" Stanza

"start on"定義了觸發工做的全部事件。"start on"的語法很簡單,以下所示:

start on EVENT [[KEY=]VALUE]... [and|or...]

EVENT 表示事件的名字,能夠在 start on 中指定多個事件,表示該工做的開始須要依賴多個事件發生。多個事件之間能夠用 and 或者 or 組合,"表示所有都必須發生"或者"其中之一發生便可"等不一樣的依賴條件。除了事件發生以外,工做的啓動還能夠依賴特定的條件,所以在 start on 的 EVENT 以後,能夠用 KEY=VALUE 來表示額外的條件,通常是某個環境變量(KEY)和特定值(VALUE)進行比較。若是隻有一個變量,或者變量的順序已知,則 KEY 能夠省略。

"stop on"和"start on"很是相似,只不過是定義工做在什麼狀況下須要中止。

代碼清單 3 是"start on"和"stop on"的一個例子。

清單 3. start on/ stop on 例子
#dbus.conf
description     「D-Bus system message bus」

start on local-filesystems
stop on deconfiguring-networking

D-Bus 是一個系統消息服務,上面的配置文件代表當系統發出 local-filesystems 事件時啓動 D-Bus;當系統發出 deconfiguring-networking 事件時,中止 D-Bus 服務。

Session Init

UpStart 還能夠用於管理用戶會話的初始化。在我寫這篇文章的今天,多數 Linux 發行版尚未使用 UpStart 管理會話。只有在 Ubuntu Raring 版本中,使用 UpStart 管理用戶會話的初始化過程。

首先讓咱們瞭解一下 Session 的概念。Session 就是一個用戶會話,即用戶從遠程或者本地登入系統開始工做,直到用戶退出。這整個過程就構成一個會話。

每一個用戶的使用習慣和使用方法都不相同,所以用戶每每須要爲本身的會話作一個定製,好比添加特定的命令別名,啓動特殊的應用程序或者服務,等等。這些工做都屬於對特定會話的初始化操做,所以能夠被稱爲 Session Init。

用戶使用 Linux 能夠有兩種模式:字符模式和圖形界面。在字符模式下,會話初始化相對簡單。用戶登陸後只能啓動一個 Shell,經過 shell 命令使用系統。各類 shell 程序都支持一個自動運行的啓動腳本,好比~/.bashrc。用戶在這些腳本中加入須要運行的定製化命令。字符會話需求簡單,所以這種現有的機制工做的很好。

在圖形界面下,事情就變得複雜一些。用戶登陸後看到的並非一個 shell 提示符,而是一個桌面。一個完整的桌面環境由不少組件組成。

一個桌面環境包括 window manager,panel 以及其它一些定義在/usr/share/gnome-session/sessions/下面的基本組件;此外還有一些輔助的應用程序,共同幫助構成一個完整的方便的桌面,好比 system monitors,panel applets,NetworkManager,Bluetooth,printers 等。當用戶登陸以後,這些組件都須要被初始化,這個過程比字符界面要複雜的多。目前啓動各類圖形組件和應用的工做由 gnome-session 完成。過程以下:

以 Ubuntu 爲例,當用戶登陸 Ubuntu 圖形界面後,顯示管理器(Display Manager)lightDM 啓動 Xsession。Xsession 接着啓動 gnome-session,gnome-session 負責其它的初始化工做,而後就開始了一個 desktop session。

圖 2.傳統 desktop session 啓動過程
init
|- lightdm
|   |- Xorg
|   |- lightdm ---session-child
|        |- gnome-session --session=ubuntu
|             |- compiz
|             |- gwibber
|             |- nautilus
|             |- nm-applet
|             :
|             :
|
|- dbus-daemon --session
|
:
:

這個過程有一些缺點(和 sysVInit 相似)。一些應用和組件其實並不須要在會話初始化過程當中啓動,更好的選擇是在須要它們的時候才啓動。好比 update-notifier 服務,該服務不停地監測幾個文件系統路徑,一旦這些路徑上發現能夠更新的軟件包,就提醒用戶。這些文件系統路徑包括新插入的 DVD 盤等。Update-notifier 由 gnome-session 啓動並一直運行着,在多數狀況下,用戶並不會插入新的 DVD,此時 update-notifier 服務一直在後臺運行並消耗系統資源。更好的模式是當用戶插入 DVD 的時候再運行 update-notifier。這樣能夠加快啓動時間,減少系統運行過程當中的內存等系統資源的開銷。對於移動,嵌入式等設備等這還意味着省電。除了 Update-notifier 服務以外,還有其它一些相似的服務。好比 Network Manager,一天以內用戶不多切換網絡設備,因此大部分時間 Network Manager 服務僅僅是在浪費系統資源;再好比 backup manager 等其它常駐內存,後臺不間斷運行卻不多真正被使用的服務。

用 UpStart 的基於事件的按需啓動的模式就能夠很好地解決這些問題,好比用戶插入網線的時候才啓動 Network Manager,由於用戶插入網線代表須要使用網絡,這能夠被稱爲按需啓動。

下圖描述了採用 UpStart 以後的會話初始化過程。

圖 3.採用 Upstart 的 Desktop session init 過程
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 使用

有兩種人員須要瞭解 Upstart 的使用。第一類是系統開發人員,好比 MySQL 的開發人員。它們須要瞭解如何編寫工做配置文件,以便用 UpStart 來管理服務。好比啓動,中止 MySQL 服務。

另一種狀況是系統管理員,它們須要掌握 Upstart 的管理命令以便配置和管理系統的初始化,管理系統服務。

系統開發人員須要瞭解的 UpStart 知識

系統開發人員不只須要掌握工做配置文件的寫法,還須要瞭解一些針對服務進程編程上的要求。本文僅列出了少數工做配置文件的語法。要全面掌握工做配置文件的寫法,須要詳細閱讀 Upstart 的手冊。這裏讓咱們來分析一下如何用 Upstart 來實現傳統的運行級別,進而瞭解如何靈活使用工做配置文件。

Upstart 系統中的運行級別

Upstart 的運做徹底是基於工做和事件的。工做的狀態變化和運行會引發事件,進而觸發其它工做和事件。

而傳統的 Linux 系統初始化是基於運行級別的,即 SysVInit。由於歷史的緣由,Linux 上的多數軟件仍是採用傳統的 SysVInit 腳本啓動方式,並無爲 UpStart 開發新的啓動腳本,所以即使在 Debian 和 Ubuntu 系統上,仍是必須模擬老的 SysVInit 的運行級別模式,以便和多數現有軟件兼容。

雖然 Upstart 自己並無運行級別的概念,但徹底能夠用 UpStart 的工做模擬出來。讓咱們完整地考察一下 UpStart 機制下的系統啓動過程。

系統啓動過程

下圖描述了 UpStart 的啓動過程。

圖 4.UpStart 啓動過程


UpStart 啓動過程

系統上電後運行 GRUB 載入內核。內核執行硬件初始化和內核自身初始化。在內核初始化的最後,內核將啓動 pid 爲 1 的 init 進程,即 UpStart 進程。

Upstart 進程在執行了一些自身的初始化工做後,當即發出"startup"事件。上圖中用紅色方框加紅色箭頭表示事件,能夠在左上方看到"startup"事件。

全部依賴於"startup"事件的工做被觸發,其中最重要的是 mountall。mountall 任務負責掛載系統中須要使用的文件系統,完成相應工做後,mountall 任務會發出如下事件:local-filesystem,virtual-filesystem,all-swaps,

其中 virtual-filesystem 事件觸發 udev 任務開始工做。任務 udev 觸發 upstart-udev-bridge 的工做。Upstart-udev-bridge 會發出 net-device-up IFACE=lo 事件,表示本地迴環 IP 網絡已經準備就緒。同時,任務 mountall 繼續執行,最終會發出 filesystem 事件。

此時,任務 rc-sysinit 會被觸發,由於 rc-sysinit 的 start on 條件以下:

start on filesystem and net-device-up IFACE=lo

任務 rc-sysinit 調用 telinit。Telinit 任務會發出 runlevel 事件,觸發執行/etc/init/rc.conf。

rc.conf 執行/etc/rc$.d/目錄下的全部腳本,和 SysVInit 很是相似,讀者能夠參考本文第一部分的描述。

程序開發時須要注意的事項

做爲程序開發人員,在編寫系統服務時,須要瞭解 UpStart 的一些特殊要求。只有符合這些要求的軟件才能夠被 UpStart 管理。

規則一,派生次數需聲明。

不少 Linux 後臺服務都經過派生兩次的技巧將本身變成後臺服務程序。若是您編寫的服務也採用了這個技術,就必須經過文檔或其它的某種方式明確地讓 UpStart 的維護人員知道這一點,這將影響 UpStart 的 expect stanza,咱們在前面已經詳細介紹過這個 stanza 的含義。

規則二,派生後便可用。

後臺程序在完成第二次派生的時候,必須保證服務已經可用。由於 UpStart 經過派生計數來決定服務是否處於就緒狀態。

規則三,遵照 SIGHUP 的要求。

UpStart 會給精靈進程發送 SIGHUP 信號,此時,UpStart 但願該精靈進程作如下這些響應工做:

完成全部必要的從新初始化工做,好比從新讀取配置文件。這是由於 UpStart 的命令"initctl reload"被設計爲可讓服務在不重啓的狀況下更新配置。

精靈進程必須繼續使用現有的 PID,即收到 SIGHUP 時不能調用 fork。若是服務必須在這裏調用 fork,則等同於派生兩次,參考上面的規則一的處理。這個規則保證了 UpStart 能夠繼續使用 PID 管理本服務。

規則四,收到 SIGTEM 即 shutdown。

當收到 SIGTERM 信號後,UpStart 但願精靈進程進程當即乾淨地退出,釋放全部資源。若是一個進程在收到 SIGTERM 信號後不退出,Upstart 將對其發送 SIGKILL 信號。

系統管理員須要瞭解的 Upstart 命令

做爲系統管理員,一個重要的職責就是管理系統服務。好比系統服務的監控,啓動,中止和配置。UpStart 提供了一系列的命令來完成這些工做。其中的核心是initctl,這是一個帶子命令風格的命令行工具。

好比能夠用 initctl list 來查看全部工做的概況:

$initctl list
alsa-mixer-save stop/waiting
avahi-daemon start/running, process 690
mountall-net stop/waiting
rc stop/waiting
rsyslog start/running, process 482
screen-cleanup stop/waiting
tty4 start/running, process 859
udev start/running, process 334
upstart-udev-bridge start/running, process 304
ureadahead-other stop/waiting

這是在 Ubuntu10.10 系統上的輸出,其它的 Linux 發行版上的輸出會有所不一樣。第一列是工做名,好比 rsyslog。第二列是工做的目標;第三列是工做的狀態。

此外還能夠用 initctl stop 中止一個正在運行的工做;用 initctl start 開始一個工做;還能夠用 initctl status 來查看一個工做的狀態;initctl restart 重啓一個工做;initctl reload 可讓一個正在運行的服務從新載入配置文件。這些命令和傳統的 service 命令十分類似。

wKioL1aE0zODsP3GAAA6Sr-hmxI727.png

不少狀況下管理員並不喜歡子命令風格,由於須要手動鍵入的字符太多。UpStart 還提供了一些快捷命令來簡化 initctl,實際上這些命令只是在內部調用相應的 initctl 命令。好比 reload,restart,start,stop 等等。啓動一個服務能夠簡單地調用

start <job>

這和執行 initctl start <job>是同樣的效果。

一些命令是爲了兼容其它系統(主要是 sysvinit),好比顯示 runlevel 用/sbin/runlevel 命令:

$runlevel
N 2

這個輸出說明當前系統的運行級別爲 2。並且系統沒有以前的運行級別,也就是說在系統上電啓動進入預約運行級別以後沒有再修改過運行級別。

那麼如何修改系統上電以後的默認運行級別呢?

在 Upstart 系統中,須要修改/etc/init/rc-sysinti.conf 中的 DEFAULT_RUNLEVEL 這個參數,以便修改默認啓動運行級別。這一點和 sysvinit 的習慣有所不一樣,你們須要格外留意。

還有一些隨 UpStart 發佈的小工具,用來幫助開發 UpStart 或者診斷 UpStart 的問題。好比 init-checkconf 和 upstart-monitor

還可使用 initctl 的 emit 命令從命令行發送一個事件。

#initctl emit <event>

這通常是用於 UpStart 自己的排錯。

文章轉載至:http://www.ibm.com/developerworks/cn/linux/1407_liuming_init2/index.html

相關文章
相關標籤/搜索