Systemd 的系统资源管理

对服务的管理知识 Systemd 系统管理功能的冰山一角。在 Systemd 的生态圈中,Unit 文件统一了过去各种不同的系统资源配置格式,例如服务的启/停、定时任务、设备自动挂载、网络配置、设备配置、虚拟内存配置等。

Systemd 的 Unit 文件

Systemd 通过不同的文件后缀名来区分这些配置文件,下表列举了 Systemd 所支持的 12 中 Unit 文件类型。

后缀名 作用
.automount 用于控制自动挂载文件系统。即当指定的目录被访问时,立即会被自动挂载
.deviece 对应 /dev 目录下的设备,主要用于定义设备之间的依赖关系
.mount 定义系统结构层次中的一个挂载点,可以替代过去的 /etc/fstab 配置文件
.path 用于监控指定目录或文件的变化,并触发其它 Unit 运行
.scope 这种 Unit 文件不是用户创建的,而是 Systemd 运行时自己产生的,描述一些系统服务的分组信息
.service 封装守护进程的启动、停止、重启和重载操作,是最常见的一种 Unit 文件
.slice 用于表示一个 CGroup 的树,通常用户不会自己创建这样的 Unit 文件
.snapshot 用于表示一个由 systemctl snapshot 命令创建的 Systemd Units 运行状态快照
.socket 监控来自于系统或网络的数据消息,用于实现基于数据自动触发服务启动
.swap 定义一个用于做虚拟内存的交换分区
.target 用于对 Unit 进行逻辑分组,引导其它 Unit 的执行
.timer 用于配置在特定时间出发的任务,替代了 Crontab 的功能

Systemd 的 Unit 文件存放目录

路径 说明
/etc/systemd/system 系统或用户提供的配置文件
/run/systemd/system 软件运行时生成的配置文件
/usr/lib64/systemd/system 系统或第三方软件安装时添加的配置文件

CoreOS 系统提供的 Unit 文件大多放在 /usr/lib64/systemd/system 目录中,而/usr/lib64/systemd/system 这个目录在 CoreOS 中属于系统只堵分区。如果需要修改系统服务的管理配置,可以将这个目录中相应 Unit 文件复制到 /etc/systemd/system 中修改即可。

定时器

定时器的 Unit 文件

定时器的 Unit 文件除了通用的 Unit 段和 Install 段以外,还有一个特别的 Timer 段,这个区段的属性主要定义了定时器的触发时机和触发的任务。

  • OnActiveSec: 当“Timer 自己被启动后”的指定秒数时,触发定时器任务。
  • OnBootSec: 当“主机开始启动后”的指定秒数时,触发定时器任务。
  • OnstartupSec: 当“操作系统启动完成后”的指定秒数时,触发定时器任务。
  • OnUnitActiveSec: 当“定时器中的指定服务被启动后”的指定秒数时,触发定时器任务。
  • OnUnitInactiveSec: 当“定时器中的指定服务停止后”的指定秒数时,触发定时器任务。

可以同时使用多个触发时机。

以上这些属性的值都可以是一个数字(即秒数),或一个合法的字符串时间,可以用的单位如下表所示。

单位 意义
usec,us 微秒
msec,ms 毫秒
seconds,second,sec,s
minuters,minute,min,m 分钟
hours,hour,hr,h 小时
days,day,d
weeks,week,w
months,month
years,year,y
  • OnCalendar: 使用日历时间,在特定日期触发。常用的日期表示格式为 yyyy-MM-dd-hh:mm:ss,例如 2015-07-23 11:12:13。

  • Unit: 这个参数的值是一个服务 Unit 文件的名称。当定时器事件触发时,就会执行这个服务指定的指令。如果没有配置这个属性,默认会将与这个定时器同名(但后缀名是.service)的服务 Unit 文件作为被指定的任务。

  • AccuracySec: 这个值设定了触发事件的精度,默认为 1min。在精度范围内到期的定时器会在一个随机时间里被触发,防止在某个整点时刻出现大量并发的定时器事件。

  • Persistent: 值为 true 或 false。默认为 false,当设为 true 时,定时器启动时会检查从上次定时器结束到当前时刻是否有漏掉的 OnCalendar 触发事件,如果有则立即触发一次指定的任务;当设为 false 时,会忽略在定时器停止期间错过的 OnCalendar 事件。
  • WakeSystem: 值为 true 或 false。默认为 false,当设为 true 时,如果定时器触发时系统处于挂起(Suspend)状态,则会自动唤醒系统并执行任务。当设为 false 时,会忽略在系统挂起期间的事件。

systemd-tmpfiles-clean.timer

下面的 Unit 文件是 CoreOS 用于自动清理临时文件的定时器配置文件。

1
2
3
4
5
6
7
[Unit]
description=Daily Cleanup of Temporary Directories
Documentation=man:tmpfiles.d(5) man:systemd-tmpfiles(8)
[Timer]
OnBootSec=15min
OnUnitActiceSec=1d

启动定时器

$ sudo systemctl start xxx.timer 启动定时器

$ sudo systemctl enable xxx.timer 注册为随系统启动

systemctl stopsystemctl disable 同理。

路径监控器

后缀名为“.path”的 Unit 文件是用来监控目录变化的。它的效果和定时器有些相似,也是在满足特定的条件时执行另一个作为指定任务的服务 Unit 文件。

路径监控器的 Unit 文件

路径监控器的 Unit 文件的特有配置段是 Path,用于配置监控的事件、目录和需要执行的任务。

  • PathExists: 列在这个属性后面的路径如果存在(被创建),就是触发任务。
  • PathExistsGlob: 功能和 PathExists 基本相同,但是这个属性后面的路径可以使用通配符。
  • PathChanged: 列在这个属性后面的文件和目录如果被修改或更新了,就会触发任务。
  • PathModified: 功能和 PathChanged 相似,不过前者只会在监听文件修改完成(文件句柄被释放)时触发任务,而这个属性后面的文件在每次修改被保存时都会触发任务。
  • DirectoryNotEmpty: 列在这个属性后面的目录如果不是空的,就是触发任务。

在同一个目录监控器中,可以同时使用多个监听条件,当任意一个触发时,都会执行指定的服务。

  • Unit: 这个参数的值是一个服务 Unit 文件的名称。当路径监控器的事件被触发时,就会执行这个服务指定的命令。如果没有配置这个属性,默认会将与这个监控器同名(但后缀名是.service)的服务 Unit 文件作为被指定的任务。

  • MakeDirectory: 值为 true 或 false。默认为 false,当设为 true 时,如果被监控的路径不存在,则会自动将其创建为一个目录(PathExists 事件监控的目录除外)。当设为 false 时,没有这个行为。

  • DirectoryMode: 这个属性用于指定自动创建的目录具有怎样的权限,默认值是 0755。

motdgen.path

1
2
3
4
5
[Unit]
Description=Watch for update engine configuration changes
[Path]
PathChanged=/etc/coreos/update.conf

数据监控器

后缀为“.socket”的 Unit 文件可以监控系统的指定 TCP/UDP 端口、系统消息队列、特殊设备、FIFO 管道或套接字文字的数据。

当检测到有数据来时,就启动指定服务。这样做的好处是,当操作系统启动时,许多对外提供服务的应用并不需要随系统立即开启,知道有真实的用户请求访问其监听的端口时,才会按需启动,从而节约了系统的开机时间。

数据监控器的 Unit 文件

  • ListenStream: 监听指定的 TCP 端口或 UNIX 套接字。(IP:PORT)
  • ListenDatagram: 监听指定的 UDP 端口。
  • ListenSequentialPacket: 监听指定的 Unix 套接字文件。
  • ListenFIFO: 监听指定的 FIFO(命名管道)文件。
  • ListenMessageQueue: 监听指定的 POSIX 消息队列。
  • ListenSpecial: 监听指定的字符设备文件或特殊设备文件。

在同一个数据监控器中,可以同时使用多个监听数据来源,当任意一个有数据到来时,都会执行指定的服务。

  • Service: 这个参数的值是一个服务 Unit 文件的名称。当监控到数据到达时,Systemd 就会启动这个服务并处理接收到的数据。如果没有配置这个属性,默认会将与这个监控器同名(但后缀名是.service)的服务 Unit 文件作为被指定的任务。

  • Accept: 值为 true 或 false。默认为 false,当设为 true 时,Systemd 会为每个连接请求创建一个新服务实例,通常只用于有连接的通信协议,列入监控 TCP 端口。当设为 false 时,Systemd会检查指定的服务是否已经在运行,如果没有运行,就会启动这个服务。

  • MaxConnections: 仅当“Accept=true”时有效,限制最大连接数,也就是最大的服务运行数量,超过这个数量的连接会被直接拒绝。
  • KeepAlive: 值为 true 或 false,只对 TCP 连接有效。默认为 false,当设为 true 时,建立的连接会被设置为长连接。
  • ExecStartPre 和 ExecStartPost: 在执行指定服务启动开始前和完成后需要执行的额外命令。
  • ExecStopPre 和 ExecStopPost: 在执行指定服务即将结束时和完整结束后需要执行的额外命令。
  • TimeoutSec: 指定 ExecStartPre、ExecStartPost、ExecStopPre 和 ExecStopPost 中每个命令的最长等待时间。
  • ReceiveBuffer 和 SendBuffer: 数据接收和发送缓存的大小。
  • RemoveOnStop: 值为 true 或 false,对系统消息队列、FIFO 管道或套接字文件有效。默认为 false,若设为 true,服务结束时会同时删除监控的文件。

sshd.socket

1
2
3
4
5
6
7
8
9
10
[Unit]
Description=OpenSSH Server Socket
Conflicts=sshd.service
[Socket]
ListenStream=22
Accept=yes
[Install]
WantedBy=sockets.target

挂载文件系统

后缀名为“.mount”的 Unit 文件用于记录和处理挂载文件系统。

挂载点的 Unit 文件

挂载点的 Unit 文件名必须以转义后的挂载目录命名。庄毅规则大致是将路径符号“/”替换为“-”,原本文件名中的“-”和其它非 ASCII 字符替换为“\x”开头的编号。

可以将挂载点路径去掉开头的分隔符作为“systemd-escape”命令的参数,从而获得转义的 Unix 文件名。

1
2
$ systemd-escape media/my-mount-point
media-my\x2dmount\x2dpoint
  • What: 被挂载设备的绝对路径。
  • Where: 挂载点目录的绝对路径,这个路径应该与该 Unit 文件名相对应。
  • Type: 挂载文件系统的类型。
  • Options: 挂载的参数,用逗号分隔。
  • SloppyOptions: 值为 true 或 false。默认为 false,若设为 true,当遇到无法识别的挂载参数时,会出错退出;若设为 false,则忽略无法识别的挂载参数。
  • DirectoryMode: 如果指定的挂载目录不存在时, Systemd 会将它自动创建出来。这个参数指定了目录的权限,默认为 0755。
  • TimeoutSec: 挂载超时的秒数。如果到了这个时间挂载仍然没有完成,则会判定为失败。

usr-share-oem.mount

1
2
3
4
5
6
7
8
9
10
11
12
[Unit]
DefaultDependencies=no
Wants=addon-run@usr-share-oem.service addon-config@usr-share-oem.service
Conflicts=umount.target
Before=local-fs.target umount.target ldconfig.service
ConditionVirtualization=!container
ConditionPathExists=!/usr/.noupdate
[Mount]
What=/dev/disk/by-label/OEM
Where=/usr/share/oem
Type=ext4

这个配置的效果等同于mkdir -p /usr/share/oem; mount -t ext4 -o nodev,commit=600 /dev/disk/by-label/OEM /usr/share/oem命令,但通过 Systemd 统一管理后,看起来更简洁了。

自动挂载文件系统

后缀名为“.automount”的 Unit 文件用于当用户访问某个目录时,自动将设定的文件系统挂载上去。在过去的 Linux 中,这个任务是由 autofs 服务完成的。

自动挂载点的 Unit 文件

自动挂载点的配置相对简单,但它必须与一个同名的“.mount”挂载点 Unit 文件配合使用。且这类 Unit 文件的命名同样必须与挂载目录转移后的名称一致的约定。

  • Where: 挂载点目录的绝对路径,这个路径应该与该 Unit 文件相对应。
  • DirectoryMode: 如果指定的挂载目录不存在时,Systemd 会将它自动创建出来。这个参数指定了目录的权限,默认是 0755。
  • TimeoutIdleSec: 这个配置可以指定一个超时时间。当挂载的目录在这段时间内都没有使用时,Systemd酒会尝试自动卸载它。将这个值设为0,则会禁用这个功能。默认这个功能是禁止的。

/etc/systemd/system/usr-share-oem.automount

1
2
3
4
5
6
7
8
[Unit]
Descrition=Test automount
[Automount]
Where=/usr/share/oem
[Install]
WantedBy=multi-user.target

交换分区(虚拟内存)

除了普通的挂载点,过去的 /etc/fstab 配置文件还有一项功能是交换分区的挂载。这部分功能在 Systemd 中是用专门的 Unit 文件完成的,它的后缀名为“.swap”。

作为一种特殊的挂载点,这类 Unit 文件的命名也必须遵守与挂载目录转义后名称一直的约定。

交换分区的 Unit 文件

  • What: 用于做交换分区的设备或文件的绝对路径。
  • Priority: 当有多个交换分区时,这个值回决定使用每个分区的优先级。
  • Options: 挂载交换分区的参数,这些参数会在实际挂载和卸载交换分区时,传递给 swapon 和 swapoff 命令。
  • TimeoutSec: 挂载交换分区的超时时间。如果在指定的时间内 swapon 命令仍然没有完成,则会被认为挂载失败。将这个值设为 0,则会禁用这个功能。默认这个功能是禁止的。

/etc/systemd/system/swapfile.swap

先创建一个大小为 2GB 的空白文件 swapfile。

1
2
3
$ sudo dd if=/dev/zero of=/swapfile bs=2048 count=1MB
$ sudo chmod 0600 /swapfile
$ sudo mkswap /swapfile
1
2
3
4
5
6
7
8
[Unit]
Description=Test swap file
[Swap]
What=/swapfile
[Install]
WantedBy=multi-user.target