首页 > 代码库 > 鸟哥的Linux私房菜 第十八章、认识系统服务 (daemons)
鸟哥的Linux私房菜 第十八章、认识系统服务 (daemons)
什么是 daemon 与服务 (service)
注:Linux下可以直接调用damon函数来实现daemon进程,没必要重新实现,理解其原理即可。
在Linux中专门提供了一个函数来完成这个daemon化的过程,这个函数的原型如下
int daemon ( int __nochdir, int __noclose) ;
如果__nochdir的值为0,则将切换工作目录为根目录;如果__noclose为0,则将标准输入,输出和标准错误都重定向到/dev /null。
经过这个函数调用后的程序将运行在后台,成为一个daemon程序,而linux下大多的服务都是以此方式运行的。
我们来看一个简单的例子。例如编写例子程序test.c
#include <unistd.h>#include <stdio.h>int do_sth(){ //Add what u want return 0;}int main(){ daemon(0,0); while(1){ do_sth(); sleep(1); }}
编译并运行
[ leconte@ localhost daemon] $ gcc -o test test.c [ leconte@ localhost daemon] $ ./ test
程序进入了后台,通过ps查看进程情况,可以看到进程的父进程id为1,即init进程
root 3239 0.0 0.0 3920 160 ? Ss 06:49 0:00 ./test
所谓的父进程是1这个表示怀疑
用lsof查看test进程所打开的文件,可以看到文件描述符0,1,2都被重定向到/dev/null
重定向到/dev/null也表示怀疑
并且能够看到,进程的当前工作目录(cwd)为根目录/,daemon函数已经帮我们完成了daemon化的过程,接下来我们只需要关注于程序功能的实现了。
daemon 的主要分类
依据 daemon 的启动与管理方式可以将 daemon 分为可独立启动的 stand alone , 与透过一支 super daemon 来统一管理两大类:
- stand_alone:此 daemon 可以自行单独启动服务
stand alone 是『独立的启动』的意思。这种类型的 daemon 可以自行启动而不必透过其他机制的管理; daemon 启动并加载到内存后就一直占用内存与系统资源。最大的优点:因为是一直存在内存内持续的提供服务, 因此对于客户端的请求,stand alone 的 daemon 响应速度较快。常见的 stand alone daemon 有 WWW 的 daemon (httpd)、FTP 的 daemon (vsftpd) 等等。
- super daemon: 由一支特殊的 daemon 来统一管理
这一种服务的启动方式则是藉由一个统一的 daemon 来负责唤起服务!这个特殊的 daemon 就被称为 super daemon 。 早期的 super daemon 是 inetd,后来被 xinetd 取代了。当没有客户端的请求时,各项服务都是未启动的状态,等到有来自客户端的请求时, super daemon 才唤醒相对应的服务。当客户端的请求结束后,被唤醒的这个服务也会关闭并释放系统资源。
这种机制的好处是: (1)由于 super daemon 负责唤醒各项服务,因此 super daemon 可以具有安全控管的机制,类似网络防火墙! (2)由于服务在客户端的联机结束后就关闭,因此不会一直占用系统资源。但是 因为有客户端的联机才会唤醒该服务,而该服务加载到内存的时间需要考虑进去,因此服务的反应时间会比较慢一些! 常见的 super daemon 所管理的服务有 telnet !
如上所示,Super daemon 是常驻在内存中的, Program 1, 2, 3 则是启动某些服务的程序 (未被启动状态)。当有客户端的请求时, Super daemon 才会去触发相关的程序加载成为 daemon 而存在于内存中,此时,客户端的请求才会被 Super daemon 导向 Daemon 1 去完成服务!当客户端的请求结束时,Daemon 1 将会被移除,图中实线的联机就会中断!
- super daemon 的处理模式有两种,分别是这样:
- multi-threaded (多线程):
- single-threaded (单线程):
- multi-threaded (多线程):
- 如上所示,左侧为多线程的运行方式, daemon 会触发多支程序来给不同 client提供的服务,所以不论你是第几个请求者, 都可以享用 daemon 的服务。至于右侧则是单线程的方式,仅会有一支 daemon 被唤醒,第一个用户完成服务之前, 后续请求的用户就得要等待,因此它们的联机是不会成功的。
- daemon 工作形态的类型
- signal-control
这种 daemon 是透过讯号来管理的,只要有任何客户端的请求进来,它就会立即启动去处理!例如打印机的服务 (cupsd)。 - interval-control
这种 daemon 则主要是『每隔一段时间就主动的去运行某项工作』,所以,你要作的是在配置文件指定服务要进行的时间与工作, 该服务在指定的时间才会去完成工作。atd 与 crond 就属于这种类型的 daemon (每分钟侦测一次配置文件)
- daemon 的命名守则
通常会在服务的名称之后会加上一个 d ,例如例行性命令的创建的 at, 与 cron 这两个服务, 他的程序文件名会被取为 atd 与 crond,这个 d 代表的就是 daemon 的意思。
服务与端口的对应系统所有的功能都是某些程序所提供的,而程序则是透过触发程序而产生的。同样的,系统提供的网络服务当然也是这样的!
当客户端联机过来我们的主机时, 我们主机是透过埠号 (port number)区分不同的服务
- http://ftp.isu.edu.tw/
- ftp://ftp.isu.edu.tw/
两个网址都是指向 ftp.isu.edu.tw 义守大学的 FTP 网站,但是浏览器上面显示的结果却是不一样的!这是因为我们指向不同的服务!一个是 http 这个 WWW 的服务,一个则是 ftp 这个文件传输服务。
图 1.2.1、 port 与 daemon 的对应,客户端连接协议不同,服务导向端口号亦不同事实上,为了统一整个因特网的端口号对应服务的功能,好让所有的主机都能够使用相同的机制来提供服务与要求服务, 所以就有了『通讯协议』这玩意儿。也就是说,有些约定俗成的服务都放置在同一个埠号上面啦!举例来说, 网址列上面的 http 会让浏览器向 WWW 服务器的 80 埠号进行联机的要求!而 WWW 服务器也会将 httpd 这个软件激活在 port 80, 这样两者才能够达成联机的!
系统上有提供服务跟端口对应的配置文件: /etc/services!
[root@www ~]# cat /etc/services....(前面省略)....ftp 21/tcpftp 21/udp fsp fspdssh 22/tcp # SSH Remote Login Protocolssh 22/udp # SSH Remote Login Protocol....(中间省略)....http 80/tcp www www-http # WorldWideWeb HTTPhttp 80/udp www www-http # HyperText Transfer Protocol....(底下省略)....# <daemon name> <port/封包协议> <该服务的说明>
daemon 的启动脚本与启动方式
提供某个服务的 daemon 虽然只是一支程序而已,但是这支 daemon 的启动还是需要运行档、配置文件、运行环境等等, 举例来说,你可以查阅一下 httpd 这个程序 (man httpd) ,里面可谈到不少的选项与参数!此外,为了管理上面的方便, 所以通常 distribution 都会记录每一支 daemon 启动后所取得程序的 PID 在 /var/run/ 这个目录下! 在启动这些服务之前,你可能也要自行处理一下 daemon 能够顺利运行的环境是否正确等等。鸟哥这里要讲的是, 要启动一支 daemon 考虑的事情很多,并非单纯运行一支程序就够了。
为了解决上面谈到的问题,因此通常 distribution 会给我们一个简单的 shell script 来进行启动的功能。 该 script 可以进行环境的侦测、配置文件的分析、PID 文件的放置,以及相关重要交换文件案的锁住 (lock) 动作, 你只要运行该 script ,上述的动作就一口气连续的进行,最终就能够顺利且简单的启动这个 daemon!
那么这些 daemon 的启动脚本 (shell script) 放在哪里啊?还有, CentOS 5.x 通常将 daemon 相关的文件放在哪里? 以及某些重要的配置文件又是放置到哪里?基本上是放在这些地方:
- /etc/init.d/* :启动脚本放置处
系统上几乎所有的服务启动脚本都放置在这里!事实上这是公认的目录,我们的 CentOS 实际上放置在 /etc/rc.d/init.d/ 啦! 不过还是有配置连:结档到 /etc/init.d/ 的!既然这是公认的目录,因此建议您记忆这个目录即可! - /etc/sysconfig/* :各服务的初始化环境配置文件
几乎所有的服务都会将初始化的一些选项配置写入到这个目录下,举例来说,登录档的 syslog 这支 daemon 的初始化配置就写入在 /etc/sysconfig/syslog 这里呢!而网络的配置则写在 /etc/sysconfig/network 这个文件中。 所以,这个目录内的文件也是挺重要的; - /etc/xinetd.conf, /etc/xinetd.d/* :super daemon 配置文件
super daemon 的主要配置文件 (其实是默认值) 为 /etc/xinetd.conf ,不过我们上面就谈到了, super daemon 只是一个统一管理的机制,他所管理的其他 daemon 的配置则写在 /etc/xinetd.d/* 里头喔! - /etc/* :各服务各自的配置文件
- /var/lib/* :各服务产生的数据库
一些会产生数据的服务都会将他的数据写入到 /var/lib/ 目录中。举例来说,数据库管理系统 MySQL 的数据库默认就是写入 /var/lib/mysql/ 这个目录下啦! - /var/run/* :各服务的程序之 PID 记录处
我们在第十七章谈到可以使用讯号 (signal) 来管理程序, 既然 daemon 是程序,所以当然也可以利用 kill 或 killall 来管理啦!不过为了担心管理时影响到其他的程序, 因此 daemon 通常会将自己的 PID 记录一份到 /var/run/ 当中!例如登录文件的 PID 就记录在 /var/run/syslogd.pid 这个文件中。如此一来, /etc/init.d/syslog 就能够简单的管理自己的程序啰。
上面谈到的部分是配置文件,那么 stand alone 与 super daemon 所管理的服务启动方式怎么作呢?他是这样做的喔:
- Stand alone 的 /etc/init.d/* 启动
刚刚谈到了几乎系统上面所有服务的启动脚本都在 /etc/init.d/ 底下,这里面的脚本会去侦测环境、搜寻配置文件、 加载 distribution 提供的函数功能、判断环境是否可以运行此 daemon 等等,等到一切都侦测完毕且确定可以运行后, 再以 shell script 的 case....esac 语法来启动、关闭、 观察此 daemon 喔!我们可以简单的以 /etc/init.d/syslog 这个登录档启动脚本来进行说明:
[root@www ~]# /etc/init.d/syslog用法: /etc/init.d/syslog {start|stop|status|restart|condrestart}# 什么参数都不加的时候,系统会告诉你可以用的参数有哪些,如上所示。范例一:观察 syslog 这个 daemon 目前的状态[root@www ~]# /etc/init.d/syslog statussyslogd (pid 4264) 正在运行...klogd (pid 4267) 正在运行...# 代表 syslog 管理两个 daemon ,这两个 daemon 正在运行中啦!范例二:重新让 syslog 读取一次配置文件[root@www ~]# /etc/init.d/syslog restart正在关闭核心记录器: [ 确定 ]正在关闭系统记录器: [ 确定 ]正在启动系统记录器: [ 确定 ]正在启动核心记录器: [ 确定 ][root@www ~]# /etc/init.d/syslog statussyslogd (pid 4793) 正在运行...klogd (pid 4796) 正在运行...# 因为重新启动过,所以 PID 与第一次观察的值就不一样了!这样了解乎?
鸟哥的Linux私房菜 第十八章、认识系统服务 (daemons)