Systemd
概述
引子
在 Linux 上进行安装某些服务之后,经常需要进行开启,关闭,重启的操作。
如我们在机器上安装了 sshd 服务,更改了配置需要让他生效,就需要进行重启
service sshd restart
在查资料的过程中,发现有的服务,是用另一套命令进行维护
systemctl sshd restart
因此想要更深入的了解一些
systemd 系列图

相关概念
1 号进程
1 号进程是 Linux 在内核加载后启动的第一个进程,会负责启动其他所需要的进程。
systemd 是作为一号进程存在,具体可以验证
服务的两种管理方式
System V 的方式
在/etc 目录下,以下的以下的子目录存放着服务脚本
drwxr-xr-x 2 root root 4096 Mar 29 10:48 rc0.d
drwxr-xr-x 2 root root 4096 Mar 29 10:48 rc1.d
drwxr-xr-x 2 root root 4096 Mar 29 10:48 rc2.d
drwxr-xr-x 2 root root 4096 Mar 29 10:48 rc3.d
drwxr-xr-x 2 root root 4096 Mar 29 10:48 rc4.d
drwxr-xr-x 2 root root 4096 Mar 29 10:48 rc5.d
drwxr-xr-x 2 root root 4096 Mar 29 10:48 rc6.d
drwxr-xr-x 2 root root 4096 Mar 29 10:48 init.d
- /etc/init.d 中存放着所有的服务脚本
- 不同运行级别,会按需添加/etc/init.d 下的具体服务
- 服务脚本一般包含 start, stop, restart 命令
Systemd 的方式
较新的 Linux 发行版会采用 systemd 作为 1 号进程,进行服务管理,详见下文的阐述
Unit
Unit 类型
- Service unit:系统服务
- Target unit:多个 Unit 构成的一个组
- Device Unit:硬件设备
- Mount Unit:文件系统的挂载点
- Automount Unit:自动挂载点
- Path Unit:文件或路径
- Scope Unit:不是由 Systemd 启动的外部进程
- Slice Unit:进程组
- Snapshot Unit:Systemd 快照,可以切回某个快照
- Socket Unit:进程间通信的 socket
- Swap Unit:swap 文件
- Timer Unit:定时器
常用的是 Service Unit,表示一个系统服务
Target 是 Unit 的打包,与传统的 Run Level 概念类似,即一次启动多个服务
服务管理
服务查看
查看所有的服务
systemctl list-unit-files --type=service
服务创建
可以在/etc/systemd/system 或者/lib/systemd/system 中仿照格式创建.service 文件
服务最简模板
[Unit]
Description=简单的Foo服务
[Service]
ExecStart=/usr/sbin/foo-daemon
WorkingDirectory=/data/XXX
[Install]
WantedBy=multi-user.target
稍微复杂的模板
# 注释
[Unit]
Description=描述
Documentation=文档命令
After=network.target nss-lookup.target # 在哪些unit或target后启动
Requires=#强依赖的unit列表,启动本unit时,也会启动Requires里面的
Wants=#弱依赖的unit列表,启动本unit时,也会启动Requires里面的,且只有他们都启动成功时,本unit才成功
Conflicts=#与这个模块有冲突的模块,如果列出的模块中有已经在运行的,这个服务就不能启动,反之亦然
[Service]
EnvironmentFile=-/etc/sysconfig/sshd #环境变量文件,-表示不存在不报错
Type=simple # 启动类型,可设置:simple(默认),exec,forking,oneshot,dbus,notify,idle
ExecStart:定义启动进程时执行的命令
ExecReload:重启服务时执行的命令
ExecStop:停止服务时执行的命令
ExecStartPre:启动服务之前执行的命令
ExecStartPost:启动服务之后执行的命令
ExecStopPost:停止服务之后执行的命令
User=以什么用户执行命令
KillMode:定义 Systemd 如何停止服务
Restart:定义了退出后,Systemd 的重启方式。
RestartSec:表示 Systemd 重启服务之前,需要等待的秒数
[Install]
WantedBy=multi-user.target
KillMode:
可以设置的值如下:
- control-group(默认值):当前控制组里面的所有子进程,都会被杀掉
- process:只杀主进程
- mixed:主进程将收到 SIGTERM 信号,子进程收到 SIGKILL 信号
- none:没有进程会被杀掉,只是执行服务的 stop 命令
Restart:
- on-success:只有正常退出时(退出状态码为 0),才会重启
- on-failure:非正常退出时(退出状态码非 0),包括被信号终止和超时,才会重启
- on-abnormal:只有被信号终止和超时,才会重启
- on-abort:只有在收到没有捕捉到的信号终止时,才会重启
- on-watchdog:超时退出,才会重启
- always:不管是什么退出原因,总是重启
服务启动顺序
After字段: 此 Unit 应该在其后启动Before字段:此 Unit 应该在其前启动
服务依赖关系
Wants 字段: 弱依赖关系,若字段值对应的服务失败或停止,不影响服务本身
Requires 字段:强依赖关系,若字段值对应的服务失败或停止,服务本身也要退出
服务自启动
以 nginx 为例,下述命令开启其自启动
sudo systemctl enable nginx.service
下述命令关闭其自启动
sudo systemctl disable nginx.service
服务操作
查看服务状态
sudo systemctl status nginx.service

结果如上图,其中
Loaded 列的 enabled 表示其开启自启动,disable 表示开启不自启动
Active 表示进程状态:
- Active 正在运行
最下方会显示其日志,所有被 systemd 管理的日志,错误数据与标准输出都会被收集,也可以使用 journalctl 查看更详细的日志
-b 0 表示只统计最后一次启动后的日志,去掉会显示历史的日志
-p 3 表示查看 error 或更高等级的日志
sudo journalctl -b 0 -p 3 -u nginx.service
日志管理
命令概述
journalctl [-b] 查看所有日志,默认显示本次启动的所有日志,基本不用,因为太多了;
journalctl -k 查看内核日志;
journalctl -u 查看指定服务的日志;
journalctl --since --until 查看指定时间的日志,时间格式为"2020-05-13 13:14:00";
journalctl -n 指定显示最近的多少行,默认为 10 行;
journalctl -f 持续监控日志输出;
journal --no-pager 设置不分页显示;
journalctl -p 查看指定级别的日志;
其中等级
0: emerg 1: alert 2: crit 3: err 4: warning 5: notice 6: info 7: debug
journal -o 设置输出格式,可选:
cat: 只显示信息字段本身。 export: 适合传输或备份的二进制格式。 json: 标准 JSON,每行一个条目。 json-pretty: JSON 格式,适合人类阅读习惯。 json-sse: JSON 格式,经过打包以兼容 server-sent 事件。 short: 默认 syslog 类输出格式。 short-iso: 默认格式,强调显示 ISO 8601 挂钟时间戳。 short-monotonic: 默认格式,提供普通时间戳。 short-precise: 默认格式,提供微秒级精度。 verbose: 显示该条目的全部可用 journal 字段,包括通常被内部隐藏的字段。
日志查看
系统日志查看
-k 代表查看系统日志,同 dmesg
sudo journalctl -k
查看之前的 oom killer 日志
-b -1,代表是上次重启周期期间的日志,以此类推
sudo journalctl -b -2 -kg 'killed process'
查看服务的日志
如,查看 ssh 启动的日志
-g 代表用后边的词进行 grep 操作
-u 后边跟着服务名
sudo journalctl -u ssh.service -g "Started"
查看系统的重启情况
sudo journalctl --list-boots
其他
json-pretty 可以用 json 格式输出日志
sudo journalctl -o json-pretty
日志清理
手动清理
方法 1:强制删除
rm -rf /var/log/journal/
方法 2: 使用 journalctl 做清理
- 查看日志磁盘占用
sudo journalctl --disk-usage
- 轮转归档日志文件,便于后续清理
sudo journalctl --rotate
- 清理指定时间之前的日志
后缀支持 d(天), h(时), s(秒)
sudo journalctl --vacuum-time=7d
- 清理指定大小之外的日志(即保留最近 xx 大小的日志)
后缀支持 G(GB), M(MB), K(KB)
sudo journalctl --vacuum-size=1G
- 清理指定数目外的日志(即保留最近的 n 个日志)
sudo journalctl --vacuum-files=5
自动清理
修改 /etc/systemd/journald.conf 配置文件
常用参数如下
SystemMaxUse=:指定 journal 所能使用的最高持久存储容量。 SystemKeepFree=:指定 journal 在添加新条目时需要保留的剩余空间。 SystemMaxFileSize=:控制单一 journal 文件大小,符合要求方可被转为持久存储。 RuntimeMaxUse=:指定易失性存储中的最大可用磁盘容量(/run 文件系统之内)。 RuntimeKeepFree=:指定向易失性存储内写入数据时为其它应用保留的空间量(/run 文件系统之内)。 RuntimeMaxFileSize=:指定单一 journal 文件可占用的最大易失性存储容量(/run 文件系统之内)
设置后需要重载配置
sudo systemctl daemon-reload
参考资料
https://www.liangzl.com/get-article-detail-164210.html
https://man7.org/linux/man-pages/man8/systemd-oomd.8.html
http://www.jinbuguo.com/systemd/systemd.service.html
https://cloud.tencent.com/developer/article/1516125
http://www.jinbuguo.com/systemd/systemd.service.html systemd 中文翻译文档
https://www.freedesktop.org/software/systemd/man/systemd.service.html systemd 官方英文文档