当前位置: 首页 > news >正文

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 的管理能力,又允许工作进程有独立的生命周期。

http://www.jsqmd.com/news/313409/

相关文章:

  • 知识图谱如何在制造业实际落地应用
  • 2026白转黑加盟项目怎么选?关键看技术与扶持体系
  • 年省500万内幕:北京企业订国际机票别再用平台了!这4家本土供应商把亏损千万的公司变成盈利巨头
  • 2026南京遗产继承律师推荐指南
  • 学霸同款2026 TOP8 AI论文写作软件:本科生毕业论文必备测评
  • 【收藏必备】Web安全完全指南:从上网到开发,小白也能掌握的防护技巧
  • 程序员转行网络安全必备:三大基础工具实战指南(附案例+简历技能点,建议收藏)
  • 科技新助力
  • ‌别再手动对比日志了!AI日志分析工具实测TOP3
  • 基于CNN的陕西降雨量气象分析-大数据深度学习算法毕设毕业设计项目Flask
  • 2026版最新黑客网站整理大全,全新整理黑客网站大全!收藏这一篇就够了
  • 2026年最适合初学者练手的10个网络安全项目,收藏这篇就够了!
  • 【2026最新版】计算机专业自学指南:从大一到大四步步为营,收藏这一篇就够了
  • 2026工业秤头部品牌厂家(综合实力强,产品线完整)
  • 零基础转行大模型:3个月入门+项目变现,程序员必藏的学习路径
  • 机箱机柜钣金加工厂家综合能力对比
  • 【干货】网络安全面试高频题:零基础也能答的通关秘籍,建议收藏
  • 京东e卡回收变现,京顺回收高效解忧
  • PPO 真正的应用场景,和你想的可能不一样
  • 近视防控大揭秘:防什么?控什么?为啥这么重要?
  • 基于spring boot的调查问卷系统的设计与实现(源码+论文+部署+安装)
  • 基于springboot的会议室预订系统设计与实现(源码+论文+部署+安装)
  • WPS 添加公式居中并靠右自动编号
  • 学长亲荐10个一键生成论文工具,本科生毕业论文轻松搞定!
  • 基于Vue的数字图书馆设计与开发793m5(程序 + 源码 + 数据库 + 调试部署 + 开发环境配置),配套论文文档字数达万字以上,文末可获取,系统界面展示置于文末
  • 2010-2024年上市公司常规低技能、非常规高技能劳动力数据
  • CAD 2026版本软件安装过程分享,免费安装包,实测稳定好用,安装简单。
  • JVM垃圾回收
  • 2026年滑轨厂家最新推荐:餐桌滑轨、服务器滑轨、餐台滑轨、阻尼滑轨、KVM滑轨、重型滑轨、座椅滑轨、导轨厂家选择指南,高效耐用实力
  • Instagram被shadowban限流?如何快速恢复流量?2026最新触发原因+有效解决方法