Linux中使用systemd服务单元定时任务

Linux中使用systemd服务单元定时任务

文章目录

一: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/filenull 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 必须是绝对路径且可执行文件。
  • 尽量给服务指定合适的 UserGroup,避免使用 root。
  • 通过 RestartRestartSec 设置服务的自动恢复机制,提升稳定性。
  • 使用 journalctl -u 服务名 查看日志,不建议直接写日志文件。
  • TimeoutStartSecTimeoutStopSec 适当调整,避免启动或停止卡死。
  • 如果脚本有依赖网络或数据库,确保 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秒,可能会出现堆积。
  • 如果业务复杂,建议改用消息队列或专业调度框架
相关推荐
Lsir10110_2 小时前
【Linux】网络编程基础—套接字
linux·运维·服务器·网络·c++
夏乌_Wx2 小时前
Linux 进程间通信 IPC 总结:管道 + 信号量 + 共享内存 + 消息队列(附代码)
linux·数据结构·算法
迁 凉2 小时前
怎么把一台ubuntu主机作为服务器,给别的xshell连接
运维·服务器·ubuntu
Trouvaille ~2 小时前
【项目篇】从零手写高并发服务器(三):日志宏与Buffer缓冲区模块
运维·服务器·网络·高并发·muduo库·日志宏·缓冲区设计
lucia_zl2 小时前
linux收集进程性能数据
linux·运维·chrome
Byte不洛2 小时前
手写一个C++ TCP服务器实现自定义协议(顺便解决粘包问题)
linux·c++·操作系统·网络编程·tcp
董可伦2 小时前
Flink DataStream2Table 总结
服务器·python·flink
amcomputer2 小时前
服务器数据如何实现备份同步?
运维·服务器
Cc琎2 小时前
api接口分布在多台服务器, 如何同步用户的每日请求次数
java·运维·服务器·redis·php