Systemd
Systemd(system daemon)实现系统服务间的依赖关系,并依此实现系统初始化时服务的并行启动,同时达到降低Shell的系统开销,最终替代init。
Systemd采用了一下新技术:
-
采用Socket激活式与总线激活式服务,以提高相互依赖的各服务的并行运行性能。
-
采用Cgroups替代PID来追踪进程,即使是两次fork之后生成的守护进程也不会脱离systemd的控制。
Systemd Unit
学习Systemd的第一步,就是搞懂 Unit(单元)是什么?
Unit就是Systemd的最小 功能/管理 单位,是单个进程的描述。一个个小的Unit相互调用和依赖,组成一个庞大的任务管理系统,这就是Systemd的基本思想。
由于Systemd要做到事情太多,导致Unit有很多种不同的类型:
-
Service Unit - 用于定义系统服务
-
Target Unit - 用于模拟实现“运行级别”
-
Socket Unit - 用于Systemd监听Socket,在有连接的时候再启动。
-
Device Unit - 用于定义内核识别的设备
-
Mount Unit - 用于定义文件系统挂载
-
Snapshot Unit - 用于管理系统快照
-
Swap Unit - 用于标识swap设备
-
Automount Unit - 用于文件系统自动挂载
-
Path Unit - 用于定义文件系统中的文件或目录
所有的Unit文件都存放在 /usr/lib/systemd/system和/etc/systemd/system
-
-
通常由三部分组成,[Unit] [Service] [Install],各部分释义:
[Unit] 段的常用选项:
Description:描述信息; 意义性描述;
After:定义unit的启动次序,表示当前unit应该晚于哪些unit启动;其功能与Before相反;
Requies:依赖到的其它units;强依赖,被依赖的units无法激活时,当前unit即无法激活;
Wants:依赖到的其它units;弱依赖;
Conflicts:定义units间的冲突关系
[Service] 段的常用选项:
Type:用于定义影响ExecStart及相关参数的功能的unit进程启动类型,其类型有:
simple:默认值,执行ExecStart指定的命令,启动主进程
forking:以 fork 方式从父进程创建子进程,创建后父进程会立即退出
oneshot:一次性进程,Systemd 会等当前服务退出,再继续往下执行
dbus:当前服务通过D-Bus启动
notify:当前服务启动完毕,会通知systemd再继续往下执行
idle:若有其他任务执行完毕,当前服务才会运行
EnvironmentFile:环境配置文件;
ExecStart:指明启动unit要运行命令或脚本;
ExecStartPre:在ExecStart之前运行;
ExecStartPost:在ExecStart之后运行;
ExecReload: 指明重新加载配置的命令或脚本; #示例 ExecReload=/bin/kill -HUP $MAINPID
ExecStop:指明停止unit要运行的命令或脚本;
Restart:当设定Restart=1时,则当次daemon服务意外终止后,会再次自动启动。
[Install] 段的常用选项:
Alias:别名,可使用systemctl command Alias.service;
RequiredBy:被哪些units所依赖;
WantedBy:被哪些units所依赖
注意:对于新建或修改unit文件,需要通过命令 systemctl daemon-reload 重新加载。
- Service Unit只是定义了如何执行任务,还必须通过Timer Unit定义执行时间,示例:
**定义Timer调用的my-timer.service **
[Unit]
Description = MyTimer
[Service]
ExecStart = /bin/echo "...Hello MyTimer..."
**定义调用Service的my-timer.timer**
[Unit]
Description = Runs mytimer every minutes
[Timer]
OnUnitActiveSec = 1m
Unit = mytimer.service
[Install]
WantedBy = multi-user.target
# [Timer] 字段
OnActiveSec:定时器生效后,多少时间开始执行任务
OnBootSec:系统启动后,多少时间开始执行任务
OnStartupSec:Systemd 进程启动后,多少时间开始执行任务
OnUnitActiveSec:该单元上次执行后,等多少时间再次执行
OnUnitInactiveSec: 定时器上次关闭后多少时间,再次执行
OnCalendar:基于绝对时间,而不是相对时间执行
AccuracySec:如果因为各种原因,任务必须推迟执行,推迟的最大秒数,默认是60秒
Unit:真正要执行的任务,默认是同名的带有.service后缀的单元
Persistent:如果设置了该字段,即使定时器到时没有启动,也会自动执行相应的单元
WakeSystem:如果系统休眠,是否自动唤醒系统
Socket Unit
-
以 "
.socket
" 为后缀的单元文件, 封装了一个用于进程间通信的套接字(socket)或管道(FIFO), 以支持基于套接字的启动。 -
让Systemd监听Socket,在有连接的时候再启动该Unit,需要同名的Service。
- 可以查看系统自带的sshd.socket示例。
Target Unit
-
Target是指一组相关进程,有点像init进程模式下面的启动级别。
-
当WantedBy设置为指定target时,执行systemctl enable/disable [UnitName]时,会自动创建软连接到/usr/lib/systemd/system下对应的target.wants目录中
-
可以通过 systemctl get-default 查看当前运行级别。
- Target 与 传统 RunLevel 的对应关系如下:
- Runlevel 0 == poweroff.target
- Runlevel 1 == rescue.target
- Runlevel 2 == multi-user.target
- Runlevel 3 == multi-user.target
- Runlevel 4 == multi-user.target
- Runlevel 5 == graphical.target
- Runlevel 6 == reboot.target
Systemd Command
# 查看单元状态
## active (running): 进程持续的运行中
## active (exited): 进程成功完成一次执行
## active (waiting): 进程等待中
## inactive: 未运行
$ systemctl status [UnitName]
# 查看是否已启用该单元
## enable、disable或static
## static是指对应的Unit文件中没有定义[Install]区域,因此无法配置为开机启动服务。
$ systemctl is-enabled [UnitName]
# 开机自动执行该单元
$ systemctl enable [UnitName]
# 关闭开机自动执行
$ systemctl disable [UnitName]
# 启动单元
$ systemctl start [UnitName]
# 关闭单元
$ systemctl stop [UnitName]
# 重启单元
$ systemctl restart [UnitName]
# 重新加载服务配置,而不中断服务
$ systemctl reload [UnitName] # 类似于 nginx -s reload
# 杀死单元进程
$ systemctl kill [UnitName]
# 禁止服务,无法启动或开机启动
$ systemctl mask [UnitName]
# List units that systemd currently has in memory.
$ systemctl list-units
# List unit files installed on the system, in combination with their enablement state (as reported by is-enabled).
$ systemctl list-unit-files
# Shows units required and wanted by the specified unit.
$ systemctl list-dependencies
Systemd 架构图