news 2026/5/16 2:54:49

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/5/10 12:24:36

浮点数在内存中的存储

一 国际标准根据国际标准IEEE754&#xff0c;任意的二进制浮点数可以表示为一下的形式&#xff1a;二 存储方式1.32位的浮点数&#xff0c;最高一位存储符号位S&#xff0c;接着8位存储指数E&#xff0c;剩下的23位存储有效数字M&#xff1b;2.对于64位的浮点数&#xff0c;最…

作者头像 李华
网站建设 2026/5/3 0:07:24

计算机毕业设计项目源码/Flask+vue的博客系统设计与实现附开题报告,毕业论文,毕设代码

博主介绍&#xff1a; CSDN毕设辅导第一人、靠谱第一人、csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客优秀创作者、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和学生毕业项目实战,高校老师/讲师/同行前辈交流✌ 技术范围&#xff1a;…

作者头像 李华
网站建设 2026/5/2 14:37:30

Thinkphp和Laravel学生宿舍分配报修管理系统_o4dvi

目录 Thinkphp与Laravel框架对比宿舍分配功能设计报修管理模块实现系统安全与权限控制性能优化建议扩展性与维护性 项目开发技术介绍PHP核心代码部分展示系统结论源码获取/同行可拿货,招校园代理 Thinkphp与Laravel框架对比 Thinkphp作为国内流行的PHP框架&#xff0c;以轻量级…

作者头像 李华
网站建设 2026/5/11 23:45:40

Thinkphp和Laravel小程序“共享书角”图书借还管理系统

目录 技术框架选择核心功能模块数据库设计接口与安全扩展性优化部署与维护 项目开发技术介绍PHP核心代码部分展示系统结论源码获取/同行可拿货,招校园代理 技术框架选择 ThinkPHP和Laravel均为流行的PHP框架&#xff0c;适用于开发“共享书角”小程序后端管理系统。ThinkPHP以…

作者头像 李华
网站建设 2026/5/9 12:44:02

【毕业设计】基于springboot个性化大学生线上聊天交友系统的设计与实(源码+文档+远程调试,全bao定制等)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

作者头像 李华