Chinaunix首页 | 论坛 | 博客
  • 博客访问: 34529
  • 博文数量: 11
  • 博客积分: 10
  • 博客等级: 民兵
  • 技术积分: 65
  • 用 户 组: 普通用户
  • 注册时间: 2012-03-02 16:53
文章分类
文章存档

2012年(11)

我的朋友

分类:

2012-05-21 17:40:27

在Linux下编写Daemon  
 
Linux(以Redhat Linux Enterprise Edition 5.3为例)下,有时需要编写ServiceService也是程序,一般随系统启动用户不干预就不退出的程序,可以称为ServiceLinux下的Service一般称为Daemon

 

以上是广义的Service的定义。Linux下的服务一般放在/etc/init.d文件夹下。浏览一下这个文件夹下的文件,可以发现在Linux下编写Service一般遵循的原则。

 

Linux下编写Service一般遵循的原则

1)真正运行的Service一般放在某个bin目录下(/bin/usr/binetc)。

2/etc/init.d文件夹下一般是shell脚本,用来控制bin目录下的Service

3/etc/init.d文件夹下的shell脚本一般接受至少两个参数,startstop。还有其他常用的可选参数如statusreloadrestart,等。

4/etc/init.d文件夹下的shell脚本至少包括两行注释,一行告诉chkconfig此服务运行的runlevel,启动优先级,结束优先级。一行告诉chkconfig此服务的描述。

 

Linux的启动过程和RunLevel

要理解Linux的启动过程和RunLevel,可以先浏览一下/etc/inittab文件。在/etc/inittab中定义了下面7RunLevel。每个Service可以设置自己在哪个RunLevel下运行。可以调用/sbin/init 进入相应的RunLevel,比如运行/sbin/init 6就会导致系统重启。如果在某个RunLevel下某个服务不能启动,导致系统启动失败,可以进入没有配置此服务的RunLevel来禁用或修改此服务(有点类似Windows下的安全模式)。

 

#   0 - halt (Do NOT set initdefault to this)

#   1 - Single user mode

#   2 - Multiuser, without NFS (The same as 3, if you do not have networking)

#   3 - Full multiuser mode

#   4 - unused

#   5 - X11

#   6 - reboot (Do NOT set initdefault to this)

 

/etc/inittab文件下还定义了缺省RunLevel。如下,代表缺省RunLevel5

 

id:5:initdefault:

 

/etc文件夹下,执行ls -d rc*,会列出下面这些文件和目录:

 

rc  rc0.d  rc1.d  rc2.d  rc3.d  rc4.d  rc5.d  rc6.d  rc.d  rc.local  rc.sysinit

 

rc是一个脚本,在/etc/inittab中,会根据RunLevel执行rc rc脚本会到相应的rcN.d中去执行下面的脚本。rc.local是最后调用的脚本,可以放一些用户自定义的任务在里面。

 

进入rcN.d文件夹下,会发现以SK开头的脚本的链接,SK后面还带2位数字。其中S代表StartK代表KillS开头的脚本,在rc中调用的时候会带start参数;K开头的脚本,在rc中调用的时候会带stop参数。SK后面带的2位数字代表Service的优先级,数字越大,越后执行。这些脚本的链接的目的地多半都在/etc/init.d文件夹下。

 

现在一切都清晰了。我们可以通过在相应的rcN.d文件夹下按既定的规范创建/etc/init.d下脚本的软链接的方式来控制系统启动和退出时服务的启动和结束。但是用手动的方式创建软链接来管理毕竟不方便,RedHatLinux提供了chkconfig来帮助创建这些软链接。只要放在/etc/init.d下的服务控制脚本符合前面提到的chkconfig的约定(注释chkconfig description),就可以用chkconfig --add   chkconfig --list chkconfig --del 等命令来控制service的启动与否。

 

一个例子

每隔10s在/tmp/dameon.log中写入一句话,用C语言编写,然后把它放到/root/bin下面:


 

点击(此处)折叠或打开

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <fcntl.h>
  5. #include <sys/types.h>
  6. #include <unistd.h>
  7. #include <sys/wait.h>
  8. #include <signal.h>
  9. #define MAXFILE 65535
  10. volatile sig_atomic_t _running = 1;
  11. void sigterm_handler(int arg);

  12. void main()
  13. {
  14.   pid_t pc;
  15.   int i, fd, len;
  16.   char *buf = "this is a Daemon\n";
  17.   len = strlen(buf);
  18.   //the first step
  19.   pc = fork();
  20.   if(pc < 0)
  21.   {
  22.     printf("error fork\n");
  23.     exit(1);//abnormal exit
  24.   }
  25.   else if(pc > 0)
  26.   {
  27.     exit(0);//normal exit of parent process
  28.   }
  29.   //the second step
  30.   setsid();
  31.   //the third step
  32.   chdir("/");
  33.   //the forth step
  34.   umask(0);
  35.   //the fiveth step
  36.   for(i = 0; i < MAXFILE; i++)
  37.   {
  38.     close(i);
  39.   }
  40.   signal(SIGTERM, sigterm_handler);
  41.   while(_running)
  42.   {
  43.     if((fd = open("/tmp/daemon.log", O_CREAT|O_WRONLY|O_APPEND, 0600)) < 0)
  44.     {
  45.       perror("open");
  46.       exit(1);
  47.     }
  48.     write(fd, buf, len);
  49.     close(fd);
  50.     usleep(10*1000);//10ms
  51.   }
  52. }

  53. void sigterm_handler(int arg)
  54. {
  55.   _running = 0;

  56. }


下面是一个脚本,名字为myTestService,放在/etc/init.d/下面:


 

点击(此处)折叠或打开

  1. #!/bin/sh
  2. # chkconfig: 2345 80 50
  3. # description: myTestService is for testing how to write service in Linux
  4. # processname: myTestService
  5. # Source function library.
  6. #. /etc/rc.d/init.d/functions

  7. ret=0

  8. start() {
  9.     # check fdb status
  10.       echo "start myTestService"
  11.       #daemon /root/bin/myrand &
  12.       ./test &
  13.       ret=$?
  14. }

  15. stop() {
  16.     echo "stop myTestService"
  17.     kill -9 $(ps -ef | grep test | grep -v grep | awk '{print $2}')
  18.     ret=$?
  19. }



  20. status() {
  21.    local result
  22.    echo "check status of myTestService..."
  23.   #lines=$( ps -ef | grep test | grep -v grep | )
  24.    #echo $lines
  25.    result=$( ps -ef | grep test | grep -v myTestService | grep -v grep | wc -l )
  26.    #echo $result
  27.    if [ $result -gt 0 ] ; then
  28.        echo "myTestService is up"
  29.        ret=0
  30.   else
  31.        echo "myTestService is down"
  32.      ret=1
  33.  fi
  34.    echo "check status of myTestService...done."
  35. }

  36. # See how we were called.

  37. case "$1" in
  38.   start)
  39.         start
  40.         ;;
  41.   stop)
  42.         stop
  43.         ;;
  44.   status)
  45.       status
  46.         ;;
  47.   *)
  48.       echo $"Usage: $0 {start|stop|status}"
  49.       exit 1
  50. esac

  51. exit $ret
阅读(1172) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~