Linux基础学习笔记之——认识系统服务(daemon)

认识系统服务(daemon)

1、什么是 daemon 与服务(service)

服务:常驻内存的程序,且可以提供一些系统或网络功能,那就是服务。达成这个 service 的程序我们就称为 daemon。


1.1、早期 System V 的 init 管理行为中 daemon 的主要分类(Optional)

在早期的系统中我们启动系统服务的管理方式被称为 Sys V 的 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 总管程序才会去唤醒对应的服务。当要求结束时,这个服务也会被结束掉
  • 服务的相依赖性问题

  • 执行的等级分类

    上面说到的 init 是开机后内核主动呼叫的,然后 init 可以根据用户自定义的执行等级(runlevel)来唤醒不同的服务,以进入不同的操作界面。基本上, Linux 提供 7 个执行等级,分别是 0,1,…,6,比较重要的是(1)单人维护模式、(3)纯文本模式、(5)文字加图形界面。而各个执行等级的启动脚本是通过:/etc/rc.d/rc[0-6]/SXXdaemon 链接到 /etc/init.d/daemon ,链接文件的功能是:S 为启动该服务,XX 是数字,为启动的顺序。由于有 SXX 的设定,因此开机时可以 “依序执行” 所有需要的服务,同时也能解决相依赖性的问题。

  • 制定执行等级默认要启动的服务

    若要建立如上提到的 SXXdaemon 的话,不需要管理员手动建立连接文件,通过如下的指令来处理默认启动、预设不启动、观察预设启动与否的行为:

    • 预设要启动:chkconfig daemon on
    • 预设不启动:chkconfig daemon off
    • 观察预设为启动否:chkconfig --list daemon
  • 执行等级的切换

    当你要从纯文本界面(lrunevel 3)切换到图形界面(runlevel 5),不需要手动启动、关闭该执行等级的相关服务,只要 “init 5” 即可切换

1.2、systemd 使用的 unit 分类

CentOS 7.x 后该用了 systemd 这个启动服务管理机制:

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

    旧的 init 启动脚本是 “一项一项任务依序启动” 的模式,因此不相邻的服务也是要一个一个等待。现在的硬件架构与操作系统都支持多核架构了,所以支持并行启动。

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

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

  • 服务相依性的自我检查

    由于 systemd 可以自定义服务相依性的检查,因此如果 B 服务是架构在 A 服务上面启动的,那当你在没有启动 A 服务的情况下仅手动启动 B 服务时,systemd 会自动帮你启动 A 服务。

  • 依 daemon 功能分类

    systemd 旗下管理的服务非常多,为了厘清所有的服务功能,因此,首先 systemd 先定义所有的服务为一个服务单元(unit),并将该 unit 归类到不同的服务类型(type)中去。systemd 将服务单元区分为 service,socket,target,path,timer 等不同类型。

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

  • 向下兼容 init 服务脚本

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

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

1.2.1、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/rc5.d/Sxx,执行优先级比/run/systemd/system/高!

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

1.2.2、systemd 的 unit 类型分类说明

那 /usr/lib/systemd/system/ 以下的数据如何区分上述所谓的不同类型呢?看扩展名即可。

[root@li ~]# ll /usr/lib/systemd/system/ | grep -E '(vsftpd|multi|cron)'
-rw-r--r--. 1 root root  318 8月   9 2019 crond.service
-rw-r--r--. 1 root root  492 8月   7 01:30 multi-user.target
drwxr-xr-x. 2 root root  258 8月  17 10:27 multi-user.target.wants
lrwxrwxrwx. 1 root root   17 8月  17 10:27 runlevel2.target -> multi-user.target
lrwxrwxrwx. 1 root root   17 8月  17 10:27 runlevel3.target -> multi-user.target
lrwxrwxrwx. 1 root root   17 8月  17 10:27 runlevel4.target -> multi-user.target

几种常见的 systemd 的服务类型如下:

扩展名 主要服务功能
.service 一般服务类型:主要是系统服务,包括服务器本身所需要的本地服务以及网络服务都是!
.socket 内部程序数据交换的插槽服务
.target 执行环境类型:其实就是一群unit的集合
.mount
.automount
文件系统挂载相关服务
.path 侦测特定文件或目录类型
.timer 循环执行的服务

2、通过 systemctl 管理服务

2.1、通过 systemctl 管理单一服务的启动/开机启动与观察状态

[root@li ~]# systemctl [command] [unit]
command主要有:
	start			:立刻启动后面的 unit
	stop			:立刻关闭后面的 unit
	restart			:立刻关闭后启动后面的 unit
	reload			:不关闭后面的 unit 的情况下,重载配置文件,让设定生效
	enable			:开机自启
	disable			:取消开机自启
	status			:显示 unit 的状态
	is-active		:目前有没有正在运行
	is-enable		:开机时有没有预设要启动 unit
#1、查看 crond 这个服务的状态信息
[root@li ~]# systemctl status crond.service
● crond.service - Command Scheduler
   Loaded: loaded (/usr/lib/systemd/system/crond.service; enabled; vendor preset: enabled)
   Active: active (running) since 三 2020-08-19 15:58:41 CST; 9min ago
 Main PID: 664 (crond)
   CGroup: /system.slice/crond.service
           └─664 /usr/sbin/crond -n

8月 19 15:58:41 li.erver systemd[1]: Started Command Scheduler.
8月 19 15:58:41 li.erver crond[664]: (CRON) INFO (RANDOM_DELAY will be scaled with factor 1...d.)
8月 19 15:58:42 li.erver crond[664]: (CRON) INFO (running with inotify support)
Hint: Some lines were ellipsized, use -l to show in full.
#重点在第 2,3 行
#Loaded:说明开机的时候这个 unit 会不会自启,enabled 为开机自启,disabled 为开机不会自启
#Active:现在这个 unit 的状态是正在执行(running)或没有执行(dead)

#2、正常关闭这个服务
[root@li ~]# systemctl stop crond
[root@li ~]# systemctl status crond.service
● crond.service - Command Scheduler
   Loaded: loaded (/usr/lib/systemd/system/crond.service; enabled; vendor preset: enabled)
   Active: inactive (dead) since 三 2020-08-19 16:11:52 CST; 2s ago
  Process: 664 ExecStart=/usr/sbin/crond -n $CRONDARGS (code=exited, status=0/SUCCESS)
 Main PID: 664 (code=exited, status=0/SUCCESS)

8月 19 15:58:41 li.erver systemd[1]: Started Command Scheduler.
8月 19 15:58:41 li.erver crond[664]: (CRON) INFO (RANDOM_DELAY will be scaled with factor 1...d.)

回到 systemctl status crond.service 的第三行,不是有个 Active 的 daemon 现在状态码?除了 running 和 dead 之外,有没有其他状态呢?基本上,常见的几种状态如下:

  • active(running):执行
  • active(exited):仅执行一次就正常结束的服务,目前并没有任何程序在系统中执行
  • active(waiting):正在执行中,不过还要等待其他的事件才能继续处理
  • inactive(dead):没有在执行

那么 daemon 的预设状态除了 enable/disable 之外,还有其他的情况吗?

  • enabled:开机被执行
  • disabled:开机不执行
  • static:不可以自己启动,但可能会被其他程序来唤醒
  • masked:无论如何都无法启动

2.1.1、服务启动/关闭与观察的练习

因为这台服务器没有打印机,因此我想把 cups 服务整个关掉,是否可以?

#1、先看看 cups 的服务是开的还是关的?
[root@li ~]# systemctl status cups.service
● cups.service - CUPS Printing Service
   Loaded: loaded (/usr/lib/systemd/system/cups.service; enabled; vendor preset: enabled)
   Active: inactive (dead) since 三 2020-08-19 16:24:19 CST; 1s ago
  Process: 10391 ExecStart=/usr/sbin/cupsd -f (code=exited, status=0/SUCCESS)
 Main PID: 10391 (code=exited, status=0/SUCCESS)
 #有趣的是,竟然是 enable 但还却是 head
 
 #2、那就直接关闭,同时确认没有启动
 [root@li ~]# systemctl stop cups.service
[root@li ~]# systemctl disable cups.service
Removed symlink /etc/systemd/system/multi-user.target.wants/cups.path.
Removed symlink /etc/systemd/system/multi-user.target.wants/cups.service.
Removed symlink /etc/systemd/system/sockets.target.wants/cups.socket.
Removed symlink /etc/systemd/system/printer.target.wants/cups.service.
#一口气关掉了 4 个连接文件,说明这 4 个文件有相依赖的关系

[root@li ~]# netstat -tulnp | grep cups
#不会产生任何数据

#3、尝试启动 cups.socket 监听客户端的需求
[root@li ~]# systemctl start cups.socket
[root@li ~]# systemctl status cups.socket cups.service cups.path
● cups.socket - CUPS Printing Service Sockets
   Loaded: loaded (/usr/lib/systemd/system/cups.socket; disabled; vendor preset: enabled)
   Active: active (listening) since 三 2020-08-19 16:28:35 CST; 22s ago
   Listen: /var/run/cups/cups.sock (Stream)

8月 19 16:28:35 li.erver systemd[1]: Listening on CUPS Printing Service Sockets.

● cups.service - CUPS Printing Service
   Loaded: loaded (/usr/lib/systemd/system/cups.service; disabled; vendor preset: enabled)
   Active: inactive (dead)

8月 19 16:23:32 li.erver systemd[1]: Started CUPS Printing Service.
8月 19 16:24:19 li.erver systemd[1]: Stopping CUPS Printing Service...
8月 19 16:24:19 li.erver systemd[1]: Stopped CUPS Printing Service.

● cups.path - CUPS Printer Service Spool
   Loaded: loaded (/usr/lib/systemd/system/cups.path; disabled; vendor preset: enabled)
   Active: inactive (dead)
#仅有 cups.socket 在启动

#4、尝试使用 lp 这个指令打印看看
[root@li ~]# echo "testing" | lp
lp: Error - no default destination available.
#实际上就是没有打印机,显示错误也没关系

[root@li ~]# systemctl status cups.service
● cups.service - CUPS Printing Service
   Loaded: loaded (/usr/lib/systemd/system/cups.service; disabled; vendor preset: enabled)
   Active: active (running) since 三 2020-08-19 16:30:17 CST; 38s ago
[root@li ~]# netstat -tulnp | grep cups
tcp        0      0 127.0.0.1:631           0.0.0.0:*               LISTEN      12876/cupsd       
tcp6       0      0 ::1:631                 :::*                    LISTEN      12876/cupsd
#竟然自己启动了,我们并没有启动它

从上面的案例可知,很多服务之间是相互依赖的。cups 是一种打印服务,这个服务会启动 631 端口来提供网络打印机的打印功能。但是其实我们无须一直启动 631 端口。因此多了一个 cups.socket 的服务,这个服务可以在 “用户有打印需求的时候,才会唤醒 cups.service” 的意思。因此,如果仅仅是 disable/stop cups.service 而忘记其他两个服务的话,那么当用户向其他两个 cups.path 和 cups.socket 提出要求时,cups.service 就会被唤醒!

2.1.2、强迫服务注销(mask)的练习

比较正规的做法是,要关闭 cups.service 时,连同其他两个会唤醒 cups.socket 与 cups.path 通通关闭,那就没事了。比较不正规的做法是,那就强迫 cups.service 注销。

[root@li ~]# systemctl stop cups.service
Warning: Stopping cups.service, but it can still be activated by:
  cups.socket	#警告就说明了,cups.service 就算是关闭了还是会被唤醒
[root@li ~]# systemctl mask cups.service
Created symlink from /etc/systemd/system/cups.service to /dev/null.

[root@li ~]# systemctl status cups.service
● cups.service
   Loaded: masked (/dev/null; bad)
   Active: inactive (dead) since 三 2020-08-19 16:37:35 CST; 1min 23s ago
 Main PID: 12876 (code=exited, status=0/SUCCESS)
 
 [root@li ~]# systemctl start cups.service
Failed to start cups.service: Unit is masked.	#再也无法唤醒

那如何取消注销呢?当然是 unmask 即可:

[root@li ~]# systemctl unmask cups.service
Removed symlink /etc/systemd/system/cups.service.

[root@li ~]# systemctl status cups.service
● cups.service - CUPS Printing Service
   Loaded: loaded (/usr/lib/systemd/system/cups.service; disabled; vendor preset: enabled)
   Active: inactive (dead) since 三 2020-08-19 16:37:35 CST; 3min 21s ago
 Main PID: 12876 (code=exited, status=0/SUCCESS)

2.2、通过 systemctl 观察系统上的所有服务

[root@li ~]# systemctl [command] [--type=TYPE] [--all]
command:
	list-units			:依据 unit 列出目前启动的 unit。若加上 --all 才会列出没启动的
	list-unit-files		:依据 /usr/lib/systemd/system 内的文件,将所有文件列表说明
#1、列出系统上所启动的 unit
[root@li ~]# systemctl
  UNIT                                LOAD   ACTIVE SUB       DESCRIPTION
  -.mount                             loaded active mounted   /
  boot.mount                          loaded active mounted   /boot
  dev-hugepages.mount                 loaded active mounted   Huge Pages File System
  dev-mqueue.mount                    loaded active mounted   POSIX Message Queue File System
  run-user-0.mount                    loaded active mounted   /run/user/0
  ...

#2、列出所有已经安装的 unit 有哪些
[root@li ~]# systemctl list-unit-files
UNIT FILE                                     STATE
proc-sys-fs-binfmt_misc.automount             static
dev-hugepages.mount                           static
dev-mqueue.mount                              static
...

假如我不想知道这么多的 unit 项目,我只想知道 service 这种类别的 daemon 而已,而且不论是否已经启动,通通列出来:

[root@li ~]# systemctl list-units --type=service --all
  UNIT                                LOAD      ACTIVE   SUB     DESCRIPTION
  auditd.service                      loaded    active   running Security Auditing Service
● cloud-init-local.service            not-found inactive dead    cloud-init-local.service
  cpupower.service                    loaded    inactive dead    Configure CPU power related setti
  crond.service                       loaded    active   running Command Scheduler
...

#查询系统上是否有以 cpu 为名的服务
[root@li ~]# systemctl list-units --type=service --all | grep cpu
  cpupower.service       loaded    inactive dead    Configure CPU power related settings

2.3、通过 systemctl 管理不同的操作环境(target unit)

如何列出与操作界面比较有关的 target 项目呢?

[root@li ~]# systemctl list-units --type=target --all
  UNIT                      LOAD      ACTIVE   SUB    DESCRIPTION
  basic.target              loaded    active   active Basic System
  cryptsetup.target         loaded    active   active Local Encrypted Volumes
  emergency.target          loaded    inactive dead   Emergency Mode
  ...
LOAD   = Reflects whether the unit definition was properly loaded.
ACTIVE = The high-level unit activation state, i.e. generalization of SUB.
SUB    = The low-level unit activation state, values depend on unit type.

32 loaded units listed.
To show all installed unit files use 'systemctl list-unit-files'.

默认有 32 个 target unit,而跟操作界面相关性比较高的 target 主要有以下几个:

  • graphical.target:就是文字加上图形界面,这个项目包含了底下的 multi-user.target 项目!
  • multi-user.target:纯文本模式!
  • rescue.target:在无法使用 root 登录的情况下,systemd 在开机时会多加一个额外的暂时系统,与你原本的系统无关。这时你可以取得 root 的权限来维护你的系统。但是这时额外的系统,因此可能需要动到 chroot 的方式来取得你原来的系统。
  • emergency.target:紧急处理系统的错误,还是需要使用 root 登录的情况,在无法使用 rescue.target 的情况下,可以尝试使用这种模式。
  • shutdown.target:就是关机的流程。
  • getty.target:可以设定你需要几个 tty 之类的,如果想要降低 tty 的项目,可以修改这个东西的配置文件。
[root@li ~]# systemctl [conmand] [unit.target]
选项与参数:
command:
	get-default:取得目前的 target
	set-default:设定后面的 target 为默认的操作模式
	isolate:切换到后面的模式
#我们没有安装图形界面,应该是纯文本模式
[root@li ~]# systemctl get-default
multi-user.target	#纯文本模式

在正常的切换情况下,使用上述的 isolate 方式即可。不过为了方便起见,systemd 也提供了数个简单的指令给我们切换操作模式使用:

[root@li ~]# systemctl poweroff	#关机
[root@li ~]# systemctl reboot	#重启
[root@li ~]# systemctl suspend	#暂停模式
[root@li ~]# systemctl hibernate	#休眠模式
[root@li ~]# systemctl rescue	#救援模式
[root@li ~]# systemctl emergency	#紧急模式
  • suspend:暂停模式会将系统的状态保存到内存中,然后关闭大部分的系统硬件,当然并没有实际关机。当用户按下唤醒机器的按键时,系统数据会从内存中恢复,然后重新驱动大部分的硬件。唤醒速度较快。
  • hibernate:休眠模式则是将系统状态保存到硬盘中,保存完毕后,将计算机关机。当用户唤醒系统时,系统会开始正常工作,然后将保存到硬盘中的系统状态恢复回来。因为是从硬盘中读取,因此速度较慢。

3、通过 systemctl 分析各服务之间的依赖性

[root@li ~]# systemctl list-dependencies [unit] [--reverse]
选项与参数:
--reverse:反向追踪谁在使用这个 unit 的意思!
#1、列出目前的 target 环境下,用到什么特别的 unit
[root@li ~]# systemctl get-default
multi-user.target
[root@li ~]# systemctl list-dependencies
default.target
● ├─auditd.service
● ├─crond.service
● ├─dbus.service
● ├─firewalld.service
● ├─irqbalance.service
● ├─kdump.service
● ├─network.service
● ├─NetworkManager.service
...

default.target 会用到 basic.target + getty.target + remote-fs.target 这三大项目。那么如何查询谁用到 multi-user.target 呢?

[root@li ~]# systemctl list-dependencies --reverse
default.target
● └─graphical.target

4、与 systemd 的 daemon 运作过程相关的目录简介

  • /usr/lib/systemd/system/

    使用 CentOS 官方提供的软件安装后,默认的启动脚本配置文件都放在这里,这里的文件尽量不要修改,要修改时请到 /etc/systemd/system/ 底下修改。

  • /run/systemd/system/

    系统执行过程中所产生的脚本,这些脚本的执行优先级比 /usr/lib/systemd/system/ 高!

  • /etc/systemd/system/

    管理员依据主机系统的需求所建立的执行脚本,其实这个目录有点像以前的 /etc/rc.d/rc5.d/Sxx 之类的功能。优先级比 /run/systemd/system/ 高!

  • /etc/sysconfig/*:

    几乎所有的服务都会将初始化的一些选项设定写入这个目录下。举例来说,网络的设定则是写在 /etc/sysconfig/network-srcipts/ 这个目录下。

  • /var/lib/

    一些会产生数据的服务都会将它的数据写入到 /var/lib/ 目录下。举例来说,数据库管理系统 MySQL 的数据库默认就是写入到 /var/lib/mysql 这个目录下的。

  • /run/

    放置了很多 daemon 的暂存文件,包括 lock file 以及 PID file 等。

猜你喜欢

转载自blog.csdn.net/qq_36879493/article/details/108108174
今日推荐