Linux Systemd 介绍

发布时间: 更新时间: 总字数:3749 阅读时间:8m 作者: IP上海 分享 网址

systemdLinux 系统的一种 中央化系统及设置管理程序(init),包括有守护进程程序库以及应用软件组成。目标是解决系统服务间的依赖关系,并依此实现系统初始化时服务的并行启动,同时达到降低系统的开销。

历史

在旧的 Linux 中,服务启动一直采用 init 进程。如:

$ /etc/init.d/apache2 start
$ service apache2 start

缺点如下:

  • 启动时间长:串行启动进程
  • 启动脚本复杂:init 进程只是执行启动脚本,不管其他事情,因此脚本需要处理各种异常情况

介绍

  • Systemd 是 Linux 的系统启动器之一
  • Unix 中通常以 d 作为系统 守护进程(daemon) 的后缀标识。Systemd 就是它要守护整个系统的进程,因此其 pid1
$ systemctl --version
systemd 215
+PAM +AUDIT +SELINUX +IMA -APPARMOR +SMACK +SYSVINIT +UTMP +LIBCRYPTSETUP +GCRYPT +GNUTLS +ACL +XZ +LZ4 -SECCOMP +BLKID +ELFUTILS +KMOD +IDN
$ pstree 1
systemd─┬─AliSecGuard───6*[{AliSecGuard}]
        ├─AliYunDun───23*[{AliYunDun}]
...

$ ps -ef
UID          PID    PPID  C STIME TTY          TIME CMD
root           1       0  0 12:07 ?        00:00:00 /lib/systemd/systemd
$ ls -lhart /sbin/init
lrwxrwxrwx 1 root root 20 Nov 21 21:10 /sbin/init -> /lib/systemd/systemd

常见 systemd unit 分类

  • systemctl -t help 查看 systemd 能管理的所有 unit 类型
systemctl -t help ...
$ systemctl -t help
Available unit types:
service
mount
swap
socket
target
device
automount
timer
path
slice
scope
  • .service Service units记录由 systemd 控制和监督的进程的信息
    • 查看命令 systemctl list-unit-files --type service
    • man systemd.service
  • .mount 系统的文件系统的挂载点
  • .swap 标识 swap 设备
  • .socket Socket units 定义进程通信用到的套接字,套接字与进程是分离的
    • 包括 IPC 或 网络套接字 Socket文件系统FIFO 的信息,用于 socket 的激活,由 systemd 控制和监督,如 systemctl cat docker.socket
  • .target Target units 是一组相关进程,定义系统启动的级别标签(用于单元分组和启动时作为同步点),systemd 没有运行级别的概念,创建标签只是为了兼容老版本
    • multi-user.target 多用户模式,目录 /usr/lib/systemd/system/multi-user.target.wants 中通过快捷键指定启动的服务
  • .device 定义系统启动时内核识别的文件
    • systemd 提供了设备的管理功能,/dev 下的设备由 /etc/udev/ 下的配置文件与 .device 共同定制
  • .automount 定义文件系统的自动挂载点
  • .timer Timer units 定时器
    • man systemd.timer
    • systemctl list-unit-files --type timer
  • .path 用于定义文件系统中的一个文件或目录使用
    • 常用于文件系统发生变化时,延迟激活服务
  • .slice Slice units 定义资源的分配组,进程组,是对一组进程的资源进行分级管理的概念
    • systemctl list-unit-files --type slice
    • slice 是一组按层级排列的单位
      • slice 并不包含进程,但会组建一个层级,并将 scopeservice 都放置其中
      • 真正的进程包含在 scopeservice
      • 在这一被划分层级的树中,每一个 slice 单位的名字对应通向层级中一个位置的路径
      • 小横线(-)起分离路径组件的作用
  • .scope Scope Unit(作用域单元)不是通过单元配置文件配置的,而是仅使用 systemd 的总线接口以编程方式创建
    • 它们的命名与文件名类似,名称以 .scope 结尾的单元指的是 Scopes Units
    • Scopes units 管理一组系统进程。与 Service Units 不同,Scopes units 管理外部创建的进程,不会自行分叉进程
  • 所有的单元文件:
    • systemctl list-unit-files [-t xxx]
    • systemctl list-units --all --state=inactive

unit 文件路径

  • /etc/systemd/system 存放系统启动的及启动的 unit 的软连接,优先级最高
  • /lib/systemd/system 默认 units 文件路径,优先级次之
  • /usr/lib/systemd/system 用户自己定义的单元文件,优先级最低

unit 文件定义

systemctl cat <UnitName> 查看 unit 文件,它通常由 3 段组成:

[Unit]
...

[<Unit 类型,如 Service Target Socket>]
...

[Install]
...

说明:

  • [Unit] 字段如下
    • Description 描述信息
    • Documentation 文档或帮助文档,如 Documentation=man:sshd(8) man:sshd_config(5)
    • After 表明需要依赖的服务,作用决定启动顺序,多个使用空格隔开 After=network.target auditd.service
    • Before 表明被依赖的服务
    • Requles 依赖到的其他 unit,强依赖,即依赖的 unit 启动失败,该 unit 不启动
    • Wants 依赖到的其他 unit,弱依赖,即依赖的 unit 启动失败,该 unit 继续启动
    • Conflicts 定义冲突关系
    • Condition... 运行必须满足的条件,否则不会运行
      • ConditionPathExists 条件 ConditionPathExists=!/etc/ssh/sshd_not_to_be_run
    • Assert... 运行必须满足的条件,否则会报启动失败
  • [<Unit 类型>] 参考
    • [Service]systemctl cat sshd.service 为例
      • Type 启动时关系的定义
        • simple ExecStart 启动的进程就是主进程
        • forking ExecStart 启动的进程生成的其中一个子进程成为主进程,启动完成后,旧的主进程会退出
        • ontshot 一次性进程,Systemd 会等当前服务退出,再继续往下执行
        • dbus 当前服务通过 D-Bus 启动
        • notify 当前服务启动完毕,会通知 Systemd,再继续往下执行
        • idle 若有其他任务执行完毕,当前服务才会运行
      • PIDFile=/var/run/sshd.pid
      • EnvironmentFile=-/etc/default/ssh 环境变量的定义文件
      • ExecStart=/usr/sbin/sshd -D $SSHD_OPTS 启动 unit 需要执行的命令
      • ExecStartPre=/usr/sbin/sshd -t 启动 unit 服务之前执行的命令
      • ExecStartpost 启动 unit 服务之后执行的命令
      • ExecStop 停止 unit 需要执行的命令
      • ExecStopPost 停止当其服务之后执行的命令
      • Restart 定义什么情况 Systemd 会自动重启当前服务,值可以为:
        • no(default) 退出后不会重启
        • always 总是重启
        • on-success 只有正常退出时(退出状态码为 0),才会重启
        • on-failure 非正常退出时(退出状态码非 0),包括被信号终止和超时,才会重启
        • on-abnormal 只有被信号终止和超时,才会重启
        • on-abort 只有在收到没有捕捉到的信号终止时,才会重启
        • on-watchdog
      • ExecReload=/usr/sbin/sshd -t 重启当前服务时执行的命令
      • ExecReload=/bin/kill -HUP $MAINPID
      • KillMode=process 只停止主进程,不停止 sshd 的子进程,即子进程打开的 SSH session 仍然保持连接,参考
        • process 只杀主进程
        • control-group(default) 杀掉当前控制组里面的所有子进程,对于 .service 单元,先执行 ExecStop= 动作
        • mixed 向主进程发送 SIGTERM 信号量,在向该.service 单元 cgroup 内的所有子进程发送 SIGKILL 信号量
        • none 不杀掉任何进程,只是执行服务的 ExecStop= 动作,可能残留 cgroup 中的其他进程
      • KillSignal 设置杀死进程的信号量
      • RestartPreventExitStatus=255
      • RuntimeDirectory=sshd
      • RuntimeDirectoryMode=0755
      • RestartSec=30s
  • [Install] 服务启动或禁用时的一些选项
    • Alias=sshd.service 当前 Unit 可用于启动的别名
    • Also 当前 Unit 激活(enable)时,会被同时激活的其他 Unit
    • WantedBy=multi-user.target 值是一个或多个 Target,当前 Unit 激活时(enable)符号链接会放入 /etc/systemd/system 目录下面以 <targetName>.wants 的子目录中
    • RequlredBy 同上,也是 Target
  • 最后,修改 unit 文件后需要执行 systemctl daemon-reload 重载生效

Target

Target 就是一个 Unit 组,包含许多相关的 Unit。解决一次批量启动多个 Unit 服务

# 查看默认启动的 Target
systemctl get-default

# 查看某个 Target 包含的所有 Unit
systemctl list-dependencies multi-user.target

# 查看当前系统的所有 Target
systemctl list-unit-files --type=target

# 设置启动时的默认 Target
sudo systemctl set-default multi-user.target
  • Target 与 传统 RunLevel 的对应关系如下。
Traditional runlevelNew target name -> Symbolically linked to…
Runlevel 0runlevel0.target -> poweroff.target
Runlevel 1runlevel1.target -> rescue.target
Runlevel 2runlevel2.target -> multi-user.target
Runlevel 3runlevel3.target -> multi-user.target
Runlevel 4runlevel4.target -> multi-user.target
Runlevel 5runlevel5.target -> graphical.target
Runlevel 6runlevel6.target -> reboot.target

slice

  • slice:A group of hierarchically organized units that manage system process. 一组分级管理系统进程的单位
    • 由程序⾃动创建或可⼿动创建
  • 启动启动时默认的 四 种 slice,采用 systemd-cgls 查看层级关系:
    • -.slice the root slice
    • system.slice the default place for all system services
    • user.slice the default place for all user sessions
    • machine.slice(maybe) the default place for all virtual machines and Linux containers.

systemctl

  • man systemctl

管理命令

# 显示所有 Unit
systemctl --all

# 启动
systemctl start <UnitName>
systemctl -H root@<ip> status <UnitName>

# 条件式重启,服务之前是启动的则进行重启,如果服务没有启动则不进行操作
systemctl try-restart <UnitName>

# 关闭
systemctl stop <UnitName>

# 重启
systemctl restart <UnitName>

# 重载或重启:首先进行重载,如果重载不成功则进行重启
systemctl reload-or-restart <UnitName>

# 重载或条件式重启:
systemctl reload-or-try-restart <UnitName>

# 查看状态
systemctl status <UnitName>

# 开机启动
# 本质是建立软连接 sudo ln -s '/usr/lib/systemd/system/xxx.service' '/etc/systemd/system/multi-user.target.wants/xxx.service'
systemctl enable <UnitName>

# 禁止开机启动
# 本质是删除上述软连接
systemctl disable <UnitName>

# 设置服务是否可以被用户设置开机启动状态
# 取消禁止
systemctl unmask <UnitName>

# 禁止
systemctl mask <UnitName>

# 查看服务的当前激活状态
systemctl is-active <UnitName>

# 查看所有已经激活的服务
# -t 指定显示的unit类型
# -a, --all 显示更加详细的信息列表
systemctl list-units
systemctl list-units -a
systemctl list-units -t service
systemctl list-units -t service -a
systemctl list-units -t slice
$ systemctl list-
list-automounts    list-jobs          list-paths         list-timers        list-units
list-dependencies  list-machines      list-sockets       list-unit-files

# 查看服务是否开机自启
systemctl is-enabled <UnitName>

# 查看服务的依赖关系
systemctl list-dependencies <UnitName>

# 重载所有修改过的配置文件
systemctl daemon-reload

# 杀死进程
systemctl kill <UnitName>

# 显示某个 Unit 的所有底层参数
systemctl show <UnitName>
# 查看 docker 的 OOM 策略
systemctl show docker | grep -i oom OOMPolicy=continue

# 查看 unit 配置
systemctl cat <UnitName>

# 重启
systemctl reboot

#
systemctl halt
systemctl poweroff
  • 查看所有服务状态
# -a, --all 查看所有服务的状态
# -t, --type 指定查看的 unit 类型
systemctl list-unit-files

status 列说明:

  • enabled 开机启动
  • disabled 开机不启动
  • static 配置文件没有 [Install] 部分(无法执行),只能作为其他配置文件的依赖
  • generated
  • enabled-runtime
  • masked 被禁止建立启动链接

set-property

  • 查看更多细节 man systemd.resource-control

在支持的情况下,在运行时设置指定的单元属性。这允许在运行时更改配置参数属性,如资源控制设置。并非所有属性都可以在运行时更改,但许多资源控制设置(主要是 systemd.resource-control(5) 中的设置)可以更改。这些更改会立即应用,并存储在磁盘上,供未来启动时使用,除非通过了 --runtime 设置,在这种情况下,设置只会应用到下一次重启。属性赋值的语法与单元文件中的赋值语法非常相似。

示例:systemctl set-property foobar.service CPUWeight=200

如果指定的单元似乎处于非活动状态,则更改只会存储在磁盘上,如前所述,因此它们将在单元启动时生效。

请注意,该命令允许同时更改多个属性,这比单独设置要好。

示例:systemctl set-property foobar.service CPUWeight=200 MemoryMax=2G IPAccounting=yes

与单元文件配置设置一样,分配空设置通常会将属性重置为默认值。

示例:systemctl set-property avahi-daemon.service IPAddressDeny=

在 206 版中添加。

# 显示某个 Unit 的指定属性的值
systemctl show -p CPUShares nginx.service

# 设置某个 Unit 的指定属性,限定 nginx.service 的 CPU 和内存占用量
sudo systemctl set-property nginx.service CPUShares=500 MemoryLimit=500M

# 临时更改,添加 --runtime 选项
systemctl set-property --runtime httpd.service CPUShares=600 MemoryLimit=500M

# CPUQuota

systemd 资源控制概念

Systemd 提供了三种有助于控制资源的单元类型:

  • service 服务 封装了 systemd 根据配置启动和停止的大量进程。服务的命名方式与 quux.service 相同。
  • scope 作用域 封装了大量进程,这些进程由任意进程通过 fork() 启动和停止,然后在运行时以 PID1 注册。作用域的命名方式与 wuff.scope 相同。
  • slice 片段 可用于将多个服务和作用域以层次树的形式组合在一起。片段本身不包含进程,但其中包含的服务和片段却包含进程。切片的命名方式是 foobar-waldo.slice,切片在树中的位置路径在名称中以"-“作为路径分隔符进行编码(因此,foobar-waldo.slice 是 foobar.slice 的子切片)。还有一个特殊的片段定义,即-.slice,它是所有片段的根片段(foobar.slice 因此是-.slice 的子片段)。这与普通文件路径中的”/“表示根目录类似。

服务、作用域和切片单元直接映射到 cgroups 树中的对象。当这些单元被激活时,它们都会直接映射到根据单元名称建立的 cgroups 路径上(在某些字符转义的情况下)。例如,foobar-waldo.slice 片中的服务 quux.service 可以在 cgroups foobar.slice/foobar-waldo.slice/quux.service/ 中找到。

服务、作用域和片段可由管理员自由创建,也可由程序员动态创建。使用 systemd-cgls 查看层级

systemd-analyze

# 查看启动耗时
$ systemd-analyze

# 查看每个服务的启动耗时
$ systemd-analyze blame

# 显示瀑布状的启动过程流
$ systemd-analyze critical-chain

# 显示指定服务的启动流
$ systemd-analyze critical-chain atd.service

loginctl

# 查看当前登录的用户
$ loginctl list-sessions
$ loginctl list-users
$ loginctl show-user root

# Systemd 支持通过 --user 参数管理用户级别的后台程序,但当用户退出登录后,属于该用户的后台服务会被终止。如果希望用户退出后仍然保持服务的运行,可以使用下面的命令启用用户的逗留状态
$ loginctl enable-linger $USER

参考

  1. https://systemd.io/
  2. https://en.wikipedia.org/wiki/Systemd
  3. https://freedesktop.org/wiki/Software/systemd/
  4. https://www.freedesktop.org/software/systemd/man/latest/systemd.unit.html
  5. https://www.freedesktop.org/software/systemd/man/latest/bootup.html#System%20Manager%20Bootup
  6. https://github.com/systemd/systemd/blob/main/docs/ARCHITECTURE.md
Home Archives Categories Tags Statistics
本文总阅读量 次 本站总访问量 次 本站总访客数