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來模擬。
[cpp] view plain copy- #include <stdio.h>
- #include <stdlib.h>
- int main()
- {
- daemon(0,0);
- while(1)
- {
- printf("Hellow World!/n");
- sleep(100000);
- }
- }
儲存上面的測試程式為dennis.c,執行如下編譯命令得到dennisd守護程序程式。
#gcc -c dennis.c
# gcc -o dennisd dennis.o
實際執行中,例如你編寫了一個tcp伺服器程式,可以程式寫成一個函式(如tcp_server),然後將while部分更換為你的函式tcp_server()即可。如下:
[cpp] view plain copy- #include <stdio.h>
- #include <stdlib.h>
- int main()
- {
- daemon(0,0);
- tcp_server();
- }
參考資料:http://www.netzmafia.de/skripten/unix/linux-daemon-howto.html
(三)如何編寫service控制指令碼
首先指令碼必須放在/etc/init.d/目錄下,因此本文在先建立/etc/init.d/dennisd指令碼檔案。內容如下:
[php] view plain copy- #!/bin/bash
- #
- # Description: This shell script takes care of starting and stopping dennis
- # Hu Dennis created on Sep. 24th, 2010
- #
- # Source function library
- . /etc/init.d/functions
- #the service name for example: dennis
- SNAME=dennisd
- #the full path and name of the daemon program
- #Warning: The name of executable file must be identical with service name
- PROG=/usr/bin/$SNAME
- # start function
- start() {
- #check the daemon status first
- if [ -f /var/lock/subsys/$SNAME ]
- then
- echo "$SNAME is already started!"
- exit 0;
- else
- action "Starting $SNAME ..." $PROG
- [ $? -eq 0 ] && touch /var/lock/subsys/$SNAME
- exit 0;
- fi
- }
- #stop function
- stop() {
- echo "Stopping $SNAME ..."
- killproc $SNAME
- rm -rf /var/lock/subsys/$SNAME
- }
- case "$1" in
- start)
- start
- ;;
- stop)
- stop
- ;;
- reload|restart)
- stop
- start
- ;;
- status)
- status $SNAME
- ;;
- *)
- echo $"Usage: $0 {start|stop|restart|status}"
- exit 1
- esac
#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服務程式從程式碼編寫到指令碼除錯以及測試執行全過程,希望對有此需求的朋友有所幫助!