基本概念可以了解
http://www.mike.org.cn/articles/understand-upstart/
http://blog.fens.me/linux-upstart/
http://zh.wikipedia.org/wiki/Upstart
- 傳統的linux采用sysvinit daemon,缺點是無法很好地處理現代硬件,如熱插拔設備、USB硬盤或山村、網絡文件系統等。
-
Upstart是一個基於事件的初始化守護進程,用於替代傳統的init。 — 幾個類Unix計算機操作系統啟動時用於執行任務的方法。它是由Canonical公司前雇員Scott James Remnant所寫。
Upstart是異步工作的 — 它在系統運行時監督服務,並且在開關機時啟動和關閉任務和服務。
- Sysvinit daemon 是一個基於運行級別的初始化程序,它使用了運行級別(如單用戶、多用戶等)並通過從 /etc/rc?.d 目錄到 /etc/init.d 目錄的初始化腳本的鏈接來啟動與終止系統服務
重要的概念
- event: 事件, 是指系統狀態的一種改變,這種改變會被通知給init進程。舉例來說,boot loader會觸發startup事件,系統進入runlevel 2的時候會觸發runlevel 2事件,某個文件系統被掛載時會觸發path-mounted事件, USB設備的插拔也都會產生相應的事件。這些時間會被通知給init進程,然后init進程來決定系統如何處理這些事件。
- job: 作業,一項作業是init進程讀入的一系列指令。你可以使用initctl start或initctl stop命令來開始或停止某項作業,這是調用作業的一種方式。另一種方式是當系統被告知發生什么事件event后,運行該事件所對應的作業。可用sudo initctl list命令列出所有系統作業的運行狀態。
- task: 任務, a job that performs its work and returns to a waiting state when it is done. 中文是一種完成指定工作后進去等待狀態的作業。
- service: 服務,a job that does not normally terminate by itself. 舉個例子來說, gettys 是以服務來實現的。 init進程監視所有服務,並在服務失敗的時候重啟服務。
http://blog.csdn.net/vecri/article/details/4735601
/etc/event.d目錄下是所有init進程讀取的job(作業)定義。該目錄下的每個文件都定義了一個job(作業),和對應該作業的事件。這和windows下的消息機制有些類似。在這里新建一個文件myjob: $cat /etc/event.d/myjob start on hithere script echo "Hi there, here I am!" > /tmp/myjob.out date >> /tmp/myjob.out end script 這個文件定義了一個作業,在作業在收到hithere事件后觸發。該作業運行時將"Hi there, here I am!"和系統時間打印到/tmp/myjob.out
一個例子,但這個例子對於ubuntu12.04稍有不同,在12.04版本中,沒有/etc/event.d/目錄,相應的目錄變為/etc/init,而且目錄下的文件名必須以.conf結尾,否則不能執行。
upstart本身使用initctl (start stop restart reload list status等都是initctl 軟鏈接而成),比如啟動或者關閉程序,使用
initctl start squid3 or start squid3
initctl stop squid3 or stop squid3
后面的job名稱是/etc/init目錄下xxxx.conf文件去除.conf結尾后的名稱。
/etc/init.d/xxxx是按照sysvinit遺留下來的舊有模式
我理解的upstart的核心是事件驅動,由事件(event)觸發。
手動觸發:
initctl emit hithere直接觸發
而系統對於某些動作會觸發相應的事件
比如:
boot loader會觸發startup事件,系統進入runlevel 2的時候會觸發runlevel 2事件
具體的例子及配置文件的語法格式
description "HTTP proxy-cache" //job描述 author "Chuck Short <zulcss@ubuntu.com>" //job作者 # The second "or" condition is to start squid in case it failed to start # because no real interface was there. start on runlevel [2345] //在2345運行級別啟動 stop on runlevel [!2345] //非2345運行級別關閉 respawn //意外關閉重啟服務 normal exit 0 //列出normal exit的代碼或者信號,正常退出不重啟 env CONFIG="/etc/squid3/squid.conf" //變量 env SQUID_ARGS="-YC" //變量 pre-start script //指定進程運行之前執行的命令,此處為腳本 if [ -f /etc/default/squid3 ]; then . /etc/default/squid3 fi find_cache_dir () { w=" " # space tab res=`sed -ne ' s/^'$1'['"$w"']\+[^'"$w"']\+['"$w"']\+\([^'"$w"']\+\).*$/\1/p; t end; d; :end q' < $CONFIG` [ -n "$res" ] || res=$2 echo "$res" } find_cache_type () { w=" " # space tab res=`sed -ne ' s/^'$1'['"$w"']\+\([^'"$w"']\+\).*$/\1/p; t end; d; :end q' < $CONFIG` [ -n "$res" ] || res=$2 echo "$res" } cache_dir=`find_cache_dir cache_dir` cache_type=`find_cache_type cache_dir` if [ "$cache_type" = "coss" -a -d "$cache_dir" -a ! -f "$cache_dir/stripe" ] || [ "$cache_type" != "coss" -a -d "$cache_dir" -a ! -d "$cache_dir/00" ] then /usr/sbin/squid3 $SQUID_ARGS -z -f $CONFIG fi end script //腳本結束 script if [ -f /etc/default/squid3 ]; then . /etc/default/squid3 fi umask 027 //設定umask值 ulimit -n 65535 // exec /usr/sbin/squid3 -N $SQUID_ARGS -f $CONFIG end script
注:
- script和exec是主啟動程序需要執行的命令行,二者不能同時出現,但script內可以嵌套exec命令。
-
exec:
在bash下輸入man exec,找到exec命令解釋處,可以看到有”No new process is created.”這樣的解釋,這就是說exec命令不產生新的子進程。那么exec與source的區別是什么呢?
exec命令在執行時會把當前的shell process關閉,然后換到后面的命令繼續執行。
1. 系統調用exec是以新的進程去代替原來的進程,但進程的PID保持不變。因此,可以這樣認為,exec系統調用並沒有創建新的進程,只是替換了原來進程上下文的內容。原進程的代碼段,數據段,堆棧段被新的進程所代替。
一個進程主要包括以下幾個方面的內容:
(1)一個可以執行的程序
(2) 與進程相關聯的全部數據(包括變量,內存,緩沖區)
(3)程序上下文(程序計數器PC,保存程序執行的位置)
如何自己編寫一個upstart程序
如手動編譯nginx,編寫nginx啟動腳本
description "nginx_daemon" author "binhoul" start on runlevel [2345] stop on runlevel [!2345] respawn normal exit 0 umask 022 env DAEMON="/app/web/nginx/sbin/nginx" exec $DAEMON
上面的腳本啟動沒有問題,但停止時無法出現錯誤:
stop: Unknown instance:
經過查找需要添加一行,或者看nginx網站上給出的啟動腳本例子
# nginx description "nginx http daemon" author "George Shammas <georgyo@gmail.com>" start on (filesystem and net-device-up IFACE=lo) stop on runlevel [!2345] env DAEMON=/usr/sbin/nginx env PID=/var/run/nginx.pid expect fork respawn respawn limit 10 5 #oom never pre-start script $DAEMON -t if [ $? -ne 0 ] then exit $? fi end script exec $DAEMON
# nginx description "nginx http daemon" author "George Shammas <georgyo@gmail.com>" start on (filesystem and net-device-up IFACE=lo) stop on runlevel [!2345] env DAEMON=/usr/sbin/nginx env PID=/var/run/nginx.pid expect fork respawn respawn limit 10 5 #oom never pre-start script $DAEMON -t if [ $? -ne 0 ] then exit $? fi end script exec $DAEMON
鏈接: http://wiki.nginx.org/Upstart
具體原因分析:
http://upstart.ubuntu.com/cookbook/#expect-fork