systemd介绍
systemd 是一个 Linux 系统基础组件的集合,提供了一个系统和服务管理器,运行为 PID 1 并负责启动其它程序。功能包括:支持并行化任务;同时采用 socket 式与 D-Bus 总线式激活服务;按需启动守护进程(daemon);利用 Linux 的 cgroups 监视进程;支持快照和系统恢复;维护挂载点和自动挂载点;各服务间基于依赖关系进行精密控制。systemd 支持 SysV 和 LSB 初始脚本,可以替代 sysvinit。除此之外,功能还包括日志进程、控制基础系统配置,维护登陆用户列表以及系统账户、运行时目录和设置,可以运行容器和虚拟机,可以简单的管理网络配置、网络时间同步、日志转发和名称解析等。
systemd目的是取代Unix时代以来一直使用的init系统,兼容SysV和LSB的启动脚本。
init系统有两个缺点:
- 一是启动时间长。init进程是串行启动,只有前一个进程启动完,才会启动下一个进程。
- 二是启动脚本复杂。init进程只是执行启动脚本,不管其他事情。脚本需要自己处理各种情况,这往往使得脚本变得很长。
使用systemd就不需要再用init了。systemd取代了initd成为系统第一个进程(PID等于1),其他进程都是它的子进程。
systemd特性:
- 支持并行化任务;
- 同时采用socket式与D-Bus总线式激活服务;
- 按需启动守护进程(daemon);
- 利用 Linux 的 cgroups 监视进程;
- 支持快照和系统恢复;
- 维护挂载点和自动挂载点;
- 各服务间基于依赖关系进行精密控制。
1 | systemctl --version #查看systemd的版本 |
Systemd 的优点是功能强大,使用方便,缺点是体系庞大,非常复杂。事实上,现在还有很多人反对使用 Systemd,理由就是它过于复杂,与操作系统的其他部分强耦合,违反”keep simple, keep stupid”的Unix 哲学。
systemd可以管理所有系统资源。不同的资源统称为Unit(单元)。
Unit一共分为12种
- 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:定时器
监视和控制systemd的主要命令是systemctl
。该命令可用于查看系统状态和管理系统及服务。
使用systemctl
控制单元时,通常需要使用单元文件的全名,包括扩展名(例如:sshd.service)。但是有些单元可以在systemctl
中使用简写的方式。
- 如果无扩展名,systemctl 默认把扩展名当作 .service 。例如 netcfg 和 netcfg.service 是等价的。
- 挂载点会自动转化为相应的 .mount 单元。例如 /home 等价于 home.mount 。
- 设备会自动转化为相应的 .device 单元,所以 /dev/sda2 等价于 dev-sda2.device 。
1 | 注意: 有一些单元的名称包含一个 @ 标记(例如: name@string.service ),这意味着它是模板单元 name@.service 的一个 实例。 string 被称作实例标识符,在 systemctl 调用模板单元时,会将其当作一个参数传给模板单元,模板单元会使用这个传入的参数代替模板中的 %I 指示符。 |
系统管理
1 | # 重启系统 |
systemd-analyze
systemd-analyze
用于查看启动耗时。
1 | # 查看启动耗时 |
hostnamectl
hostnamectl
命令用于查看主机的信息
1 | # 显示当前主机的信息 |
localectl
localectl
命令用于查看本地化设置。
1 | # 查看本地化设置 |
timedatectl
timedatectl
命令用于查看当前时区设置。
1 | # 查看当前时区设置 |
loginctl
loginctl
命令用于查看当前登录的用户。
1 | # 列出当前session |
Unit 单元
1 | # 列出所有可用单元 |
Unit管理
下面命令是最长用到的一些命令
立即激活单元:
1 | $ sudo systemctl start <单元> |
立即停止单元:
1 | $ sudo systemctl stop <单元> |
杀死一个服务的所有子进程:
1 | $ sudo systemctl kill <单元> |
重启单元:
1 | $ sudo systemctl restart <单元> |
重新加载配置:
1 | $ sudo systemctl reload <单元> |
输出单元运行状态:
1 | $ sudo systemctl status <单元> |
检查单元是否配置为自动启动:
1 | $ sudo systemctl is-enabled <单元> |
开机激活单元:
1 | $ sudo systemctl enable <单元> |
设置单元为自动启动并立即启动这个单元:
1 | $ sudo systemctl enable --now <单元> |
取消开机自动激活单元:
1 | $ sudo systemctl disable <单元> |
禁用一个单元(禁用后,间接启动也是不可能的):
1 | $ sudo systemctl mask <单元> |
取消禁用一个单元:
1 | $ sudo systemctl unmask <单元> |
显示单元的手册页(必须由单元文件提供):
1 | $ sudo systemctl help <单元> |
重新载入 systemd,扫描新的或有变动的单元:
1 | $ sudo systemctl daemon-reload <单元> |
显示某个Unit的所有底层参数
1 | $ sudo systemctl show <单元> |
显示某个 Unit 的指定属性的值
1 | $ sudo systemctl show -p CPUShares httpd.service |
设置某个 Unit 的指定属性
1 | sudo systemctl set-property httpd.service CPUShares=500 |
提示:
- 上面的大部分命令可以跟多个单元名,详细参见 systemctl(1)
systemctl
命令在enable
、disable
和mask
子命令中增加了--now
选项,可以实现激活的同时启动服务,取消激活的同时停止服务。- 一个软件包可能会提供多个不同的单元。如果你已经安装了软件包,可以通过
pacman -Qql package | grep systemd
命令检查这个软件包提供了哪些单元。
依赖关系
Unit之间存在依赖关系:A依赖B,就意味着Systemd在启动A的时候,同时会去启动B。
systemctl list-dependencies
命令列出一个Unit的所有依赖 。
1 | $ sudo systemctl list-dependencies nginx.service |
上面命令的输出结果之中,有些依赖是 Target 类型(详见下文),默认不会展开显示。如果要展开 Target,就需要使用–all参数。
1 | $ sudo systemctl list-dependencies --all nginx.service |
target 目标
运行级别(runlevel)是一个旧的概念。现在,systemd 引入了一个和运行级别功能相似又不同的概念——目标(target)。不像数字表示的启动级别,每个目标都有名字和独特的功能,并且能同时启用多个。一些目标继承其他目标的服务,并启动新服务。systemd 提供了一些模仿 sysvinit 运行级别的目标,仍可以使用旧的 telinit 运行级别 命令切换。
运行级别:指的是Unix或者Linux等类Unix操作系统下不同的运行模式。
RunLevel是互斥的,不可能多个RunLevel同时启动,但是过个Target可以同时启动。简单说,Target 就是一个 Unit 组,包含许多相关的 Unit 。启动某个 Target 的时候,Systemd 就会启动里面所有的 Unit。从这个意义上说,Target 这个概念类似于”状态点”,启动某个 Target 就好比启动到某种状态。
查看当前系统的所有 Target
1 | $ systemctl list-unit-files --type=target |
获取当前目标
1 | systemctl list-units --type=target |
查看一个Target 包含的多有Unit
1 | $ systemctl list-dependencies multi-user.target |
查看启动时的默认 Target
1 | $ systemctl get-default |
设置启动时的默认 Target
1 | $ sudo systemctl set-default multi-user.target |
切换 Target 时,默认不关闭前一个 Target 启动的进程,
systemctl isolate 命令改变这种行为,
关闭前一个 Target 里面所有不属于后一个 Target 的进程
1 | $ sudo systemctl isolate multi-user.target |
目标表
SysV 运行级别 | Systemd 目标 | 注释 |
---|---|---|
0 | runlevel0.target, poweroff.target | 中断系统(halt) |
1, s, single | runlevel1.target, rescue.target | 单用户模式 |
2,4 | runlevel2.target, runlevel4.target, multi-user.target | 用户自定义运行级别,通常识别为级别3。 |
3 | runlevel3.target, multi-user.target | 多用户,无图形界面。用户可以通过终端或网络登录。 |
5 | runlevel5.target, graphical.target | 多用户,图形界面。继承级别3的服务,并启动图形界面服务。 |
6 | runlevel6.target, reboot.target | 重启 |
emergency | emergency.target | 急救模式(Emergency shell) |
开机启动的目标时default.target
,默认链接到graphical.target
(大致相当于原来的运行级别5)。可以通过内核参数更改默认的运行级别:
systemd.unit=multi-user.target
(大致相当于级别3)systemd.unit=rescue.target
(大致相当于级别1)
另一个方法是修改default.target
是通过systemctl
:
1 | systemctl set-default multi-user.target |
要覆盖已经设置的default.target
请使用force:
1 | systemctl set-default -f multi-user.target |
日志管理
Systemd 统一管理所有 Unit 的启动日志。带来的好处就是,可以只用journalctl
一个命令,查看所有日志(内核日志和应用日志)。日志的配置文件是/etc/systemd/journald.conf
。journalctl
功能强大,用法非常多。
1 | # 查看所有日志(默认情况下 ,只保存本次启动的日志) |
参考
https://zh.wikipedia.org/wiki/Systemd
https://wiki.archlinux.org/index.php/systemd_(%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87)
http://www.ruanyifeng.com/blog/2016/03/systemd-tutorial-commands.html
https://linux.cn/article-5926-1.html
作者: Fynn
链接: https://fynn90.github.io/2017/11/29/systemd%E5%85%A5%E9%97%A8/
本文采用知识共享署名-非商业性使用 4.0 国际许可协议进行许可