登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  文章 >  linux

systemd 服务怎样使用 RuntimeDirectory 管理运行目录

来源:17golang原创

时间:2026-10-15 05:34:36 367浏览 收藏

在 systemd 服务的 [Service] 段设置 RuntimeDirectory=目录名,即可把运行目录的创建与清理交给服务管理器。系统服务使用相对名称,例如 rtd-demo 对应 /run/rtd-demo;再用 User、Group 和 RuntimeDirectoryMode 声明归属与权限。默认停止服务会清理目录,是否跨重启保留由 RuntimeDirectoryPreserve 决定。

官方地址:https://github.com/systemd/systemd

把目录声明放进单元文件,意味着维护者能在服务配置中看到运行资源的约定,而不是依赖分散的 mkdir 与清理脚本。这是可采用的管理方式,不代表所有发行版都已采用同样配置,也没有搜索热度或性能提升数据可据此推出。

把目录交给服务单元,而不是启动脚本

先列清应用要存放的东西:控制套接字、可重建的运行标记可以归入临时运行资料;任务结果、数据库与需恢复的业务文件则不应只依靠运行目录。选择 RuntimeDirectory 前,先回答“停止服务后丢掉这些文件,应用是否仍能正常重新启动”。

这个做法对服务打包人员与运维人员的主要价值是集中表达资源约定。它不会替应用生成套接字,也不能修复错误的文件路径。若应用必须自己管理跨服务共享的目录,先厘清谁负责清理,不要直接套入示例。

用三个配置项声明目录和权限

下面是原创的系统服务演示单元,仅用于已采用 systemd 的 Linux 测试主机。先准备存在的 runtime-demo 用户与同名组,并确认 /usr/bin/sleep 可执行。示例用 sleep 保持服务活动,便于观察目录本身,不冒充真实业务服务。

[Unit]
Description=Runtime directory demonstration

[Service]
Type=simple
# 使用预先创建的测试账户;名称须与本机账户一致。
User=runtime-demo
Group=runtime-demo
# 写相对名称;系统服务对应 /run/rtd-demo。
RuntimeDirectory=rtd-demo
RuntimeDirectoryMode=0750
# 停止时清理目录,重启也不保留旧内容。
RuntimeDirectoryPreserve=no
# 此进程只保持服务活动,不创建任何业务文件。
ExecStart=/usr/bin/sleep infinity

RuntimeDirectory 声明的是相对名称,不能写成 /run/rtd-demo,也不能夹带 ..。0750 表示拥有者可读写进入、所属组可读取进入、其他用户无权限;它是本例的选择,不是所有服务的通用权限答案。正式配置应按需要访问目录的进程身份决定。

对应关系是:RuntimeDirectory=rtd-demo 定义路径,User=runtime-demo 与 Group=runtime-demo 定义归属,RuntimeDirectoryMode=0750 定义目录权限。先确认这些信息,再判断应用为何无法写入。

RuntimeDirectory、服务身份和运行目录权限的静态关系
图1:目录归属结构图。配置分组定义路径和身份,资源分组显示 /run/rtd-demo 与目录权限的关联;不是运行截图。

应用仍要使用正确的运行路径

管理器会向进程提供 RUNTIME_DIRECTORY 环境变量。它与“应用会主动使用这个变量”不是一回事:应用需要有相应支持,或者通过自身配置接入这一路径。本例只有一个目录;配置多个目录时,变量中是冒号连接的路径列表,不宜直接当成单个文件夹。

sleep 演示进程不会读取这个变量,也不会写入 /run/rtd-demo。迁移真实应用时,应把它原来使用的套接字目录或临时文件目录明确改到声明的路径,不能仅删除 mkdir 语句就认为迁移完成。用户服务的目录根在 XDG_RUNTIME_DIR 下,不要照搬系统服务的 /run 路径。

停机清理与重启保留要分别选择

RuntimeDirectoryPreserve 的三种常用选择对应不同管理需求:

取值服务停止或重启时的约定适合考虑的需求
no停止时清理,默认行为重新启动应获得干净运行目录
restart自动或手动重启时保留;单独停止不保留重启过程中需保留临时资料
yes停止时也保留有明确的后续管理责任

restart 对应 systemctl restart 或 Restart 策略触发的重启,不能把分开的 stop、start 当成同一个保留承诺。yes 也不意味着数据能跨系统重启留存;/run 是临时运行存储,不应拿它代替持久数据目录。

保留设置不会让服务自动重启;这里的“重启策略”是指已有重启动作发生时如何处理目录,而不是是否触发重启。对本例,no 是为了让观察结果简单且不遗留运行资料。

RuntimeDirectoryPreserve三种值与服务动作、临时存储的静态关系
图2:保留策略结构图。策略分组连接服务停止与服务重启两类语义,/run 分组独立强调临时存储;连线不表示时间顺序。

从测试环境迁移时观察哪些变化

将上面的单元保存到测试主机后,可以使用以下命令自行观察。本文没有在本地启动 systemd 服务,没有真实输出或截图。启动前应确认 /run/rtd-demo 不是其他应用使用的目录。

# 以下仅在专用测试主机运行,不要替换线上服务单元。
# 将示例保存为 /etc/systemd/system/rtd-demo.service,并先准备测试账户。
getent passwd runtime-demo
getent group runtime-demo
test -x /usr/bin/sleep

# 重新读取单元文件,再启动这个专用示例服务。
sudo systemctl daemon-reload
sudo systemctl start rtd-demo.service

# 核对单元配置与目录归属;无输出结果预先假定。
systemctl show rtd-demo.service -p ActiveState -p User -p Group -p RuntimeDirectory -p RuntimeDirectoryPreserve
stat -c '%U:%G %a %n' /run/rtd-demo

# 停止只会影响示例服务;no 策略会清理其运行目录。
sudo systemctl stop rtd-demo.service
if test -d /run/rtd-demo; then
    printf '%s\n' '目录仍存在,请检查单元状态和其他管理者'
else
    printf '%s\n' '示例运行目录已不存在'
fi

判断重点不是“命令没有报错”而是:服务实际处于活动状态、目录归属符合配置、停止后的表现符合 no 策略。若服务启动即退出,目录也可能很快消失,不能据此断言 RuntimeDirectory 没有生效。需要错误原因时,查看该示例服务的状态与日志,而不是放宽目录权限来掩盖问题。

已有目录也要谨慎接管:当目录的拥有者不符合配置时,systemd 可能递归调整下面文件的归属。迁移前应确认目录独占,不能用共享路径试验。不要同时保留另一个会删除同一路径的清理脚本。

RuntimeDirectory 会创建 PID 文件吗?

不会。目录由管理器准备,具体文件仍由应用按自身逻辑创建。本例刻意不放 PID 文件,避免把“目录存在”与“业务文件存在”混为一谈。

应该默认开启 restart 保留吗?

先判断旧文件是否会影响应用重新启动。有恢复需求时才考虑保留;如果旧套接字或标记会被应用误用,应先解决应用的恢复逻辑,不能仅靠保留开关。

发行版的 systemd 较旧怎么办?

查本机随包安装的 systemd.exec 手册,确认这些指令受支持后再迁移;官方仓库主分支手册不能替代本机版本支持范围。不要把未知指令被忽略误判成配置成功。

核心规则来自 systemd 官方手册源文件:https://github.com/systemd/systemd/blob/main/man/systemd.exec.xml。这个方案适用于生命周期归属清晰的运行目录;其采用收益是配置集中、责任明确,不是持久化或自动修复保证。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>