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

架构图

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 的启动而启动

Ubuntu Manpage: systemd.unit - Unit configuration

Install 段

主要字段如下:

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

Ubuntu Manpage: systemd.unit - Unit configuration

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:不管是什么退出原因,总是重启

【上下文】

Why are some systemd services in the "masked" state? - Ask Ubuntu

示例

Systemd 内建命令

systemd-analyze

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

systemd-analyze

systemd-analyze time

查看初始化耗时

systemd-analyze blame

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

systemd-run

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

未测试

参考 systemd-run

systemctl 系统服务管理命令

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

与 service 命令的区别

打印 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 对单元的管理,不涉及单元文件自身属性和内容
动作SysV Init 指令Systemd 指令
启动某服务service httpd startsystemctl start httpd
停止某服务service httpd stopsystemctl stop httpd
重启某服务service httpd restartsystemctl restart httpd
检查服务状态service httpd statussystemctl status httpd
删除某服务chkconfig --del httpd停掉应用,删除其配置文件
使服务开机自启动chkconfig --level 5 httpd onsystemctl enable httpd
使服务开机不自启动chkconfig --level 5 httpd offsystemctl disable httpd
查询服务是否开机自启chkconfig --list | grep httpdsystemctl is-enabled httpd
加入自定义服务chkconfig --add testsystemctl load test
显示所有已启动的服务chkconfig --listsystemctl 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

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

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

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

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

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

  • Ubuntu Manpage: systemd.service - Service unit configuration

    占位符

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

    详细了解见 可能是史上最全面易懂的 Systemd 服务管理教程!( 强烈建议收藏 ) - 腾讯云开发者社区-腾讯云

    模板

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

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

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

    systemctl start apache@8080.service
    

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

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

    详细了解见 可能是史上最全面易懂的 Systemd 服务管理教程!( 强烈建议收藏 ) - 腾讯云开发者社区-腾讯云

    状态

    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指定的命令就会执行,从而重新开启触摸板
  • systemctl 融合了 service 和 chkconfig 的功能
  • 在 Ubuntu18.04 中没有自带 chkconfig 命令;service 命令实际上重定向到 systemctl 命令

打印 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里面的启动脚本

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值