Linux Systemd 详细介绍: Unit、Unit File、Systemctl、Target
Systemd
简介
CentOS 7 使用 Systemd 替换了SysV
Ubuntu 从 15.04 开始使用 Systemd
Systemd 是 Linux 系统工具,用来启动守护进程,已成为大多数发行版的标准配置
特点
优点:
-
按需启动进程,减少系统资源消耗
-
并行启动进程,提高系统启动速度
在 SysV-init 时代,将每个服务项目编号,依次执行启动脚本。Ubuntu 的 Upstart 解决了没有直接依赖的启动之间的并行启动。而 Systemd 通过 Socket 缓存、DBus 缓存和建立临时挂载点等方法进一步解决了启动进程之间的依赖,做到了所有系统服务并发启动。对于用户自定义的服务,Systemd 允许配置其启动依赖项目,从而确保服务按必要的顺序运行。
SystemV Upstart 参考上一篇博文:Linux 初始化系统 SystemV Upstart
-
使用 CGroup 监视和管理进程的生命周期
CGroup 提供了类似文件系统的接口,当进程创建子进程时,子进程会继承父进程的 CGroup。因此无论服务如何启动新的子进程,所有的这些相关进程都会属于同一个 CGroup
在 Systemd 之前的主流应用管理服务都是使用 进程树 来跟踪应用的继承关系的,而进程的父子关系很容易通过 两次 fork 的方法脱离。
而 Systemd 则提供通过 CGroup 跟踪进程关系,引补了这个缺漏。通过 CGroup 不仅能够实现服务之间访问隔离,限制特定应用程序对系统资源的访问配额,还能更精确地管理服务的生命周期
-
统一管理服务日志
-
支持快照和系统恢复
缺点:
- 过于复杂,与操作系统的其他部分强耦合,违反"keep simple, keep stupid"的Unix 哲学
架构图
Unit(单元|服务)
Systemd 可以管理所有系统资源:
- 将系统资源划分为12类
- 将每个系统资源称为一个 Unit。Unit 是 Systemd 管理系统资源的基本单位
- 使用一个 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=forking
:ExecStart
字段将以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、运行服务的用户等。这些信息可以使用占位符来表示,然后在实际运行中动态地替换为实际的值。
模板
在现实中,往往有一些应用需要被复制多份运行,就会用到模板文件
模板文件的写法与普通单元文件基本相同,只是模板文件名是以 @ 符号结尾。例如:apache@.service
通过模板文件启动服务实例时,需要在其文件名的 @ 字符后面附加一个用于区分服务实例的参数字符串,通常这个参数是用于监控的端口号或控制台 TTY 编译号
systemctl start apache@8080.service
Systemd 在运行服务时,首先寻找跟单元名完全匹配的单元文件,如果没有找到,才会尝试选择匹配模板
例如上面的命令,System 首先会在约定的目录下寻找名为 apache@8080.service 的单元文件,如果没有找到,而文件名中包含 @ 字符,它就会尝试去掉后缀参数匹配模板文件。对于 apache@8080.service,Systemd 会找到 apache@.service 模板文件,并通过这个模板文件将服务实例化。
状态
systemctl list-unit-files
将会列出文件的 state,包括 static, enabled, disabled, masked, indirect
-
masked
service软链接到
/dev/null
该单元文件被禁止建立启动链接
-
static
该单元文件没有
[Install]
部分(无法执行),只能作为其他配置文件的依赖 -
enabled
已建立启动链接
-
disabled
没建立启动链接
示例
-
关掉触摸板配置文件
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 命令的区别
- systemctl 融合了 service 和 chkconfig 的功能
- 在 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 --state
按Tab
键,显示所有可用的值单元文件状态
另外还可以用 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.service
为mysql.service.bak
然后通过service mysql restart
启动/etc/init.d/mysql
脚本
下面是启动后的一些信息
注:在恢复
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
重启 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
两个含义
-
系统的某个状态称为一个 target(类似于"状态点")
-
达到某个系统状态,所需的一个或多个资源(Unit)称为一个 target(一个 Unit 组)
-
target是一个抽象的系统资源,不像MySQL有实体
-
如果一个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 | 重启系统 |
启动过程
-
读入
/boot
目录下的内核文件 -
内核文件加载完之后,开始执行第一个程序
/sbin/init
初始化进程,由 Systemd 初始化系统引导,完成相关的初始化工作 -
Systemd 执行
default.target
,获知设定的启动 target实际上
default.target
是指向设定的启动 target 的软链接
-
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/
目录下的UnitSysV对应的 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
其他操作
修改配置文件
-
直接修改
/lib/systemd/system
目录下的单元文件如果软件包更新,修改会被丢弃
-
将
/lib/systemd/system
中的单元文件复制到/etc/systemd/system/
如果软件包更新,不会同步更新
-
在
/etc/systemd/system/
中添加配置(推荐)
添加配置
步骤:
- 在
/etc/systemd/system/
目录下新建<单元名>.d
目录 - 在
<单元名>.d
目录下,新建<单元名>.conf
文件 - 在
<单元名>.conf
文件中修改配置
测试:
-
创建目录及文件
# /mysql.service.d lfp@legion:/etc/systemd/system/mysql.service.d$ ls mysql.conf
-
修改配置
# MySQL Systemd service config file # 不需要所有的组,仅添加需要修改的组及选项 [Unit] Description=MySQL Community Server config test [Service] ExecStartPost=/home/lfp/bin/espeak.sh
-
重启测试
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
添加开机启动服务
- 添加启动配置文件
- 通过
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-