一 service与一般的程序的区别
service(也称为daemon)表示后台运行的程序,一般随系统的启动自动地启动且在用户logoff后仍然能够继续运行。该daemon进程一般在启动后需要与父进程断开关系,并使进程没有控制终端(tty)。因为daemon程序在后台执行,不需要于终端交互,通常就关闭STDIN、STDOUT和STDER。daemon无法输出信息,可以使用syslog或自己的日志系统进行日志处理。
可以使用/etc/rc.d/init.d/functions脚本中的daemon函数来将一般的程序启动为daemon,例如nfs daemon的启动:
echo -n $"Starting NFS daemon: "
daemon rpc.nfsd $RPCNFSDARGS $RPCNFSDCOUNT
ETVAL=$?
echo
[ $RETVAL -ne 0 ] && exit $RETVAL
二 跟 service相关的目录和文件
/etc/init.d -> /etc/rc.d/init.d : /etc/rc.d/init.d 下包含了所有的service的控制脚本,/etc/init.d 是 /etc/rc.d/init.d 的链接。
/etc/rc*.d -> /etc/rc.d/rc*.d : /etc/rc.d/rc*.d 下包含了所有的service的自动启动选项的配置,/etc/rc*.d 是 /etc/rc.d/rc*.d 的链接。
/etc/rc.d/rc*.d/ 下的脚本是对 /etc/rc.d/init.d 下的脚本的链接,只是名字增加K或S前缀,用来表示自动启动或自动停止。
所有的service相关的目录树结构如下:
/etc
|-- init.d -> rc.d/init.d
|-- rc -> rc.d/rc
|-- rc.d
| |-- init.d
| | |-- NetworkManager
| | |-- network
| | |-- nfs
| | |-- xinetd
| | |-- ... ...
| |-- rc
| |-- rc.local
| |-- rc.sysinit
| |-- rc3.d
| | |-- K02NetworkManager -> ../init.d/NetworkManager
| | |-- K20nfs -> ../init.d/nfs
| | |-- S10network -> ../init.d/network
| | |-- S56xinetd -> ../init.d/xinetd
| | |-- ... ...
|-- rc.local -> rc.d/rc.local
|-- rc.news
|-- rc.sysinit -> rc.d/rc.sysinit
|-- rc0.d -> rc.d/rc0.d
|-- rc1.d -> rc.d/rc1.d
|-- rc2.d -> rc.d/rc2.d
|-- rc3.d -> rc.d/rc3.d
|-- rc4.d -> rc.d/rc4.d
|-- rc5.d -> rc.d/rc5.d
|-- rc6.d -> rc.d/rc6.d
三 一个service的组成和部署
一个service通常包含一个可执行的文件和一个service控制脚本。 作为service程序本身的可执行程序一般存储在/usr/bin下;作为控制service的脚本一般存储在/etc/rc.d/init.d下,且控制service的脚本的格式相对固定,至少支持start,stop,status参数。 例如smb的service控制脚本为:
#!/bin/sh
#
# chkconfig: - 91 35
# description: Starts and stops the Samba smbd and nmbd daemons \
# used to provide SMB network services.
#
# pidfile: /var/run/samba/smbd.pid
# pidfile: /var/run/samba/nmbd.pid
# config: /etc/samba/smb.conf
# Source function library.
if [ -f /etc/init.d/functions ] ; then
. /etc/init.d/functions
elif [ -f /etc/rc.d/init.d/functions ] ; then
. /etc/rc.d/init.d/functions
else
exit 1
fi
# Avoid using root's TMPDIR
unset TMPDIR
# Source networking configuration.
. /etc/sysconfig/network
if [ -f /etc/sysconfig/samba ]; then
. /etc/sysconfig/samba
fi
# Check that networking is up.
[ ${NETWORKING} = "no" ] && exit 1
# Check that smb.conf exists.
[ -f /etc/samba/smb.conf ] || exit 6
RETVAL=0
start() {
KIND="SMB"
echo -n $"Starting $KIND services: "
daemon smbd $SMBDOPTIONS
RETVAL=$?
echo
KIND="NMB"
echo -n $"Starting $KIND services: "
daemon nmbd $NMBDOPTIONS
RETVAL2=$?
echo
[ $RETVAL -eq 0 -a $RETVAL2 -eq 0 ] && touch /var/lock/subsys/smb || \
RETVAL=1
return $RETVAL
}
stop() {
KIND="SMB"
echo -n $"Shutting down $KIND services: "
killproc smbd
RETVAL=$?
echo
KIND="NMB"
echo -n $"Shutting down $KIND services: "
killproc nmbd
RETVAL2=$?
[ $RETVAL -eq 0 -a $RETVAL2 -eq 0 ] && rm -f /var/lock/subsys/smb
echo ""
return $RETVAL
}
restart() {
stop
start
}
reload() {
echo -n $"Reloading smb.conf file: "
killproc smbd -HUP
RETVAL=$?
echo
return $RETVAL
}
rhstatus() {
status smbd
RETVAL=$?
status nmbd
RETVAL2=$?
if [ $RETVAL -ne 0 ] ; then
return $RETVAL
fi
if [ $RETVAL2 -ne 0 ] ; then
return $RETVAL2
fi
}
# Allow status as non-root.
if [ "$1" = status ]; then
rhstatus
exit $?
fi
# Check that we can write to it... so non-root users stop here
[ -w /etc/samba/smb.conf ] || exit 4
case "$1" in
start)
start
;;
stop)
stop
;;
restart)
restart
;;
reload)
reload
;;
status)
rhstatus
;;
condrestart)
[ -f /var/lock/subsys/smb ] && restart || :
;;
*)
echo $"Usage: $0 {start|stop|restart|reload|status|condrestart}"
exit 2
esac
exit $?
四 service的管理工具/sbin/service
可以使用工具/sbin/service来查看和管理系统上的所有的service,例如查看所有的service的状态使用/sbin/service --status-all, 或者启动停止或重启某个service为/sbin/service XXX start/stop/restat。
打开/sbin/service脚本,我们可以看到其实service命令实现很简单,就是遍历/etc/init.d (-> /etc/rc.d/init.d)下的所有的service控制脚本,执行相应service控制脚本中的操作。
你可以使用命令cat /sbin/service 来查看/sbin/service的实现。
五 service的自动启动控制工具/sbin/chkconfig
当你实现你的service且部署到/etc/init.d下后,你的脚本已经可以手动地启动和关闭,但是要实现在系统启动的时候你的service自动地启动,还需要做简单的配置。我们知道/etc/rc.d/rc*.d下的脚本是对/etc/rc.d/init.d下的service控制脚本的一个连接,用来控制service的自动启动选项的。例如在/etc/rc.d/rc3.d下lrwxrwxrwx 1 root root 16 2009-05-20 S12syslog -> ../init.d/syslog ,此连接文件以S开头表示了在runlevel为3下syslog service将会与系统一起自动地启动。
手动地在/etc/rc.d/rc*.d下创建连接文件来配置service是否自动地启动,实在是有点麻烦,我们可以使用工具/sbin/chkconfig来简化service启动选项的配置。/sbin/chkconfig工具要求service的控制脚本的前几行必须包含如下的类似信息:
# chkconfig: - 91 35
# description: Starts and stops the Samba smbd and nmbd daemons \
# used to provide SMB network services.
#
使用chkconfig的实例如下:
chkconfig --list 用来查看所有的service的启动选项的配置;
chkconfig network 用来查看network service的启动选项的配置;
更多查看:6个Linux chkconfig命令实例 - 增加,删除,查看和修改services的自动启动选项
六xinetd
xinetd本身是一个service,他的作用是监听所有的端口,根据配置对不同的端口启动不同的应用。 对于有些需要在后台运行的程序,可以选择设置为service在后台一直运行,也可以选择使用xinetd来配置此程序根据需要激活。
对于需要频繁访问的服务,需要在/etc/rc.d/init.d下配置为service;
对于不是频繁访问的服务,可以使用xinetd来激活,从而节约服务器的资源;
总之service与xinetd,选一即可。
七 参考: 在Linux下编写Daemon
+++++++++++++++++++++++++++++++++++++++++====
/etc/init.d 是 /etc/rc.d/init.d 的软链接(soft link)。可以通过 ll 命令查看,如下:
/*********************************************************************************************************************
[root@Rex ~]# ll /etc/init.d
lrwxrwxrwx 1 root root 11 3?10 09:24 /etc/init.d -> rc.d/init.d
*********************************************************************************************************************/
init.d指的是/etc/rc.d/init.d目录。
本文包括3部分内容
1、 Linux的引导过程
2、 运行级别
3、 /etc/rc.d/ 与/etc/rc.d/init.d的关系
“/etc/rc.d/init.d/目录下的脚本就类似与windows中的注册表,在系统启动的时候某些指定脚本将被执行”。开始之前,先引用李善明经理昨天晚上总结时的一个理解,让大家先对init.d目录有个大概的印象。在进入init.d之前,我们一起来做两个准备工作,linux的引导过程和运行级别的概念。
一、 Linux的引导过程
系统启动之后,在进入init.d之前,我们先来看看系统都做了什么工作。
系统加电之后,首先进行的硬件自检,然后是bootloader对系统的初始化,加载内核。内核被加载到内存中之后,就开始执行了。一旦内核启动运行,对硬件的检测就会决定需要对哪些设备驱动程序进行初始化。从这里开始,内核就能够挂装根文件系统(这个过程类似于Windows识别并存取C盘的过程)。内核挂装了根文件系统,并已初始化所有的设备驱动程序和数据结构等之后,就通过启动一个叫init的用户级程序,完成引导进程。
二、 运行级别(run level)
Init进程是系统启动之后的第一个用户进程,所以它的pid(进程编号)始终为1。init进程上来首先做的事是去读取/etc/目录下inittab文件中initdefault id值,这个值称为运行级别(run-level)。它决定了系统启动之后运行于什么级别。运行级别决定了系统启动的绝大部分行为和目的。这个级别从0到6 ,具有不同的功能。不同的运行级定义如下: # 0 - 停机(千万别把initdefault设置为0,否则系统永远无法启动) # 1 - 单用户模式 # 2 - 多用户,没有 NFS # 3 - 完全多用户模式(标准的运行级) # 4 – 系统保留的 # 5 - X11 (x window) # 6 - 重新启动 (千万不要把initdefault 设置为6,否则将一直在重启 ) 这是两个表较常用运行级别(后期补上),左图redhat9 级别3启动的将是文本界面,右图fc7级别5启动的将是图形界面。
三、 /etc/rc.d/与/etc/rc.d/init.d的关系
写到这里,应该差不多要进入init.d了,可是我觉得单写/etc/rc.d/init.d的话不一定能说得清楚明白,就拿它跟/etc/rc.d这个它上一级的目录一起来讨论,可能比较合适一些,因为他们之间有着千丝万缕的关系。
在这里先解释一下init.d里面放的都是什么东西。这个目录存放的是一些脚本,一般是linux以rpm包安装时设定的一些服务的启动脚本。系统在安装时装了好多rpm包,这里面就有很多对应的脚本。执行这些脚本可以用来启动,停止,重启这些服务。
前面说到,/etc/rc.d/init.d这个目录下的脚本就类似与windows中的注册表,在系统启动的时候执行。程序运行到这里(init进程读取了运行级别),相信从命名的角度大家也能猜到该运行/etc/rc.d/init.d里面的脚本了,不然它为什么也叫init(.d)呢是吧。没错,是该运行init.d里的脚本了,但是并不是直接运行,而是有选择的因为系统并不需要启动所有的服务。
那么,系统是如何选择哪些需要启动哪些不要呢?这时刚才说的运行级别就起作用了。在决定了系统启动的run level之后,/etc/rc.d/rc这个脚本先执行。在RH9和FC7的源码中它都是一上来就check_runlevel()(虽然实现的代码不一样,也大同小异),知道了运行级别之后,对于每一个运行级别,在rc.d下都有一个子目录分别是rc0.d,rc1.d ….. rc6.d。每个目录下都是到init.d目录的一部分脚本一些链接。每个级别要执行哪些服务就在相对应的目录下,比如级别5要启动的服务就都放在rc5.d下,但是放在这个rc5.d下的都是一些链接文件,链接到init.d中相对应的文件,真正干活到init.d里的脚本。
redhat9 ls
fc7 ls -l
这样看的就很清楚了。
到这里,估计大家可能都比较清楚了,我开始也以为是这样的。可是后来我仔细看过和比较这些链接文件和init.d里真正被执行的脚本的文件名之后,一直有几个问题没弄明白。借着写这个文章的机会,我做了一些功课,总算是大概解开了那些疑惑。
1、这些链接文件前面为什么会带一个Kxx或者Sxx呢?
是这样的,带K的表示停止(Kill)一个服务,S表示开启(Start)的意思
2、K和S后面带的数字呢?干什么用的
这个我开始的时候还以为是排列起来好看或者数数用呢。后来发现不是的。它的作用是用来排序,就是决定这些脚本执行的顺序,数值小的先执行,数值大的后执行。很多时候这些执行顺序是很重要的,比如要启动Apache服务,就必须先配置网络接口,不然一个没有IP的机子来启动http服务那岂不是很搞笑。。。
3、无意中我发现同一个服务带S的和带K的链接到init.d之后是同一个脚本。我就纳闷了,为什么会是执行同一个脚本呢?
这个时候真是S和K的妙用了,原来S和K并不止是用来看起来分的清楚而已。S给和K还分别给init.d下面的脚本传递了start和stop的参数。哦,是这样的(焕然大悟的样子,呵呵)!这时我才想起来原来曾经无数用过的/etc/rc.d/init.d/network restart命令。原来传S时相当于执行了/etc/rc.d/init.d/xxx start这条命令,当然K就相当于/etc/rc.d/init.d/xxx stop了
完!