郝健:Linux下服務程序啓動管理方式的分析與總結

作者:郝健

目前就職於瑞星咖啡,負責4層負載均衡的研究與開發。曾就職於天融信,賽爾網絡,雲杉網絡幾家公司。主要感興趣的方向:linux內核網絡子系統,dpdk。

目前,Linux平臺下主流的服務程序啓動管理方式有以下幾種: 

  1. daemon

  2.  sysvinit

  3. systemd

  4. nohup

1. daemon 


守護進程是在後臺運行不受控端控制的進程,通常情況下守護進程在系統啓動時自動運行。 

1.1 概念說明 

進程組 

每個進程除了有一進程ID( PID )之外,還屬於一個進程組。進程組是一個或多個進程的集合。每個進程組有一個唯一的進程組ID( PGID )。進程組ID類似於進程ID, 它是一個正整數,並可存放在pid_t數據類型中。函數getpgrp返回調用進程的進程組ID。

會話期(session) 

會話期是一個或多個進程組的集合。通常是由shell的管道將幾個進程編成一組的。比如,下圖中的安排 可能是由下列形式的shell命令形成的: 

procl | proc2 & 

proc3 | proc4 | proc5

一般,登陸一個shell時就會創建一個會話期。進程調用setsid函數就可建立一個新會話期。

如果調用此函數的進程不是一個進程組的組長,則此函數創建一個新會話期,結果爲:

  1. 此進程變成該新會話期的會話期首進程(session leader,會話期首進程是創建該會話期的進 程)。此進程是該新會話期中的唯一進程。

  2. 此進程成爲一個新進程組的組長進程。新進程組ID是此調用進程的進程ID。

  3. 此進程沒有控制終端。如果在調用setsid之前此進程有一個控制終端,那麼這種聯繫也被解除。如果此調用進程已經是一個進程組的組長,則此函數返回出錯。爲了保證不處於這種情況,通常先 調用fork,然後使其父進程終止,而子進程則繼續。因爲子進程繼承了父進程的進程組ID,而其進程ID則是新分配的,兩者不可能相等,所以這就保證了子進程不是一個進程組的組長。

控制終端(terminal) 

會話期和進程組有一些其他特性:

  1. 一個會話期可以有一個單獨的控制終端(controlling terminal)。這通常是我們在其上登錄的終端設備(終端登錄情況)或僞終端設備(網絡登錄情況)。

  2. 建立與控制終端連接的會話期首進程,被稱爲控制進程(controlling process)。

  3.  一個會話期中的幾個進程組可被分成一個前臺進程組(foreground process group)以及一個或 幾個後臺進程組(background process group)。

  4.  如果一個會話期有一個控制終端,則它有一個前臺進程組,其他進程組則爲後臺進程組。

  5. 無論何時鍵入中斷鍵(常常是DELETE或Ctrl -C)或退出鍵(常常是Ctrl -\),就會造成將中斷信號或退出信號送至前臺進程組的所有進程。

  6. 如果終端界面檢測到網絡已經斷開連接,則將掛斷信號送至控制進程(會話期首進程)。通常,我們不必關心控制終端,登錄時,將自動建立控制終端。

1.2 創建方法 

創建守護進程,應該創建一個進程然後將其放到一個新的會話期中。

  1. 首先要做的是調用umask將文件模式創建屏蔽字設置爲0。

  2. 調用fork(子進程會是將來的守護進程),然後使父進程退出(exit),保證子進程不是進程組組長(這 是setsid調用的必要前提條件)。

  3. 調用setsid創建新的會話期。

  4. 將當前目錄改爲根目錄(如果不改爲根目錄可能導致不能umount某個目錄)。

  5. 關閉不再需要的文件描述符。

  6. 某些守護進程打開/dev/null使其具有描述符0、1和2(將標準輸入、標準輸出、標準錯誤重定向 到/dev/null)。

或者直接調用daemon函數

2. sysvinit 


sysvinit主要依賴於Shell腳本,在/etc/rc.d/rc*.d建立軟連接。在RedHat系列發行版中,還提供了 service,chkconfig 等命令行工具,來方便來管理 init 系統。sysvinit的主要問題是啓動慢,已經逐漸 被淘汰。

目前Ubuntu和Centos等主流發行版都以移步到systemd,但仍然兼容老的寫法,這裏簡單舉個的例 子,編寫一個simple腳本,添加執行權限後,保存到/etc/init.d/目錄下。

測試:

3. systemd 


systemd是目前主流Linux髮型版採用的init項目,systemd起初飽受爭議,可以搜索“the software that currently breaks your audio”查看。但隨着越來越穩定和使用c開發,高效啓動,已經逐漸成爲主角。Linus也表示:Torvalds says he has no strong opinions on systemd

https://www.itwire.com/business-it-news/open-source/65402-torvalds-says-he-has-no-strong-opinions-on-systemd

我們簡單實現一個simple-server來感受一下systemd,主要步驟如下:

 

1. 編寫一個需要作爲守護的程序,如:simple-server.c

2. 編寫service文件

具體的說明詳見;

https://www.freedesktop.org/software/systemd/man/systemd.service.html 

其中Restart=always代表在任何情況下service被殺死後,都需要自動重啓,其他說明詳見如上鍊接中的 Table 2。

 

3. sudo cp simple-server.service /lib/systemd/system 

4. sudo systemctl enable simple-server 設置爲開機啓動,會自動創建軟連接 /etc/systemd/system/multi-user.target.wants/simpleserver.service -> /lib/systemd/system/simple-server.service 

5. sudo systemctl start simple-server 啓動 

6. sudo systemctl status simple-server 查看狀態 

7. cat /var/log/syslog 查看日誌輸出 

8. pstree | grep simple-server 

9. sudo killall simple-server 殺死服務,驗證是否自動重啓。

幾點說明:

  1. 修改simple-server.service後,需要執行systemctl daemon-reload重新加載。

  2. 在自daemon的方式中,是無法決定服務程序信息輸出的位置的,只能重定向到/dev/null,而 systemd的方式可以靈活配置重定向的位置,/var/log/syslog爲默認日誌路徑。

  3. service文件中Restart選項體現了"子死父知因"的重要性。 

4. nohup 


一個terminal一旦關閉,其綁定的shell會收到SIGHUP信號,且shell在退出之前會將SIGHUP信號廣播 給其上的進程組,即其上所有進程都會退出。這也是自daemon需要調用setsid脫離terminal的原因。nohup命令並不是真正脫離terminal,而是忽略SIGHUP。將標準輸入重定向到/dev/null,標準輸出和標準出錯重定向到nohup.out,且不會隨着terminal的關閉而退出。驗證:


1)正常啓動一個死循環程序

2)nohup啓動同樣的死循環程序

對比總結 


  1. daemon 通過自實現daemon,可以清楚的看出一個守護進程實現的原理,方便理清概念。但缺點是在實際工程中默認將輸出重定向/dev/null,無法保存服務日誌,排查服務問題,即使在程序中重定向到 某個日誌目錄,也只能寫死,修改位置需要重新編譯,不夠靈活。

  2. sysvinit sysvinit的優點是簡單,只需要編寫腳本。將服務添加到某個runlevel時,只需要創建軟鏈接文件 即可,DevOPs興起之前,傳統運維人員可以很快上手。順序執行,方便排查問題。但順序執行既 是優點也是缺點,帶來的弊端是運行效率慢,這也是逐漸被淘汰的主要原因。畢竟現在Linux不只 用於服務器系統,終端用戶更追求fast boot的用戶體驗。

  3. systemd systemd是目前主流Linux發行版中最新的初始化系統,主要的設計目標就是提高系統的啓動速 度。.service文件中包含很多選項,配置靈活,比如日誌位置和重啓方式等。當然,最主要的賣點 還是並行啓動速度快。

  4. nohup 在實際工程中,nohup也挺常用。比如一個類服務程序的調試,簡單執行即可在一段時間通過 nohup.out文件觀察問題,但其並不能算正真的守護程序。

綜上,systemd看起來可以滿足一個產品級別服務程序的兩個最重要的需求:根據不同情況重啓;記錄 日誌靈活可查,而這是daemon和nohup方式無法快速方便滿足的。sysvinit簡單清晰,但啓動慢,就作爲傳統運維人員的美好記憶保留吧。

Linux閱碼場原創精華文章彙總

更多精彩,盡在"Linux閱碼場",掃描下方二維碼關注

點一點右下角”在看”,爲閱碼場打Call~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章