一個完整的upstart腳本分析


基本概念可以了解

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM