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

以上是广义的Service的定义。Linux下的服务一般放在/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的启动与否。

一个例子

下面是用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);

}

}

下面是一个脚本,名字是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 <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等,分别用来杀掉服务和查看服务状态。

命令使用:

用 /dev/null 2>&1 这样的写法.这条命令的意思是将标准输出和错误输出全部重定向到/dev/null中,也就是将产生的所有信息丢弃.

下面就为大家来说一下, command > file 2>file  与command > file 2>&1 有什么不同的地方.

      首先 command > file 2>file 的意思是将命令所产生的标准输出信息,和错误的输出信息送到file中 command  > file 2>file 这样的写法,stdout和stderr都直接送到file中, file会被打开两次,这样stdout和stderr会互相覆盖,这样写相当使用了FD1和FD2两个同时去抢占file 的管道.
      而command >file 2>&1 这条命令就将stdout直接送向file, stderr 继承了FD1管道后,再被送往file,此时,file 只被打开了一次,也只使用了一个管道FD1,它包括了stdout和stderr的内容.
      从IO效率上,前一条命令的效率要比后面一条的命令效率要低,所以在编写shell脚本的时候,较多的时候我们会用command > file 2>&1 这样的写法.
关于shell中:>/dev/null 2>&1 详解

shell中可能经常能看到:>/dev/null 2>&1

命令的结果可以通过%>的形式来定义输出

分解这个组合:“>/dev/null 2>&1” 为五部分。

1:> 代表重定向到哪里,例如:echo "123" > /home/123.txt
2:/dev/null 代表空设备文件
3:2> 表示stderr标准错误
4:& 表示等同于的意思,2>&1,表示2的输出重定向等同于1
5:1 表示stdout标准输出,系统默认值是1,所以">/dev/null"等同于 "1>/dev/null"

因此,>/dev/null 2>&1也可以写成“1> /dev/null 2> &1”

那么本文标题的语句执行过程为:
1>/dev/null :首先表示标准输出重定向到空设备文件,也就是不输出任何信息到终端,说白了就是不显示任何信息。
2>&1 :接着,标准错误输出重定向 到标准输出,因为之前标准输出已经重定向到了空设备文件,所以标准错误输出也重定向到空设备文件。

在Linux下编写Daemon(Linux启动流程2)相关推荐

  1. 在Linux下编写Daemon

    在Linux下编写Daemon 转自:http://blog.163.com/prevBlogPerma.do?host=manyhappy163&srl=164476831201071811 ...

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

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

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

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

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

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

  5. Docker Linux下安装配置及启动

    Docker Linux下安装配置及启动 linux配置环境 基础下载镜像: wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliy ...

  6. linux环境下查看进程,Linux下查看进程(程序)启动时的环境变量

    背景: 因最近试安装Linux下的jira,有一个中文插件安装后,一旦设置开机启动后,它是英文,而在终端再重新启动一次后呢,似乎插件生效,它又恢复为正常中文界面,我首先想这这涉及到一个环境变量的问题, ...

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

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

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

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

  9. 在linux下编写动态链接库的步骤: g++ -lc

    引用自http://blog.csdn.net/lwhsyit/article/details/2828306 类似Windows系统中的动态链接库,Linux中也有相应的共享库用以支持代码的复用.W ...

最新文章

  1. %fplot('Untitled1',[-1,2])画图
  2. poj 3082多边形相交 'Roid Rage
  3. 关于json_decode乱码及NULL的解决方法
  4. 天猫方糖 篇一:新版天猫放糖改造立体声
  5. windows7中安装jdk1.8
  6. vue组件样式scoped
  7. Faster R-CNN理论
  8. vue下载所有格式的文件
  9. Ubuntu状态栏显示网速,内存利用率等信息——sysmonitor
  10. 用ctrl+鼠标滚动调节字体大小
  11. 从0开始制作H5直播源码的教程
  12. 助力湾区金融科技,巨杉数据库入选首届粤港澳大湾区金融科技飞鱼企业20强榜单
  13. 0006-Flink原理(Flink数据流 执行图)
  14. 哲学家问题(图形化实现)
  15. 获得ISO20000体系认证过程介绍
  16. 在大功率DCDC中为什么LLC输出要用mos管整流而不是二极管?
  17. UEFI原理与编程实践--EFI System Table中的输入输出
  18. wordpress开放注册和邮件问题解决
  19. socks5进程代理模拟器单窗口单IP软件分享及使用教程
  20. Delphi快速开发本机跨平台Google Maps谷歌地理信息系统GIS解决方案

热门文章

  1. 关于urllib2.urlopen()的理解
  2. Flink实操 : DataSource操作
  3. 多媒体卡和SD卡的卡识别过程
  4. 面试高级算法梳理笔记
  5. Python——保存图片到本地
  6. Linux Debian 系统的单网卡绑定多个IP地址的操作步骤
  7. NPDP产品经理认证:产品开发项目的风险评估
  8. TI的CC2530单片机检测不同类型的方波
  9. 升级至MacOS Catalina安装Anaconda后,Terminal不识别conda命令乍办?
  10. mbedtls 安装与使用