Linux基础服务 Linux基础知识 ·

系统服务(daemons)-systemV与systemd

[隐藏]

什么是 daemons 与服务(service)

系统为了某些功能必须要提供一些服务(不论是系统本身还是网络方面),这个服务就称为 service 。它们向本地和网络用户提供了Linux的系统功能接口,直接面向应用程序和用户。

而提供这些服务的程序是由运行在后台的守护进程(daemons)来执行的。守护进程是生存期长的一种进程。它们独立于控制终端并且周期性的执行某种任务或等待处理某些发生的事件。他们常常在系统引导装入时启动,在系统关闭时终止。linux系统有很多守护进程,大多数服务器是用守护进程实现的。

daemon 是一个在后台执行的程序,而 daemon 所处的那个原本的程序命名通常是在服务的名称被建立之后,被挂上Linux使用时,会在服务的名称之后会加上一个 d ,例如例行性命令的建立的at,与cron这两个服务,他的程序名会被取为 atd 与 crond ,这个 d 代表的就是 daemon 的意思。

system V 的 init 管理中daemon 的主要分类(optional)

早期的 system V 版本中,启动系统服务的管理方式被称为 SysV 的 init 脚本程序处理方式!亦即系统内核第一个启动的程序是 init ,然后 init 去唤起系统所需要的所有的服务,不论是本机服务还是网路服务。

init 的管理机制有如下几个特色:

  • 服务的启动、关闭与查看等方式
    所有的服务启动脚本通通放置于 /etc/init.d/ 底下,基本上都是使用 bash shell script 所写成的脚本程序,需要启动、关闭、重新启动、查看状态时,可以通过如下的方式来处理:

    • 启动:/etc/init.d/daemon start
    • 关闭:/etc/init.d/daemon stop
    • 重新启动:/etc/init.d/daemon restart
    • 状态观察:/etc/init.d/daemon status
  • 服务启动的分类
    init 服务的分类中,依据服务是独立启动或被一支总管程序管理而分为两大类:

    • 独立启动模式(stand alone):服务独立启动,该服务直接常驻于内存中,提供本机或用户的服务行为,反应速度快。
    • 总管程序模式(super daemon):由特殊的 xinetd 或 inetd 这两个总管程序提供 socket 对应或 port 对应的管理。当没有用户要求某 socket 或 port 时, 所需要的服务是不会被启动的。若有用户要求时, xinetd 总管才会去唤醒相对应的服务程序。当该要求结束时,这个服务也会被结束掉~ 因为通过 xinetd 所总管,因此这个家伙就被称为 super daemon 。好处是可以通过 super daemon 来进行服务的时程、连线需求等的控制,缺点是唤醒服务需要一点时间的延迟。
  • 服务的依赖性问题
    服务是可能会有依赖性的~例如,你要启动网络服务,但是系统没有网络,那怎么可能可以唤醒网络服务呢?如果你需要连线到外部取得认证服务器的连线,但该连线需要另一个 A 服务的需求,问题是,A 服务没有启动,因此,你的认证服务就不可能会成功启动的!这就是所谓的服务依赖性问题。init 在管理员自己手动处理这些服务时,是没有办法协助依赖服务的唤醒
  • 执行等级的分类
    上面说到 init 是开机后内核主动唤醒的,然后 init 可以根据使用者自订的执行等级(runlevel)来唤醒不同的服务,以进入不同的操作模式。基本上 Linux 提供7个执行等级,分别是0, 1, 2...6 ,比较重要的是(1)单人维护模式、(3)纯字符模式、(5)图形界面模式。而各个执行等级的启动脚本是通过 /etc/rc.d/rc[0-6]/SXXdaemon 链接到 /etc/init.d/daemon 。链接文件名 (SXXdaemon) 的功能为: S 为启动该服务,XX是数字,为启动的顺序。由于有 SXX 的设定,因此在开机时可以『依序执行』所有需要的服务,同时也能解决相依服务的问题。这点与管理员自己手动处理不太一样。
  • 制定执行等级预设要启动的服务
    若要建立如上提到的 SXXdaemon 的话,不需要管理员手动建立链接文件,通过如下的命令可以来处理预设启动、预设不启动、观察预设启动否的行为:

    • 预设要启动: chkconfig daemon on
    • 预设不启动: chkconfig daemon off
    • 观察预设为启动否: chkconfig --list daemon
  • 执行等级的切换行为
    当你要从纯字符界面(runlevel 3)切换到图形界面(runlevel 5),不需要手动启动、关闭该执行等级的相关服务,只要『 init 5 』即可切换,init 会主动去分析 /etc/rc.d/rc[35].d/ 这两个目录内的脚本,然后启动转换 runlevel 中需要的服务,就可以完成整体的 runlevel 切换。

基本上 init 主要的功能都写在上头了,重要的指令包括 daemon 本身自己的脚本(/etc/init.d/daemon) 、xinetd 这个特殊的总管程序 (super daemon)、设定预设开机启动的 chkconfig, 以及会影响到执行等级的 init N 等。虽然CentOS 7 已经不使用 init 来管理服务了,不过因为考虑到某些脚本没有办法直接交给 systemd 处理,因此这些脚本还是被保留下来。点这里可以查看其说明:init及其配置文件/etc/inittab 与 runlevel

systemd 使用的 unit 分类

从CentOS 7.x 以后,Red Hat 系列的 distribution 放弃沿用多年的 System V 开机启动服务的流程,就是前面提到的 init 启动脚本的方法, 改用 systemd 这个启动服务管理机制。

systemd 的优势:

  • 平行处理所有服务,加速开机流程

旧的 init 启动脚本是『一项一项任务依序启动』的模式,因此不相依的服务也是得要一个一个的等待。但目前我们的主机与操作系统几乎都支持多核心架构,而未相依的服务也能够支持同时启动!所以 systemd 就是可以让所有的服务同时启动,因此你会发现到,系统启动的速度变快了!

  • 一经要求就回应的 on-demand 启动方式

systemd 全部就是仅有一支 systemd 服务搭配 systemctl 指令来处理,无须其他额外的指令来支持。不像 systemV 还要 init ,  chkconfig ,  service...等等指令。此外, systemd 由于常驻内存,因此任何要求( on-demand )都可以立即处理后续的 daemon 启动的任务。

  • 服务依赖性的自我检查

由于 systemd 可以自订服务依赖性的检查,因此如果 B 服务是架构在 A 服务上面启动的,那当你在没有启动 A 服务的情况下仅手动启动 B 服务时, systemd 会自动帮你启动 A 服务!这样就可以免去管理员得要一项一项服务去分析的麻烦。

  • 依据 daemon 功能分类

systemd 旗下管理的服务非常多,为了厘清所有服务的功能,因此,首先 systemd 先定义所有的服务为一个服务单位( unit ),并将该 unit 归类到不同的服务类型( type )去。旧的 init 仅分为 stand alone 与 super daemon,而 systemd 将服务单位( unit )区分为 service, socket, target, path, snapshot, timer 等多种不同的类型( type ),方便管理员的分类与记忆。

  • 将多个 daemons 集合成为一个群组

如同 systemV 的 init 里头有个 runlevel 的特色, systemd 亦将许多的功能集合成为一个所谓的 target 项目,这个项目主要在设计操作环境的建置,所以是集合了许多的 daemons,亦即是执行某个 target 就是执行好多个 daemon 的意思!

  • 向下兼容旧有的 init 服务脚本

基本上, systemd 是可以兼容于 init 的启动脚本的,因此,旧的 init 启动脚本也能够通过 systemd 来管理,不过更进阶的 systemd 功能就没有办法支持了。

虽然如此,不过 systemd 也是有些地方无法完全取代 init 的!包括:

  • 在 runlevel 的对应上,大概仅有 runlevel 1, 3, 5 有对应到 systemd 的某些 target 类型而已,没有全部对应;
  • 全部的 systemd 都用 systemctl 这个管理程序管理,而 systemctl 支持的语法有限制,不像 /etc/init.d/daemon 就是纯脚本可以自定义参数,systemctl 不能自定义参数。;
  • 如果某个服务启动是管理员自己手动执行启动,而不是使用 systemctl 去启动的(例如你自己手动输入 crond 以启动 crond 服务),那么 systemd 将无法检查到该服务,而无法进一步管理。
  • systemd 启动过程中,无法与管理员通过 standard input 传入信息!因此,自行编写 systemd 的启动设定时,务必要取消交互机制 ( 连通过启动时传进的标准输入信息也要避免!)

不过,光是同步启动服务脚本这个功能就可以节省你很多开机的时间,同时 systemd 还有很多特殊的服务类型(type) 可以提供更多有趣的功能!

systemd 的配置文件存放目录

基本上, systemd 将过去所谓的 daemon 执行脚本通通称为一个服务单位( unit ),而每种服务单位依据功能来区分时,就分类为不同的类型( type )。基本的类型有包括系统服务、数据监听与交换的套接字服务( socket )、储存系统状态的快照类型、提供不同类似执行等级分类的操作环境( target ) 等等。

其配置文件放置在底下的目录中:

  • /usr/lib/systemd/system/:每个服务最主要的启动脚本设定,有点类似 /etc/init.d 底下的文件;
  • /run/systemd/system/:系统执行过程中所产生的服务脚本,这些脚本的优先序要比 /usr/lib/systemd/system/ 高!
  • /etc/systemd/system/:管理员依据主机系统的需求所建立的执行脚本,这个目录有类似/etc/rc.d/rcN.d/Sxx 之类的功能!执行优先序又比 /run/systemd/system/ 高!

也就是说系统开机会不会执行某些服务其实是看 /etc/systemd/system/ 底下的设定,所以该目录底下就是一大堆链接文件。而实际执行的 systemd 启动脚本配置文件, 其实都是放置在 /usr/lib/systemd/system/ 底下的!因此如果你想要修改某个服务启动的设定,应该要去 /usr/lib/systemd/system/ 底下修改!/etc/systemd/system/ 仅是链接到正确的执行脚本配置文件而已。所以想要看执行脚本设定,应该就得要到 /usr/lib/systemd/system/ 底下去查看!

systemd 的 unit 类型分类说明

/usr/lib/systemd/system/ 以下的资料可以通过其后缀名,来区分不同的类型(type) 。

其大致分一下几类:

副档名主要服务功能
.service一般服务类型(service unit):主要是系统服务,包括伺服器本身所需要的本机服务以及网路服务都是!比较经常被使用到的服务大多是这种类型!所以,这也是最常见的类型了!
.socket内部程序资料交换的插槽服务(socket unit):主要是IPC (Inter-process communication) 的传输讯息插槽档(socket file) 功能。这种类型的服务通常在监控讯息传递的插槽档,当有透过此插槽档传递讯息来说要连结服务时,就依据当时的状态将该用户的要求传送到对应的daemon, 若daemon 尚未启动,则启动该daemon 后再传送用户的要求。

使用socket 类型的服务一般是比较不会被用到的服务,因此在开机时通常会稍微延迟启动的时间 (因为比较没有这么常用嘛!)。一般用于本机服务比较多,例如我们的图形界面很多的软体都是透过socket 来进行本机程序资料交换的行为。(这与早期的xinetd 这个super daemon 有部份的相似!)
.target执行环境类型(target unit):其实是一群unit 的集合,例如上面表格中谈到的multi-user.target 其实就是一堆服务的集合~也就是说, 选择执行multi-user.target 就是执行一堆其他.service 或/及.socket 之类的服务就是了!
.mount
.automount
档案系统挂载相关的服务(automount unit / mount unit):例如来自网路的自动挂载、NFS 档案系统挂载等与档案系统相关性较高的程序管理。
.path侦测特定档案或目录类型(path unit):某些服务需要侦测某些特定的目录来提供伫列服务,例如最常见的列印服务,就是透过侦测列印伫列目录来启动列印功能!这时就得要.path 的服务类型支援了!
.timer循环执行的服务(timer unit):这个东西有点类似anacrontab !不过是由systemd 主动提供的,比anacrontab 更加有弹性!

其中 .service 的系统服务类型最常见!因为我们一堆网路服务都是通过这种类型来设计的!

参与评论