文章目录

  • 一、系统服务管理器 systemd
    • (一)systemd 的特性
    • (二)systemd 与 传统 init 系统的区别
    • (三)systemd 的目录和文件
    • (四)systemd 的 Unit 介绍
      • 1.Unit 类型
      • 2.Unit 的配置文件
        • (1)配置文件的状态
        • (2)配置文件的格式
        • (4)配置文件的区块
          • 1)[Unit]区块
          • 2)[Service]区块
          • 3)[Install]区块
            • A.替换符
      • 3.Unit 的依赖管理
    • (五)systemd 的 Target 介绍
      • 1.查看当前系统的所有 Target
      • 2.查看一个 Target 包含的所有 Unit
      • 3.查看启动时的默认 Target
      • 4.设置启动时的默认 Target
      • 5.切换 Target
      • 6.Target 与 传统 Run Level 的对应关系
    • (六)systemd 并行启动原理
      • 并发启动原理之一:解决 socket 依赖
      • 并发启动原理之二:解决 D-Bus 依赖
      • 并发启动原理之三:解决文件系统依赖
    • (七)systemd 配置使用
      • 1.对于系统开发人员
      • 2.对于系统管理员
    • (八)日志管理
  • 二、使用命令 systemctl 管理系统服务
    • (一)命令介绍
    • (二)命令选项
    • (三)systemd 命令和 SysV init 命令的对比
    • (四)命令示例
      • 1.重启服务
      • 2.纯重启 try-restart
      • 3.重新加载某个服务的配置文件
      • 4.启动服务
      • 5.停止服务
      • 6.查看服务状态
        • (1)解读服务状态信息
        • (2)关于服务的启动状态
        • (3)关于服务的运行状态
      • 7.设置开机启动某个服务
      • 8.取消某个服务的开机启动
      • 9.查看某个服务是否开机启动
      • 10.查看启动失败的服务
      • 11.查看进程是不是在运行中
      • 12.查看系统中所有已经启动的服务
      • 13.列出目录 /lib/systemd/system/ 下的所有 unit
      • 14.只看服务类型的 unit
      • 15.查看加载失败的 unit
      • 16.管理系统的操作环境(target unit)
        • (1)查看系统目前的操作模式(target)
        • (2)设置系统默认的操作模式
        • (3)切换操作模式
      • 17.让系统进入暂停模式
      • 18.让系统进入休眠模式
      • 19.强制系统进入救援模式
      • 20.强制系统进入紧急救援模式
      • 22.重新加载 systemd 程序的配置文件
      • 23.杀死服务
      • 24.管理系统挂载点的命令
      • 25.查看 systemd 的版本
      • 26.查看系统启动耗时
      • 27.查看每个进程在引导时花费的时间
      • 28.查看指定服务的关键链
      • 29.获取服务的依赖项列表
      • 30.按层次列出控制组
      • 31.根据CPU,内存,输入和输出列出控制组
      • 32.查看指定类型的 unit
      • 33.列出所有没有运行的 Unit
      • 34.查看系统状态
      • 35.显示远程主机的某个 Unit 的状态
      • 36.显示某个 Unit 是否处于启动失败状态
      • 37.重载所有修改过的配置文件
      • 38.显示某个 Unit 的指定属性的值
      • 39.设置某个 Unit 的指定属性
      • 40.电源管理命令

systemd GitHub 主页:https://github.com/systemd/systemd

systemd 官方网站:https://www.freedesktop.org/wiki/Software/systemd/

arch 的 systemd 的 wiki 主页:https://wiki.archlinux.org/title/systemd_(%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87)

fedora 的 systemd 说明页面:http://fedoraproject.org/wiki/Packaging:Systemd,中文:https://fedoraproject.org/wiki/Systemd/zh-cn

unbuntu 的 systemd 说明页面:https://wiki.edubuntu.org/systemd

一、系统服务管理器 systemd

init(initialization 的简写)是 Unix 和 类 Unix 系统中用来产生其它所有进程的程序。Linux 内核加载启动后,用户空间的第一个进程就是 init 进程,这个进程的进程号为1,代表第一个运行的用户空间进程,它作为父守护进程在运行,用户空间中的其它进程都是它的子进程。

Linux 系统在引导时加载 Linux 内核后,便由 Linux 内核加载 init 程序,由 init 程序完成余下的引导过程,比如加载运行级别,加载服务,引导 Shell/图形化界面等。

Systmed 是 Linux 下的一种系统初始化程序,负责控制和管理系统服务,由 Lennart Poettering 带头开发,并在 LGPL 2.1 及其后续版本许可证下开源发布。其开发目标是提供更优秀的框架以表示系统服务间的依赖关系,并依此实现系统初始化时服务的并行启动,同时达到降低系统开销的效果,最终代替现在常用的 System V 与 BSD 风格 init 程序。

传统的 System V 是串行启动,即在启动下一个脚本前,上一个脚本必须执行完,这样在启动时间上会有很大的浪费。在这个时间就是金钱的年代,这种启动方式必将被淘汰。首先是 Ubuntu 最先造反,启用了自己的 upstart 启动方式,upstart 基于事件触发,但还是串行启动,但是对于没有必要的服务就不会启动。

systemd 尽可能减少对 Shell 脚本的依赖。传统 SysVinit使用inittab来决定运行哪些Shell脚本,大量使用Shell脚本被认为是效率低下无法并行的原因。systemd 使用了Linux专属技术,不再顾及POSIX兼容,只要能满足社会变革的需要,突破一些可能过时的技术约束,这也是当今创新理念的需要,相信市场会给出评判。

这时 systemd出现了,主要优点就是并行启动,节约启动时间,systemd作者曾口出狂言,最快2秒启动。

systemd 其实是一个用户空间的程序,属于应用程序,不属于 Linux 内核范畴,Linux 内核的主要特征在所有发行版中是统一的,厂商可以自由改变的是用户空间的应用程序。以 systemd 作为系统服务管理器(启动程序)的 Linux 系统开启后,systemd 就是 init 进程。

传统的启动是内核启动完后,首先执行的第一个进程是 /sbin/init。如果要以 systemd 方式启动,则首先让内核执行的第一个进程是 /lib/systemd/systemd 或者 /usr/lib/systemd/systemd。

systemd 启动后,首先会去三个目录下找相应的配置文件,按优先级从高到底为 /etc/systemd/,/usr/lib/systemd/ 和/ lib/systemd/,优先级高的配置文件会覆盖优先级低的配置文件。

systemd 这一名字源于 Unix 中的一个惯例:在 Unix 中常以 d 作为系统守护进程的后缀标识。d 是英文单词 daemon(意指后台进程) 的首字母。

不同发行版采用了不同的启动程序:

  1. Ubuntu 的 Linux 发行版采用 Upstart。
  2. Red Hat 旗下的 7.0 版本之前的 CentOS 采用 System V init。
  3. Red Hat 旗下的 7.0 版本的 CentOS 采用 systemd。
  4. Gentoo 的 Linux 发行版采用 OpenRC 。

Fedora 15 是第一个采用 systemd 作为系统服务管理器的 Linux 发行版,后来 Red Hat 旗下 CentOS 7.0 也抛弃之前的 SysV,改用 systemd,逐渐地其它派系也开始使用 systemd 作为最新发行版的初始化系统。

从设计构思上说,由于systemd使用了cgroup与fanotify 等组件以实现其特性,所以只适用于Linux。有鉴于此,基于 kFreeBSD 分支的软件源无法纳入 systemd。

备注:Lennart Poettering 就职于红帽,systemd 是红帽的 Fedora 首先在推,OpenSUSE 后面跟随

(一)systemd 的特性

  1. 开机时并行启动系统服务,极大地提高了系统启动速度

  2. 按需启动守护进程

  3. 支持系统状态快照

  4. 基于依赖的服务控制逻辑,自动化的服务依赖关系管理

  5. 用 CGroup 代替 PID 统计跟踪子进程,即使是两次 fork 之后生成的守护进程也不会脱离systemd的控制

  6. 同时采用socket式与D-Bus总线式激活服务,以提高相互依赖的各服务的并行运行性能

(二)systemd 与 传统 init 系统的区别

  1. systemd用目标(target)代替了System V init 中运行级别的概念

  2. 默认的 Run Level(在/etc/inittab文件设置)现在被默认的 Target 取代,由文件 /etc/systemd/system/default.target 定义,通常符号链接到 graphical.target(图形界面)或者 multi-user.target(多用户命令行)

  3. 启动脚本的位置,以前是 /etc/init.d 目录,符号链接到不同的 Run Level 目录 (比如 /etc/rc3.d、/etc/rc5.d 等),现在则存放在 /lib/systemd/system 和 /etc/systemd/system 目录下

  4. 配置文件的位置,以前 init 进程的配置文件是 /etc/inittab,各种服务的配置文件存放在 /etc/sysconfig 目录。现在的配置文件主要存放在/lib/systemd目录,在 /etc/systemd 目录里面的修改可以覆盖原始设置

(三)systemd 的目录和文件

在不同的发行版中与 systemd 相关的文件路径可能会不太一样,在此以 ubuntu 16.04 举例简单介绍如下:

  1. /lib/systemd/system/:大多数 unit 的配置文件都放在这个目录下,CentOS 则放在 /usr/lib/systemd/system/ 目录中,使用命令:systemctl list-unit-files 可以列出该目录下的所有配置文件。

  2. /etc/systemd/system/:这个目录中主要的文件都是指向 /lib/systemd/system/ 目录中的链接文件。注意,在我们自己创建 unit 配置文件时,既可以把配置文件放在 /lib/systemd/system/ 目录下,也可以放在 /etc/systemd/system/ 目录下。

  3. /run/systemd/system/:系统运行过程中产生的脚本,比如用户相关的脚本和会话相关的脚本。

  4. /etc/default/ 这个目录中放置很多服务默认的配置文件。

  5. /var/lib/ 一些会产生数据的服务都会将他的数据写入到 /var/lib/ 目录中,比如 docker 相关的数据文件就放在这个目录下。

  6. /bin/sbin 工具命令位于这两个目录下。

  7. /run/ 这个目录放置了好多服务运行时的临时数据,比如 lock file,PID file,socket file 等。

我们使用命令:systemctl list-sockets 查看下 socket 文件所存放的位置:

[root@htlwk0001host ~]# systemctl list-sockets
LISTEN                            UNIT                            ACTIVATES
/run/dbus/system_bus_socket       dbus.socket                     dbus.service
/run/dmeventd-client              dm-event.socket                 dm-event.service
/run/dmeventd-server              dm-event.socket                 dm-event.service
/run/initctl                      systemd-initctl.socket          systemd-initctl.service
/run/lvm/lvmpolld.socket          lvm2-lvmpolld.socket            lvm2-lvmpolld.service
/run/systemd/coredump             systemd-coredump.socket
/run/systemd/journal/dev-log      systemd-journald-dev-log.socket systemd-journald.service
/run/systemd/journal/socket       systemd-journald.socket         systemd-journald.service
/run/systemd/journal/stdout       systemd-journald.socket         systemd-journald.service
/run/udev/control                 systemd-udevd-control.socket    systemd-udevd.service
/var/run/.heim_org.h5l.kcm-socket sssd-kcm.socket                 sssd-kcm.service
kobject-uevent 1                  systemd-udevd-kernel.socket     systemd-udevd.service12 sockets listed.
Pass --all to see loaded but inactive sockets, too.

在 CentOS 系统下我们可以使用命令:rpm -ql systemd 查看 systemd 的相关目录和文件:

[root@htlwk0001host ~]# rpm -ql systemd
/etc/X11/xinit/xinitrc.d/50-systemd-user.sh
/etc/X11/xorg.conf.d/00-keyboard.conf
/etc/binfmt.d
/etc/crypttab
/etc/dnf/protected.d/systemd.conf
/etc/hostname
/etc/inittab

文件 /etc/inittab 是 System V init 的标准配置文件,而使用 systemd 作为 init 系统后,我们再看看这个文件的内容:

[root@htlwk0001host ~]# cat /etc/inittab
# inittab is no longer used.
#
# ADDING CONFIGURATION HERE WILL HAVE NO EFFECT ON YOUR SYSTEM.
#
# Ctrl-Alt-Delete is handled by /usr/lib/systemd/system/ctrl-alt-del.target
#
# systemd uses 'targets' instead of runlevels. By default, there are two main targets:
#
# multi-user.target: analogous to runlevel 3
# graphical.target: analogous to runlevel 5
#
# To view current default target, run:
# systemctl get-default
#
# To set a default target, run:
# systemctl set-default TARGET.target

如上的内容可以看到在 systemd 掌权后,/etc/inittab 这个文件不再使用了,也没有了“运行级”的概念。现在起作用的配置文件是 /etc/systemd/system/default.target 这个文件了。此文件的内容如下:

[root@htlwk0001host ~]# cat /etc/systemd/system/default.target
#  SPDX-License-Identifier: LGPL-2.1+
#
#  This file is part of systemd.
#
#  systemd is free software; you can redistribute it and/or modify it
#  under the terms of the GNU Lesser General Public License as published by
#  the Free Software Foundation; either version 2.1 of the License, or
#  (at your option) any later version.[Unit]
Description=Multi-User System
Documentation=man:systemd.special(7)
Requires=basic.target
Conflicts=rescue.service rescue.target
After=basic.target rescue.service rescue.target
AllowIsolate=yes

(四)systemd 的 Unit 介绍

systemd 的核心概念是 Unit(单元),Unit 表示不同类型的 systemd 对象,通过配置文件进行标识和配置。使用 SysV 或者 UpStart 初始化的 Linux 发行版,都是使用位于目录 /etc/rc.d/init.d/ 下的 bash 初始化脚本来对系统服务进行管理的,而使用 systemd 作为初始化系统的 Linux 发行版(例如:RHEL 7.x、CentOS 7.x)则用服务单元(Service Unit)取代了这些启动脚本,服务单元是一种以 .service 作为扩展名的服务文件,提供了与初始化脚本同样的用途。

systemd 启动的第一个 unit 文件为 /lib/systemd/system/ 下的 default.target 文件(这里的 default.target 一般为链接文件,这样default.target 指向不同的文件,可达到不同的启动等级)

1.Unit 类型

Service:文件扩展名为.service, 用于定义系统服务

Target:Unit 的逻辑分组,包含多个相关的 Unit,用于模拟实现 System V 的运行级别。此类 unit 为其他 unit 进行逻辑分组。它们本身实际上并不做什么,只是引用其他 unit 而已。这样便可以对 unit 做一个统一的控制。(例如:multi-user.target 相当于在传统使用 SysV 的系统中运行级别5);bluetooth.target 只有在蓝牙适配器可用的情况下才调用与蓝牙相关的服务,如:bluetooth 守护进程、obex 守护进程等)

Device:用于定义内核识别的设备,对应 udev 规则标记的一个设备。此类 unit 封装一个存在于 Linux 设备树中的设备。每一个使用 udev 规则标记的设备都将会在 systemd 中作为一个设备 unit 出现。udev 的属性设置可以作为配置设备 unit 依赖关系的配置源。

Mount:定义文件系统挂载点,systemd 据此进行自动挂载。为了与 System V init 兼容,目前 systemd 自动处理 /etc/fstab 并转化为Mount

Socket:用于标识进程间通信用的 socket 文件,也可在系统启动时,延迟启动服务,实现按需启动。此类 unit 封装系统和互联网中的一个 socket 。当下,systemd 支持流式、数据报和连续包的 AF_INET、AF_INET6、AF_UNIX socket 。也支持传统的 FIFOs 传输模式。每一个 socket unit 都有一个相应的服务 unit 。相应的服务在第一个“连接”进入 socket 或 FIFO 时就会启动(例如:nscd.socket 在有新连接后便启动 nscd.service)。

Snapshot:管理系统快照,与 Target 类似,表示当前的运行状态。快照本身不做什么,唯一的目的就是引用其他 unit 。

Swap:用于标识 swap 设备

Automount:文件系统的自动挂载点。此类 unit 封装系统结构层次中的一个自挂载点。每一个自挂载 unit 对应一个已挂载的挂载 unit (需要在自挂载目录可以存取的情况下尽早挂载)。

Path:用于定义文件系统中的一个文件或目录使用,常用于当文件系统变化时,延迟激活服务

Timer:定时器,用来定时触发用户定义的操作,它可以用来取代传统的 atd,crond 等

Scope:不是由 systemd 启动的外部进程

Slice:进程组

2.Unit 的配置文件

每一个 Unit 都有一个配置文件,告诉 systemd 怎么启动这个 Unit 。系统管理员的任务就是编写和维护这写不同的配置文件。

systemd 默认从目录 /etc/systemd/system/ 读取配置文件。但是里面存放的大部分文件都是符号链接,指向目录 /usr/lib/systemd/system/ 内的配置文件,该目录是配置文件存放的真正目录。

配置文件的后缀名,就是该 Unit 的种类,比如 sshd.socket。

  • 如果省略,systemd 默认后缀名为.service,所以 sshd 会被理解成sshd.service。
  • 挂载点会自动转化为相应的 .mount 单元。例如 /home 等价于 home.mount。
  • 设备会自动转化为相应的 .device 单元,所以 /dev/sda2 等价于 dev-sda2.device。

一旦修改配置文件,就要让 systemd 重新加载配置文件,然后重新启动,否则修改不会生效,例如:

$ sudo systemctl daemon-reload
$ sudo systemctl restart httpd.service

注: 有一些单元的名称包含一个 @ 标记, (e.g. name@string.service): 这意味着它是模板单元 name@.service 的一个 实例。 string 被称作实例标识符, 在 systemctl 调用模板单元时,会将其当作一个参数传给模板单元,模板单元会使用这个传入的参数代替模板中的 %I 指示符。 在实例化之前,systemd 会先检查 name@string.suffix 文件是否存在(如果存在,应该就是直接使用这个文件,而不是模板实例化了)。大多数情况下,包含 @ 标记都意味着这个文件是模板。如果一个模板单元没有实例化就调用,该调用会返回失败,因为模板单元中的 %I 指示符没有被替换。

systemd 单元文件的语法来源于 XDG 桌面入口配置文件.desktop文件,最初的源头则是Microsoft Windows的.ini文件。单元文件可以从两个地方加载,优先级从高到低分别是:

  • /etc/systemd/system/: 系统管理员安装的单元
  • /usr/lib/systemd/system/: 软件包安装的单元

注意: 当systemd运行在用户模式下时,使用的加载路径是完全不同的。

单元文件的语法,可以参考系统已经安装的单元,也可以参考man systemd.service中的Examples章节。

小贴士: 以 # 开头的注释可能也能用在 unit-files 中, 但是只能在新行中使用。 不要在 systemd 的参数后面使用行末注释, 否则 unit 将会启动失败。

(1)配置文件的状态

一共有四种:
enabled:已建立启动链接
disabled:没建立启动链接
static:该配置文件没有 [Install] 部分(无法执行),只能作为其他配置文件的依赖
masked:该配置文件被禁止建立启动链接

(2)配置文件的格式

配置文件就是普通的文本文件,可以用文本编辑器打开。systemctl cat 命令可以查看配置文件的内容。

$ systemctl cat atd.service[Unit]
Description=ATD daemon[Service]
Type=forking
ExecStart=/usr/bin/atd[Install]
WantedBy=multi-user.target

从上面的输出可以看到,配置文件分成几个区块。每个区块的第一行,是用方括号表示的区别名,比如 [Unit]。注意,配置文件的区块名和字段名,都是大小写敏感的。

每个区块内部是一些等号连接的键值对。

[Section]
Directive1=value
Directive2=value
. . .

注意,键值对的等号两侧不能有空格。

(4)配置文件的区块

1)[Unit]区块

[Unit]区块通常是配置文件的第一个区块,用来定义 Unit 的元数据,以及配置与其他 Unit 的关系。它的主要字段如下。

Description:一些简短描述,显示给用户界面看的,可以是任何字符串,一般是关于服务的说明。

Documentation:指定参考文档的地址列表,以空格分开的 URI 形式,如http://, https://, file:, info:, man:,这是有顺序的,最好是先解释这个服务的目的是什么,然后是它是如何配置的,再然后是其它文件,这个选项可以多次指定,会将多行的合并,如果指定了一个空的,那么会重置此项,前的配置不在起作用。

Requires:当前 Unit 依赖的其他 Unit,如果它们没有运行,当前 Unit 会启动失败。指定此服务依赖的其它服务,如果本服务被激活,那么 Requires 后面的服务也会被激活,反之,如果 Requires 后面的服务被停止或无法启动,则本服务也会停止。这个选项可以指定多次,那么就要求所有指定的服务都被激活。需要注意的是这个选项不影响启动或停止的顺序,启动顺序使用单句的 After= 和 Before= 来配置。例如,如果 foo.service 依赖 bar.serivce,但是只配置了 Requires= 而没有 After= 或 Before=,那么 foo.service 启动时会同时激活 foo.service 和 bar.service。通常使用 Wants= 代替 Requires= 是更好的选择,因为系统会更好的处理服务失败的情况。注意,这种依赖关系,也可以在文件之外来处理,即使用 .requires/ 目录,可以参看上面的说明。

RequiresOverridable:类似上面的 Requires,不过这种情况下,只要用户明确要求它启动,才会影响到被依赖的服务,不然服务出错什么的,不会影响被依赖服务的启动。

Requisite 和 RequisiteOverridable:分别类似上面的两个,不过如果是这个指定服务没有启动,被依赖的服务会不启动,立即失败。

Wants:与当前 Unit 配合的其他 Unit,如果它们没有运行,当前 Unit 不会启动失败。相对弱化的依赖,这里列出的服务会被启动,但如果无法启动或无法添加到事务处理,并不影响本服务做为一个整体的启动。这是推荐的两个服务关联的方式。这种依赖也可以配置文件外,通过 .wants/ 目录添加,具体可以看上面的说明。

BindsTo:与Requires类似,它指定的 Unit 如果退出,会导致当前 Unit 停止运行,即如果它后面列出的服务停止运行或崩溃之类的,本服务也会同时停止。

PartOf:又一个类似 Requires 的选项,但是限制在停止或重启动服务,如果这里列出的服务被停止或重启动,那么本服务也会停止或重启动,注意这个依赖是意向,即本服务停止或重启动,不会影响到这里列出服务的运行状态。

Before:如果该字段指定的 Unit 也要启动,那么必须在当前 Unit 之后启动。比如一个 foo.service 包含了一行 Before=bar.service,那么当他们同时启动时,bar.service 会等待 foo.service 启动完成后才启动。注意这个设置和 Requires= 的相互独立的,同时包含 After= 和 Requires= 也是常见的。此选项可以指定一次以上,这时是按顺序全部启动。

After:如果该字段指定的 Unit 也要启动,那么必须在当前 Unit 之前启动

Conflicts:这里指定的 Unit 不能与当前 Unit 同时运行,配置一个依赖冲突,当 A 服务启动时,B 服务停止,反过来,B 服务启动,那么 A 就会停止。注意,此设置和 After= 和 Before= 是互相独立的。如果服务 A 和 B 冲突,且在 B 启动的时候同时启动,那么有可能会启动失败。

Condition:当前 Unit 运行必须满足的条件,否则不会运行

Assert:当前 Unit 运行必须满足的条件,否则会报启动失败

AllowIsolate:布尔值。如果是真值,则此服务可以使用 systemctl isolate 命令进行操作。否则会拒绝此操作。默认值是假。最好的办法是不要动这处选项,除非目标服务的行为类似于 SysV 启动系统中的 runlevels。只是一种预防措施,避免系统无法使用的状态。默认值是假。

OnFailure:列出一个或更多的服务,当本服务启动状态是 failed 的时候,激活这些服务。

PropagatesReloadTo 和 ReloadPropagatedFrom:这两个是列出一些服务,当其它服务 reload 时同时 reload 这个服务,或者反之。

RequiresMountsFor:用空格分开的绝对路径列表,是 Requires 和 After 添加的依赖中的 mount 文件需要访问的指定的路径。

OnFailureIsolate:是一个布尔值,如果是真,那么 OnFailure 后面的服务会进入隔离模式,即所有不是它依赖的服务都会停止。如果只设置一个服务,可以放在 OnFailure 后,默认值是假。

IgnoreOnIsolate:一个布尔值.如果是真则当隔离其它服务时本服务不会停止,默认是假。

IgnoreOnSnapshot:一个布尔值.如果是真则本服务不包含快照(snapshots)。对 device 和 snapshot 服务默认为真,其它服务默认为假。

StopWhenUnneeded:一个布尔值。如果是真则当本服务不使用时会停止。 注意,为了尽量减少 systemd 的工作,默认情况下是不会停止不使用的服务的,除非和其它服务冲突,或用户明确要求停止。如果设置了这个选项,那么如果没有其它活动的服务需要此服务,它会自动停止。默认值是假。

RefuseManualStart 和 RefuseManualStop:布尔值。如果设为真值,则此服务只能间接的激活或停止。这种情况下,用户直接启动或停止此服务会被拒绝,只有做为其它的服务依赖关系,由其它服务进行启动或停止才可以。这主要是为了停止用户误操作。默认值是假。

DefaultDependencies:布尔值。如果是真(默认值),一些本服务默认的依赖会隐式的建立,具体是哪些依赖,则于服务的类型决定。比如,对于普通的服务(.service类型),它会确保在系统基本服务启动后才启动本服务,会在系统关机前确保本服务已关闭。一般来说,只有早期开机服务和后期的关机服务,才需要把这个设成假。强烈对大多数普通服务,让这个选项启用即可。如果设成假,也不会禁用所有的隐式依赖,只是禁用那些非必要的。

JobTimeoutSec:当一个客户端等待本服务的某个 Job 完成时,所指定的超时时间。如果达到了限制的时间,此 Job 会取消运行,但服务不会更改状态,包括进入“failed”状态。除了设备服务(即.device类型),其它的默认值是0(即没有超时设置)。注意,这个是独立于特定服务所设置的超时设置的(比如对 .service 类型所设置的 Timeout=),它对服务本身没有影响,但特定服务的设置是有影响的(能用来更改服务状态)。

SourcePath:这个服务生成的配置文件所在的路径,这主要是用在生成工具从外部配置文件的格式转换到本地服务的配置格式中。因此,对一般的服务不要使用此选项。

接下来几个以 Condition 开头的字段一组类似的东西。检测特定的条件是不是真值,如果不是真值,服务会略过启动,但是它依赖的服务还是会正常运行的。这个条件测试失败不会让服务进入失败状态。条件是在服务开始运行时检查的。

ConditionPathExists= 是指定在服务启动时检查指定文件的存在状态。如果指定的绝对路径名不存在,这个条件的结果就是失败。如果绝对路径带有 ! 前缀,则条件反转,即只有路径不存在时服务才启动。

ConditionPathExistsGlob:类似上面的选项,但支持通配符。

ConditionPathIsDirectory:判断指定路径是不是目录。

ConditionPathIsSymbolicLink:判断指定路径是不是链接。

ConditionPathIsMountPoint:判断指定路径是不是一个挂载点。

ConditionPathIsReadWrite:年指定路径是否可读写(即不是做为只读系统挂载的)

ConditionDirectoryNotEmpty:判断指定目录是否存在且不为空。

ConditionFileNotEmpty:判断指定文件是否是常规文件且不为空(即大小不是0)。

ConditionFileIsExecutable:判断指定文件是否是常规文件且可执行。

ConditionKernelCommandLine:是判断有没有指定的内核命令行启动参数(或带有 ! 取反),这个参数必须是一个单词或用=分开的两个单词,前一种情况下,会寻找内核参数是否有此单词或是赋值的左边。后一种情况则必须是赋值的左右同时符合。

ConditionVirtualization:是判断是不是在虚拟化环境下执行的服务。这可以是个布尔值以判断是不是任意的虚拟化环境,或者下列的字符串之一: qemu, kvm, vmware, microsoft, oracle, xen, bochs, chroot, openvz, lxc, lxc-libvirt, systemd-nspawn,以判断是不是特定的虚拟化环境,多重嵌套的虚拟化环境,只判断最后一层。可以使用!进行反转判断。

ConditionSecurity:是判断系统是否启用了安全环境,当前仅能识别selinux, apparmor, 和 smack。可以使用!进行反转判断。

ConditionCapability:是判断服务管理器绑定的 capability 是否存在。(可以查看其它部分的详细信息。)设置为 capability 的名字,比如 CAP_MKNOD。可以通过在前面加!反转判断。

ConditionHost:是判断主机名 (hostname)或机器ID(machine ID)是否匹配。可以加!反转。

ConditionACPower:是判断机器是否在使用交流电源。如果设成 true,而只有至少连接一个交流电源时结果才为真,反过来,设成 false,则不连接所有交流电源时才为真。

ConditionNull:是一个常量性质的判断条件,它应该是布尔值,如果设成 false ,则条件永远失败,反过来则永远成立。

如果指定多个条件,则所有条件都需要成立(即条件之间是 AND 的关系)。条件前面可以加上 | 符号,这时条件变成一个触发条件,服务定义了触发条件,那么在满足其它非触发条件和这个触发条件的情况下,服务会至少执行一次。同时指定|和!前缀时,先处理|,后处理!。除了ConditionPathIsSymbolicLink=,其它条件均跟随链接。如果这些条件指定为空,则相当于重置,前面的任何设置都不再起作用。

2)[Service]区块

[Service]区块用来 Service 的配置,只有 Service 类型的 Unit 才有这个区块。它的主要字段如下:
Type:定义启动时的进程行为。它有以下几种值。

Type=simple:默认值,执行ExecStart指定的命令,启动主进程。systemd 认为该服务将立即启动。服务进程不会fork。如果该服务要启动其他服务,不要使用此类型启动,除非该服务是socket激活型。

Type=forking:以 fork 方式从父进程创建子进程,创建后父进程会立即退出。systemd认为当该服务进程fork,且父进程退出后服务启动成功。对于常规的守护进程(daemon),除非你确定此启动方式无法满足需求,使用此类型启动即可。使用此启动类型应同时指定 PIDFile=,以便systemd能够跟踪服务的主进程。

Type=oneshot:一次性进程,systemd 会等当前服务退出,再继续往下执行。这一选项适用于只执行一项任务、随后立即退出的服务。可能需要同时设置 RemainAfterExit=yes 使得 systemd 在服务进程退出之后仍然认为服务处于激活状态。

Type=dbus:当前服务通过D-Bus启动。若以此方式启动,当指定的 BusName 出现在DBus系统总线上时,systemd认为服务就绪。

Type=notify:当前服务启动完毕,会通知systemd,再继续往下执行。与 Type=simple 相同,但约定服务会在就绪后向 systemd 发送一个信号。这一通知的实现由 libsystemd-daemon.so 提供。

Type=idle:若有其他任务执行完毕,当前服务才会运行。systemd会等待所有任务(Jobs)处理完成后,才开始执行idle类型的单元。除此之外,其他行为和Type=simple 类似。

小贴士:type的更多解释可以参考 systemd.service(5)。

ExecStart:启动当前服务的命令

ExecStartPre:启动当前服务之前执行的命令

ExecStartPost:启动当前服务之后执行的命令

ExecReload:重启当前服务时执行的命令

ExecStop:停止当前服务时执行的命令

ExecStopPost:停止当其服务之后执行的命令

RestartSec:自动重启当前服务间隔的秒数

Restart:定义何种情况 systemd 会自动重启当前服务,可能的值包括always(总是重启)、on-success、on-failure、on-abnormal、on-abort、on-watchdog

TimeoutSec:定义 systemd 停止当前服务之前等待的秒数

Environment:指定环境变量

3)[Install]区块

[Install]通常是配置文件的最后一个区块,用来定义如何启动,以及是否开机启动。这个段的内容服务的安装信息。它不在 systemd 的运行期间使用。只在使用 systemctl enable 和 systemctl disable 命令启用/禁用服务时有用。

它的主要字段如下:

WantedBy 和 RequiredBy:在 .wants/ 或 .requires/ 子目录中为服务建立相应的链接。这样做的效果是当列表中的服务启动,本服务也会启动。 在  bar.service 中的 WantedBy=foo.service  和 Alias=foo.service.wants/bar.service 基本是一个意思。

WantedBy:它的值是一个或多个 Target,当前 Unit 激活时(enable)符号链接会放入/etc/systemd/system目录下面以 Target 名 + .wants后缀构成的子目录中

RequiredBy:它的值是一个或多个 Target,当前 Unit 激活时,符号链接会放入/etc/systemd/system目录下面以 Target 名 + .required后缀构成的子目录中

Alias:当前 Unit 可用于启动的别名。在安装使用应该使用的别名。名字必须和服务本身有同样的后缀(即同样的类型)。这个选项可以指定多次,所有的名字都起作用,当执行 systemctl enable 命令时,会建立相当的链接。

Also:当前 Unit 激活(enable)时,会被同时激活的其他 Unit。当此服务安装时同时需要安装的附加服务。 如果用户请求安装的服务中配置了此项,则 systemctl enable 命令执行时会自动安装本项所指定的服务。

Unit 配置文件的完整字段清单,请参考官方文档。

A.替换符

在 [Install] 小节的选项中,可以使用如下替换符: %n, %N, %p, %i, %j, %g, %G, %U, %u, %m, %H, %b, %v 。 在许多选项中都可以使用一些替换符(不只是 [Install] 小节中的选项), 以引用一些运行时才能确定的值, 从而可以写出更通用的单元文件。 替换符必须是已知的、并且是可以解析的,这样设置才能生效。 当前可识别的所有替换符及其解释如下:

替换符 含义
“%b” 系统的"Boot ID"字符串。参见 random(4) 手册
“%C” 缓存根目录。对于系统实例来说是 /var/cache ;对于用户实例来说是 “$XDG_CACHE_HOME”
“%E” 配置根目录。对于系统实例来说是 /etc ;对于用户实例来说是 “$XDG_CONFIG_HOME”
“%f” 原始单元文件名称(不含路径,且遵守前文描述的已转义绝对文件系统路径的还原规则)。对于实例化的单元,就是带有 / 前缀的原始实例名;对于其他单元,就是带有 / 前缀的原始前缀名。
“%h” 用户的家目录。运行 systemd 实例的用户的家目录,对于系统实例则是 “/root”
“%H” 系统的主机名(hostname)
“%i” 已转义的实例名称。对于实例化单元,就是 “@” 和后缀之间的部分。对于非实例化单元则为空。
“%I” 原始实例名称。对于实例化单元,就是 “@” 和后缀之间的部分(已还原的)。对于非实例化单元则为空。
“%j” 已转义的前缀名最后一部分。也就是前缀名中最后一个 “-” 之后的部分。如果没有 “-” 那么与 “%p” 相同。
“%J” 原始前缀名最后一部分。也就是前缀名中最后一个 “-” 之后的部分(已还原的)。如果没有 “-” 那么与 “%p” 相同。
“%L” 日志根目录。对于系统实例来说是 /var/log ;对于用户实例来说是 “$XDG_CONFIG_HOME”/log
“%m” 系统的"Machine ID"字符串。参见 machine-id(5) 手册
“%n” 带类型后缀的完整单元名称
“%N” 无类型后缀的完整单元名称
“%p” 已转义的前缀名称。对于实例化单元来说,就是单元名称里第一个 “@” 之前的字符串。对于非实例化单元来说,等价于 “%N”
“%P” 原始前缀名称。对于实例化单元来说,就是单元名称里第一个 “@” 之前的字符串(已还原的)。对于非实例化单元来说,等价于 “%N”
“%s” 用户的shell。运行 systemd 实例的用户的shell,对于系统实例则是 “/bin/sh”
“%S” 状态根目录。对于系统实例来说是 /var/lib ;对于用户实例来说是 “$XDG_CONFIG_HOME”
“%t” 运行时根目录。对于系统实例来说是 /run ;对于用户实例来说是 “$XDG_RUNTIME_DIR”
“%T” 临时文件目录。也就是 /tmp 或 “$TMPDIR”, “$TEMP”, “$TMP” 之一(若已设置)
“%g” 运行 systemd 用户实例的组名称。对于 systemd 系统实例来说,则是 “root”
“%G” 运行 systemd 用户实例的组GID。对于 systemd 系统实例来说,则是 “0”
“%u” 运行 systemd 用户实例的用户名称。对于 systemd 系统实例来说,则是 “root”
“%U” 运行 systemd 用户实例的用户UID。对于 systemd 系统实例来说,则是 “0”
“%v” 内核版本(uname -r 的输出)
“%V” 存放大体积临时文件以及持久临时文件的目录。也就是 /var/tmp 或 “$TMPDIR”, “$TEMP”, “$TMP” 之一(若已设置)
“%%” 百分号自身(%)。使用 “%%” 表示一个真正的 “%” 字符。

3.Unit 的依赖管理

很多服务之间是有依赖关系的,systemd 的一大亮点就是可以管理 unit 之间的依赖关系。我们可以通过下面的命令来查看 unit 间的依赖关系:

systemctl list-dependencies [unit] [–reverse],选项 --reverse 会反向追踪是谁在使用这个 unit。

下面让我们看看 graphical.target 的依赖关系:

[root@htlwk0001host ~]# systemctl list-dependencies multi-user.target
multi-user.target
● ├─aegis.service
● ├─aliyun.service
● ├─AssistDaemon.service

系统当前运行在 multi-user.target 下,它有一个长长的依赖列表(上面仅仅截取了部分项目),其中有一个依赖项目为 aliyun.service。下面我们使用 --reverse 选项查看 aliyun.service unit 被谁使用:

[root@htlwk0001host ~]# systemctl list-dependencies --reverse aliyun.service
aliyun.service
● └─multi-user.target
●   └─graphical.target

上面可以看到,aliyun.service 被 multi-user.target 使用,而 multi-user.target 被 graphical.target 使用,换句话说,multi-user.target 依赖于 aliyun.service,而 graphical.target 又依赖于 multi-user.target。

列出一个 Unit 的所有依赖:

$ systemctl list-dependencies nginx.service

有些依赖是 Target 类型,默认不会展开显示。如果要展开 Target,就需要使用 --all 参数:

$ systemctl list-dependencies --all nginx.service

(五)systemd 的 Target 介绍

启动计算机的时候,需要启动大量的 Unit。如果每一次启动,都要一一写明本次启动需要哪些 Unit,显然非常不方便。systemd 的解决方案就是 Target。

简单说,Target 就是一个 Unit 组,包含许多相关的 Unit 。启动某个 Target 的时候,systemd 就会启动里面所有的 Unit。从这个意义上说,Target 这个概念类似于"状态点",启动某个 Target 就好比启动到某种状态。

使用命令 systemctl enable 设置开机自启时,/usr/lib/systemd/system 下的 mysqld.service 就被加入到目录 /etc/systemd/system 下的子目录 multi-user.target.wants 中。效果如下面的语句:

Created symlink from /etc/systemd/system/multi-user.target.wants/mysqld.service to /usr/lib/systemd/system/mysqld.service.

传统的 init 启动模式里面,有 Run Level 的概念,跟 Target 的作用很类似。不同的是,Run Level 是互斥的,不可能多个 Run Level 同时启动,但是多个 Target 可以同时启动。

systemd 使用 Target 取代了 System V 的运行级的概念。在 systemd 中,默认运行级别由 /etc/systemd/system/default.target 定义,这个文件本身是一个软连接,如果它指向 graphical.targer 那么默认的运行级别就是图形界面。

备注:Target 类型的 Unit 也可以理解为系统环境,当运行或切换个环境时往往会伴随着启动很多其他的 Unit 用以支持这个环境,最常见的环境就是字符界面(multi-user.target)和图形界面(graphical.target)

1.查看当前系统的所有 Target

[root@htlwk0001host ~]# systemctl list-unit-files --type=target
UNIT FILE                     STATE
basic.target                  static
bluetooth.target              static
cloud-config.target           static
cloud-init.target             enabled-runtime
cryptsetup-pre.target         static

2.查看一个 Target 包含的所有 Unit

[root@htlwk0001host ~]# systemctl list-dependencies multi-user.target

3.查看启动时的默认 Target

[root@htlwk0001host ~]# systemctl get-default

4.设置启动时的默认 Target

[root@htlwk0001host ~]# sudo systemctl set-default multi-user.target

如果需要将系统默认运行的目标修改为“多用户,无图形”模式,可以直接用 ln 命令把多用户模式目标文件连接到 /etc/systemd/system/ 目录:

[root@htlwk0001host ~]# ln -sf /lib/systemd/system/multi-user.target /etc/systemd/system/default.target

5.切换 Target

切换 Target 时,默认不关闭前一个 Target 启动的进程,

[root@htlwk0001host ~]# systemctl isolate multi-user.target

6.Target 与 传统 Run Level 的对应关系

Traditional runlevel      New target name     Symbolically linked to...Runlevel 0           |    runlevel0.target -> poweroff.target     关闭系统
Runlevel 1           |    runlevel1.target -> rescue.target        救援模式,单用户模式
Runlevel 2           |    runlevel2.target -> multi-user.target    多用户,无图形模式,字符界面,标准模式,即命令行模式
Runlevel 3           |    runlevel3.target -> multi-user.target   多用户,无图形模式,字符界面,标准模式,即命令行模式
Runlevel 4           |    runlevel4.target -> multi-user.target   多用户,无图形模式,字符界面,标准模式,即命令行模式
Runlevel 5           |    runlevel5.target -> graphical.target    多用户,图形化模式
Runlevel 6           |    runlevel6.target -> reboot.target       重启系统

(六)systemd 并行启动原理

在 systemd 中,所有的服务都并发启动,比如 Avahi、D-Bus、livirtd、X11、HAL 可以同时启动。乍一看,这似乎有点儿问题,比如 Avahi 需要 syslog 的服务,Avahi 和 syslog 同时启动,假设 Avahi 的启动比较快,所以 syslog 还没有准备好,可是 Avahi 又需要记录日志,这岂不是会出现问题?

systemd 的开发人员仔细研究了服务之间相互依赖的本质问题,发现所谓依赖可以分为三个具体的类型,而每一个类型实际上都可以通过相应的技术解除依赖关系。

并发启动原理之一:解决 socket 依赖

绝大多数的服务依赖是套接字依赖。比如服务 A 通过一个套接字端口 S1 提供自己的服务,其他的服务如果需要服务 A,则需要连接 S1。因此如果服务 A 尚未启动,S1 就不存在,其他的服务就会得到启动错误。所以传统地,人们需要先启动服务 A,等待它进入就绪状态,再启动其他需要它的服务。systemd 认为,只要我们预先把 S1 建立好,那么其他所有的服务就可以同时启动而无需等待服务 A 来创建 S1 了。如果服务 A 尚未启动,那么其他进程向 S1 发送的服务请求实际上会被 Linux 操作系统缓存,其他进程会在这个请求的地方等待。一旦服务 A 启动就绪,就可以立即处理缓存的请求,一切都开始正常运行。

那么服务如何使用由 init 进程创建的套接字呢?

Linux 操作系统有一个特性,当进程调用 fork 或者 exec 创建子进程之后,所有在父进程中被打开的文件句柄 (file descriptor) 都被子进程所继承。套接字也是一种文件句柄,进程 A 可以创建一个套接字,此后当进程 A 调用 exec 启动一个新的子进程时,只要确保该套接字的 close_on_exec 标志位被清空,那么新的子进程就可以继承这个套接字。子进程看到的套接字和父进程创建的套接字是同一个系统套接字,就仿佛这个套接字是子进程自己创建的一样,没有任何区别。

这个特性以前被一个叫做 inetd 的系统服务所利用。Inetd 进程会负责监控一些常用套接字端口,比如 Telnet,当该端口有连接请求时,inetd 才启动 telnetd 进程,并把有连接的套接字传递给新的 telnetd 进程进行处理。这样,当系统没有 telnet 客户端连接时,就不需要启动 telnetd 进程。Inetd 可以代理很多的网络服务,这样就可以节约很多的系统负载和内存资源,只有当有真正的连接请求时才启动相应服务,并把套接字传递给相应的服务进程。

和 inetd 类似,systemd 是所有其他进程的父进程,它可以先建立所有需要的套接字,然后在调用 exec 的时候将该套接字传递给新的服务进程,而新进程直接使用该套接字进行服务即可。

并发启动原理之二:解决 D-Bus 依赖

D-Bus 是 desktop-bus 的简称,是一个低延迟、低开销、高可用性的进程间通信机制。它越来越多地用于应用程序之间通信,也用于应用程序和操作系统内核之间的通信。很多现代的服务进程都使用D-Bus 取代套接字作为进程间通信机制,对外提供服务。比如简化 Linux 网络配置的 NetworkManager 服务就使用 D-Bus 和其他的应用程序或者服务进行交互:邮件客户端软件 evolution 可以通过 D-Bus 从 NetworkManager 服务获取网络状态的改变,以便做出相应的处理。

D-Bus 支持所谓"bus activation"功能。如果服务 A 需要使用服务 B 的 D-Bus 服务,而服务 B 并没有运行,则 D-Bus 可以在服务 A 请求服务 B 的 D-Bus 时自动启动服务 B。而服务 A 发出的请求会被 D-Bus 缓存,服务 A 会等待服务 B 启动就绪。利用这个特性,依赖 D-Bus 的服务就可以实现并行启动。

并发启动原理之三:解决文件系统依赖

系统启动过程中,文件系统相关的活动是最耗时的,比如挂载文件系统,对文件系统进行磁盘检查(fsck),磁盘配额检查等都是非常耗时的操作。在等待这些工作完成的同时,系统处于空闲状态。那些想使用文件系统的服务似乎必须等待文件系统初始化完成才可以启动。但是 systemd 发现这种依赖也是可以避免的。

systemd 参考了 autofs 的设计思路,使得依赖文件系统的服务和文件系统本身初始化两者可以并发工作。autofs 可以监测到某个文件系统挂载点真正被访问到的时候才触发挂载操作,这是通过内核 automounter 模块的支持而实现的。比如一个 open()系统调用作用在"/misc/cd/file1"的时候,/misc/cd 尚未执行挂载操作,此时 open()调用被挂起等待,Linux 内核通知 autofs,autofs 执行挂载。这时候,控制权返回给 open()系统调用,并正常打开文件。

systemd 集成了 autofs 的实现,对于系统中的挂载点,比如/home,当系统启动的时候,systemd 为其创建一个临时的自动挂载点。在这个时刻/home 真正的挂载设备尚未启动好,真正的挂载操作还没有执行,文件系统检测也还没有完成。可是那些依赖该目录的进程已经可以并发启动,他们的 open()操作被内建在 systemd 中的 autofs 捕获,将该 open()调用挂起(可中断睡眠状态)。然后等待真正的挂载操作完成,文件系统检测也完成后,systemd 将该自动挂载点替换为真正的挂载点,并让 open()调用返回。由此,实现了那些依赖于文件系统的服务和文件系统本身同时并发启动。

当然对于"/"根目录的依赖实际上一定还是要串行执行,因为 systemd 自己也存放在/之下,必须等待系统根目录挂载检查好。

不过对于类似/home 等挂载点,这种并发可以提高系统的启动速度,尤其是当/home 是远程的 NFS 节点,或者是加密盘等,需要耗费较长的时间才可以准备就绪的情况下,因为并发启动,这段时间内,系统并不是完全无事可做,而是可以利用这段空余时间做更多的启动进程的事情,总的来说就缩短了系统启动时间。

(七)systemd 配置使用

1.对于系统开发人员

开发人员需要了解 systemd 的更多细节。比如您打算开发一个新的系统服务,就必须了解如何让这个服务能够被 systemd 管理。这需要您注意以下这些要点:

(1)后台服务进程代码不需要执行两次派生来实现后台精灵进程,只需要实现服务本身的主循环即可。

(2)不要调用 setsid(),交给 systemd 处理。

(3)不再需要维护 pid 文件。

(4)systemd 提供了日志功能,服务进程只需要输出到 stderr 即可,无需使用 syslog。

(5)处理信号 SIGTERM,这个信号的唯一正确作用就是停止当前服务,不要做其他的事情。

(6)SIGHUP 信号的作用是重启服务。

(7)需要套接字的服务,不要自己创建套接字,让 systemd 传入套接字。

(8)使用 sd_notify()函数通知 systemd 服务自己的状态改变。一般地,当服务初始化结束,进入服务就绪状态时,可以调用它。

对于开发者来说,工作量最大的部分应该是编写配置单元文件,定义所需要的单元。

举例来说,开发人员开发了一个新的服务程序,比如 httpd,就需要为其编写一个配置单元文件以便该服务可以被 systemd 管理,类似 UpStart 的工作配置文件。在该文件中定义服务启动的命令行语法,以及和其他服务的依赖关系等。

此外我们之前已经了解到,systemd 的功能繁多,不仅用来管理服务,还可以管理挂载点,定义定时任务等。这些工作都是由编辑相应的配置单元文件完成的。我在这里给出几个配置单元文件的例子。

服务配置单元文件以 .service 为文件名后缀,下面是 SSH 服务的配置单元文件:

[root@htlwk0001host ~]# cat /etc/system/system/sshd.service[Unit]Description=OpenSSH server daemon[Service]EnvironmentFile=/etc/sysconfig/sshdExecStartPre=/usr/sbin/sshd-keygenExecStart=/usrsbin/sshd –D $OPTIONSExecReload=/bin/kill –HUP $MAINPIDKillMode=processRestart=on-failureRestartSec=42s[Install]WantedBy=multi-user.target

文件分为三个小节:
第一部分是[Unit],这里仅仅有一个描述信息。
第二部分是[Service] ,对服务进行相关的定义。其中,ExecStartPre 定义启动服务之前应该运行的命令;ExecStart 定义启动服务的具体命令行语法。
第三部分是[Install],WangtedBy 表明这个服务是在多用户模式下所需要的。

那我们再就来看下 multi-user.target:

  [root@htlwk0001host ~]# cat multi-user.target[Unit]Description=Multi-User SystemDocumentation=man.systemd.special(7)Requires=basic.targetConflicts=rescue.service rescure.targetAfter=basic.target rescue.service rescue.targetAllowIsolate=yes[Install]Alias=default.target

第一部分中的 Requires 定义表明 multi-user.target 启动的时候 basic.target 也必须被启动;另外 basic.target 停止的时候,multi-user.target 也必须停止。如果您接着查看 basic.target 文件,会发现它又指定了 sysinit.target 等其他的单元必须随之启动。同样 sysinit.target 也会包含其他的单元。采用这样的层层链接的结构,最终所有需要支持多用户模式的组件服务都会被初始化启动好。

在[Install]小节中有 Alias 定义,即定义本单元的别名,这样在运行 systemctl 的时候就可以使用这个别名来引用本单元。这里的别名是 default.target,比 multi-user.target 要简单一些。

此外在/etc/systemd/system 目录下还可以看到诸如*.wants 的目录,放在该目录下的配置单元文件等同于在[Unit]小节中的 wants 关键字,即本单元启动时,还需要启动这些单元。比如您可以简单地把您自己写的 foo.service 文件放入 multi-user.target.wants 目录下,这样每次都会被默认启动了。

最后,让我们来看看 sys-kernel-debug.mout 文件,这个文件定义了一个文件挂载点:

[root@htlwk0001host ~]# cat sys-kernel-debug.mount
[Unit]
Description=Debug File Syste
DefaultDependencies=no
ConditionPathExists=/sys/kernel/debug
Before=sysinit.target
[Mount]
What=debugfs
Where=/sys/kernel/debug
Type=debugfs

这个配置单元文件定义了一个挂载点。挂载配置单元文件有一个[Mount]配置小节,里面配置了 What,Where 和 Type 三个数据项。这都是挂载命令所必须的,例子中的配置等同于下面这个挂载命令:

[root@htlwk0001host ~]# mount –t debugfs /sys/kernel/debug debugfs

配置单元文件的编写需要很多的学习,必须参考 systemd 附带的 man 等文档进行深入学习。希望通过上面几个小例子,大家已经了解配置单元文件的作用和一般写法了。

2.对于系统管理员

作为系统管理员必须非常熟悉系统服务和 init 系统的管理,否则请自动辞职。比如 service、chkconfig 以及 telinit 命令的使用。而使用 systemd 作为初始化系统的 Linux 系统则是使用命令 systemctl 来管理和控制系统服务,systemctl 和旧命令存在较大的语法差别,所以作为系统管理员必须牢记其中的差别,能够做到在新旧系统灵活切换。

其实 systemctl 只是 systemd 的主命令,还有几个较为常用的命令如下:

(1)hostnamectl:用于查看当前主机的信息。

(2)localectl:用于查看本地化设置。

(3)timedatectl:用于查看当前时区设置。

(4)loginctl:用于查看当前登录的用户。

(八)日志管理

systemd 统一管理所有 Unit 的启动日志。带来的好处就是,可以只用 journalctl一个命令,查看所有日志(内核日志和应用日志)。日志的配置文件是 /etc/systemd/journald.conf。

# 查看所有日志(默认情况下 ,只保存本次启动的日志)
$ sudo journalctl# 查看内核日志(不显示应用日志)
$ sudo journalctl -k# 查看系统本次启动的日志
$ sudo journalctl -b
$ sudo journalctl -b -0# 查看上一次启动的日志(需更改设置)
$ sudo journalctl -b -1# 查看指定时间的日志
$ sudo journalctl --since="2012-10-30 18:17:16"
$ sudo journalctl --since "20 min ago"
$ sudo journalctl --since yesterday
$ sudo journalctl --since "2015-01-10" --until "2015-01-11 03:00"
$ sudo journalctl --since 09:00 --until "1 hour ago"# 显示尾部的最新10行日志
$ sudo journalctl -n# 显示尾部指定行数的日志
$ sudo journalctl -n 20# 实时滚动显示最新日志
$ sudo journalctl -f# 查看指定服务的日志
$ sudo journalctl /usr/lib/systemd/systemd# 查看指定进程的日志
$ sudo journalctl _PID=1# 查看某个路径的脚本的日志
$ sudo journalctl /usr/bin/bash# 查看指定用户的日志
$ sudo journalctl _UID=33 --since today# 查看某个 Unit 的日志
$ sudo journalctl -u nginx.service
$ sudo journalctl -u nginx.service --since today# 实时滚动显示某个 Unit 的最新日志
$ sudo journalctl -u nginx.service -f# 合并显示多个 Unit 的日志
$ journalctl -u nginx.service -u php-fpm.service --since today# 查看指定优先级(及其以上级别)的日志,共有8级
# 0: emerg
# 1: alert
# 2: crit
# 3: err
# 4: warning
# 5: notice
# 6: info
# 7: debug
$ sudo journalctl -p err -b# 日志默认分页输出,--no-pager 改为正常的标准输出
$ sudo journalctl --no-pager# 以 JSON 格式(单行)输出
$ sudo journalctl -b -u nginx.service -o json# 以 JSON 格式(多行)输出,可读性更好
$ sudo journalctl  -b -u httpd.service  -o json-pretty# 显示日志占据的硬盘空间
$ sudo journalctl --disk-usage# 指定日志文件占据的最大空间
$ sudo journalctl --vacuum-size=1G# 指定日志文件保存多久
$ sudo journalctl --vacuum-time=1years

二、使用命令 systemctl 管理系统服务

(一)命令介绍

我们知道使用 SysV 或者 UpStart 初始化的 Linux 发行版(例如:Red Hat 旗下的 7.0 版本之前的CentOS)都是使用命令 servicechkconfig 来管理系统服务,而使用 systemd 作为 Init System 的Linux 发行版(例如:7.0 版本之后的CentOS)则是使用新的管理命令 systemctl 来启动、停止、重启、禁用、查看系统服务,该命令集成了命令 servicechkconfigsetupinit 的大部分功能于一身。

systemctl 命令有两大类功能:

  1. 控制 systemd 系统
  2. 管理系统上运行的服务

备注:为了向前兼容,旧命令 service 在新版本的 Linux 中仍然可以使用,只是会被重定向到新的 systemctl 工具

(二)命令选项

systemctl 提供了一组子命令(命令选项)来管理单个的 unit,其命令格式为: systemctl <command> <unit>。unit 是指服务单元,就是指服务进程。命令选项如下:

选项 说明
start 立刻启动后面接的 unit
stop 立刻关闭后面接的 unit
restart 立刻关闭后启动后面接的 unit,亦即执行 stop 再 start 的意思
reload 不关闭 unit 的情况下,重新载入配置文件,让设置生效
enable 设置下次开机时,后面接的 unit 会被启动
disable 设置下次开机时,后面接的 unit 不会被启动
status 目前后面接的这个 unit 的状态,会列出有没有正在执行、开机时是否启动等信息
is-active 目前有没有正在运行中
is-enable 开机时有没有默认启动这个 unit
kill 向运行 unit 的进程发送终止信号
show 列出 unit 的配置
mask 注销 unit,注销后你就无法启动这个 unit 了
unmask 取消对 unit 的注销
list-dependencies 添加选项 --reverse 会反向追踪是谁在使用这个 unit
list-units 列出当前所有已启动的服务,如果添加 -all 选项会同时列出没有启动的服务,添加 --type 可以过滤某个类型的 unit
list-unit-files 根据 /lib/systemd/system/ 目录内的文件列出所有的 uni
get-default 取得目前的操作模式(target)
set-default 设置后面接的 target 成为默认的操作模式
isolate 切换到后面接的模式
poweroff 系统关机,systemctl poweroff 关机(相当于 systemctl isolate poweroff.target)
reboot 重启系统
suspend 进入暂停模式,即待机模式,将系统数据写入内存,同时将大部分硬件关闭,等待唤醒(相当于Windows下的睡眠)
hibernate 进入休眠模式,将系统数据写入硬盘,然后关机
rescue 强制进入救援模式
hybrid-sleep 混合休眠模式(同时休眠到硬盘并待机)
emergency 强制进入紧急救援模式,比救援模式更强更彻底

(三)systemd 命令和 SysV init 命令的对比

systemd 命令 SysV init 命令 说明
systemctl start foo.service service foo start 启动一个服务
systemctl stop foo.service service foo stop 停止一个服务
systemctl restart foo.service service foo restart 重启一个服务
systemctl reload foo.service service foo reload 重新装载配置文件而不中断等待操作
systemctl condrestart foo.service service foo condrestart 如果服务正在运行那么重启它
systemctl status foo.service service foo status 查看服务的状态
systemctl list-unit-files --type=service ls /etc/rc.d/init.d/ 列出可以启动或停止的服务列表
systemctl list-units --type=service chkconfig --list 显示所有已启动的服务
systemctl enable foo.service chkconfig foo on 或者 chkconfig --level 3 httpd on 设置开机时启动某个服务
systemctl disable foo.service chkconfig foo off 或者 chkconfig --level 3 httpd off 取消开机时启动某个服务
systemctl is-enabled foo.service chkconfig foo 查看某个服务是否开机启动
ls /etc/systemd/system/*.wants/foo.service chkconfig foo –list 用来列出该服务在哪些运行级别下启用和禁用
systemctl daemon-reload chkconfig foo –add 重载配置文件,当您创建新服务文件或者变更设置时使用
systemctl isolate multi-user.target 或者 systemctl isolate runlevel3.target 或者 telinit 3 telinit 3 切换至多用户运行级别

(四)命令示例

1.重启服务

restart
使用选项 restart,如果服务在运行中,它将重启服务;如果服务不在运行中,它将会启动服务

[root@htlwk0001host ~]# systemctl restart httpd.service

2.纯重启 try-restart

使用选项 try-restart,服务若处于运行中则重启服务:

[root@htlwk0001host ~]# systemctl try-restart httpd.service

3.重新加载某个服务的配置文件

使用选项 reload,它会重新加载配置文件

[root@htlwk0001host ~]# systemctl reload httpd.service

4.启动服务

启动服务

[root@htlwk0001host ~]# systemctl start httpd.service

5.停止服务

停止服务

[root@htlwk0001host ~]# systemctl stop httpd.service

6.查看服务状态

查看服务的状态,我们看看服务 mysqld 的基本信息有些什么:

[root@htlwk0001host ~]# systemctl status mysqld.service
● mysqld.service - MySQL ServerLoaded: loaded (/usr/lib/systemd/system/mysqld.service; enabled; vendor preset: disabled)Active: active (running) since Fri 2021-04-23 16:11:01 CST; 1 weeks 1 days agoDocs: man:mysqld(8)http://dev.mysql.com/doc/refman/en/using-systemd.htmlProcess: 1069004 ExecStart=/usr/sbin/mysqld --daemonize --pid-file=/var/run/mysqld/mysqld.pid $MYSQLD_OPTS (code=exited, status=0/SUCCESS)Process: 1068982 ExecStartPre=/usr/bin/mysqld_pre_systemd (code=exited, status=0/SUCCESS)Main PID: 1069006 (mysqld)Tasks: 55 (limit: 23070)Memory: 344.2MCGroup: /system.slice/mysqld.service└─1069006 /usr/sbin/mysqld --daemonize --pid-file=/var/run/mysqld/mysqld.pid4月 23 16:10:59 htlwk0001host systemd[1]: Starting MySQL Server...
4月 23 16:11:01 htlwk0001host systemd[1]: Started MySQL Server.

(1)解读服务状态信息

第一行是对 mysqld 的基本描述。
第二行是描述操作系统启动时会不会启动这个服务,enabled 表示开机时启动,disabled 表示开机时不启动。而启动该服务的配置文件路径为:/usr/lib/systemd/system/mysqld.service。
第三行是描述服务当前的状态,active (running) 表示服务正在运行中。如果是 inactive (dead) 则表示服务当前没有运行。后面则是服务的启动时间。
第四行提供了关于服务的在线文档地址。
第七行显示出该服务的主进程的 ID。
第八行显示了该服务关联的任务数量。
第九行显示了该服务占用的内存大小。
第十行显示的是 mysqld 的所有子进程。
最后两行是输出的日志信息。

(2)关于服务的启动状态

关于 unit 的启动状态,除了 enable 和 disable 之外还有:

  • static:这个 unit 不可以自己启动,不过可能会被其它的 enabled 的服务来唤醒。
  • mask:这个 unit 无论如何都无法被启动!因为已经被强制注销。可通过 systemctl unmask 改回原来的状态。

(3)关于服务的运行状态

关于 unit 的运行状态 Active,除了 active 和 inactive 之外还有:

  • active (exited):仅执行一次就正常结束的服务,举例来说,开机或者是挂载时才会进行一次的 quotaon 功能,就是这种模式。Quotaon 不需要一直执行,只在执行一次之后,就交给文件系统去自行处理。通常用 bash shell 写的小型服务,大多是属于这种类型。
  • active (waiting):正在执行当中,不过还再等待其他的事件才能继续处理。举例来说,打印的相关服务就是这种状态。

7.设置开机启动某个服务

使用选项 enable 设置开机启动某个服务

[root@htlwk0001host ~]# systemctl enable mysqld.service

开机启动的原理说明:
MySQL 安装后会自动在 /usr/lib/systemd/system 添加一个配置文件 mysqld.service。每次开机,systemd 都会默认从 /etc/systemd/system/ 读取配置文件。 而 systemctl enable 其实就是创建一个从 /etc/systemd/system/ 到 /usr/lib/systemd/system/mysqld.service 的软链接(符号链接)。而 mysqld.service 这个 unit 配置文件里的 [Install] 定义了自启行为,所以 systemctl enable 相当于给服务设置开机自启。

这也意味着,如果把自己修改后的配置文件放在该目录,就可以达到覆盖原始配置的效果。

8.取消某个服务的开机启动

使用选项 disable 设置开机禁用某个服务,就是取消某个服务的开机启动

[root@htlwk0001host ~]# systemctl disable httpd.service

9.查看某个服务是否开机启动

[root@htlwk0001host ~]# systemctl is-enabled httpd.service

10.查看启动失败的服务

[root@htlwk0001host ~]# systemctl –failed

11.查看进程是不是在运行中

[root@htlwk0001host ~]# systemctl is-active sshd.service

12.查看系统中所有已经启动的服务

输入命令 systemctl,相当于 输入 systemctl list-units

[root@htlwk0001host ~]# systemctl
UNIT                                                                        LOAD   ACTIVE SUB       DESCRIPTION
proc-sys-fs-binfmt_misc.automount                                           loaded active running   Arbitrary Executable File Formats File System Automount Point
sys-devices-pci0000:00-0000:00:03.0-virtio0-virtio\x2dports-vport0p1.device loaded active plugged   /sys/devices/pci0000:00/0000:00:03.0/virtio0/virtio-ports/vport0p1
sys-devices-pci0000:00-0000:00:04.0-virtio1-block-vda-vda1.device           loaded active plugged   /sys/devices/pci0000:00/0000:00:04.0/virtio1/block/vda/vda1
sys-devices-pci0000:00-0000:00:04.0-virtio1-block-vda.device                loaded active plugged   /sys/devices/pci0000:00/0000:00:04.0/virtio1/block/vda
sys-devices-pci0000:00-0000:00:05.0-virtio2-net-eth0.device                 loaded active plugged   Virtio network device
sys-devices-platform-serial8250-tty-ttyS1.device                            loaded active plugged   /sys/devices/platform/serial8250/tty/ttyS1
sys-devices-platform-serial8250-tty-ttyS2.device                            loaded active plugged   /sys/devices/platform/serial8250/tty/ttyS2

UNIT:项目的名称,包括各个 unit 的类别(看扩展名)。
LOAD:开机时 unit 的配置是否被加载。
ACTIVE:服务的运行主状态,active 表示“活着”,inactive 表示“死了”
SUB:服务的运行子状态,例如:running,表示服务不仅“活着”,还正在“忙碌”呢!
DESCRIPTION:描述信息

13.列出目录 /lib/systemd/system/ 下的所有 unit

[root@htlwk0001host ~]# systemctl list-unit-files;
UNIT FILE                                  STATE
proc-sys-fs-binfmt_misc.automount          static
-.mount                                    generated
dev-hugepages.mount                        static
dev-mqueue.mount                           static
proc-sys-fs-binfmt_misc.mount              static
sys-fs-fuse-connections.mount              static
sys-kernel-config.mount                    static
sys-kernel-debug.mount                     static
tmp.mount                                  disabled

在返回的列表里,显示每个配置文件的状态,一共有 4 种:

(1)enabled:已建立启动链接

(2)disabled:没建立启动链接

(3)static:该配置文件没有 [Install] 部分(无法执行),只能作为其他配置文件的依赖

(4)masked:该配置文件被禁止建立启动链接

从配置文件的状态无法看出,该 Unit 是否正在运行。这必须执行前面提到的 systemctl status 命令。

14.只看服务类型的 unit

[root@htlwk0001host ~]# systemctl list-units --type=service
UNIT                               LOAD   ACTIVE SUB     DESCRIPTION
aegis.service                      loaded active running LSB: aegis update.
aliyun.service                     loaded active running 阿里云助手
AssistDaemon.service               loaded active running AssistDaemon
atd.service                        loaded active running Job spooling tools
auditd.service                     loaded active running Security Auditing Service

15.查看加载失败的 unit

[root@htlwk0001host ~]# systemctl --failed
0 loaded units listed. Pass --all to see loaded but inactive units, too.
To show all installed unit files use 'systemctl list-unit-files'.

16.管理系统的操作环境(target unit)

通过指定 --type=target 就可以用 systemctl list-units 命令查看系统中默认有多少种 target:

[root@htlwk0001host ~]# systemctl list-units --type=target -allUNIT                      LOAD      ACTIVE   SUB    DESCRIPTION                  basic.target              loaded    active   active Basic System                 cloud-config.target       loaded    active   active Cloud-config availability    cloud-init.target         loaded    active   active Cloud-init target            cryptsetup.target         loaded    active   active Local Encrypted Volumes      emergency.target          loaded    inactive dead   Emergency Mode               getty-pre.target          loaded    inactive dead   Login Prompts (Pre)          getty.target              loaded    active   active Login Prompts                graphical.target          loaded    inactive dead   Graphical Interface          initrd-fs.target          loaded    inactive dead   Initrd File Systems          initrd-root-device.target loaded    inactive dead   Initrd Root Device           initrd-root-fs.target     loaded    inactive dead   Initrd Root File System      initrd-switch-root.target loaded    inactive dead   Switch Root                  initrd.target             loaded    inactive dead   Initrd Default Target        local-fs-pre.target       loaded    active   active Local File Systems (Pre)     local-fs.target           loaded    active   active Local File Systems           multi-user.target         loaded    active   active Multi-User System            network-online.target     loaded    active   active Network is Online            network-pre.target        loaded    active   active Network (Pre)                network.target            loaded    active   active Network                      nss-lookup.target         loaded    active   active Host and Network Name Lookupsnss-user-lookup.target    loaded    active   active User and Group Name Lookups  paths.target              loaded    active   active Paths                        remote-fs-pre.target      loaded    inactive dead   Remote File Systems (Pre)    remote-fs.target          loaded    active   active Remote File Systems          rescue.target             loaded    inactive dead   Rescue Mode                  shutdown.target           loaded    inactive dead   Shutdown                     slices.target             loaded    active   active Slices                       sockets.target            loaded    active   active Sockets                      sshd-keygen.target        loaded    active   active sshd-keygen.target           swap.target               loaded    active   active Swap                         sysinit.target            loaded    active   active System Initialization        syslog.target             not-found inactive dead   syslog.target                time-sync.target          loaded    inactive dead   System Time Synchronized     timers.target             loaded    active   active Timers                       umount.target             loaded    inactive dead   Unmount All Filesystems      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.35 loaded units listed.
To show all installed unit files use 'systemctl list-unit-files'.

我的服务器主机居然有 34 个 target,在此仅介绍几个常用的 target:

  • graphical.target:就是文字界面再加上图形界面,这个 target 已经包含了下面的 multi-user.target
  • multi-user.target:纯文本模式
  • rescue.target:在无法使用 root 登陆的情况下,systemd 在开机时会多加一个额外的临时系统,与你原本的系统无关。这时你可以取得 root 的权限来维护你的系统
  • emergency.target:紧急处理系统的错误,在无法使用 rescue.target 时,可以尝试使用这种模式
  • shutdown.target:就是执行关机
  • getty.target:可以设置 tty 的配置

正常的模式是 multi-user.target 和 graphical.target 两个,救援方面的模式主要是 rescue.target 以及更严重的 emergency.target。如果要修改可提供登陆的 tty 数量,则修改 getty.target。

(1)查看系统目前的操作模式(target)

[root@htlwk0001host ~]# systemctl get-default;
multi-user.target

(2)设置系统默认的操作模式

[root@htlwk0001host ~]# systemctl set-default multi-user.target

(3)切换操作模式

可以在不重新启动的情况下切换不同的 target,比如从图形界面切换到纯文本的模式(即命令行模式):

[root@htlwk0001host ~]# systemctl isolate multi-user.target

切换到图形模式:

[root@htlwk0001host ~]# systemctl isolate runlevel5.target # 运行等级5

或者

[root@htlwk0001host ~]# systemctl isolate graphical.target

17.让系统进入暂停模式

[root@htlwk0001host ~]# systemctl suspend

暂停模式会将系统的状态保存到内存中,然后关闭掉大部分的系统硬件,当然,并没有实际关机。当用户按下唤醒机器的按钮,系统数据会从内存中回复,然后重新驱动被大部分关闭的硬件,所以唤醒系统的速度比较快。

18.让系统进入休眠模式

[root@htlwk0001host ~]# systemctl hibernate

休眠模式则是将系统状态保存到硬盘当中,保存完毕后,将计算机关机。当用户尝试唤醒系统时,系统会开始正常运行,然后将保存在硬盘中的系统状态恢复回来。因为数据需要从硬盘读取,因此唤醒的速度比较慢(如果你使用的是 SSD 磁盘,唤醒的速度也是非常快的)。

19.强制系统进入救援模式

[root@htlwk0001host ~]# systemctl rescue

20.强制系统进入紧急救援模式

[root@htlwk0001host ~]# systemctl emergency

22.重新加载 systemd 程序的配置文件

[root@htlwk0001host ~]# systemctl daemon-reload

(1)新添加 unit 配置文件时需要执行 systemctl daemon-reload
(2)有 unit 的配置文件发生变化时也需要执行 systemctl daemon-reload

daemon-reload 命令会做很多的事情,其中之一是重新生成依赖树(也就是 unit 之间的依赖关系),所以当你修改了 unit 配置文件中的依赖关系后如果不执行 daemon-reload 命令是不会生效的。

23.杀死服务

有时候使用子命令 stop 停止服务可能没有响应,服务停不下来。这时候就不得不"杀进程"了,向正在运行的进程发出kill信号。

[root@htlwk0001host ~]# systemctl kill mysqld.service

24.管理系统挂载点的命令

(1)挂载

[root@htlwk0001host ~]# systemctl start tmp.mount

(2)卸载

[root@htlwk0001host ~]# systemctl stop tmp.mount

(3)重新挂载

[root@htlwk0001host ~]# systemctl restart tmp.mount

(4)重新加载挂载点

[root@htlwk0001host ~]# systemctl reload tmp.mount

(5)查看挂载点状态

[root@htlwk0001host ~]# systemctl status tmp.mount

25.查看 systemd 的版本

[root@htlwk0001host ~]# systemctl --version
systemd 239
+PAM +AUDIT +SELINUX +IMA -APPARMOR +SMACK +SYSVINIT +UTMP +LIBCRYPTSETUP +GCRYPT +GNUTLS +ACL +XZ +LZ4 +SECCOMP +BLKID +ELFUTILS +KMOD +IDN2 -IDN +PCRE2 default-hierarchy=legacy

26.查看系统启动耗时

[root@htlwk0001host ~]# systemd-analyze
Startup finished in 659ms (kernel) + 5.114s (initrd) + 10.495s (userspace) = 16.269s
multi-user.target reached after 9.540s in userspace

27.查看每个进程在引导时花费的时间

查看每个服务的启动耗时:

[root@htlwk0001host ~]# systemd-analyze blame5.405s cloud-init-local.service2.875s cloud-init.service2.631s sshd-keygen@rsa.service1.707s dracut-pre-pivot.service1.501s mysqld.service1.095s aegis.service954ms systemd-logind.service

28.查看指定服务的关键链

显示指定服务的瀑布状的启动过程流:

[root@htlwk0001host ~]# systemd-analyze critical-chain httpd.service
The time after the unit is active or started is printed after the "@" character.
The time the unit takes to start is printed after the "+" character.
httpd.service +142ms
└─network.target @11.168s
└─network.service @9.456s +1.712s
└─NetworkManager.service @8.858s +596ms
└─firewalld.service @4.931s +3.926s
└─basic.target @4.916s
└─sockets.target @4.916s
└─dbus.socket @4.916s
└─sysinit.target @4.905s
└─systemd-update-utmp.service @4.864s +39ms
└─auditd.service @4.563s +301ms
└─systemd-tmpfiles-setup.service @4.485s +69ms
└─rhel-import-state.service @4.342s +142ms
└─local-fs.target @4.324s
└─boot.mount @4.286s +31ms
└─systemd-fsck@dev-disk-by\x2duuid-79f594ad\x2da332\x2d4730\x2dbb5f\x2d85d196080964.service @4.092s +149ms
└─dev-disk-by\x2duuid-79f594ad\x2da332\x2d4730\x2dbb5f\x2d85d196080964.device @4.092s

显示瀑布状的启动过程流:

[root@htlwk0001host ~]# systemd-analyze critical-chain

29.获取服务的依赖项列表

[root@htlwk0001host ~]# systemctl list-dependencies httpd.service
httpd.service
├─system.slice
└─basic.target
├─firewalld.service
├─microcode.service
├─rhel-autorelabel-mark.service
├─rhel-autorelabel.service
├─rhel-configure.service
├─rhel-dmesg.service
├─rhel-loadmodules.service
├─paths.target
├─slices.target
│ ├─-.slice
│ └─system.slice
├─sockets.target
│ ├─dbus.socket
....

30.按层次列出控制组

[root@htlwk0001host ~]# systemd-cgls
├─1 /usr/lib/systemd/systemd --switched-root --system --deserialize 23
├─user.slice
│ └─user-0.slice
│   └─session-1.scope
│     ├─2498 sshd: root@pts/0
│     ├─2500 -bash
│     ├─4521 systemd-cgls
│     └─4522 systemd-cgls
└─system.slice
├─httpd.service
│ ├─4440 /usr/sbin/httpd -DFOREGROUND
│ ├─4442 /usr/sbin/httpd -DFOREGROUND
│ ├─4443 /usr/sbin/httpd -DFOREGROUND
│ ├─4444 /usr/sbin/httpd -DFOREGROUND
│ ├─4445 /usr/sbin/httpd -DFOREGROUND
│ └─4446 /usr/sbin/httpd -DFOREGROUND
├─polkit.service
│ └─721 /usr/lib/polkit-1/polkitd --no-debug
....

31.根据CPU,内存,输入和输出列出控制组

[root@htlwk0001host ~]# systemd-cgtop
Path                                                              Tasks   %CPU   Memory  Input/s Output/s
/                                                                    83    1.0   437.8M        -        -
/system.slice                                                         -    0.1        -        -        -
/system.slice/mariadb.service                                         2    0.1        -        -        -
/system.slice/tuned.service                                           1    0.0        -        -        -
/system.slice/httpd.service                                           6    0.0        -        -        -
/system.slice/NetworkManager.service                                  1      -        -        -        -
/system.slice/atop.service                                            1      -        -        -        -
/system.slice/atopacct.service                                        1      -        -        -        -
/system.slice/auditd.service                                          1      -        -        -        -
/system.slice/crond.service                                           1      -        -        -        -
/system.slice/dbus.service                                            1      -        -        -        -
/system.slice/firewalld.service                                       1      -        -        -        -
/system.slice/lvm2-lvmetad.service                                    1      -        -        -        -
/system.slice/polkit.service                                          1      -        -        -        -
/system.slice/postfix.service                                         3      -        -        -        -
/system.slice/rsyslog.service                                         1      -        -        -        -
/system.slice/system-getty.slice/getty@tty1.service                   1      -        -        -        -
/system.slice/systemd-journald.service                                1      -        -        -        -
/system.slice/systemd-logind.service                                  1      -        -        -        -
/system.slice/systemd-udevd.service                                   1      -        -        -        -
/system.slice/webmin.service                                          1      -        -        -        -
/user.slice/user-0.slice/session-1.scope                              3      -        -        -        -

32.查看指定类型的 unit

[root@htlwk0001host ~]# systemctl -t target
UNIT                   LOAD   ACTIVE SUB    DESCRIPTION
basic.target           loaded active active Basic System
cloud-config.target    loaded active active Cloud-config availability
cloud-init.target      loaded active active Cloud-init target
cryptsetup.target      loaded active active Local Encrypted Volumes
getty.target           loaded active active Login Prompts
local-fs-pre.target    loaded active active Local File Systems (Pre)
local-fs.target        loaded active active Local File Systems
multi-user.target      loaded active active Multi-User System
network-online.target  loaded active active Network is Online
network-pre.target     loaded active active Network (Pre)
network.target         loaded active active Network
nss-lookup.target      loaded active active Host and Network Name Lookups
nss-user-lookup.target loaded active active User and Group Name Lookups
paths.target           loaded active active Paths
remote-fs.target       loaded active active Remote File Systems
slices.target          loaded active active Slices
sockets.target         loaded active active Sockets
sshd-keygen.target     loaded active active sshd-keygen.target
swap.target            loaded active active Swap
sysinit.target         loaded active active System Initialization
timers.target          loaded active active Timers                       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.21 loaded units listed. Pass --all to see loaded but inactive units, too.
To show all installed unit files use 'systemctl list-unit-files'.
[root@htlwk0001host ~]# systemctl --type target
UNIT                   LOAD   ACTIVE SUB    DESCRIPTION
basic.target           loaded active active Basic System
cloud-config.target    loaded active active Cloud-config availability
cloud-init.target      loaded active active Cloud-init target
cryptsetup.target      loaded active active Local Encrypted Volumes
getty.target           loaded active active Login Prompts
local-fs-pre.target    loaded active active Local File Systems (Pre)
local-fs.target        loaded active active Local File Systems
multi-user.target      loaded active active Multi-User System
network-online.target  loaded active active Network is Online
network-pre.target     loaded active active Network (Pre)
network.target         loaded active active Network
nss-lookup.target      loaded active active Host and Network Name Lookups
nss-user-lookup.target loaded active active User and Group Name Lookups
paths.target           loaded active active Paths
remote-fs.target       loaded active active Remote File Systems
slices.target          loaded active active Slices
sockets.target         loaded active active Sockets
sshd-keygen.target     loaded active active sshd-keygen.target
swap.target            loaded active active Swap
sysinit.target         loaded active active System Initialization
timers.target          loaded active active Timers                       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.21 loaded units listed. Pass --all to see loaded but inactive units
[root@htlwk0001host ~]# systemctl --type=target
UNIT                   LOAD   ACTIVE SUB    DESCRIPTION
basic.target           loaded active active Basic System
cloud-config.target    loaded active active Cloud-config availability
cloud-init.target      loaded active active Cloud-init target
cryptsetup.target      loaded active active Local Encrypted Volumes
getty.target           loaded active active Login Prompts
local-fs-pre.target    loaded active active Local File Systems (Pre)
local-fs.target        loaded active active Local File Systems
multi-user.target      loaded active active Multi-User System
network-online.target  loaded active active Network is Online
network-pre.target     loaded active active Network (Pre)
network.target         loaded active active Network
nss-lookup.target      loaded active active Host and Network Name Lookups
nss-user-lookup.target loaded active active User and Group Name Lookups
paths.target           loaded active active Paths
remote-fs.target       loaded active active Remote File Systems
slices.target          loaded active active Slices
sockets.target         loaded active active Sockets
sshd-keygen.target     loaded active active sshd-keygen.target
swap.target            loaded active active Swap
sysinit.target         loaded active active System Initialization
timers.target          loaded active active Timers                       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.21 loaded units listed. Pass --all to see loaded but inactive units, too.
To show all installed unit files use 'systemctl list-unit-files'.

33.列出所有没有运行的 Unit

$ systemctl list-units --all --state=inactive

34.查看系统状态

[root@htlwk0001host ~]# systemctl status
● htlwk0001hostState: runningJobs: 0 queuedFailed: 0 unitsSince: Sun 2020-08-23 18:02:02 CST; 8 months 10 days agoCGroup: /├─user.slice│ └─user-0.slice│   ├─session-10.scope│   │ ├─ 26556 nginx: master process nginx│   │ ├─414774 nginx: worker process│   │ └─414775 nginx: worker process│   ├─session-575.scope│   │ ├─1111169 sshd: root [priv]│   │ ├─1111171 sshd: root@pts/0

35.显示远程主机的某个 Unit 的状态

$ systemctl -H root@rhel7.example.com status httpd.service

36.显示某个 Unit 是否处于启动失败状态

$ systemctl is-failed application.service

37.重载所有修改过的配置文件

$ sudo systemctl daemon-reload

38.显示某个 Unit 的指定属性的值

$ systemctl show -p CPUShares httpd.service

39.设置某个 Unit 的指定属性

$ sudo systemctl set-property httpd.service CPUShares=500

40.电源管理命令

安装 polkit 后才可使用电源管理。

命令 说明
systemctl reboot 重启机器
systemctl poweroff 关机
systemctl suspend 待机
systemctl hibernate 休眠
systemctl hybrid-sleep 混合休眠模式(同时休眠到硬盘并待机)

关机不是每个登录用户在任何情况下都可以执行的,一般只有管理员才可以关机。正常情况下系统不应该允许 SSH 远程登录的用户执行关机命令。否则其他用户正在工作,一个用户把系统关了就不好了。为了解决这个问题,传统的 Linux 系统使用 ConsoleKit 跟踪用户登录情况,并决定是否赋予其关机的权限。现在 ConsoleKit 已经被 systemd 的 logind 所替代。

logind 不是 pid-1 的 init 进程。它的作用和 UpStart 的 session init 类似,但功能要丰富很多,它能够管理几乎所有用户会话(session)相关的事情。logind 不仅是 ConsoleKit 的替代,它可以:

(1)维护,跟踪会话和用户登录情况。如上所述,为了决定关机命令是否可行,系统需要了解当前用户登录情况,如果用户从 SSH 登录,不允许其执行关机命令;如果普通用户从本地登录,且该用户是系统中的唯一会话,则允许其执行关机命令;这些判断都需要 logind 维护所有的用户会话和登录情况。

(2)Logind 也负责统计用户会话是否长时间没有操作,可以执行休眠/关机等相应操作。

(3)为用户会话的所有进程创建 CGroup。这不仅方便统计所有用户会话的相关进程,也可以实现会话级别的系统资源控制。

(4)负责电源管理的组合键处理,比如用户按下电源键,将系统切换至睡眠状态。

(5)多席位(multi-seat) 管理。如今的电脑,即便一台笔记本电脑,也完全可以提供多人同时使用的计算能力。多席位就是一台电脑主机管理多个外设,比如两个屏幕和两个鼠标/键盘。席位一使用屏幕 1 和键盘 1;席位二使用屏幕 2 和键盘 2,但他们都共享一台主机。用户会话可以自由在多个席位之间切换。或者当插入新的键盘,屏幕等物理外设时,自动启动 gdm 用户登录界面等。所有这些都是多席位管理的内容。ConsoleKit 始终没有实现这个功能,systemd 的 logind 能够支持多席位。

小贴士:

  1. 在 systemctl 参数中添加 -H <用户名>@<主机名> 可以实现对其他机器的远程控制。该过程使用ssh链接。
  2. systemadm 是 systemd 的官方图形前端

Linux 系统服务管理器(初始化系统/init system) -- systemd 及命令 systemctl 的详细介绍相关推荐

  1. Linux 系统服务管理和控制程序(初始化系统/Init System) -- systemd 介绍

    文章目录 systemd 简介 systemd 启动过程概述 Systemd的争议 systemd 简介 开发systemd的主要目的就是减少系统引导时间和计算开销.systemd(系统管理守护进程) ...

  2. Linux 及其它类 Unix 系统的系统服务管理和控制程序(初始化系统/init system)简单梳理

    文章目录 一.Linux 的启动过程 二.初始化程序 (一)System V init (二)Upstart init (三)systemd (四)Launchd (五)Epoch (六)Mudar ...

  3. 系统服务管理与控制程序(Init System/初始化系统)-- Systemd 的 Unit 配置文件详解

    文章目录 一.Service 的配置文件 (一)[Unit] 区块 (二)[Service] 区块 1.启动命令 2.启动类型 3.重启行为 (三)[Install] 区块 二.Target 的配置文 ...

  4. Linux 系统服务管理(启动服务/停止服务/重启服务)的命令 - chkconfig/service/systemctl

    文章目录 一.使用命令 chkconfig 管理系统服务 (一)命令介绍 二.使用命令 service 管理系统服务 (一)命令介绍 (二)命令用法 1.启动服务 2.停止服务 3.重启服务 4.查看 ...

  5. Linux系统服务管理

    Linux系统服务管理 ********************************** 目 录 ********************************** Linux系统服务及其分类 ...

  6. 8种最好的Linux密码管理器

    推荐8种最好的Linux密码管理器,可以安全地存储你的登录信息. ·Fiagaro's Password Manager ·Gpass ·Gpassword Manager ·Gringotts ·K ...

  7. 【Linux基础】Linux软件包管理器yum的使用指南rzsz安装

    [Linux基础]Linux软件包管理器yum的使用指南|rzsz安装 前言 主页: 潮.eth的博客_CSDN博客-C学习,C++学习,数据结构and算法领域博主 Linux基础专栏: Linux基 ...

  8. linux远程管理器 - xshell和xftp使用教程(zhuan)

    linux远程管理器 - xshell和xftp使用教程(zhuan) 准备好连接linux服务器的工具,推荐用xshell和xftp. xshell 是一个强大的安全终端模拟软件,它支持SSH1, ...

  9. Linux包管理器apt/apt-get发现远程代码执行漏洞

    研究人员Max Justicz日前发现了知名Linux包管理器apt/apt-get中的远程代码执行漏洞,该漏洞允许外部进行中间人攻击并获取root权限以执行任何代码.该漏洞已在最新版本apt修复,如 ...

最新文章

  1. 快速入门 Nginx,这篇就够了!
  2. 【POJ - 2318】TOYS(计算几何,叉积判断点与直线位置关系,二分)
  3. Tornado框架的初步使用
  4. php刷数据库数据库,php数据库操作种
  5. linux下安装redis-cli
  6. 对 cloudwu 简单的 cstring 进行简单解析
  7. 软件工程造价师和软件造价评估师有什么区别?
  8. Web3D软件WebMax正式版发布
  9. 暨南大学计算机系录取分数线,暨南大学2017年在广东省各专业录取分数线
  10. win7电脑麦克风有电流声怎么办
  11. 【Linux】一步一步学Linux系列教程汇总(更新中......)
  12. BIM为绿色建筑提供数据技术支持,Revit软件及插件提供BIM效率
  13. Android recyclerview item获焦时更新UI导致列表自动滚动到获焦处
  14. cs1.6服务器修改弹道,CS1.6 比赛弹道能不能改?
  15. David I 盛大之行 --关于delphi2010
  16. HEAD, ORIG_HEAD, FETCH_HEAD, MERGE_HEAD标志
  17. 基于matlab的眼底视网膜静脉血管分割仿真
  18. 导入MVVMLight出现错误 ViewModelLocator does not exist in the namespace clr-namespace:WpfApp1.ViewModel
  19. wamp php不可用_使用wamp扩展php时出现服务未启动的解决方法
  20. matlab的自定义常数是a,Simulink仿真入门到精通(二) Simulink模块

热门文章

  1. c++ 嵌套私有类_嵌套类和私有方法
  2. java 方法 示例_Java 9示例–收集的工厂方法–创建不可修改的列表,集合和映射...
  3. java 使用本机代理_Java与本机代理–他们所做的强大功能
  4. 分布式事务 camel_使用Camel在Amazon上构建分布式工作流应用程序
  5. Java程序员应在2018年学习的3种JVM语言
  6. 正则表达式 guava_带有正则表达式模式的Google Guava Cache
  7. Apache Kafka简介
  8. moxy json介绍_MOXy的对象图和动态JAXB
  9. 在Hibernate中启用实体和查询缓存
  10. 多线程编程反模式_编程反模式