在Linux下编写Daemon

转自:http://blog.163.com/prevBlogPerma.do?host=manyhappy163&srl=1644768312010718111142260&mode=prev

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

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

一 Linux下编写Service一般遵循的原则
1)真正运行的Service一般放在某个bin目录下(/bin,/usr/bin,etc)。
2)/etc/init.d文件夹下一般是shell脚本,用来控制bin目录下的Service。
3)/etc/init.d文件夹下的shell脚本一般接受至少两个参数,start和stop。还有其他常用的可选参数如status,reload,restart,等。
4)/etc/init.d文件夹下的shell脚本至少包括两行注释,一行告诉chkconfig此服务运行的runlevel,启动优先级,结束优先级。一行告诉chkconfig此服务的描述。

二 Linux的启动过程和RunLevel
要理解Linux的启动过程和RunLevel,可以先浏览一下/etc/inittab文件。在/etc/inittab中定义了下面7种RunLevel。每个Service可以设置自己在哪个RunLevel下运行。可以调用/sbin/init <runlevel>进入相应的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。如下,代表缺省RunLevel是5。
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 <runlevel>。rc脚本会到相应的rcN.d中去执行下面的脚本。rc.local是最后调用的脚本,可以放一些用户自定义的任务在里面。

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

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

三 一个例子
1)下面是用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 <iostream>
#include <fstream>
using namespace std;
#include <unistd.h>

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);
    }
}

2) 下面是一个脚本,名字是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

3)使用/sbin/chkconfig --add myrandservice 来将次daemon设置为自动启动。 同时可以在rc3.d,rc4.d,rc5.d下面看到相应的脚本链接被自动地创建了。

4)例子的一些说明
例子中脚本的下面两行既是给chkconfig用的。其中2345代表此服务在RunLevel 2, 3, 4, 5下开启;80代表启动优先级;50代表结束优先级。如果RunLevel处不添值,用“-”代替,则代表此服务在任何runlevel下都不会自动启动,需要手动启动。可以通过service <service-name> 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中还包括其他一些有用的函数,如killproc,status等,分别用来杀掉服务和查看服务状态。

四 deamon的另一种实现

不使用/etc/rc.d/init.d/functions中的daemon,则Daemon程序设计要遵从以下过程:

(1)       程序运行后调用fork,并让父进程退出。子进程获得一个新的进程ID,但继承了父进程的进程组ID。

(2)       调用setsid创建一个新的session,使自己成为新session和新进程组的leader,并使进程没有控制终端(tty)。

(3)       设置文件创建mask为0,避免创建文件时权限的影响。

(4)       关闭不需要的打开文件描述符。因为Daemon程序在后台执行,不需要于终端交互,通常就关闭STDIN、STDOUT和STDERR。其它根据实际情况处理。

(5)       Daemon无法输出信息,可以使用SYSLOG或自己的日志系统进行日志处理。(可选)

(6)       编写管理Daemon的SHELL脚本,使用service对Daemon进行管理和监控。(可选)

参考:

http://www.cnblogs.com/khler/archive/2011/01/30/1947971.html

完!

在Linux下编写Daemon相关推荐

  1. 在Linux下编写Daemon(Linux启动流程2)

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

  2. linux编写php,Linux 下编写一个 PHP 扩展

    假设需求 开发一个叫做 helloWord 的扩展. 扩展里有一个函数,helloWord(). echo helloWord('Tom'); //返回:Hello World: Tom 本地环境 P ...

  3. 专业的LaTeX: 在Linux下编写高质量的文档

    专业的LaTeX: 在Linux下编写高质量的文档 Linux下的OpenOffice.KWord等字处理软件虽然在功能上与Microsoft Word类似,但目前在易用性和可用性方面仍然存在许多不足 ...

  4. Linux下编写UDP/TCP版本的服务器和客户端的流程

    Linux下编写UDP/TCP版本的服务器和客户端的流程 文章目录 Linux下编写UDP/TCP版本的服务器和客户端的流程 一:UDP和TCP的区别 二.UDP编写服务器的步骤 三.UDP编写客户端 ...

  5. spdlog linux编译出错,Linux下编写Makefile引入第三方库

    Linux下编写Makefile引入第三方库 前言:一直在使用CmakaList 生成Makefile文件,其实很少去写Makefile,但是最近帮朋友处理了一个Makefile引入第三方库的问题,就 ...

  6. Linux下编写贪吃蛇游戏

    Linux下编写贪吃蛇游戏 文章目录 Linux下编写贪吃蛇游戏 前言 一.贪吃蛇代码 二.运行贪吃蛇代码 前言 本程序需要ncurses库,ubuntu下安装ncurses可以执行下面命令: sud ...

  7. linux应用程序的编写实验原理,操作系统实验 1.在linux下编写一个应用程序 联合开发网 - pudn.com...

    操作系统实验 所属分类:Linux/Unix编程 开发工具:C/C++ 文件大小:1KB 下载次数:3 上传日期:2019-05-01 20:34:21 上 传 者:烟雨南风起 说明:  1.在lin ...

  8. Linux运行911,韦东山-Linux下编写GT911触摸驱动 - 百问网嵌入式问答社区

    源码在最下面 问题一:资源获取Gt911数据手册 在韦老师给的资料里,路径为\06_Datasheet\Extend_modules\7寸LCD模块\电容触控芯片GT911 Datasheet_121 ...

  9. texlive - 专业的LaTeX: 在Linux下编写高质量的文档

    dnf install texlive* dnf install texworks dnf install latex* http://www.ibm.com/developerworks/cn/li ...

最新文章

  1. type=file的未选择任何文件修改_PDF文件怎样输入到CAD图纸中?懂得这个功能可以快速实现...
  2. mysql装一次后再装_MySQL再安装
  3. python管理系统-基于Python实现用户管理系统
  4. windows下的正向shell
  5. CodeSmith生成SQL Server视图的实体类脚本/对应的生成模板
  6. 各种抠图动态图片_不用手。自动、智能抠图,图片去背景
  7. php输出位置最右,php动态读取数据清除最右边距的方法
  8. JAVA JDK1.5-1.9新特性
  9. mysql查询两个表中的不同数据_如何实现大数据在多工作表中精准查询
  10. fstream与 C 风格(例如fread 和 fwrite )两种读写文件方法的效率比较
  11. leetcode889.ConstructBinaryTreefromPreorderandPostorderTrav
  12. h5打开app_移动端产品比较分析:APP、小程序、H5
  13. 大数据工程师职场面试攻略技巧有哪些?
  14. Windows 上 curl 的安装
  15. 计算机基础知识题二,计算机基础知识题库(五)
  16. 信号处理之freqz函数
  17. js左右弹性滚动对联广告代码
  18. photoshop(ps)基础入门知识 认识图层
  19. 嵌入式linux机械臂,一款基于ARM嵌入式的机械臂的设计与实现
  20. 初学RabbitMQ(三),了解回调函数,并手动确认消息进行消费

热门文章

  1. ASP.NET的实时天气及24小时天气预报(C#)
  2. Spring源码分析【9】-SpringSecurity密码Remove原理
  3. 手机内存RAM、ROM简介
  4. 【经验】如何查看gcc、g++不加-std时的默认版本
  5. ue4 函数和宏区别_【UE4】通俗易懂 用蓝图来学习 C++ 基础知识
  6. vmware响应时间过长_性能调优高并发下如何缩短响应时间
  7. 高斯拟合原理_看得见的高斯过程:这是一份直观的入门解读
  8. java基础入门传智播客 源码_Java-_2020年版Java零基础视频教程(Java 0基础,Java初学入门)魔鬼讲师老杜出品...
  9. 学生管理系统(C语言版)
  10. mysql计算两gps坐标的距离_mysql 计算两坐标间的距离