systemd 的使用
在配置程序开机自启时,常常会用到 systemctl,其是 systemd 的主命令,用于管理系统。systemd 名字来源于 Unix 中的一个惯例:在 Unix 中常以 ‘d’ 作为系统守护进程(daemon,亦称为后台进程)的后缀标识。systemd 是 Linux 系统下的一套中央化系统及设定管理程式(init),包括守护进程、程式库以及应用软体,由 Lennart Poettering 带头开发。目前绝大多数的 Linux 发行版都已采用 systemd 代替原来的 System V,除了 systemctl,systemd 还引入了 localectl
、timedatectl
、hostnamectl
等新命令,使得系统配置更方便。本篇以 Ubuntu 为例,所有命令以普通用户运行,部分命令需要 sudo 权限。
常用命令
设置开机自启
支持 systemd 的软件,在安装的时候会自动在 /lib/systemd/system
目录中添加一个配置文件。设置开机自启命令如下
1 | sudo systemctl enable docker |
执行上面命令之后,会在 /etc/systemd/system
目录或其下的 *.target.wants
下添加一个符号链接,*
跟 docker.service
里的配置项 WantedBy
相关。开机时, systemd 只执行 /etc/systemd/system
目录里面的配置文件。当把修改后的 .service 配置文件直接放在 /etc/systemd/system 目录下会覆盖原始配置。
获取 systemd 默认启动服务组(即上面的 target)方法如下:
1 | systemctl get-default |
启动服务
默认安装的软件会自动设置开机自启和立即启动服务。但有时程序停止后,需要启动。常使用如下命令
1 | sudo systemctl start docker |
查看程序是否启动成功,可以使用如下命令
1 | sudo systemctl status docker |
正常结果如下:
1 | ● docker.service - Docker Application Container Engine |
上面输出结果含义:
Loaded
表示配置文件的位置,是否设为开机自启;Active
表示运行状态,active 表示正在运行,inactive 表示没有运行;Docs
表示文档说明信息;Main PID
表示主进程;Tasks
表示子进程数;CGroup
表示应用的所有子进程;日志块 最下面的以日期开头的表示程序运行日志信息
查看实时日志信息,可以使用如下命令:
1 | sudo journalctl -u docker -f |
停止服务
当需要停止服务时,可使用如下命令:
1 | sudo systemctl stop docker |
有时候,该命令可能没有相应,服务停不下来。这个时候可以使用 kill
向正在运行的进程发出 “杀进程” 的信号。
1 | sudo systemctl kill docker |
如果更改了 docker.service
里面的信息,那么需要重新加载,然后重启
1 | sudo systemctl daemon-reload |
配置文件
服务的运行启动完全有配置文件决定。一般 systemd 运行的软件的配置文件主要放在 /usr/lib/systemd/system
或 /etc/systemd/system
目录下。找到配置文件后我们可以使用 vim
打开。或者使用如下命令查看。
1 | systemctl cat sshd.service |
结果大概是这样
1 | # /lib/systemd/system/ssh.service |
配置文件分成 Unit, Service, Install
三个块。下面分别对其进行介绍。
Unit:启动顺序与依赖关系
1 | [Unit] |
Description
表示当前服务的简单描述;有时还会有
Documentation
字段,给出文档位置;After
表示如果network.target, auditd.service
如果需要启动,那么sshd
应在它们之后启动;有时会有
Before
字段,表示在哪些服务之前启动;After
和Before
只涉及启动顺序,不涉及依赖关系;有时会有
Wants
字段,表示该程序与其有”弱依赖“关系;有时会有
Requires
字段,表示该程序与其有“强依赖”关系;
Service:启动行为
1 | [Service] |
Service 区块定义了如何启动当前服务。
EnvironmentFile
指定当前服务的环境参数文件。该文件内部是key=value
键值对,可以用$key
获取参数文件中的值;上面配置文件中有时会有-
,表示“抑制错误”,即发生错误时,不影响其他命令执行;ExecReload
字段:重启服务时执行的命令ExecStop
字段:停止服务时执行的命令ExecStartPre
字段:启动服务之前执行的命令ExecStartPost
字段:启动服务之后执行的命令ExecStopPost
字段:停止服务之后执行的命令KillMode
字段:定义 systemd 如何停止服务,上面的 process 表示只停止主进程,不停止任何 sshd 子进程,即子进程打开的 SSH session 仍然保持连接。这对于 SSH 很重要,不会连自己打开的 SSH session 一起杀掉;除了 process,还有 control-group (默认值),当前控制组里面的所有子进程都会被杀掉;mixed 主进程将收到 SIGTERM 信号,子进程收到 SIGKILL 信号;none 没有进程会被杀掉,只是执行服务的 stop 命令;Restart
字段:定义了 sshd 退出后,systemd 的重启方式,默认为 no,表示退出后不会重启;on-success 表示只有正常退出时(退出状态码为 0)才会重启;on-failure 表示非正常退出时(退出状态码非 0),包括被信号终止和超时,才会重启;on-abnormal 表示只有被信号终止和超时,才会重启;on-abort 表示只有在收到没有博捉到的信号终止时,才会重启;on-watchdog 表示超时退出,才会重启;always 表示不管是什么原因退出,总是重启;Type
字段:定义启动类型。simple(默认值):ExecStart 字段启动的进程为主进程;forking:ExecStart 字段将以 fork() 方式启动,此时父进程将会退出,子进程将成为主进程;oneshot:类似于 simple,但只执行一次,systemd 会等它执行完,才启动其他服务;dbus:类似于 simple,但会等待 D-Bus 信号后启动;notify:类似于 simple,启动结束后会发出通知信号,然后 systemd 再启动其他服务;idle:类似于 simple,但是要等到其他任务都执行完,才会启动该服务。一种使用场合是为让该服务的输出,不与其他服务的输出相混合。
Install 区块
Install 区块定义如何按照这个配置文件,即怎样做到开机自启。
1 | [Install] |
WantedBy
字段:表示该服务所在的 Target,Target 的含义是服务组,表示一组服务。WantedBy=multi-user.target
指的是, sshd 所在的 Target 是multi-user.target
。这个设置非常重要,因为在执行systemctl enable sshd
命令时,sshd.service
的一个符号链接,就会放在/etc/systemd/system
目录下面的multi-user.target.wants
子目录之中。获取 systemd 默认的启动 target 命令是systemctl get-default
.
关于 target 有如下两个命令
1 | # 查看 multi-user.target 包含的所有服务 |
一般来说,常用的 Target 有两个:一个是multi-user.target
,表示多用户命令行状态;另一个是graphical.target
,表示图形用户状态,它依赖于multi-user.target
.
查看 target 的配置文件
1 | systemctl cat multi-user.target |
结果如下
1 | # /lib/systemd/system/multi-user.target |
注意,Target 配置文件里面没有启动命令。
上面输出结果中,主要字段含义如下。
Requires
字段:要求basic.target
一起运行。
Conflicts
字段:冲突字段。如果rescue.service
或rescue.target
正在运行,multi-user.target
就不能运行,反之亦然。
After
:表示multi-user.target
在basic.target
、rescue.service
、rescue.target
之后启动,如果它们有启动的话。
AllowIsolate
:允许使用systemctl isolate
命令切换到multi-user.target
。