news 2026/6/25 15:10:30

Linux Systemd 停止服务时杀死子进程的机制及 KillMode 参数详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Linux Systemd 停止服务时杀死子进程的机制及 KillMode 参数详解

Systemd 停止服务时杀死子进程的机制

1.Systemd 的进程控制原理

Cgroup 控制组

Systemd 利用 Linux 的 cgroup 机制来管理进程树:

# 查看服务的cgroupsystemctl show aservice --property=ControlGroup systemd-cgls /system.slice/aservice.service

进程树关联

当 systemd 启动服务时:

  1. 服务进程(通常是 ExecStart 指定的进程)被放入专用的 cgroup
  2. 该进程的所有子进程会自动继承相同的 cgroup
  3. systemd 监控整个 cgroup 中的所有进程

2.停止服务时的默认行为

默认信号发送

# 默认发送 SIGTERMsystemctl stop aservice# 等同于kill-TERM<main_pid>

超时后的强制终止

[Service] TimeoutStopSec=90 # 默认90秒后发送SIGKILL KillMode=control-group # 默认:杀死cgroup中的所有进程

3.KillMode 参数详解

[Service] # 默认值:杀死cgroup中的所有进程 KillMode=control-group # 可选值: # control-group: 杀死cgroup中所有进程(默认) # process: 只杀死主进程 # mixed: 向主进程发SIGTERM,向子进程发SIGKILL # none: 不杀死任何进程

4.避免子进程被停止的方法

方法1:使用 KillMode=none

[Service] Type=simple ExecStart=/usr/bin/aservice KillMode=none

问题:主进程退出后,子进程变成僵尸或继续运行但systemd认为服务已停止。

方法2:分离子进程到不同cgroup

使用setsidnohup
[Service] Type=forking ExecStart=/usr/bin/aservice-wrapper # 包装脚本 # wrapper脚本示例 #!/bin/bash /usr/bin/nohup /usr/bin/real-daemon > /dev/null 2>&1 & # 或 /usr/bin/setsid /usr/bin/real-daemon exit 0

方法3:使用 Type=forking 和正确的 PIDFile

[Service] Type=forking PIDFile=/var/run/aservice-main.pid ExecStart=/usr/bin/aservice-daemonize KillMode=process # 只杀死主进程

方法4:通过 Systemd 的 Scope 机制

[Service] Type=oneshot RemainAfterExit=yes ExecStart=/bin/bash -c "systemd-run --scope --unit=aservice-children.service /usr/bin/child-process"

方法5:使用 Systemd 单元分离

# aservice-parent.service [Service] Type=oneshot RemainAfterExit=yes ExecStart=/bin/systemctl start aservice-children.service # aservice-children.service [Service] Type=simple ExecStart=/usr/bin/child-process

5.完整的最佳实践示例

方案1:双服务模式

# /etc/systemd/system/aservice-main.service [Unit] Description=AService Main Controller After=network.target Wants=aservice-workers.service [Service] Type=simple ExecStart=/usr/bin/aservice-controller Restart=always KillMode=process # 只杀控制器 [Install] WantedBy=multi-user.target # /etc/systemd/system/aservice-workers.service [Unit] Description=AService Workers PartOf=aservice-main.service # 主服务停止时,这个服务也会停止 BindsTo=aservice-main.service # 主服务重启时,这个服务也重启 [Service] Type=forking ExecStart=/usr/bin/aservice-worker-manager KillMode=none # 不杀工作进程

方案2:分离进程组

[Service] Type=simple ExecStart=/bin/bash -c 'cd / && /usr/bin/setsid /usr/bin/real-daemon &' KillSignal=SIGINT SendSIGKILL=no

6.生命周期管理策略

使用启动脚本分离

#!/bin/bash# /usr/libexec/aservice-starter# 创建独立会话{# 脱离当前控制组execsetsid"$@"&child_pid=$!# 将子进程移出当前cgroupecho$child_pid>/sys/fs/cgroup/systemd/tasks2>/dev/null||true# 等待主进程结束wait$child_pidexit$?}&

Cgroup 手动管理

[Service] Type=oneshot ExecStart=/bin/bash -c ' # 启动子进程到独立cgroup mkdir -p /sys/fs/cgroup/systemd/independent echo $$ > /sys/fs/cgroup/systemd/independent/tasks exec /usr/bin/child-process '

7.信号转发机制

信号处理器方案

#!/usr/bin/env python3# signal-forwarder.pyimportosimportsignalimportsubprocessimporttimedefsignal_handler(signum,frame):# 不转发SIGTERM给子进程ifsignum==signal.SIGTERM:print("Received SIGTERM, exiting without killing children")os._exit(0)defmain():# 设置信号处理器signal.signal(signal.SIGTERM,signal_handler)# 启动子进程child=subprocess.Popen(["/usr/bin/real-daemon"])# 等待子进程或信号whileTrue:time.sleep(1)if__name__=="__main__":main()

8.注意事项和风险

  1. 僵尸进程风险:如果父进程退出而不等待子进程,可能产生僵尸进程
  2. systemd 状态不一致KillMode=none可能导致服务状态不准确
  3. 资源泄露:脱离管理的进程可能导致资源无法回收
  4. 日志管理:分离的进程需要独立的日志处理

9.推荐的架构设计

推荐架构: ┌─────────────────┐ │ Systemd │ │ (主服务单元) │ └─────────┬───────┘ │ control-group ▼ ┌─────────────────┐ │ 控制器进程 │ ← SIGTERM │ (轻量级) │ └─────────┬───────┘ │ 通过IPC/套接字 ▼ ┌─────────────────┐ │ 工作进程池 │ ← 独立管理生命周期 │ (setsid启动) │ └─────────────────┘

关键原则

  • 主进程作为"监督者",负责启动/停止工作进程
  • 工作进程通过 setsid 创建独立会话
  • 使用 IPC 机制而不是父子进程关系进行通信
  • 工作进程优雅处理自己的终止逻辑

这种方法既保持了 systemd 的管理能力,又允许工作进程有独立的生命周期。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/25 0:38:04

‌别再手动对比日志了!AI日志分析工具实测TOP3

软件测试中的日志分析痛点‌ 在软件测试工作中&#xff0c;日志分析是核心环节&#xff0c;涉及错误追踪、性能监控和测试报告生成。传统手动方法耗时耗力&#xff1a;测试工程师需逐行比对日志文件&#xff0c;识别异常模式&#xff0c;平均每个项目消耗20-30小时。常见问题包…

作者头像 李华
网站建设 2026/6/22 7:58:56

基于Vue的数字图书馆设计与开发793m5(程序 + 源码 + 数据库 + 调试部署 + 开发环境配置),配套论文文档字数达万字以上,文末可获取,系统界面展示置于文末

系统程序文件列表 系统功能 用户,图书类别,图书信息 开题报告内容 一、 课题背景、研究目的与意义 1. 课题背景 随着信息技术的高速发展和数字化转型的深入推进&#xff0c;传统图书馆的服务模式面临诸多挑战&#xff1a;空间限制导致藏书容量有限&#xff0c;纸质资源易损…

作者头像 李华
网站建设 2026/6/24 12:33:57

基于spring boot的调查问卷系统的设计与实现(源码+论文+部署+安装)

感兴趣的可以先收藏起来&#xff0c;还有在毕设选题&#xff0c;项目以及论文编写等相关问题都可以给我留言咨询&#xff0c;我会一一回复&#xff0c;希望可以帮到大家。一、程序背景在当前信息化快速发展的大环境下&#xff0c;传统纸质问卷调查存在效率低下、成本高昂、地域…

作者头像 李华
网站建设 2026/6/18 13:26:40

为什么你的测试覆盖率是“静态的”?因为你没做“动态分析”

覆盖率指标的迷思 在软件测试领域&#xff0c;测试覆盖率常被视为质量保证的黄金标准&#xff0c;但许多团队发现&#xff0c;即使覆盖率数字高达90%&#xff0c;上线后仍频发缺陷。这种矛盾源于覆盖率指标的“静态化”——它仅反映代码被扫描的比例&#xff0c;却忽略运行时行…

作者头像 李华
网站建设 2026/6/17 16:12:18

NetApp数据平台助力Super Bowl LX实现高效数据运营

智能数据基础设施全面赋能Levi’s Stadium&#xff0c;显著提升球迷观赛体验 NetApp&#xff08;NASDAQ&#xff1a;NTAP&#xff09;智能数据基础设施公司今日宣布&#xff0c;其正为Super Bowl LX提供数据运营支持。作为旧金山49人队及美国国家橄榄球联盟&#xff08;NFL&…

作者头像 李华
网站建设 2026/6/25 13:16:47

Thinkphp和Laravel学生档案管理系统_8xpgg

目录ThinkPHP与Laravel框架的学生档案管理系统对比框架特性开发效率安全性性能表现适用场景项目开发技术介绍PHP核心代码部分展示系统结论源码获取/同行可拿货,招校园代理ThinkPHP与Laravel框架的学生档案管理系统对比 框架特性 ThinkPHP以轻量级和简单易用著称&#xff0c;适…

作者头像 李华