systemd,upstart, systemV服務(wù)啟動(dòng)編寫

systemd,upstart, systemV是LInux系統(tǒng)三種主流的啟動(dòng)方式。但是技術(shù)的發(fā)展,systemV以及upstart的一些局限,systemd已經(jīng)成為當(dāng)下最主要的啟動(dòng)方式了,systemd的最大優(yōu)點(diǎn)就是可以讓開(kāi)機(jī)啟動(dòng)的服務(wù)并行運(yùn)行,減少了開(kāi)機(jī)運(yùn)行的時(shí)間。

systemd管理的服務(wù)的配置文件存放在三個(gè)目錄,三個(gè)目錄分別是:
/usr/lib/systemd/system/ 安裝包自帶的service配置文件存放的位置
/etc/systemd/system/ systemctl enable創(chuàng)建的service文件(當(dāng)你手動(dòng)添加了一個(gè)服務(wù)的配置文件,并且還要讓它開(kāi)機(jī)自啟動(dòng)運(yùn)行,那么就必須執(zhí)行systemctl enable xxx.service)。通常情況下,這些文件基本都是/usr/lib/systemd/system/下的軟連接,而且是以target組分類存放的的;也或者是用戶手動(dòng)添加的服務(wù)的service文件。
/run/systemd/system/ 運(yùn)行時(shí)創(chuàng)建的service文件;優(yōu)先級(jí)/etc/systemd/system/ > /run/systemd/system/ > /usr/lib/systemd/system/
談到systemd的target組,他其實(shí)就和systemV的runlevel(運(yùn)行等級(jí))對(duì)應(yīng)。

用戶自己手動(dòng)在systemd下增加一個(gè)服務(wù),就需要在/etc/systemd/system下創(chuàng)建一個(gè)service配置文件,當(dāng)然在 /usr/lib/systemd/system/創(chuàng)建也可以。配置文件大致如下:

[Unit]
Description=Systemd service test
After=syslog.target #在syslog.target中的服務(wù)啟動(dòng)后再啟動(dòng)

[Service] #Unit類型
ExecStart=/bin/bash -c "exec FOO.sh" #這樣執(zhí)行,即使FOO.sh有while死循環(huán),systemctl start/top 也會(huì)執(zhí)行完就退出
ExecStart=Other CMD
ExecStartPost=/bin/bash -c "exec   FOO1.sh" #ExecStart執(zhí)行完后執(zhí)行這個(gè)

Restart=on-failure
RestartSec=30s
Type=simple

[Install]
WantedBy=multi-user.target #systemctl enable 后,就會(huì)在/etc/systemd/multi-user.target.wants下創(chuàng)建一個(gè)軟連接到這里

Service項(xiàng)中的ExecStart是必須的,但是其他的,比如ExecStartPost,ExecStop,都是可選的。對(duì)于ExecStop,就是停止服務(wù)所需要運(yùn)行的腳本,看到這里可能會(huì)產(chǎn)生疑問(wèn),沒(méi)有設(shè)定ExecStop,那么怎么停止服務(wù)呢,答案是系統(tǒng)中已經(jīng)記錄已經(jīng)通過(guò)systemd啟動(dòng)的服務(wù),執(zhí)行systemctl stop 就會(huì)向?qū)?yīng)的服務(wù)發(fā)送SIGTERM信號(hào),默認(rèn)5分鐘如果沒(méi)有收到對(duì)應(yīng)服務(wù)的答復(fù),那么就會(huì)在發(fā)送SIGKILL信號(hào)強(qiáng)行終止服務(wù)。
需要說(shuō)明一下的就是,用戶手動(dòng)起的服務(wù),是沒(méi)辦法通過(guò)這三個(gè)工具去停止或者查詢狀態(tài)的,因?yàn)閟ystemd沒(méi)辦法監(jiān)控"
The systemctl utility does not communicate with services that have not been started by systemd. When systemd starts a system service, it stores the ID of its main process in order to keep track of it. The systemctl utility then uses this PID to query and manage the service. Consequently, if a user starts a particular daemon directly on the command line, systemctl is unable to determine its current status or stop it."

在對(duì)應(yīng)的目錄編寫好service配置文件后,執(zhí)行systemctl daemon-reload后就可以通過(guò)syetemctl start/stop去停起服務(wù)了
如果要加到開(kāi)機(jī)自啟動(dòng),那么還要執(zhí)行systemctl enable xxx.service,這個(gè)服務(wù)就加到了對(duì)應(yīng)的target組了。
具體參考
https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/System_Administrators_Guide/chap-Managing_Services_with_systemd.html
https://wiki.ubuntu.com/SystemdForUpstartUsers
http://www.jinbuguo.com/systemd/systemd.service.html

關(guān)于upstart,它是ubuntu主推的,向下兼容systemV,他的配置文件是/etc/init/目錄下以.conf結(jié)尾的文件。因此在upstart管理服務(wù)的系統(tǒng)中要加入一個(gè)服務(wù),就在/etc/init/目錄增加一個(gè)服務(wù)對(duì)應(yīng)的配置文件即可。配置文件的大致內(nèi)容如下:
/etc/init/FOO.conf

description "uwsgi service"
start on runlevel [2345]  #哪些運(yùn)行等級(jí)自動(dòng)運(yùn)行該服務(wù)
stop on runlevel [06]  #哪些運(yùn)行等級(jí)不自動(dòng)運(yùn)行該服務(wù)

env LANG=en_US.UTF-8
limit nofile 65535 65535

script
    exec cmd #服務(wù)啟動(dòng)時(shí)執(zhí)行的腳本
end script

post-start script
    exec cmd #服務(wù)啟動(dòng)后執(zhí)行的腳本
end script

respawn
respawn limit 10 5

對(duì)于更多腳本語(yǔ)法和配置,可參照http://upstart.ubuntu.com/
或者:http://upstart.ubuntu.com/cookbook/
想要看到start或者stop的大概執(zhí)行過(guò)程,可以先sudo initctl log-priority debug改變initctl的日志級(jí)別,然后就可以在/var/log/syslog中查看執(zhí)行過(guò)程的日志了。

關(guān)于systemV,三者中最傳統(tǒng),最古老的服務(wù)啟動(dòng)方式,他的配置文件存放在/etc/init.d/目錄下,這個(gè)目錄下是服務(wù)停起的直接控制腳本,而關(guān)于開(kāi)機(jī)時(shí)啟動(dòng)哪些服務(wù),這個(gè)是根據(jù)runlevel決定的,系統(tǒng)開(kāi)機(jī)分為7個(gè)運(yùn)行等級(jí),分別是0到6,每個(gè)運(yùn)行等級(jí)所需要運(yùn)行的服務(wù)存放在/etc/rc.d/rc(0,1...6).d/目錄下,這個(gè)目錄下的腳本是/etc/init.d/目錄下腳本的軟連接。systemV的腳本樣例如下:

#!/bin/bash
#
# chkconfig: 2345 80 20  #chkconfig --add service 會(huì)根據(jù)這里的設(shè)定,在對(duì)應(yīng)的啟動(dòng)級(jí)別加上這個(gè)服務(wù)
# description: Agent daemon service
# /etc/rc.d/init.d/xxxserver

name=xxxservice
pid_file="/var/run/${name}.pid"
stdout_log="/var/log/${name}_success.log"
stderr_log="/var/log/${name}_error.log"
cmd="需要啟動(dòng)的服務(wù)的命令"

# Get function from functions library
. /etc/init.d/functions  #關(guān)鍵是這個(gè)文件,這個(gè)文件中有很多有用的函數(shù)

get_pid() {
    cat "$pid_file"
}

is_running() {
    [ -f "$pid_file" ] && ps -p `get_pid` > /dev/null 2>&1
}

# Start the host agent
start() {
        if is_running; then
            echo "$name already started"
        else
            echo  "Starting $name ..."
            date -R >> "$stdout_log" 2>> "$stderr_log"
            $cmd >> "$stdout_log" 2>> "$stderr_log" &
            ### Create the lock file ###
            echo $! > "$pid_file"

            if ! is_running; then
                echo "Unable to start $name, see $stdout_log and $stderr_log"
                exit 1
            fi
            echo "$name startup success"
        fi
}

# Stop the host agent
stop() {
    if is_running; then
        echo -n "Stopping $name ..."
        killproc $name  #這里可以自己寫一個(gè)kill的命令,但是要能保證殺死所有由這個(gè)服務(wù)起的進(jìn)程
        for i in 1 2 3 4 5 6 7 8 9 10
        do
            if ! is_running; then
                break
            fi

            echo -n "."
            sleep 1
        done
        echo

        if is_running; then
            echo "Not stopped; may still be shutting down or shutdown may have failed"
            exit 1
        else
            echo "Stopped"
            if [ -f "$pid_file" ]; then
                rm "$pid_file"
            fi
        fi
    else
        echo "$name not running"
    fi
}

### main logic ###
case "$1" in
  start)
        start
        ;;
  stop)
        stop
        ;;
  status)
        status $name  #status這個(gè)命令也是/etc/init.d/functions里面的命令,當(dāng)然你也可以更簡(jiǎn)單的使用上面的is_runing函數(shù)
        ;;
  restart|reload)
        stop
        start
        ;;
  *)
        echo $"Usage: $0 {start|stop|restart|reload|status}"
        exit 1
esac

exit 0

這個(gè)腳本的缺點(diǎn)就是使用了. /etc/init.d/functions,這句就相當(dāng)于source /etc/init.d/functions,因?yàn)樵趕ystemd和upstart主導(dǎo)的系統(tǒng)中,很可能沒(méi)有自帶/etc/init.d/functions,這個(gè)文件中定義了很多內(nèi)部的shell命令函數(shù),沒(méi)有這個(gè)文件,很多功能函數(shù)都得自己去寫,或者找替代,比如上面腳本中用到的killproc函數(shù)。但是,幸運(yùn)的是,對(duì)于uwsgi程序spawan出來(lái)的多進(jìn)程,只需要?dú)⒌舾高M(jìn)程就會(huì)把其他進(jìn)程全部殺掉,所以/etc/init.d/functions中的很多功能函數(shù)比如killproc還是可以自己實(shí)現(xiàn)的。
對(duì)于systemV,如果要將開(kāi)服務(wù)設(shè)置成開(kāi)機(jī)自啟動(dòng),那么就執(zhí)行chkconfig --add 服務(wù)名,這個(gè)命令會(huì)依據(jù)腳本開(kāi)頭設(shè)置的chkconfig: 2345 80 20,在/etc/rc.d/rc(2345).d/4個(gè)目錄下創(chuàng)建S80開(kāi)頭家K20開(kāi)頭的軟連接到這個(gè)服務(wù)在/etc/init.d/下的腳本。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 最近在研究Docker的源碼.讀到ApiServer的啟動(dòng)過(guò)程時(shí),發(fā)現(xiàn)其有一個(gè)新的概念,叫做service act...
    AlstonWilliams閱讀 1,237評(píng)論 1 4
  • 啟動(dòng)流程:POST --> Boot Sequence --> Bootloader --> kernel +in...
    尛尛大尹閱讀 1,182評(píng)論 0 1
  • 系統(tǒng)啟動(dòng)是一項(xiàng)非常復(fù)雜的程序,因?yàn)閮?nèi)核得先檢測(cè)硬件并加載適當(dāng)?shù)尿?qū)動(dòng)程序后,接下來(lái)則必須要調(diào)用程序來(lái)準(zhǔn)備好系統(tǒng)運(yùn)行的...
    Zhang21閱讀 12,336評(píng)論 3 10
  • 系統(tǒng)巡檢腳本:Version 2016.08.09 ############################ 系統(tǒng)...
    NamasAmitabha閱讀 1,479評(píng)論 0 0
  • muahao閱讀 2,172評(píng)論 0 3

友情鏈接更多精彩內(nèi)容