systemd 服务脚本编写和管理

systemd 服务脚本编写和管理

基础

Linux系统管理服务的方式

管理服务的方式取决于初始化系统

初始化系统和服务管理器 说明 适用
systemd 配置文件unit,使用systemd命令集管理 CentOS7/RHEL7以及以后版本
init.d 适用脚本文件管理服务:/etc/init.d/ CentOS6 以及之前版本中
Upstart 事件驱动的初始化系统 较老的Ubuntu系统
rc.d 与init.d类似 较老的Ubuntu系统

当前,systemd取代了传统的init系统,成为许多Linux发行版的默认初始化系统。

systemd

功能简介

功能 说明
服务管理 命令语法:systemctl [command] [unit](配置的应用名称)
启动/停止/重启:sudo systemctl start/stop/restart <service_name>
重新加载配置:sudo systemctl reload <service_name>
查看状态:sudo systemctl status <service_name>
启用/禁用:sudo systemctl enable/disable <service_name>
查看所有服务状态:systemctl list-units --type=service
查看服务日志:journalctl -u <service_name>
服务依赖管理 允许你定义服务之间的依赖关系,以确保服务按照正确的顺序启动或停止
自动重启管理 可以配置服务在崩溃后自动重启
日志管理 包含 journal 功能,用于集中化管理和查看系统日志
并行化管理 ?并行启动多个服务
cgroups支持 使用控制组(cgroups)来管理和限制服务的资源使用,例如CPU和内存
目标(Targets) 取代传统的运行级别,systemd 使用目标(targets)来定义系统的不同状态,例如多用户模式、图形界面模式等
定时任务 提供了 systemd-timers 作为定时任务的替代工具,类似于 cron
socket激活 支持 socket 激活,允许服务在需要时启动,并在有请求到达时监听特定的端口或套接字

基本概念

术语 解释
单元Unit 使用单元表示可管理的对象:服务service、套接字socket、设备device、挂载点mount、目标target。
每一个单元都有一个配置文件:通常位于 /etc/systemd/system//lib/systemd/system/

常见的单元:

术语 解释
服务单元Service unit 文件扩展名为.service,用于定义系统服务(常用)
目标单元Target unit 文件名扩展为.target,用于模拟实现“运行级别”
挂载单元Mount unit 文件名扩展为.mount,定义文件系统挂载点

Systemd是内核启动后的第一个用户进程,PID为1,是所有其它用户进程的父进程。

service unit

扩展名.service

存放路径:

路径 说明
/etc/systemd/system/* 系统管理员和用户自定义创建的服务单元的主要位置
在此目录下创建的单元文件具有最高的优先级,会覆盖掉其他的同名文件
通常用于定义本地服务和自定义服务单元
/usr/lib/systemd/system/* 该目录中包含的是软件包安装的单元
也就是说通过yum、dnf、rpm等软件包管理命令管理的systemd单元文件,都放置在该目录下。
/lib/systemd/system 指向/usr/lib/systemd/system
/run/systemd/system/* 运行时生成的服务单元文件和临时文件, 一般很少修改,系统重启会消失

systemd 默认从目录/etc/systemd/system/读取配置文件。但是,里面存放的大部分文件都是符号链接,指向目录 /usr/lib/systemd/system/,真正的配置文件是(自动生成)存放在这个目录。

注释:ubuntu20.04的/etc/systemd/system/目录下符号链接指向/lib/systemd/system,可将service文件放置在/lib/systemd/system目录

示例:ubuntu:/lib/systemd/system下NetworkManager.service文件

[Unit]
Description=Network Manager
Documentation=man:NetworkManager(8)
Wants=network.target
After=network-pre.target dbus.service
Before=network.target

[Service]
Type=dbus
BusName=org.freedesktop.NetworkManager
ExecReload=/usr/bin/busctl call org.freedesktop.NetworkManager /org/freedesktop/NetworkManager org.freedesktop.NetworkManager Reload u 0
#ExecReload=/bin/kill -HUP $MAINPID
ExecStart=/usr/sbin/NetworkManager --no-daemon
Restart=on-failure
# NM doesn't want systemd to kill its children for it
KillMode=process
CapabilityBoundingSet=CAP_NET_ADMIN CAP_DAC_OVERRIDE CAP_NET_RAW CAP_NET_BIND_SERVICE CAP_SETGID CAP_SETUID CAP_SYS_MODULE CAP_AUDIT_WRITE CAP_KILL CAP_SYS_CHROOT

ProtectSystem=true
ProtectHome=read-only

[Install]
WantedBy=multi-user.target
Also=NetworkManager-dispatcher.service

# We want to enable NetworkManager-wait-online.service whenever this service
# is enabled. NetworkManager-wait-online.service has
# WantedBy=network-online.target, so enabling it only has an effect if
# network-online.target itself is enabled or pulled in by some other unit.
Also=NetworkManager-wait-online.service

整个文件分为三个部分:[Unit]·[Service]·[lnstall]

区分 说明
Unit 记录unit文件的通用信息:元数据和依赖关系,控制服务的启动顺序和依赖性
Service 定义服务的执行细节:控制服务如何启动、停止以及如何管理进程
Install 定义服务的安装行为:控制服务与系统目标的关联性

选项说明

区分 选项 说明
Unit Description 对本service的描述
Documentation 提供有关服务的文档链接/手册页
Wants 定义服务的弱依赖关系
NetworkManager 需要 network.target(一个系统目标,表示网络服务的状态)存在
但如果 network.target 没有启动,NetworkManager 仍然会尝试启动
Before/After 定义服务的启动顺序
Before=xxx.service,代表本服务在xxx.service启动之前启动
After=xxx.service,代表本服务在 xxx之后启动
Requires 该服务依赖的其他服务或目标。如果指定的服务或目标未能启动,本服务也不会启动。
Service Type 服务的启动类型
service的种类:
simple:默认,最简单的服务类型。启动的程序就是主体程序,这个程序要是退出,那么一切都退出
forking:标准启动方式。服务包含父、子进程,启动程序后会调用fork()函数,通过父进程生成子进程。
oneshot:这种服务类型就是启动完成,进程就没了。属于一次性启动。
notify:跟simple类似,但是notify会在当前服务启动完毕,发送一个信号通知Systemd。
EnvironmentFile:环境配置文件
dbus:表示该服务将注册一个 D-Bus 名称并在 D-Bus 总线上运行
BusName D-Bus 总线上用于标识服务的名称
NetworkManager 在 D-Bus 上的唯一标识符
ExecReload 重新加载服务配置时执行的命令
ExecStartPre/ExecStartPost ExecStart执行前/后所调用的命令
ExecStart/ExecStop 服务启动时执行的命令,此命令就是服务的主体 / 停止当前服务时执行的命令
注意:启动、重启、停止命令全部要求使用绝对路径
--no-daemon:前台运行,不会作为守护进程后台运行
Restart 配置服务的重启策略
no:服务终止后不会自动重启
on-success:只有在服务正常退出(即返回状态码为 0)时才会自动重启
on-failure:: 只有在服务因失败退出(即返回状态码为非 0)或因信号(非 SIGTERM)终止时才会自动重启
on-abnormal:只有在服务因非标准的原因终止时(如由于信号 SIGKILL, SIGSEGV 等)才会自动重启
on-abort:只有在服务因未捕获的信号(如 SIGABRT)而终止时才会自动重启
on-watchdog:仅当 systemd 的看门狗检测到服务未响应并强制终止时才会自动重启
always:无论服务如何终止,都会自动重启
RestartSec 与 Restart 选项一起使用,用于设置重启服务前的等待时间,以秒为单位
KillMode 指定当服务被停止或重启时,systemd 如何处理该服务及其子进程
control-group:默认,终止属于该服务的整个控制组(cgroup)中的所有进程(主进程和子进程),适用于需要确保所有相关进程都被停止的情况
process:只会终止主进程,不会终止其生成的子进程,适用于服务需要自行管理子进程的场景
mixed:systemd 会发送 SIGTERM 信号给主进程,并向该服务的其他子进程发送 SIGKILL 信号(强制终止),适用于希望主进程有机会正常终止,但强制终止所有子进程的场景
none:systemd 不会终止任何进程。当服务被停止或重启时,systemd 仅会将服务标记为已停止,而不发送任何信号,适用于服务进程需要独立管理其生命周期,或者某些进程必须在 systemd 外继续运行的场景
CapabilityBoundingSet 该服务进程可以使用的 Linux 能力集合
能力(capabilities)是一种比传统的 root 权限更细粒度的权限控制方式
CAP_NET_ADMIN(网络管理)
CAP_NET_RAW(原始套接字操作)
CAP_SETUID(设置用户ID)
CAP_SETGID(设置组ID)
ProtectSystem true-开启systemd的一个保护机制,使系统文件变为只读状态
ProtectHome read-only使用户的主目录变为只读
Install WantedBy 在何种情况下,服务都可以被启用。
multi-user.target:多用户环境下启用
Also 其他相关服务单元文件,当启用或禁用本服务时,这些文件也会相应地启用或禁用

示例

测试环境:ubuntu20.04

1、编写服务脚本

/root/systemd_test.sh

#!/bin/bash
while true
do
        echo `date`
        sleep 60
done

赋权

chmod +x /root/systemd_test.sh

2、编写systemd service

systemd_my.service

[Unit]
Description=date daemon
 
[Service]
ExecStart=/root/systemd_test.sh
Restart=always
Type=simple
 
[Install]
WantedBy=multi-user.target

3、放置service文件位置

/lib/systemd/system

4、启动服务

# 重新加载 systemd 的配置
sudo systemctl daemon-reload
# 启动服务
systemctl start systemd_my.service
# 查看服务状态
systemctl status systemd_my.service	

错误

1、Failed with result 'start-limit-hit'

【错误信息】

示例脚本设置:

#!/bin/bash
exit 0

while true
do
        echo `date`
        sleep 60
done

重启服务引发错误

● systemd_my.service - date daemon
     Loaded: loaded (/lib/systemd/system/systemd_my.service; disabled; vendor preset: enabled)
     Active: failed (Result: start-limit-hit) since Wed 2024-08-14 10:07:07 CST; 7s ago
    Process: 138519 ExecStart=/root/systemd_test.sh (code=exited, status=0/SUCCESS)
   Main PID: 138519 (code=exited, status=0/SUCCESS)

8月 14 10:07:07 lym-vm systemd[1]: systemd_my.service: Scheduled restart job, restart counter is at 5.
8月 14 10:07:07 lym-vm systemd[1]: Stopped date daemon.
8月 14 10:07:07 lym-vm systemd[1]: systemd_my.service: Start request repeated too quickly.
8月 14 10:07:07 lym-vm systemd[1]: systemd_my.service: Failed with result 'start-limit-hit'.
8月 14 10:07:07 lym-vm systemd[1]: Failed to start date daemon.

【原因】

Start request repeated too quickly表示: systemd 尝试启动你的服务多次,但因为启动请求过于频繁,导致达到了启动限制。systemd 出于保护机制,停止进一步尝试启动该服务,并给出了 start-limit-hit 的错误。

【解决】

(1)调整启动限制参数

StartLimitIntervalSec: 指定启动限制时间窗口的长度(单位为秒)。在这个时间窗口内,systemd 将应用 StartLimitBurst 限制。

StartLimitBurst: 指定在 StartLimitIntervalSec 时间内允许的最大启动次数。

[Service]
StartLimitIntervalSec=60  # 在 60 秒内
StartLimitBurst=5         # 允许最多 5 次启动尝试

(2)设置启动条件

Restart=on-failure # 根据需求选择

参考

1、systemd 服务脚本编写与管理_systemd脚本-CSDN博客

2、linux系统编写Systemd Service方法(Redhat9)_如何写入systemd服务-CSDN博客

posted @ 2024-08-14 09:52  circlelll  阅读(43)  评论(0编辑  收藏  举报