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的退出码和管道逻辑。 - 先在非生产机跑启动、容器和回滚路径。