收起左侧

【问题反馈】因 Systemd 服务配置不当导致启动序列阻塞及其他服务失效

1
回复
191
查看
[ 复制链接 ]

1

主题

0

回帖

0

牛值

江湖小虾

2026-2-1 14:59:07 显示全部楼层 阅读模式

问题背景

cron_for_fix.service

系统预设了包含死循环逻辑的脚本,并将其注册为 Type=oneshot 的 Systemd 服务,会导致系统启动序列发生严重阻塞。这不仅会使系统无法进入完整的 multi-user.target 状态,还会导致所有依赖该状态的服务(例如自定义的硬盘控温脚本)处于永久等待(Waiting)状态而失效。


问题表现

  1. 服务启动卡死:执行 systemctl restart <service> 时终端无响应,无法退出。
  2. 硬件保护失效:自定义的硬盘风扇控制脚本(hdd-fan.service)状态长期为 inactive (dead),即使已设置为 enabled
  3. 系统状态异常:执行 systemctl list-**s 会发现大量任务处于 waiting 状态,multi-user.target 无法达成。
  4. 典型案例/usr/trim/bin/cron_for_fix.sh 包含 while true 循环,其对应的 cron_for_fix.service 类型为 oneshot

根本原因分析

Systemd 对 Type=oneshot 的处理机制要求脚本必须执行完毕并退出,才会继续推进启动队列。

在以下配置中:

  • 脚本内容
    Bash

    while true; do
        /usr/trim/bin/liveupdate -Hu
        sleep 5h
    done
    
  • 服务配置
    Ini, TOML

    [Service]
    Type=oneshot
    ExecStart=/usr/trim/bin/cron_for_fix.sh
    

逻辑冲突:脚本由于 while true 永远不会退出,Systemd 因此永久等待 cron_for_fix.service 完成,从而挂起了整个 multi-user.target 的达成。所有配置了 After=multi-user.target 的服务都会被“锁死”。


复现步骤

  1. 创建一个包含死循环的脚本并赋予执行权限。
  2. 创建一个 Systemd 服务文件,设置 Type=oneshot 并指向该脚本。
  3. systemctl enable 并重启系统。
  4. 尝试启动任何依赖 multi-user.target 的其他服务,观察是否卡住。

建议修复方案

  1. 修正服务类型:对于需要长期驻留后台的循环脚本,必须使用 Type=simple 而非 Type=oneshot
  2. 优化依赖顺序:对于涉及硬件安全(如风扇控制、过热保护)的关键服务,建议将 After= 依赖项从 multi-user.target 提升至 basic.targetsysinit.target,以确保即使应用层服务阻塞,底层保护依然有效。
  3. 规范配置检查:在系统集成自定义脚本时,建议增加对 oneshot 类型服务是否包含阻塞逻辑的审计。

环境信息:

  • Systemd Version: 1.1.18
收藏
送赞
分享

266

主题

1万

回帖

0

牛值

管理员

fnOS1.0上线纪念勋章

2026-2-11 14:57:45 显示全部楼层
已收到反馈 我转给负责的同事看看
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则