综合 systemd 258 升级踩坑:cgroup v1 没了、uaccess 规则失效、tty 默认 0600

2026-10-24 21:07:32

systemd 258 升级踩坑笔记:cgroup v1、uaccess 与 tty 权限怎么排查

systemd 258 移除和改动了多处以旧接口为前提的行为,老机器、老容器镜像和旧运维脚本最容易受影响。下面按“现象 → 怎么查 → 怎么改”记录与服务器运维直接相关的几项。

1. cgroup v1 支持被移除

现象:systemd 启动和 systemd-nspawn 初始化时总是挂载 cgroup v2;老内核、混合层级、老容器镜像可能启动失败,或资源限制不生效。

查:stat -fc %T /sys/fs/cgroup 应输出 cgroup2fs;uname -r 确认内核,最低 5.4,推荐 5.7;再看 /proc/cmdline 是否还有强制 v1/hybrid 的参数。

改:删掉 systemd.unified_cgroup_hierarchy=0 一类参数;容器和 nspawn 配置按 cgroup v2 重建;依赖 v1 目录的采集脚本要改路径。

2. udev 的 uaccess 规则不再由 logind 写 ACL

现象:hidraw 等设备 ACL 时有时无。258 起 logind 不再应用 ACL,改由 systemd-udevd 的 uaccess builtin 处理,并触发 change uevent;只写 ACTION=="add" 的规则失效。

查:udevadm test /sys/class/hidraw/hidraw0、udevadm info -q all -n /dev/hidraw0。

改:规则改成除 remove 外都命中:

ACTION!="remove", SUBSYSTEM=="hidraw", TAG+="uaccess"

重载后执行 udevadm control --reload && udevadm trigger --action=change。关键是触发 change,而不是只触发 add。

3. tty/pts 默认权限从 0620 改成 0600

现象:等价于 mesg n 成为默认;串口 console、共享终端场景读不到别人输出,老脚本以为终端可读写。

查:stat -c '%a %n' /dev/tty /dev/pts/0。

改:自建包用 -Dtty-mode=0620 编回旧行为;发行版包需等包方提供该构建选项,临时场景可用 udev 规则或 chmod 兜底,但要评估安全影响。

4. System V 运行级别整体移除

现象:/dev/initctl、initctl、runlevel、telinit、runlevel[0-6].target 都没了;脚本里的 init 3、telinit 6 直接失败。

查:grep -RInE '(/dev/initctl|telinit|runlevel|init [0-6])' /etc/init.d /usr/local/bin /opt。

改:状态切换改用 systemctl isolate multi-user.target;重启用 systemctl isolate reboot.target 或 reboot;默认目标用 systemctl get-default / set-default。

5. /forcefsck、/fastboot 不再生效

现象:touch /forcefsck 后重启不再强制 fsck,/fastboot 同理。

查:搜镜像构建和运维脚本里的 touch /forcefsck、/fastboot。

改:改用内核参数 fsck.mode=force(或 skip),也可用 fsck.mode credential;systemd-quotacheck 对应 quotacheck.mode。

6. udev 规则 OWNER=/GROUP= 指向非系统用户会被忽略

现象:规则的 OWNER=/GROUP= 指向非系统用户/组时,systemd-udevd 不再应用,设备属主不变,规则静默失效。

查:udevadm verify /etc/udev/rules.d/*.rules,再用 udevadm test /sys/class/... 看实际结果。

改:改用系统账户/组,或在服务层处理权限;systemd-networkd 的 .netdev 里 User=/Group= 同样拒绝非系统用户。

7. systemd-creds 与 PrivateDevices 的交互变化

现象:带 PrivateDevices=yes 或 DeviceAllow=/DevicePolicy= 的 unit,凭据解密改走 systemd-creds.socket,不再在进程内解密;旧版自动扩展 DeviceAllow= 列表的兼容行为移除。

查:systemctl show -p PrivateDevices -p DeviceAllow ,并查看带 LoadCredentialEncrypted= 的服务日志。

改:确认 systemd-creds.socket 可用,清理对自动扩展设备白名单的假设,升级后逐个重启并验证凭据读取。

8. journalctl --follow 退出码变化

现象:journalctl --follow 在 SIGTERM/SIGINT 以及写入管道断开时以成功退出;脚本按非零退出码判断“采集失败”会误判。

查:搜 journalctl -f / --follow,重点看 set -o pipefail、timeout 和 supervisor 的退出码逻辑。

改:别再把被杀当成失败;需要断流检测就加独立心跳/健康检查,或改为有界读取后再判断。

升级前 checklist

  • 确认 /sys/fs/cgroup 为 cgroup2fs,内核 ≥5.4,容器镜像支持 cgroup v2。
  • 全量跑 udevadm verify,把 uaccess 规则改成 ACTION!="remove",测试 change 触发。
  • 检查 tty/pts 权限和串口 console 场景,确定是否用 -Dtty-mode=0620。
  • 搜 init/telinit/runlevel、/forcefsck、/fastboot 的脚本残留。
  • 检查 udev OWNER/GROUP 与 networkd User/Group 是否使用系统账户。
  • 对 PrivateDevices= 和加密凭据 unit 做重启验证。
  • 复核所有 journalctl -f 的退出码和管道逻辑。
  • 先在非生产机跑启动、容器和回滚路径。
复制全文 生成海报 systemd Linux 运维

推荐文章

程序员茄子在线接单