Linux平臺下的service程序編寫指南

Linux平臺下的service程序編寫指南

Hu Dennis Sep 24, 2010轉載註明出處http://blog.csdn.net/gobitan

 

摘要:本文主要介紹瞭如何編寫一個service服務所涉及的兩個主要方面。1)將一個普通程序裝成daemon程序;2)編寫service方式的shell腳本。並以C語言爲例,基於Red hat 企業版5.3平臺演示了一個service服務程序從代碼編寫到腳本調試以及測試運行全過程。

 

(一)  Service介紹

Service是一種被稱爲守護進程(daemon)的程序。它通常一旦啓動後就在後臺持續運行,通常在等待什麼輸入或者監控系統有什麼變化。例如Apache服務器有一個叫httpd的守護進程監聽80端口以等待http請求。

Service程序通常通過service命令來啓動或停止等。例如apache服務的啓動可通過”service httpd start”來啓動。

通過” chkconfig --list”可以查看系統當前所有的service服務。

通過” service --status-all”可以查看系統當前所有service服務的狀態。

 

要自己編寫一個類似httpd的service方式的服務應該包括兩個部分:(1)將普通程序包裝成daemon程序;(2)編寫service控制腳本來管理daemon程序。

因此,每個service服務在/etc/rc.d/目錄下都對應一個可執行的腳本。如apache的httpd對應/etc/init.d/httpd。

 

參考資料:http://bobpeers.com/linux/services.php

 

(二)如何將普通程序包裝成daemon程序

    這裏僅介紹一種較爲簡單的方式,關於其原理及更詳細的介紹請參見本節參考資料。

    Linux提供了一個名叫daemon的函數來初始化環境,如下:

              int daemon(int nochdir, int noclose);

    使用該函數需加入#include <stdlib.h>頭文件包含。調用該函數之後,其後的程序將會以daemon方式運行。

    下面以Hello world爲例,因爲daemon程序是一個持續運行程序,爲了測試運行本文以while+sleep來模擬。

  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3.   
  4. int main()  
  5. {  
  6.     daemon(0,0);  
  7.   
  8.     while(1)  
  9.     {  
  10.        printf("Hellow World!/n");  
  11.   
  12.        sleep(100000);  
  13.   
  14.     }  
  15. }  

 

保存上面的測試程序爲dennis.c,執行如下編譯命令得到dennisd守護進程程序。

#gcc -c dennis.c

# gcc -o dennisd dennis.o

 

    實際運行中,例如你編寫了一個tcp服務器程序,可以程序寫成一個函數(如tcp_server),然後將while部分更換爲你的函數tcp_server()即可。如下:

  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3.   
  4. int main()  
  5. {  
  6.     daemon(0,0);  
  7.   
  8.     tcp_server();  
  9. }  
  

參考資料:http://www.netzmafia.de/skripten/unix/linux-daemon-howto.html

 

(三)如何編寫service控制腳本

    首先腳本必須放在/etc/init.d/目錄下,因此本文在先創建/etc/init.d/dennisd腳本文件。內容如下:

  1. #!/bin/bash  
  2. #  
  3. # Description:  This shell script takes care of starting and stopping dennis  
  4. # Hu Dennis created on Sep. 24th, 2010  
  5. #  
  6. # Source function library  
  7. . /etc/init.d/functions  
  8.   
  9. #the service name  for example: dennis  
  10. SNAME=dennisd  
  11.   
  12. #the full path and name of the daemon program  
  13. #Warning: The name of executable file must be identical with service name  
  14. PROG=/usr/bin/$SNAME  
  15.   
  16.   
  17. # start function  
  18. start() {  
  19.     #check the daemon status first  
  20.     if [ -f /var/lock/subsys/$SNAME ]  
  21.     then  
  22.         echo "$SNAME is already started!"  
  23.         exit 0;  
  24.     else  
  25.         action "Starting $SNAME ..." $PROG  
  26.         [ $? -eq 0 ] && touch /var/lock/subsys/$SNAME  
  27.         exit 0;  
  28.     fi  
  29. }  
  30.   
  31. #stop function  
  32. stop() {  
  33.     echo "Stopping $SNAME ..."  
  34.     killproc $SNAME  
  35.     rm -rf /var/lock/subsys/$SNAME  
  36. }  
  37.   
  38. case "$1" in  
  39. start)  
  40.   start  
  41.   ;;  
  42. stop)  
  43.   stop  
  44.   ;;  
  45. reload|restart)  
  46.   stop  
  47.   start  
  48.   ;;  
  49. status)  
  50.   status $SNAME  
  51.   ;;  
  52. *)  
  53.   echo $"Usage: $0 {start|stop|restart|status}"  
  54.   exit 1  
  55. esac  
腳本較爲簡單,再次不做過多解釋。然後執行如下命令給dennisd增加可執行權限:

#chmod +x dennisd

 

(四)常見調試錯誤

    在調試該腳本的時候常見的集中錯誤如下:

(1)dennisd: unrecognized service:先檢查/etc/rc.d/init.d/dennisd是否存在,然後再看該文件是否有可執行權限。

(2)env: /etc/init.d/dennisd: No such file or directory:這種情況一般是windows與linux的格式兼容問題,執行dos2unix將dos格式轉換程序linux格式(ubuntu下爲fromdos命令)。

(3)Usage: status [-p pidfile] {program}: status後面的參數不對

(4)dennisd dead but subsys locked:可執行程序的名字需要與service名字保持一致。

 

(五)測試運行

    將第二步編譯得到的dennisd程序拷貝至/usr/bin/目錄下,然後執行如下命令測試:

(1)啓動服務

     [root init.d]# service dennisd start

Starting dennisd ... [  OK  ]

  通過ps命名確認dennisd已經啓動:

         [root init.d]# ps -ef|grep dennisd

root      3885     1  0 14:30 ?        00:00:00 /usr/bin/dennisd

 

(2)查看狀態

[root init.d]# service dennisd status

dennisd (pid 3885) is running...

 

(3)停止服務

[root init.d]# service dennisd stop

Stopping dennisd ...

再執行status命令查看狀態

[root init.d]# service dennisd status

dennisd is stopped

   (4)多次啓動

        [root init.d]# service dennisd start

Starting dennisd ... [  OK  ]

[root init.d]# service dennisd start

dennisd is already started!

如果服務已經啓動,系統會提示而不會啓動多個。

 

(六)結束語

    本文以C語言爲例,在linux環境下演示了一個service服務程序從代碼編寫到腳本調試以及測試運行全過程,希望對有此需求的朋友有所幫助!

    Hu Dennis 2010-9-24 於成都 Email: dennis.hu.cd at gmail.com

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