在Linux下编写Daemon

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的启动与否。

 

一个例子

下面是用c++语言写的一个Service,此Service/tmp/random文件中,每隔5秒生成一个4位随机数字。通过g++ -o myrand myrand.cpp编译。然后把myrand放到/root/bin/文件夹下。

 

/* myrand.cpp

 * this program read 4 chars from /dev/random in each iteration,

 * and then adjust it to 0-9. Finally the 4 chars are written

 * to /tmp/random. This is only for testing /dev/random, and

 * at the same time serve as a example service.

 */

#include

#include

using namespace std;

#include

 

 

int main()

{

                while (true)

                {

                                ifstream ifile("/dev/random");

                                char ch;

                                char str[5];

                                str[4]=0;

                                int i;

                                for(i=0;i<4;i++)

                                {

                                                ifile >> ch;

                                                if(ch<0) ch=-ch;

                                                ch = ch % 10;

                                                ch='0' + ch;

                                                str[i]=ch;

                                }

 

                                ofstream ofile("/tmp/random");

                                ofile << str << endl;

                                sleep(5);

                }

}

 

下面是一个脚本,名字是myrandservice,放在/etc/init.d文件夹下:

 

#!/bin/sh

#

# chkconfig: 2345  80 50

# description: myrandservice is for testing how to write service in Linux

#             

# processname: myrandservice

#

# Source function library.

. /etc/rc.d/init.d/functions

 

 

ret=0

 

 

start() {

    # check fdb status

                echo "start myrandservice"

                daemon /root/bin/myrand &

                ret=$?

}

 

stop() {

    echo "stop myrandservice"

                kill -9 $(ps -ef | grep myrand | grep -v grep | awk '{print $2}')

                ret=$?

}

 

status() {

                local result

                echo "check status of myrandservice..."

                #lines=$( ps -ef | grep myrand | grep -v grep  |  )

                #echo $lines

                result=$( ps -ef | grep myrand | grep -v myrandservice | grep -v grep | wc -l )

                #echo $result

                if [ $result -gt 0 ] ; then

                                echo "my randservice is up"

                                ret=0

                else

                                echo "my randservice is down"

                                ret=1

                fi

                echo "check status of myrandservice...done."

}

 

# See how we were called.

case "$1" in

  start)

        start

        ;;

  stop)

        stop

        ;;

  status)

                                status

        ;;

  *)

        echo $"Usage: $0 {start|stop|status}"

        exit 1

esac

 

exit $ret

 

例子的一些说明

例子中脚本的下面两行既是给chkconfig用的。其中2345代表此服务在RunLevel 2, 3, 4, 5下开启;80代表启动优先级;50代表结束优先级。如果RunLevel处不添值,用“-”代替,则代表此服务在任何runlevel下都不会自动启动,需要手动启动。可以通过service start/stop/status等来控制或查询Service

 

# chkconfig: 2345  80 50

# description: myrandservice is for testing how to write service in Linux

 

脚本中的daemon函数存在于/etc/rc.d/init.d/functions中。daemon会重定向输出到/dev/null,也会设置是否生成coredump文件。通过daemon启动的程序,即使用户退出了命令行shell,也会保证Service会运行而不会退出。在/etc/rc.d/init.d/functions中还包括其他一些有用的函数,如killprocstatus等,分别用来杀掉服务和查看服务状态。

 

(一觉亮天。发文为学习和交流,如有错误或纰漏,欢迎指正。)

 

你可能感兴趣的:(sys-admin)