[转]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

posted @ 2016-06-15 17:52  Jingle Guo  阅读(1155)  评论(0编辑  收藏  举报