Linux Systemd 详细介绍: Unit、Unit File、Systemctl、Target

Systemd

简介

CentOS 7 使用 Systemd 替换了SysV

Ubuntu 从 15.04 开始使用 Systemd

Systemd 是 Linux 系统工具,用来启动守护进程,已成为大多数发行版的标准配置

特点

优点:

  1. 按需启动进程,减少系统资源消耗

  2. 并行启动进程,提高系统启动速度

    在 SysV-init 时代,将每个服务项目编号,依次执行启动脚本。Ubuntu 的 Upstart 解决了没有直接依赖的启动之间的并行启动。而 Systemd 通过 Socket 缓存、DBus 缓存和建立临时挂载点等方法进一步解决了启动进程之间的依赖,做到了所有系统服务并发启动。对于用户自定义的服务,Systemd 允许配置其启动依赖项目,从而确保服务按必要的顺序运行。

    SystemV Upstart 参考上一篇博文:Linux 初始化系统 SystemV Upstart

  3. 使用 CGroup 监视和管理进程的生命周期

    CGroup 提供了类似文件系统的接口,当进程创建子进程时,子进程会继承父进程的 CGroup。因此无论服务如何启动新的子进程,所有的这些相关进程都会属于同一个 CGroup

    在 Systemd 之前的主流应用管理服务都是使用 进程树 来跟踪应用的继承关系的,而进程的父子关系很容易通过 两次 fork 的方法脱离。

    而 Systemd 则提供通过 CGroup 跟踪进程关系,引补了这个缺漏。通过 CGroup 不仅能够实现服务之间访问隔离,限制特定应用程序对系统资源的访问配额,还能更精确地管理服务的生命周期

  4. 统一管理服务日志

  5. 支持快照和系统恢复

缺点:

  1. 过于复杂,与操作系统的其他部分强耦合,违反"keep simple, keep stupid"的Unix 哲学

架构图

Linux Systemd 详细介绍: Unit、Unit File、Systemctl、Target_第1张图片

Unit(单元|服务)

Systemd 可以管理所有系统资源:

  1. 将系统资源划分为12类
  2. 将每个系统资源称为一个 Unit。Unit 是 Systemd 管理系统资源的基本单位
  3. 使用一个 Unit File 作为 Unit 的单元文件,Systemd 通过单元文件控制 Unit 的启动

例如,MySQL服务被 Systemd 视为一个 Unit,使用一个 mysql.service 作为启动配置文件

Unit File(单元文件|配置文件)

单元文件中包含该单元的描述、属性、启动命令等

类型

Systemd 将系统资源划分为12类,对应12种类型的单元文件

系统资源类型 单元文件扩展名 单元文件描述
Service .service 封装守护进程的启动、停止、重启和重载操作,是最常见的一种 Unit 文件
Target .target 定义 target 信息及依赖关系,一般仅包含 Unit 段
Device .device 对于 /dev 目录下的硬件设备,主要用于定义设备之间的依赖关系
Mount .mount 定义文件系统的挂载点,可以替代过去的 /etc/fstab 配置文件
Automount .automount 用于控制自动挂载文件系统,相当于 SysV-init 的 autofs 服务
Path .path 用于监控指定目录或文件的变化,并触发其它 Unit 运行
Scope .scope 这种 Unit 文件不是用户创建的,而是 Systemd 运行时产生的,描述一些系统服务的分组信息
Slice .slice 用于表示一个 CGroup 的树
Snapshot .snapshot 用于表示一个由 systemctl snapshot 命令创建的 Systemd Units 运行状态快照,可以切回某个快照
Socket .socket 监控来自于系统或网络的数据消息
Swap .swap 定义一个用户做虚拟内存的交换分区
Timer .timer 用于配置在特定时间触发的任务,替代了 Crontab 的功能

对于操作单元文件的命令,如果缺省扩展名,则默认.service扩展名

而操作 target 的命令,例如 isolate,则默认.target扩展名

语法

单元文件的语法来源于 XDG桌面入口配置文件.desktop文件

Unit 文件可以分为三个配置区段:

  • Unit 段:所有 Unit 文件通用,用来定义 Unit 的元数据,以及配置与其他 Unit 的关系
  • Install 段:所有 Unit 文件通用,用来定义如何启动,以及是否开机启动
  • Service 段:服务(Service)类型的 Unit 文件(后缀为 .service)特有的,用于定义服务的具体管理和执行动作

单元文件中的区段名和字段名大小写敏感

每个区段内都是一些等号连接的键值对(键值对的等号两侧不能有空格)

Unit 段

主要字段如下:

  • Description:当前服务的简单描述

  • Documentation:文档地址,可以是一个或多个文档的 URL 路径

    【依赖关系】

  • Requires:与其它 Unit 的强依赖关系,如果其中任意一个 Unit 启动失败或异常退出,当前 Unit 也会被退出

  • Wants:与其它 Unit 的弱依赖关系,如果其中任意一个 Unit 启动失败或异常退出,不影响当前 Unit 继续执行

    只涉及依赖关系,默认情况下 两个 Unit 同时启动

    【启动顺序】

  • After:该字段指定的 Unit 全部启动完成以后,才会启动当前 Unit

  • Before:该字段指定的 Unit 必须在当前 Unit 启动完成之后再启动

    只涉及启动顺序,不影响启动结果和运行情况

  • Binds To:与 Requires 相似,该字段指定的 Unit 如果退出,会导致当前 Unit 停止运行

  • Part Of:一个 Bind To 作用的子集,仅在列出的 Unit 失败或重启时,终止或重启当前 Unit,而不会随列出Unit 的启动而启动

http://manpages.ubuntu.com/manpages/bionic/en/man5/systemd.unit.5.html

Install 段

主要字段如下:

  • WantedBy:它的值是一个或多个 target,执行enable命令时,符号链接会放入/etc/systemd/system目录下以 target 名 + .wants后缀构成的子目录中
  • RequiredBy:它的值是一个或多个 target,执行enable命令时,符号链接会放入/etc/systemd/system目录下以 target 名 + .required后缀构成的子目录中
  • Alias:当前 Unit 可用于启动的别名
  • Also:当前 Unit 被 enable/disable 时,会被同时操作的其他 Unit

http://manpages.ubuntu.com/manpages/bionic/en/man5/systemd.unit.5.html

Service 段

主要字段如下:

【启动类型】

  • Type:定义启动时的进程行为。它有以下几种值。
    • Type=simple:默认值,ExecStart字段启动的进程为主进程
      • 服务进程不会 fork,如果该服务要启动其他服务,不要使用此类型启动,除非该服务是 socket 激活型
    • Type=forkingExecStart字段将以fork()方式从父进程创建子进程启动,创建后父进程会立即退出,子进程成为主进程。
      • 通常需要指定PIDFile字段,以便 Systemd 能够跟踪服务的主进程
      • 对于常规的守护进程(daemon),除非你确定此启动方式无法满足需求,使用此类型启动即可
    • Type=oneshot:只执行一次,Systemd 会等当前服务退出,再继续往下执行
      • 适用于只执行一项任务、随后立即退出的服务
      • 通常需要指定RemainAfterExit=yes字段,使得 Systemd 在服务进程退出之后仍然认为服务处于激活状态
    • Type=dbus:当前服务通过 D-Bus 信号启动。当指定的 BusName 出现在 DBus 系统总线上时,Systemd认为服务就绪
    • Type=notify:当前服务启动完毕会发出通知信号,通知 Systemd,然后 Systemd 再启动其他服务
    • Type=idle:Systemd 会等到其他任务都执行完,才会启动该服务。
      • 一种使用场合是:让该服务的输出,不与其他服务的输出相混合

【启动行为】

  • ExecStart:启动当前服务的命令

    ExecStart=/bin/echo execstart1
    ExecStart=
    ExecStart=/bin/echo execstart2
    

    顺序执行设定的命令,把字段置空,表示清除之前的值

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

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

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

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

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

  • RemainAfterExit:当前服务的所有进程都退出的时候,Systemd 仍认为该服务是激活状态

    • 这个配置主要是提供给一些并非常驻内存,而是启动注册后立即退出,然后等待消息按需启动的特殊类型服务使用的
  • TimeoutSec:定义 Systemd 停止当前服务之前等待的秒数

    注:所有的启动设置之前,都可以加上一个连词号(-),表示"抑制错误",即发生错误的时候,不影响其他命令的执行。比如,EnvironmentFile=-/etc/sysconfig/sshd(注意等号后面的那个连词号),就表示即使/etc/sysconfig/sshd文件不存在,也不会抛出错误。

【重启行为】

  • RestartSec:Systemd 重启当前服务间隔的秒数
  • KillMode:定义 Systemd 如何停止服务,可能的值包括:
    • control-group(默认值):当前控制组里面的所有子进程,都会被杀掉
    • process:只杀主进程(sshd 服务,推荐值)
    • mixed:主进程将收到 SIGTERM 信号,子进程收到 SIGKILL 信号
    • none:没有进程会被杀掉,只是执行服务的 stop 命令。
  • Restart:定义何种情况 Systemd 会自动重启当前服务,可能的值包括:
    • no(默认值):退出后不会重启
    • on-success:只有正常退出时(退出状态码为0),才会重启
    • on-failure:非正常退出时(退出状态码非0),包括被信号终止和超时,才会重启(守护进程,推荐值)
    • on-abnormal:只有被信号终止和超时,才会重启(对于允许发生错误退出的服务,推荐值)
    • on-abort:只有在收到没有捕捉到的信号终止时,才会重启
    • on-watchdog:超时退出,才会重启
    • always:不管是什么退出原因,总是重启

【上下文】

  • PIDFile:指向当前服务 PID file 的绝对路径。

  • User:指定运行服务的用户

  • Group:指定运行服务的用户组

  • EnvironmentFile:指定当前服务的环境参数文件。该文件内部的key=value键值对,可以用$key的形式,在当前配置文件中获取

    启动sshd,执行的命令是/usr/sbin/sshd -D $OPTIONS,其中的变量$OPTIONS就来自EnvironmentFile字段指定的环境参数文件。

http://manpages.ubuntu.com/manpages/bionic/en/man5/systemd.service.5.html

占位符

在 Unit 文件中,有时会需要使用到一些与运行环境有关的信息,例如节点 ID、运行服务的用户等。这些信息可以使用占位符来表示,然后在实际运行中动态地替换为实际的值。

详细了解见 https://cloud.tencent.com/developer/article/1516125

模板

在现实中,往往有一些应用需要被复制多份运行,就会用到模板文件

模板文件的写法与普通单元文件基本相同,只是模板文件名是以 @ 符号结尾。例如:[email protected]

通过模板文件启动服务实例时,需要在其文件名的 @ 字符后面附加一个用于区分服务实例的参数字符串,通常这个参数是用于监控的端口号或控制台 TTY 编译号

systemctl start [email protected]

Systemd 在运行服务时,首先寻找跟单元名完全匹配的单元文件,如果没有找到,才会尝试选择匹配模板

例如上面的命令,System 首先会在约定的目录下寻找名为 [email protected] 的单元文件,如果没有找到,而文件名中包含 @ 字符,它就会尝试去掉后缀参数匹配模板文件。对于 [email protected],Systemd 会找到 [email protected] 模板文件,并通过这个模板文件将服务实例化。

详细了解见 https://cloud.tencent.com/developer/article/1516125

状态

systemctl list-unit-files 将会列出文件的 state,包括 static, enabled, disabled, masked, indirect

  • masked

    service软链接到/dev/null

    该单元文件被禁止建立启动链接

  • static

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

  • enabled

    已建立启动链接

  • disabled

    没建立启动链接

https://askubuntu.com/a/731674

示例

  1. 关掉触摸板配置文件

    Unit]
    Description=Switch-off Touchpad
    
    [Service]
    Type=oneshot
    ExecStart=/usr/bin/touchpad-off start
    ExecStop=/usr/bin/touchpad-off stop
    RemainAfterExit=yes
    
    [Install]
    WantedBy=multi-user.target
    
    • oneshot 表明这个服务只要运行一次就够了,不需要长期运行
    • RemainAfterExit字段设为yes,表示进程退出以后,服务仍然保持执行。这样的话,一旦使用systemctl stop命令停止服务,ExecStop指定的命令就会执行,从而重新开启触摸板

Systemd 内建命令

systemd-analyze

Analyze and debug system manager, If no command is passed, Systemd-analyze time is implied

https://www.freedesktop.org/software/systemd/man/systemd-analyze.html

systemd-analyze time

查看初始化耗时

systemd-analyze blame

打印所有运行单元,按它们初始化的时间排序。此信息可用于优化启动时间。注意,输出可能具有误导性,因为一个服务的初始化可能非常缓慢,因为它等待另一个服务的初始化完成

systemd-run

将一个指定的服务变成后台服务

未测试

参考 https://www.freedesktop.org/software/systemd/man/systemd-run.html

systemctl 系统服务管理命令

systemctl是 Systemd 的主命令,用于管理系统

与 service 命令的区别

  1. systemctl 融合了 service 和 chkconfig 的功能
  2. 在 Ubuntu18.04 中没有自带 chkconfig 命令;service 命令实际上重定向到 systemctl 命令
动作 SysV Init 指令 Systemd 指令
启动某服务 service httpd start systemctl start httpd
停止某服务 service httpd stop systemctl stop httpd
重启某服务 service httpd restart systemctl restart httpd
检查服务状态 service httpd status systemctl status httpd
删除某服务 chkconfig --del httpd 停掉应用,删除其配置文件
使服务开机自启动 chkconfig --level 5 httpd on systemctl enable httpd
使服务开机不自启动 chkconfig --level 5 httpd off systemctl disable httpd
查询服务是否开机自启 chkconfig --list | grep httpd systemctl is-enabled httpd
加入自定义服务 chkconfig --add test systemctl load test
显示所有已启动的服务 chkconfig --list systemctl list-unit-files | grep enabled

参数

--all

显示加载到内存的所有单元

--type

-t --type=

显示指定类型(12种类型)的单元

--state

--state=

显示指定状态的单元或单元文件

  • 单元状态

    输入 systemctl list-units --stateTab键,显示所有可用的值

  • 单元文件状态

    另外还可以用 enabled static disabled 等systemctl list-unit-files 显示的状态

--failed

--state=failed

显示加载失败的单元

 systemctl --failed
--version

打印 Systemd 版本

lfp@legion:/lib/systemd/system$ systemctl --version
Systemd 237
+PAM +AUDIT +SELINUX +IMA +APPARMOR +SMACK +SYSVINIT +UTMP +LIBCRYPTSETUP +GCRYPT +GNUTLS +ACL +XZ +LZ4 +SECCOMP +BLKID +ELFUTILS +KMOD -IDN2 +IDN -PCRE2 default-hierarchy=hybrid

单元命令

我的理解

  • systemd 对单元的管理,不涉及单元文件自身属性和内容
list-units

相当于systemctl

列出当前已加载的单元(内存)

默认情况下仅显示处于激活状态(正在运行)的单元

UNIT 单元名

LOAD 加载状态

ACTIVE SUB 执行状态(大状态 子状态)

DESCRIPTION 描述

start

启动单元

systemctl start mysql.service
stop

停止单元

systemctl stop mysql.service
kill

杀掉单元进程

systemctl kill mysql.service
reload

不终止单元,重新加载 针对该单元的 运行配置文件,而不是 针对 systemd的 该单元的启动配置文件

例如启动 MySQL 服务,reload 可以在不停止服务的情况下重载 MySQL 的配置文件 my.cnf

restart

重启单元

该单元在重启之前拥有的资源不会被完全清空,比如文件描述符存储设施

systemctl reload mysql.service
status

status [unit | PID]

显示单元或进程所属单元的运行信息

systemctl status mysql.service

Loaded行:配置文件的位置,是否设为开机启动

Active行:表示正在运行

Main PID行:主进程ID

CGroup块:应用的所有子进程

日志块:应用的日志

is-active

判断指定的单元是否处于激活状态

# 默认会打印当前单元的状态,可以通过 --quiet 参数取消打印
lfp@legion:~$ systemctl is-active mysql
active
is-failed

判断指定的单元是否处于启动失败状态

lfp@legion:~$ systemctl is-failed mysql
active
list-dependencies

查看单元之间的依赖关系

systemctl list-dependencies graphical.target 
systemctl list-dependencies mysql.service
show

show --property= Unit <==> show -p Unit

显示单元所有底层参数

lfp@legion:~$ systemctl show -p MainPID mysql
MainPID=1061
set-property

在单元启动的时候设置运行时的某个属性,立即生效,并保存在磁盘中作为启动配置

如果添加了--runtime则重启后失效

并非所有的属性都可以设置,只是 systemd.resource-control 包含的属性

isolate

切换到某个 target(系统状态),立即停止该 target 未包含的单元进程。也可以理解为切换 runlevel

如果没有指定扩展名,则默认.target

只有当.target单元文件中的AllowIsolate=yes时,才能使用 isolate 切换;也可以用IgnoreOnIsolate=yes字段来拒绝使用 isolate 切换

systemctl isolate multi-user.target
cat

显示单元配置文件的备份文件,包括插入式配置drop-ins,可以完整的看到单元服务的配置。注意这里打印的依据是磁盘的上内容,如果用户修改了配置文件(磁盘已修改)但是未执行daemon-reload命令(内存中未更新),那么该命令显示的配置和实际执行情况有出入

lfp@legion:~$ systemctl cat mysql.service 
# /lib/systemd/system/mysql.service
# MySQL Systemd service file

[Unit]
Description=MySQL Community Server
...

[Install]
WantedBy=multi-user.target

[Service]
Type=forking
...
# 这段就显示的是 插入式配置 drop-in 的内容
# /etc/systemd/system/mysql.service.d/mysql.conf
# MySQL Systemd service file

[Unit]
# Description=MySQL Community Server conf

[Service]
# ExecStartPost=/home/lfp/bin/espeak.sh

单元文件命令

我的理解

  • systemd 对单元文件自身属性和内容的管理
list-unit-files

列出所有已安装的单元文件和它们的启用状态

list-units的区别是

  • list-units 仅显示当前已加载到内存中的单元
  • list-unit-files 会读取单元文件内容,列出所有单元,包括存在于硬盘未加载进内存的单元

实际测试结果:

systemctl list-unit-files 显示“348 Unit files listed”

systemctl list-units --all 显示“405 loaded units listed”

systemctl list-units 显示 “232 loaded units listed”

enable

使某个单元开机自启动

这会根据单元文件内容中的[Install]指定的 target 组,创建一个软链接

lfp@legion:/etc/systemd/system$ vim v2rayL.service
# 文件内容 [Install] 段
......
[Install]
WantedBy=multi-user.target
......

lfp@legion:/etc/systemd/system$ systemctl is-enabled v2rayL.service 
disabled
lfp@legion:/etc/systemd/system$ systemctl enable v2rayL.service 
# 根据 [Install] 段指定的组,添加软链接
Created symlink /etc/systemd/system/multi-user.target.wants/v2rayL.service → /etc/systemd/system/v2rayL.service.
lfp@legion:/etc/systemd/system$ systemctl is-enabled v2rayL.service 
enabled
disable

取消某个单元开机自启动设置,删除软链接

这会删除所有指向该单元文件的软链接,不仅仅是 enable 操作创建的

reenable

disable 和 enable 的结合,根据单元文件内容中的 [Install] 段,重置软链接

is-enabled

检查某个单元是否是开机自启动的(建立的启动链接)

lfp@legion:~$ systemctl is-enabled mysql
enabled
get-default

获取默认启动 target,default-target 是指向该 target 的软链接

set-default

设置默认启动 target,同时修改 default-target 指向设定的 target

systemctl set-default multi-user.target

生命周期管理命令

daemon-reload

重新加载所有的单元文件和依赖关系

对单元文件有修改的时候,需要执行该命令重新加载文件内容

系统管理命令

reboot
systemctl reboot

重启系统(异步操作)

it will return after the reboot operation is enqueued, without waiting for it to complete

poweroff

关闭系统,切断电源(异步操作)

halt

仅CPU停止工作,其他硬件仍处于开机状态(异步操作)

suspend

暂停系统(异步操作)

将触发执行suspend.target

hibernate

让系统进入冬眠状态(异步操作)

将触发执行hibernate.target

目录、文件

/run/systemd/system/

单元(服务)运行时生成的配置文件所在目录
/etc/systemd/system/

系统或用户自定义的配置文件,初始化过程中Systemd只执行/etc/systemd/system目录里面的配置文件

/lib/systemd/system/

软件安装时添加的配置文件,类似于 /etc/init.d/

对于支持 Systemd 的程序,安装的时候,会自动的在 /lib/systemd/system 目录添加一个配置文件

其他目录都是软链接

/etc/systemd/system/default.target

Systemd 执行的第一个单元文件,符号链接到默认启动 target 对应的 .target 单元文件

优先级

SysV 的启动脚本放在/etc/init.d目录下

Systemd 的单元文件放在/etc/systemd/system/lib/systemd/system目录下

当一个程序在3个目录下都存在启动方式时,优先级是/etc/systemd/system --> /lib/systemd/system --> /etc/init.d

lfp@legion:/etc/init.d$ ll
-rwxr-xr-x   1 root root  5650 5月  19 22:09 mysql*

lfp@legion:/etc/systemd/system$ ll
-rw-r--r--  1 root root  511 5月  20 01:42  mysql.service

lfp@legion:/lib/systemd/system$ ll
-rw-r--r--  1 root root   499 5月  20 01:20  mysql.service
  • /etc/systemd/system 里面的同名service会覆盖/lib/systemd/system 里面的

    注意查看文件信息,该同名文件不能是指向 /lib/systemd/system 的软链接

    软链接不会覆盖而会同步

  • 如果某个程序不存在Systemd 单元文件,那么会执行/etc/init.d里面的启动脚本

根据启动过程, /etc/systemd/system/multi-user.target.wants/ 目录下是很多指向 /lib/systemd/system/目录的软链接,所以两个目录下的单元文件会互相同步。

如果/etc/systemd/system//etc/systemd/system/multi-user.target.wants/ 同时存在单元文件,测试发现,不管是手动启动还是开机自启动,使用的都是 /etc/systemd/system/ 目录下的service单元文件

测试
执行/etc/init.d目录下的脚本

mysql 修改 mysql.servicemysql.service.bak 然后通过service mysql restart启动/etc/init.d/mysql脚本

下面是启动后的一些信息

Linux Systemd 详细介绍: Unit、Unit File、Systemctl、Target_第2张图片

注:在恢复mysql.service之前,需要先通过service mysql stop 利用/etc/init.d/mysql脚本中的stop结束上面的进程,否则一旦恢复,service mysql stop 执行的操作就不是 /etc/init.d/mysql脚本中的stop,无法结束上面的进程,出现命令无法正常执行的情况

结束上面的进程,恢复mysql.service,重新启动

/etc/systemd/system 覆盖测试

未修改前,查看MySQL的状态

lfp@legion:~$ service mysql status
● mysql.service - MySQL Community Server
	# 可以发现这里的 mysql.service 是在 /lib/systemd/system 下面
   Loaded: loaded (/lib/systemd/system/mysql.service; enabled; vendor preset: en
   Active: active (running) since Sat 2020-04-25 18:34:30 CST; 5h 33min ago
 Main PID: 988 (mysqld)
    Tasks: 28 (limit: 4915)
   CGroup: /system.slice/mysql.service
           └─988 /usr/sbin/mysqld --daemonize --pid-file=/run/mysqld/mysqld.pid

4月 25 18:34:30 legion Systemd[1]: Starting MySQL Community Server...
4月 25 18:34:30 legion Systemd[1]: Started MySQL Community Server.

将 /lib/systemd/system 下面的文件复制到 /etc/systemd/system/ 下面

sudo cp /lib/systemd/system/mysql.service /etc/systemd/system/

修改 mysql.service

sudo vim /etc/systemd/system/mysql.service

Linux Systemd 详细介绍: Unit、Unit File、Systemctl、Target_第3张图片

重启 mysql.service ,系统提示需要重新加载

lfp@legion:~$ systemctl restart mysql.service 
Warning: The Unit file, source configuration file or drop-ins of mysql.service changed on disk. 
Run 'systemctl daemon-reload' to reload units.
lfp@legion:~$ systemctl daemon-reload	#  重新加载
lfp@legion:~$ systemctl restart mysql.service # 重启
lfp@legion:~$ systemctl status mysql.service 
● mysql.service - MySQL Community Server hahahaha	# 发现这里是修改之后的,覆盖了 /lib/systemd/lib 中的
#                                 这里也可以看到加载路径
   Loaded: loaded (/etc/systemd/system/mysql.service; enabled; vendor preset: en
   Active: active (running) since Sun 【2020-04-26】 00:47:02 CST; 5s ago
  Process: 21590 ExecStart=/usr/sbin/mysqld --daemonize --pid-file=/run/mysqld/m
  Process: 21581 ExecStartPre=/usr/share/mysql/mysql-Systemd-start pre (code=exi
 Main PID: 21592 (mysqld)
    Tasks: 27 (limit: 4915)
   CGroup: /system.slice/mysql.service
           └─21592 /usr/sbin/mysqld --daemonize --pid-file=/run/mysqld/mysqld.pi

4月 26 00:47:02 legion Systemd[1]: Starting MySQL Community Server hahahaha...
4月 26 00:47:02 legion Systemd[1

Target

两个含义

  1. 系统的某个状态称为一个 target(类似于"状态点")

  2. 达到某个系统状态,所需的一个或多个资源(Unit)称为一个 target(一个 Unit 组)

    1. target是一个抽象的系统资源,不像MySQL有实体

    2. 如果一个target只包含一个Unit,那么该 target,没有对应的目录,指的就是这个 Unit

      例如 hibernate.target 只包含 systemd-hibernate.service一个Unit

      如果一个target包含多个Unit,那么该target,有对应的 xxx.target.wants 目录,指的是目录里面所有的Unit

      例如 multi-user.target 包含位于/etc/systemd/system/multi-user.target.wants目录下的多个 Unit

target也是一个 Target 类型的系统资源,有对应的单元文件 xxx.target

Systemd 使用 target 来划分和管理资源(Unit),启动(激活)某个 xxx.target 单元文件,通过执行该 target 包含的 Unit,使系统达到某种状态

对于状态点的理解:

例如,执行systemd suspend命令让系统暂停,会触发启动suspend.target,然后执行里面的systemd-suspend.service Unit,使系统达到一个暂停的状态

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

启动 target

runlevel是 SysV init 初始化系统中的概念,在Systemd初始化系统中使用的是 Target,他们之间的映射关系是

Runlevel Target 说明
0 poweroff.target 关闭系统
1 rescue.target 维护模式
2,3,4 multi-user.target 多用户,无图形系统(命令行界面)
5 graphical.target 多用户,图形化系统(图形用户界面)
6 reboot.target 重启系统

启动过程

  1. 读入 /boot 目录下的内核文件

  2. 内核文件加载完之后,开始执行第一个程序/sbin/init 初始化进程,由 Systemd 初始化系统引导,完成相关的初始化工作

  3. Systemd 执行default.target ,获知设定的启动 target

    实际上 default.target 是指向设定的启动 target 的软链接

  4. Systemd 执行启动 target 对应的单元文件。根据单元文件中定义的依赖关系,传递控制权,依次执行其他 target 单元文件,同时启动每个 target 包含的单元

    对于图形化界面,默认 target 是 graphical,Systemd 执行位于/lib/systemd/system/ 目录下的 graphical.target 单元文件,根据 target 单元文件中定义的依赖关系,依次启动其他 target 单元文件以及各个 target 包含的位于/etc/systemd/system/目录下的单元

    例如: graphical.target 的依赖关系是

    [Unit]
    Description=Graphical Interface
    Documentation=man:systemd.special(7)
    Requires=multi-user.target #
    Wants=display-manager.service #
    Conflicts=rescue.service rescue.target
    After=multi-user.target rescue.service rescue.target display-manager.service #
    AllowIsolate=yes
    

    因此,依次启动 multi-user.target --> basic.target --> sysinit.target --> local-fs.target -->local-fs-pre.target --> ...

    同时启动每个 target 包含的位于/etc/systemd/system/目录下的Unit

    SysV对应的 rc5.d --> /etc/init.d 目录下的指定的脚本就不会在开机的时候执行了

查看默认 target

systemctl get-default

lfp@legion:~$ runlevel
N 5
lfp@legion:~$ systemctl get-default
graphical.target

修改默认 target

systemctl set-default [xxx.target]

# Ubuntu18.04
# 图形用户界面 切换 命令行界面
sudo systemctl set-default multi-user.target
# 命令行界面 切换 图形用户界面
 systemctl set-default graphical.target
 reboot
 # 命令行界面 想进入 图形用户界面(仅进入一次,重启系统后仍然会进入命令行模式)
 sudo systemctl start lightdm

https://ask.csdn.net/questions/695344

https://askubuntu.com/a/788465

其他操作

修改配置文件

  1. 直接修改/lib/systemd/system目录下的单元文件

    如果软件包更新,修改会被丢弃

  2. /lib/systemd/system中的单元文件复制到/etc/systemd/system/

    如果软件包更新,不会同步更新

  3. /etc/systemd/system/ 中添加配置(推荐)

添加配置

步骤:

  1. /etc/systemd/system/ 目录下新建<单元名>.d目录
  2. <单元名>.d目录下,新建<单元名>.conf文件
  3. <单元名>.conf文件中修改配置

测试:

  1. 创建目录及文件

    # /mysql.service.d
    lfp@legion:/etc/systemd/system/mysql.service.d$ ls
    mysql.conf
    
  2. 修改配置

    # MySQL Systemd service config file
    # 不需要所有的组,仅添加需要修改的组及选项
    
    [Unit]
    Description=MySQL Community Server config test
    
    [Service]
    ExecStartPost=/home/lfp/bin/espeak.sh
    
  3. 重启测试

    lfp@legion:/etc/systemd/system/mysql.service.d$ systemctl daemon-reload
    lfp@legion:/etc/systemd/system/mysql.service.d$ systemctl restart mysql.service
    lfp@legion:/etc/systemd/system/mysql.service.d$ systemctl status mysql.service
    lfp@legion:/etc/systemd/system/mysql.service.d$ systemctl status mysql.service
    #                                                                            描述已经被修改
    ● mysql.service - MySQL Community Server config test
       Loaded: loaded (/lib/systemd/system/mysql.service; enabled; vendor preset: enabled)
    # 加入了配置文件
      Drop-In: /etc/systemd/system/mysql.service.d
               └─mysql.conf
       Active: active (running) since Thu 2020-05-21 20:18:02 CST; 12min ago
    # 新增的动作执行成功
      Process: 4703 ExecStartPost=/home/lfp/bin/espeak.sh (code=exited, status=0/SUCCESS)
      Process: 4672 ExecStart=/usr/sbin/mysqld --daemonize --pid-file=/run/mysqld/mysqld.pid (code=exited, status=0/SUCCESS)
      Process: 4663 ExecStartPre=/usr/share/mysql/mysql-Systemd-start pre (code=exited, status=0/SUCCESS)
     Main PID: 4674 (mysqld)
        Tasks: 27 (limit: 4915)
       CGroup: /system.slice/mysql.service
               └─4674 /usr/sbin/mysqld --daemonize --pid-file=/run/mysqld/mysqld.pid
    
    5月 21 20:18:02 legion espeak.sh[4703]: ALSA lib pcm_route.c:867:(find_matching_chmap) Found no matching channel map
    

添加开机启动服务

  1. 添加启动配置文件
  2. 通过 rc.local文件

/lib/systemd/rc.local.service

# 如果存在,就自动添加到 multi-user.target
# This Unit gets pulled automatically into multi-user.target by
# Systemd-rc-local-generator if /etc/rc.local is executable.
[Unit]
Description=/etc/rc.local Compatibility
Documentation=man:systemd-rc-local-generator(8)
ConditionFileIsExecutable=/etc/rc.local
After=network.target

[Service]
Type=forking
ExecStart=/etc/rc.local start
TimeoutSec=0
RemainAfterExit=yes
GuessMainPID=no

创建 rc.local 文件,赋予可执行权限,即可添加启动命令

sudo touch /etc/rc.local
chmod 755 /etc/rc.local

lfp@legion:/etc$ vim rc.local
#!/bin/sh -e
echo "test rc.local" > /usr/local/rclocal.log
echo "rc.local `date +%Y-%m-%d-%H:%M:%S`" >/home/lfp/log/rclocal.log
exit 0

system 工具集

hostnamectl 主机名管理命令

hostnamectl
hostnamectl status

Show current system hostname and related information

lfp@legion:/lib/systemd/system$ hostnamectl status
   Static hostname: legion
         Icon name: computer-laptop
           Chassis: laptop
        Machine ID: b28xxxxxxxx2ecafa29e
           Boot ID: 21xxxxxxxxxxxx1d3a47504d
  Operating System: Ubuntu 18.04.4 LTS
            Kernel: Linux 5.3.0-51-generic
      Architecture: x86-64

journalctl 日志管理命令

Systemd 统一管理所有 Unit 的启动日志。带来的好处就是,可以只用journalctl一个命令,查看所有日志(内核日志和应用日志)。

配置文件

/etc/systemd/journald.conf

日志保存目录

/var/log/journal/

默认日志最大限制为所在文件系统容量的 10%,可通过 /etc/systemd/journald.conf 中的 SystemMaxUse 字段来指定

该目录是 systemd 软件包的一部分。若被删除,systemd 不会自动创建它,直到下次升级软件包时重建该目录。如果该目录缺失,systemd 会将日志记录写入 /run/systemd/journal。这意味着,系统重启后日志将丢失。

journalctl -u [服务名]

查看指定单元的日志

journalctl -b
  • journalctl -b -0 显示本次启动的信息
  • journalctl -b -1 显示上次启动的信息
  • journalctl -b -2 显示上上次启动的信息

参考

http://manpages.ubuntu.com/manpages/bionic/en/man1/systemctl.1.html

http://manpages.ubuntu.com/manpages/bionic/en/man5/systemd.unit.5.html

https://www.cnblogs.com/yingsong/p/6012180.html

https://www.cnblogs.com/sparkdev/p/8472711.html

http://www.ruanyifeng.com/blog/2016/03/systemd-tutorial-commands.html

http://www.ruanyifeng.com/blog/2016/03/systemd-tutorial-part-two.html

https://linoxide.com/linux-how-to/systemd-boot-process/

https://cloud.tencent.com/developer/article/1516125

https://www.cnblogs.com/sparkdev/p/8472711.html

https://www.ibm.com/developerworks/cn/linux/1407_liuming_init3/index.html?ca=drs-

你可能感兴趣的:(Linux Systemd 详细介绍: Unit、Unit File、Systemctl、Target)