Linux中使用systemd服务单元定时任务
文章目录
- Linux中使用systemd服务单元定时任务
-
- 一:Systemd简介
- [systemd 服务单元文件结构](#systemd 服务单元文件结构)
- 各节详细参数说明及常用配置示例
-
- [1. `[Unit]` 节](#1.
[Unit]节) - [2. `[Service]` 节](#2.
[Service]节) - [3. `[Install]` 节](#3.
[Install]节)
- [1. `[Unit]` 节](#1.
- 一个完整示例
- 建议和注意事项
- 二:实现demo
- 方案概述
- 具体步骤
-
- [1. 编写脚本](#1. 编写脚本)
- [2. 创建 systemd 服务单元文件](#2. 创建 systemd 服务单元文件)
- [3. 让 systemd 识别新服务并启动](#3. 让 systemd 识别新服务并启动)
- [4. 查看服务状态和日志](#4. 查看服务状态和日志)
- 补充说明
一:Systemd简介
systemd 服务单元文件(通常放在 /etc/systemd/system/ 目录)是用来定义和管理服务的配置文件。它采用 INI 格式,由多节(section)组成,每节里包含若干参数。理解这些参数,有助于你根据实际需求准确配置服务。
systemd 服务单元文件结构
一个标准的 systemd 服务文件主要包含以下几节:
[Unit]------ 描述服务单元的元数据和依赖关系[Service]------ 定义服务的启动方式、运行命令、重启策略等[Install]------ 定义服务如何被安装(比如开机启动)
各节详细参数说明及常用配置示例
1. [Unit] 节
用于描述服务单元本身、依赖和启动顺序。
| 参数 | 说明及常用值说明 |
|---|---|
| Description | 服务描述,简短说明服务作用 |
| After | 定义服务启动顺序,指定本服务在指定服务或目标(target)之后启动,如 network.target 表示网络启动后启动 |
| Requires | 依赖服务,若指定服务未启动,本服务不会启动 |
| Wants | 弱依赖服务,若指定服务启动失败,本服务仍尝试启动 |
| Conflicts | 指明和本服务冲突的服务,避免同时运行 |
| Condition... | 条件参数,控制服务是否启动,比如 ConditionPathExists= 判断文件是否存在 |
示例:
ini
[Unit]
Description=My per-second task runner
After=network.target
Requires=network.target
2. [Service] 节
定义服务的执行方式,关键参数非常多,常用参数说明如下:
| 参数 | 说明 | 示例 |
|---|---|---|
| Type | 服务类型,常用类型:simple(默认)、forking、oneshot、notify等。 simple: ExecStart 启动的进程即为主进程。 | Type=simple |
| ExecStart | 启动服务时执行的命令(必须),完整路径推荐 | ExecStart=/usr/local/bin/run_every_second.sh |
| ExecStop | 停止服务时执行的命令(可选) | ExecStop=/bin/kill $MAINPID |
| Restart | 服务退出后的重启策略。可选值:no(默认)、on-success、on-failure、always、on-abnormal等。 | Restart=always |
| RestartSec | 服务退出后重启延时,单位秒 | RestartSec=5 |
| User | 指定运行该服务的用户,推荐非root用户 | User=someuser |
| Group | 指定运行该服务的用户组 | Group=somegroup |
| WorkingDirectory | 服务启动时的工作目录 | WorkingDirectory=/home/youruser |
| Environment | 设置环境变量,一行一个,如 KEY=value |
Environment=JAVA_HOME=/usr/lib/jvm/java-11-openjdk |
| StandardOutput | 标准输出去向,常用journal(日志系统)、file:/path/to/file 或 null |
StandardOutput=journal |
| StandardError | 标准错误输出去向,同上 | StandardError=journal |
| TimeoutStartSec | 启动等待超时时间,单位秒,默认90秒 | TimeoutStartSec=30 |
| TimeoutStopSec | 停止等待超时时间 | TimeoutStopSec=30 |
| KillMode | 进程终止方式,常用 control-group(默认,终止整个进程组) |
KillMode=control-group |
| ExecReload | 重新加载配置命令 | ExecReload=/bin/kill -HUP $MAINPID |
3. [Install] 节
定义服务的安装行为,主要用于控制服务是否开机启动。
| 参数 | 说明 | 示例 |
|---|---|---|
| WantedBy | 指定安装时绑定的目标(target),常用 multi-user.target 表示多用户模式 |
WantedBy=multi-user.target |
| Alias | 给服务创建别名 | Alias=myservice |
一个完整示例
下面是一个典型的 systemd 服务单元示例,服务会启动一个脚本,并且异常退出后自动重启,开机自启:
ini
[Unit]
Description=Run my script every second service
After=network.target
[Service]
Type=simple
ExecStart=/usr/local/bin/run_every_second.sh
Restart=always
RestartSec=5
User=youruser
Group=yourgroup
WorkingDirectory=/home/youruser
StandardOutput=journal
StandardError=journal
Environment=MY_ENV_VAR=production
TimeoutStartSec=30
TimeoutStopSec=30
KillMode=control-group
[Install]
WantedBy=multi-user.target
建议和注意事项
ExecStart必须是绝对路径且可执行文件。- 尽量给服务指定合适的
User和Group,避免使用 root。 - 通过
Restart和RestartSec设置服务的自动恢复机制,提升稳定性。 - 使用
journalctl -u 服务名查看日志,不建议直接写日志文件。 TimeoutStartSec和TimeoutStopSec适当调整,避免启动或停止卡死。- 如果脚本有依赖网络或数据库,确保
After=配置正确,或在脚本内部做重试。
二:实现demo
你想用 systemd 实现服务器开机后,每秒调用一次脚本,下面给你一份详细的方案和步骤,确保你的任务能稳定、自动运行。
方案概述
- 编写一个脚本,内部用死循环和
sleep 1实现每秒调用。 - 用 systemd 创建一个服务,启动时运行这个脚本。
- 设置服务开机自启,自动重启,方便管理和日志查看。
具体步骤
1. 编写脚本
假设你的业务脚本是 /path/to/your_script.sh,你可以写一个"循环调用脚本"的启动脚本,例如:
创建文件 /usr/local/bin/run_every_second.sh
bash
#!/bin/bash
while true; do
/path/to/your_script.sh
sleep 1
done
给脚本执行权限:
bash
chmod +x /usr/local/bin/run_every_second.sh
2. 创建 systemd 服务单元文件
新建文件 /etc/systemd/system/run_every_second.service
ini
[Unit]
Description=Run script every second service
After=network.target
[Service]
Type=simple
ExecStart=/usr/local/bin/run_every_second.sh
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
Restart=always:如果脚本意外退出,systemd 会自动重启服务。RestartSec=5:重启前等待5秒,避免频繁重启。
3. 让 systemd 识别新服务并启动
bash
# 重新加载 systemd 配置
sudo systemctl daemon-reload
# 设置服务开机启动
sudo systemctl enable run_every_second.service
# 立即启动服务
sudo systemctl start run_every_second.service
4. 查看服务状态和日志
bash
# 查看服务状态
sudo systemctl status run_every_second.service
# 实时查看日志,方便调试
sudo journalctl -u run_every_second.service -f
补充说明
- 你的
/path/to/your_script.sh也要有执行权限,且写好业务代码。 - 这个方案适合脚本执行时间较短的场景,确保1秒能跑完。如果脚本执行时间超过1秒,可能会出现堆积。
- 如果业务复杂,建议改用消息队列或专业调度框架