当前位置:首页 > 文章列表 > 文章 > linux > Linux systemd.service RestartPreventExitStatus 怎样让指定退出码不重启

Linux systemd.service RestartPreventExitStatus 怎样让指定退出码不重启

来源:17golang原创 2026-11-05 03:01:56 0浏览 收藏

如果一个长期运行的 Linux 服务大多数异常退出都应该自动拉起,但某个退出码代表“主动结束、等待人工处理”或“配置已经明确失效”,可以把默认重启策略和例外状态拆开配置:用 Restart=on-failure 负责常规恢复,用 RestartPreventExitStatus= 列出不应自动重启的退出码或信号。

本文只讨论 systemd.service 的主服务进程,不把 ExecStartPre=、ExecStop= 等控制命令的退出状态混进来。当前 systemd.service 官方手册地址:https://www.freedesktop.org/software/systemd/man/latest/systemd.service.html。

最小可靠写法是:先给服务设置明确的 Restart=,再把需要阻止自动重启的状态写入 RestartPreventExitStatus=。该规则只检查服务主进程的退出状态;它不是一个覆盖所有 Exec* 命令的全局失败开关。

先把“默认重启”和“禁止重启”分成两层

Restart=on-failure 表示服务因为非正常退出、信号、超时等情况失败时尝试重启。它解决的是默认策略:大多数故障希望服务回来。RestartPreventExitStatus= 则是例外集合:主服务进程返回其中某个退出码或信号时,即使 Restart= 原本允许重启,也不再自动重启。

例如,应用约定退出码 75 表示“外部依赖暂时不可用但由运维流程接管”,可以把 75 放入禁止列表。这里的数字是应用协议示例,不是 systemd 为所有程序规定的统一含义;systemd 只负责根据主进程实际返回的状态做策略判断。

systemd 根据主服务退出状态决定是否自动重启的流程说明图
图1:静态结构说明图,展示 Restart= 默认策略与 RestartPreventExitStatus= 例外列表的判断关系,不是命令运行截图或真实运行证据。

用最小 service 单元表达退出状态例外

下面的 unit 文件让主服务默认按失败自动重启,但当主进程返回 75 或收到 SIGTERM 时,不再按该规则自动拉起。配置文件中的注释使用 systemd 支持的 # 语法,便于把每个策略的目的留在配置旁边。

[Unit]
Description=带退出状态例外的示例服务

[Service]
# 这里替换为真实的长期运行程序,示例程序约定 75 是人工接管状态。
ExecStart=/usr/local/bin/example-worker

# 普通失败尝试自动恢复,避免一次偶发退出就让服务永久停住。
Restart=on-failure

# 主进程返回 75 或被 SIGTERM 终止时,禁止自动重启。
RestartPreventExitStatus=75 SIGTERM

# 让日志直接进入 journal,便于和 unit 状态一起查看。
StandardOutput=journal
StandardError=journal

[Install]
# 仅在希望随多用户目标启动时启用该安装关系。
WantedBy=multi-user.target

如果业务只想排除一个数字,就只写这个数字;如果要排除信号,也可以写信号名。不要把应用自己的“正常结束”概念直接套到所有服务上:先在程序文档或退出码约定中确认状态含义,再决定是否加入禁止列表。

修改后按顺序检查配置和状态

将文件保存到例如 /etc/systemd/system/example-worker.service 后,先让 systemd 重新读取 unit 文件,再查看最终内容和关键属性。下面命令只展示检查流程,example-worker 是占位 unit 名称。

# 重新读取 unit 文件;不会自动启动服务。
sudo systemctl daemon-reload

# 查看 systemd 当前读取到的完整 unit 内容。
systemctl cat example-worker.service

# 只查看重启策略和禁止重启状态,减少人工翻查。
systemctl show example-worker.service \
  --property=Restart,RestartPreventExitStatus

# 查看当前状态与最近日志,确认失败原因和主进程状态。
systemctl status example-worker.service --no-pager
journalctl -u example-worker.service -n 50 --no-pager

daemon-reload 只负责重新读取配置,不等于已经重启服务。真正需要切换进程时,再根据变更窗口选择 systemctl restart;如果只是确认 unit 文本和属性,先不要把检查动作和重启动作混在一起。

配置项解决的问题容易误读的地方
Restart=on-failure定义大多数失败退出时的默认恢复动作不是无条件重启,仍受退出原因和限速影响
RestartPreventExitStatus=75让主进程返回 75 时跳过自动重启75 的业务含义需要由应用约定,systemd 不替你定义
systemctl show查看解析后的关键属性看到了配置不代表已经执行了重启

只对主服务进程生效,别把 ExecStartPre 当成主进程

RestartPreventExitStatus= 关注的是服务主进程,也就是通常由 ExecStart= 启动、并由 Type= 等设置帮助 systemd 识别的进程。官方手册明确说明,它不作用于 ExecStartPre=、ExecStartPost=、ExecStop=、ExecStopPost= 或 ExecReload=。

[Service]
# 预启动命令只是准备步骤,不是 RestartPreventExitStatus 的目标进程。
ExecStartPre=/usr/local/bin/prepare-worker

# 这个命令才是长期运行服务的主入口,退出状态会参与重启策略判断。
ExecStart=/usr/local/bin/example-worker

# 仅为主进程指定不自动重启的状态。
Restart=on-failure
RestartPreventExitStatus=75

因此,如果 ExecStartPre 失败,应该回到该控制命令本身的退出行为、unit 状态和日志判断原因,而不是期待把它的退出码塞进 RestartPreventExitStatus= 就能改变所有启动阶段行为。

systemd 主服务进程与 ExecStartPre 等控制命令的生效范围说明图
图2:静态范围说明图,突出 RestartPreventExitStatus 作用于主服务进程,不是 ExecStartPre、ExecStop 等控制命令的通用过滤器。

退出状态、Restart= 和启动限速要一起看

禁止某个状态重启,不等于所有退出都不会重启;没有命中禁止列表的失败仍按 Restart= 处理。另外,自动重启还受 unit 的启动速率限制影响。若服务短时间内反复失败,StartLimitIntervalSec= 与 StartLimitBurst= 可能让后续启动暂时被限制,这和 RestartPreventExitStatus= 是两个不同层次的问题。

排查时可以按三件事分层:

  1. 从日志确认主进程到底返回了哪个数字或信号,而不是凭 status=1/FAILURE 的展示文字猜测。
  2. 用 systemctl show 对照 systemd 解析后的 Restart 与 RestartPreventExitStatus。
  3. 如果没有命中禁止列表却仍不重启,再检查启动限速、依赖关系和服务是否被人工停止。

这三层信息能把“退出状态例外”“默认重启策略”“重启次数被限制”区分开,避免单独修改一个参数后得出错误结论。

适合生产的收口方式

我的建议是让退出码语义保持少而稳定:应用只为明确的人工接管、不可自动恢复或需要外部配置修正的场景约定例外码;临时网络抖动、普通依赖失败等仍交给 Restart=on-failure 和日志告警处理。禁止列表越长,自动恢复覆盖面越小,后续维护者越难判断服务为什么停住。

上线前把 unit 文件、退出码约定、回滚文件和告警说明放在同一个变更记录里。验证时先用非生产 unit 名称或维护窗口观察状态,再决定是否启用。不要把本文中的占位路径、退出码和服务名直接复制到生产环境,也不要把“命令已写出”当成“机器已执行”。

RestartPreventExitStatus 可以写多个状态吗?

可以,状态之间用空格分隔,可以混合数字、状态名和信号名。需要重置此前继承或重复配置的列表时,按 systemd.service 手册说明使用空值重置,再写入最终集合。

它会改变服务状态中的退出码含义吗?

不会。它改变的是自动重启决策,不会把数字 75 改名,也不会自动把应用的退出码变成成功。状态含义仍要看程序约定和日志。

为什么服务没有重启,但我没有写 RestartPreventExitStatus?

先检查 Restart= 是否允许该退出原因重启,再检查启动限速、人工停止、依赖失败和 unit 文件是否真的被重新加载。禁止列表只是其中一种原因。

ExecStartPre 返回指定退出码时也会被这个选项拦截吗?

不会。该选项针对主服务进程,控制命令的失败需要通过启动日志、unit 状态和对应的 Exec* 行为单独分析。

最后可以把它记成一句话:Restart= 负责“默认怎么恢复”,RestartPreventExitStatus= 负责“哪些主进程状态例外不恢复”。先确认退出状态来源,再写最小例外集合,配置才不会把可恢复故障和应停机状态混成一团。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
Linux systemd.exec OOMScoreAdjust怎样调整服务被 OOM 选择的优先级Linux systemd.exec OOMScoreAdjust怎样调整服务被 OOM 选择的优先级
上一篇
Linux systemd.exec OOMScoreAdjust怎样调整服务被 OOM 选择的优先级
Linux ip route get 怎样按源地址和网卡确认内核选路
下一篇
Linux ip route get 怎样按源地址和网卡确认内核选路
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    888次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    887次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    970次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    955次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    782次使用