Skip to content

在Linux系统中注册服务为系统服务

systemctl是一个系统软件服务的管理工具,可以用于启动、停止、重启和重新加载服务,查看服务状态以及设置默认启动级别等。它还可以管理服务之间的依赖关系,定制服务配置,并对服务的日志进行管理。

在Linux中,定义软件服务的文件通常是systemd服务单元文件,具有.service后缀,这些文件通常位于以下目录:

powershell
/etc/systemd/system			存放的是需要开机执行的服务,该目录下有大量的链接文件,链接到/usr/lib/systemd/system/目录下,该目录下的文件才是systemd实际启动的服务脚本文件。管理员依据主机系统的需求所创建的执行脚本,执行优先级又比 /run/systemd/system/
/lib/systemd/system
/run/systemd/system/		系统执行过程中所产生的服务脚本,这些脚本的优先级要比/usr/lib/systemd/system/
/usr/lib/systemd/			systemctl脚本目录
/usr/lib/systemd/system		系统服务目录,每个服务最主要的启动脚本设置
/usr/lib/systemd/user/		用户服务目录

service文件

格式说明

service文件通常由三部分组成:

powershell
[Unit]:		定义与Unit类型无关的通用选项,用于提供unit的描述信息、unit行为及依赖关系等【启动顺序与依赖关系】
[Service]:	与特定类型相关的专用选项,此处为Service类型【启动行为】
[Install]:	定义由“systemctl enable”以及"systemctl disable“命令在实现服务启用或禁用时用到的一些选项
# 注:
# 以“#”开头的行后面的内容会被认为是注释
# 1、yes、on、true代表开启,0、no、off、false代表关闭
# 时间单位默认是秒,可以用毫秒(ms)分钟(m)等须显式说明

可选项说明

Unit部分

powershell
Description:	对当前服务的简单描述
Documentation:	文档地址
After:			可以指定在哪些服务之后进行启动
Before:			可以指定在哪些服务之前进行启动
BindsTo:		与Requires类似,它指定的 Unit 如果退出,会导致当前 Unit 停止运行
Requires:		可以指定服务依赖于哪些服务(这种依赖是"强依赖",一旦所依赖的服务异常,当前的服务也随之停止)
Wants:			可以指定服务依赖于哪些服务(这种依赖是"弱依赖",即使所依赖的服务的启动情况不影响当前的服务是否启动)
Conflicts:		定义units间的冲突关系,这里指定的 Unit 不能与当前 Unit 同时运行
Condition...:	当前 Unit 运行必须满足的条件,否则不会运行
Assert...:		当前 Unit 运行必须满足的条件,否则会报启动失败

注:After和Before字段只涉及启动顺序,不涉及依赖关系。

Service部分

powershell
EnvironmentFile:	环境配置文件,用来指定当前服务启动的环境变量
ExecStart:			指定服务启动时执行的命令或脚本
ExecStartPre:		指定服务启动前执行的命令或脚本
ExecStartPost:		指定服务启动后执行的命令或脚本
ExecStop:			指明停止服务要运行的命令或脚本
ExecStopPost:		指定服务停止之后执行的命令或脚本
RestartSec:			指定服务在重启时等待的时间,单位为秒
ExecReload:			指明重启服务要运行的命令或脚本
TimeoutSec:			定义 Systemd 停止当前服务之前等待的秒数
Restart:			当设定Restart=1 时,则当次daemon服务意外终止后,会再次自动启动此服务,具体看下列类型
PrivateTmp:			设定为yes时,会在生成/tmp/systemd-private-UUID-NAME.service-XXXXX/tmp/目录
KillMode:			指定停止的方式,具体见下面
Restart:			指定重启时的类型,具体见下面
Type:				指定启动类型,具体见下面

注:所有的启动设置之前,都可以加上一个连词号(-),表示"抑制错误",即发生错误的时候,不影响其他命令的执行。比如EnvironmentFile=-/etc/sysconfig/sshd(注意等号后面的那个连词号),就表示即使/etc/sysconfig/sshd文件不存在,也不会抛出错误。 注意:[Service]中的启动、重启、停止命令全部要求使用绝对路径!

type的可选值

powershell
simple		【默认值】指定ExecStart字段的进程为主进程
forking		ExecStart字段将以fork()方式启动,此时父进程将会退出,子进程将成为主进程(后台运行)
oneshot		类似于simple,但只执行一次,Systemd 会等它执行完,才启动其他服务
dbus		类似于simple,但会等待 D-Bus 信号后启动
notify		类似于simple,启动结束后会发出通知信号通知systemd,然后 Systemd 再启动其他服务
idle		类似于simple,但是要等到其他任务都执行完,才会启动该服务。一种使用场合是为让该服务的输出,不与其他服务的输出相混合

Restart的可选值

powershell
no:				【默认值】退出后不会重启
on-success:		当进程正常退出时(退出码为0) 执行重启
on-failure:		当进程不正常退出时(退出码不为0) 包括被信号终止和超时,执行重启
on-abnormal:	只有被信号终止和超时,才会重启
on-abort:		只有在收到没有捕捉到的信号终止时,才会重启
on-watchdog:	超时退出,才会重启
always:			不管是什么退出原因,总是重启

注:对于守护进程,推荐设为on-failure。对于那些允许发生错误退出的服务,可以设为on-abnormal。 RestartSec字段:表示 Systemd 重启服务之前,需要等待的秒数。

KillMode可选值

powershell
control-group:	【默认值】杀掉当前进程中所有的进程,当前控制组里面的所有子进程,都会被杀掉
process:		杀掉当前进程的主进程
mixed:			主进程将收到 SIGTERM 信号,子进程收到 SIGKILL 信号
none:			不杀掉任何进程,只是执行服务的 stop 命令

Install部分

定义如何安装这个配置文件,即怎样做到开机启动

powershell
Alias:			别名,可使用systemctl command Alias.service
RequiredBy:		被哪些units所依赖,强依赖
WantedBy:		被哪些units所依赖,弱依赖,表示该服务所在的 Target
Also:			安装本服务的时候还要安装别的相关服务

Target的含义是服务组,表示一组服务

WantedBy=multi-user.target指的是:所在的 Target 是multi-user.target

这个设置非常重要,因为执行systemctl enable xxxxx.service命令时,xxxxx.service的一个符号链接,就会放在/etc/systemd/system目录下面的multi-user.target.wants子目录之中

Systemd 默认的启动 Target

bash
systemctl get-default
# 输出multi-user.target

上面的结果表示,默认的启动 Target 是multi-user.target。在这个组里的所有服务,都将开机启动。这就是为什么systemctl enable命令能设置开机启动的原因。 使用 Target 的时候,systemctl list-dependencies命令和systemctl isolate命令也很有用

bash
# 查看 multi-user.target 包含的所有服务
systemctl list-dependencies multi-user.target

# 切换到另一个 target
# shutdown.target 就是关机状态
systemctl isolate shutdown.target

一般来说,常用的 Target 有两个: multi-user.target:表示多用户命令行状态; graphical.target:表示图形用户状态,它依赖于multi-user.target

Install:一般填为WantedBy=multi-user.target

service文件样例

在/usr/lib/systemd/system目录下新建service-name.service文件

shell
[UNIT]
# 服务描述
Description=Media wanager Service
# 指定了在systemd在执行完那些target之后再启动该服务
After=network.target
 
[Service]
# 定义Service的运行类型,一般是forking(后台运行)   
Type=forking
 
# 定义systemctl start|stop|reload *.service 的执行方法(具体命令需要写绝对路径)
# 注:ExecStartPre为启动前执行的命令
ExecStartPre=/usr/bin/test "x${NETWORKMANAGER}" = xyes
ExecStart=/home/mobileoa/apps/shMediaManager.sh -start
ExecReload=
ExecStop=/home/mobileoa/apps/shMediaManager.sh -stop
 
# 创建私有的内存临时空间
PrivateTmp=True
 
[Install]
# 多用户
WantedBy=multi-user.target

将自己部署的nginx注册为系统服务

shell
[Unit]
Description=The nginx web and reverse proxy server
Documentation=https://nginx.org/en/docs/
After=network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target

[Service]
Type=forking
#启动检测命令
ExecStartPre=/usr/local/nginx/sbin/nginx -t
#启动命令
ExecStart=/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
#重载配置文件命令
ExecReload=/usr/local/nginx/sbin/nginx -s reload
#停止命令
ExecStop=/usr/local/nginx/sbin/nginx -s quit

[Install]
WantedBy=multi-user.target

将自己部署的mysql注册为系统服务

shell
[Unit]
Description=Mysql
After=syslog.target network.target remote-fs.target nss-lookup.target
 
[Service]
Type=forking
#指定PID文件
PIDFile=/usr/local/mysql/data/centos-linux.shared.pid
#启动MySQL
ExecStart=/usr/local/mysql/support-files/mysql.server start
#重载
ExecReload=/bin/kill -s HUP $MAINPID
#停止服务
ExecStop=/usr/local/mysql/support-files/mysql.server stop
PrivateTmp=false
 
[Install]
WantedBy=multi-user.target

systemctl命令合集

shell
# 语法
systemctl COMMAND name.service

# 启动
systemctl start name.service
# 停止
systemctl stop name.service
# 重启
systemctl restart name.service
# 查看状态
systemctl status name.service
# 设定某服务开机自启,相当于chkconfig name on
systemctl enable name.service
# 设定某服务开机禁止启动:相当于chkconfig name off
systemctl disable name.service
# 禁止自动和手动启动
systemctl mask name.service
# 取消禁止
systemctl unmask name.service
# 重新加载配置文件
systemctl daemon-reload
# 查看所有服务的开机自启状态,相当于chkconfig --list
systemctl list-unit-files --type service
# 查看某服务当前激活与否的状态
systemctl is-active name.service
# 查看服务是否开机自启
systemctl is-enabled name.service
# 查看某服务当前启动失败与否的状态
systemctl is-failed name.service
# 查看所有已经激活的服务
systemctl list-units --type|-t service
# 查看所有服务
systemctl list-units --type service --all
# 用来列出该服务在哪些运行级别下启用和禁用:chkconfig –list name
ls /etc/systemd/system/*.wants/name.service
# 列出失败的服务
systemctl --failed --type=service
# 开机并立即启动或停止
systemctl enable --now postfix
systemctl disable --now postfix
# 查看服务的依赖关系
systemctl list-dependencies name.service
# 杀掉进程
systemctl kill unitname
# 关机
systemctl halt、systemctl poweroff
# 重启
systemctl reboot
# 挂起
systemctl suspend
# 休眠
systemctl hibernate
# 休眠并挂起
systemctl hybrid-sleep
# 开机时不启动图形界面
systemctl set-default multi-user.target
# 开机时启动图形界面
systemctl set-default graphical.target

启动分析

分析关键耗时

bash
systemd-analyze critical-chain

分析每个服务的耗时

bash
systemd-analyze blame

将每个服务的耗时输出到图片

bash
systemd-analyze plot > boot.svg

列出所有开机自动启动的服务

bash
systemctl list-unit-files --type=service | grep enabled