前言
在 Linux
生态系统中,Systemd
被部署到大多数标准 Linux
发行版中,作为默认初始化系统和服务管理器,.service
文件是 Systemd
的单元配置文件,用于定义服务的启动、停止、依赖关系等行为,通过编写 .service
文件,可以将自定义服务集成到系统服务管理中。而systemctl
是一个 Systemd
工具,主要负责控制 Systemd
系统和服务管理器。
检查 Systemd 是否安装
检查系统中是否安装有 Systemd
并确定安装版本。
systemctl --version
打印如下,表明当前系统已安装 Systemd
。
systemd 219
+PAM +AUDIT +SELINUX +IMA -APPARMOR +SMACK +SYSVINIT +UTMP +LIBCRYPTSETUP +GCRYPT +GNUTLS +ACL +XZ +LZ4 -SECCOMP +BLKID +ELFUTILS +KMOD +IDN
Systemd 的 Unit 文件
Systemd
可以管理所有系统资源,不同的资源统称为 Unit
(单位)。
在 Systemd
生态圈中,Unit 文件统一了过去各种不同系统资源配置格式,如:服务的启动/停止、定时任务、设备自动挂载、网络配置、虚拟内存等,而 Systemd
通过不同的文件后缀来区分这些配置文件。
Systemd 支持的 12 种 Unit 文件类型
.automount
:用于控制自动挂载文件系统,相当于 SysV-init 的 autofs 服务。.device
:对于 /dev 目录下的设备,主要用于定义设备之间的依赖关系。.mount
:定义系统结构层次中的一个挂载点,可以替代过去的 /etc/fstab 配置文件。.path
:用于监控指定目录或文件的变化,并触发其它 Unit 运行。.scope
:这种 Unit 文件不是用户创建的,而是 Systemd 运行时产生的,描述一些系统服务的分组信息。.service
:封装守护进程的启动、停止、重启和重载操作,是最常见的一种 Unit 文件。.slice
:用于表示一个 CGroup 的树,通常用户不会自己创建这样的 Unit 文件。.snapshot
:用于表示一个由 systemctl snapshot 命令创建的 Systemd Units 运行状态快照。.socket
:监控来自于系统或网络的数据消息,用于实现基于数据自动触发服务启动。.swap
:定义一个用户做虚拟内存的交换分区。.target
:用于对 Unit 文件进行逻辑分组,引导其它 Unit 的执行。它替代了 SysV-init 运行级别的作用,并提供更灵活的基于特定设备事件的启动方式。.timer
:用于配置在特定时间触发的任务,替代了 Crontab 的功能。
Systemd 目录
按照 Systemd
约定,Unit
文件应该放置在指定的三个系统目录之一中,优先级由上往下,因此在三个目录中有同名文件时,只有优先级最高的目录里的文件会被使用。
/etc/systemd/system
:系统或用户自定义的配置文件。/run/systemd/system
:软件运行时生成的配置文件。/usr/lib/systemd/system
:系统或第三方软件安装时添加的配置文件。
systemd
默认从目录 /etc/systemd/system/
中读取配置文件,但是大部分文件都是符号链接,指向实际配置文件存放目录 /usr/lib/systemd/system/
。
Unit 和 Target
Unit 是 Systemd 管理系统资源的基本单元,可以认为每个系统资源就是一个 Unit,并使用一个 Unit 文件定义,在 Unit 文件中,需要包含相应服务的描述、属性以及需要运行的命令。
Target 是 Systemd 中用于指定系统资源启动组的方式,简单理解就是,Target 是一个 Unit 组,包含许多相关的 Unit,启动某个 Target 的时候,Systemd 就会启动里面所有的 Unit, 类似于一个状态点,启动某个 Target 就好比启动到某种状态。
Systemd Service Unit
Unit 文件结构
以 sshd.service
为例,文件结构如下:
# /usr/lib/systemd/system/sshd.service
[Unit]
Description=OpenSSH server daemon
Documentation=man:sshd(8) man:sshd_config(5)
After=network.target sshd-keygen.service
Wants=sshd-keygen.service
[Service]
Type=notify
EnvironmentFile=/etc/sysconfig/sshd
ExecStart=/usr/sbin/sshd -D $OPTIONS
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
RestartSec=42s
[Install]
WantedBy=multi-user.target
如上所示,Systemd
服务的 Unit
文件可以分为三个配置片段:
Unit
和Install
:所有Unit
文件通用,用于配置服务的描述、依赖和启动方式。Service
:服务类型的Unit
文件(后缀为.service
)特有的,用于设置服务的管理和操作方法。
[Unit]
用来配置服务的描述信息、依赖关系和随系统启动的方式。
Description
:服务的描述信息,可以是任意字符串。Documentation
:指定服务的文档,可以是一个或多个 URL 地址。After
:在指定依赖之后运行,多项以空格分隔。(仅影响启动顺序)Before
:在指定依赖之前运行,多项以空格分隔。(仅影响启动顺序)Wants
:设置弱依赖
关系,即所依赖服务启动失败或停止,不会影响当前服务。Requires
:设置强依赖
关系,即所依赖服务启动失败或停止,当前服务也必须退出。.....
依赖支持如下:
依赖条件 | 描述 |
---|---|
network.target | 表示网络就绪 |
network-online.target | 表示网络完全就绪 (需要 NetworkManager-wait-online.service 支持) |
syslog.target | 表示系统日志服务就绪 |
例:postgresql.service | 表示 postgresql 服务就绪 |
[Service]
定义服务的运行参数,
Type
:指定服务启动类型,支持类型如下:
类型 | 描述 |
---|---|
simple | 默认值,主进程由 ExecStart 启动后不后台化(适用于前台程序)。 |
forking | 服务启动会派生到后台(需配合 PIDFile 指定 PID 文件)。 |
onshot | 进程退出后服务视为完成(适合执行一次性任务,如初始化脚本)。 |
dbus | 服务通过 D-Bus 激活(如桌面应用通信)。 |
notify | 服务通过 sd_notify 发送 READY=1 信号告知启动完成(需程序支持)。 |
idle | 若有其他任务执行完毕,当前服务才会运行。 |
User
:服务运行的用户,应避免使用root
,建议创建专用用户。Group
:服务运行的用户组。PIDFile
:服务PID
文件,可不填,如果填了,服务需要生成PID
文件,否则不能启动。ExecStart
:服务启动命令。ExecStop
:服务停止命令。WorkingDirectory
:服务启动时的工作目录。Environment
:为服务指定环境变量。EnvironmentFile
:服务环境参数文件。Restart
:服务退出后的重启策略,支持策略如下:
策略 | 描述 |
---|---|
no | 不重启(默认值)。 |
always | 无论退出状态码如何都重启。 |
on-failure 推荐 | 仅在非正常退出(状态码非 0)时重启。 |
on-abnormal | 仅在因信号终止或超时情况下重启。 |
on-abort | 仅在未正常终止(如:SIGABRT )时重启。 |
on-watchfdog | 仅在看门狗超时情况下重启(需配置 RuntimeWatchdogSec )。 |
TimeoutStartSec
:启动服务时等待的秒数。TimeoutStopSec
:停止服务时等待的秒数。RestartSec
:服务退出后,重启前的等待时间,避免设置较短频繁重启导致系统负载过高。ExecReload
:服务重启的命令。ExecStartPre
:服务启动之前执行的命令。ExecStartPost
:服务启动之后执行的命令。ExecStopPost
:服务停止之后执行的命令。PrivateTmp
:是否给服务分配独立的临时空间。
[Install]
配置特定目标的 .target
文件,用来使得服务在系统启动时自动运行。
WantedBy
:定义依赖当前服务的模块,在哪些目标(target)下会被激活,当 Unit 激活时,符号链接会放入/etc/systemd/system/<Target名>.wants/
目录中,支持目标参数如下:
目标 | 描述 |
---|---|
multi-user.target | 多用户命令行模式(CentOS 7 默认运行级别 3)。 |
graphical.target | 图形界面模式(运行级别 5)。 |
default.target | 系统默认目标(通常是 multi-user.target 或 graphical.target )。 |
也可通过如下命令,查看当前正在使用的运行目标。
systemctl list-units --type=target
如下:
UNIT LOAD ACTIVE SUB DESCRIPTION
basic.target loaded active active Basic System
cryptsetup.target loaded active active Local Encrypted Volumes
getty.target loaded active active Login Prompts
local-fs-pre.target loaded active active Local File Systems (Pre)
local-fs.target loaded active active Local File Systems
multi-user.target loaded active active Multi-User System
network-online.target loaded active active Network is Online
network.target loaded active active Network
nfs-client.target loaded active active NFS client services
paths.target loaded active active Paths
remote-fs-pre.target loaded active active Remote File Systems (Pre)
remote-fs.target loaded active active Remote File Systems
rpc_pipefs.target loaded active active rpc_pipefs.target
rpcbind.target loaded active active RPC Port Mapper
slices.target loaded active active Slices
sockets.target loaded active active Sockets
swap.target loaded active active Swap
sysinit.target loaded active active System Initialization
timers.target loaded active active Timers
LOAD = Reflects whether the unit definition was properly loaded.
ACTIVE = The high-level unit activation state, i.e. generalization of SUB.
SUB = The low-level unit activation state, values depend on unit type.
RequireBy
:定义依赖当前服务的模块,在哪些目标(target)下会被激活,当 Unit 激活时,符号链接会放入/etc/systemd/system/<Target名>.required/
目录中。Also
:Alias
:当前 Unit 可用于启动的别名。
创建服务
使用 vim
编辑器,打开并创建 myApp.service
。
vim /lib/systemd/system/myApp.service
常用命令
命令 | 说明 |
---|---|
systemctl start <service> | 启动服务 |
systemctl stop <service> | 停止服务 |
systemctl restart <service> | 重启服务 |
systemctl status <service> | 查看服务状态 |
systemctl reload <service> | 重载服务 |
systemctl enable <service> | 启用开机自启动 |
systemctl disable <service> | 禁用开机自启动 |
journalctl -u <service> | 查看服务日志 |