Failed to take /etc/passwd lock: Invalid argument解决方案

x86 宿主机构建 ARM64 Ubuntu 24.04 rootfs 报错解决记录

x86宿主机构建ARM64 Ubuntu 24.04 rootfs时,systemd postinst脚本因qemu-user-static不支持OFD锁而失败,通过升级QEMU 8.0.x解决。

一、问题现象

环境

  • 宿主机:VMware Ubuntu 20.04(x86_64,内核 6.6)

  • 构建方式:通过 debootstrap + qemu-user-static 在 chroot 环境中构建 ARM64 架构的 Ubuntu 24.04 (Noble) rootfs

错误信息

Setting up systemd (255.4-1ubuntu8) ...
Failed to take /etc/passwd lock: Invalid argument
dpkg: error processing package systemd (--configure):
installed systemd package post-installation script subprocess returned error exit status 1

该问题发生在 debootstrap --second-stage 阶段,systemd 包的 postinst 脚本执行时触发。systemd 包配置失败后,整个构建过程卡死,无法继续安装其他包。

二、根本原因分析

2.1 systemd v254 移除了 OFD 锁的 fallback 机制

在 systemd v253 及更早版本中,文件锁的实现逻辑是:

  1. 先尝试 Linux 特有的 fcntl(F_OFD_SETLKW)(OFD 锁)

  2. 如果失败(返回 EINVAL),则回退到传统的 POSIX flock(F_SETLKW)。

从 systemd v254 开始,这个 fallback 被彻底移除(commit ed70a34ec0)。systemd 现在硬性要求底层环境必须支持 F_OFD_SETLKW。

受影响的版本包括 Ubuntu 24.04 自带的 systemd 255.4-1ubuntu8.1。

关键时间点:该问题于 2024年6月5日 systemd 版本 255.4-1ubuntu8.1 发布后开始被大规模报告。

2.2 qemu-user-static 不支持 OFD 锁

  • QEMU 的用户态模拟(linux-user)不支持 Open File Description (OFD) 锁。

  • 在 linux-user/syscall.c 中,target_to_host_fcntl_cmd 函数没有处理 F_OFD_SETLK / F_OFD_SETLKW / F_OFD_GETLK 的 case 分支,任何调用都直接返回 EINVAL。

  • QEMU Bug #1893010 于 2020 年 8 月报告,有人在 2020 年提交了补丁(qemu-5.0.0-ofd-fcntl.patch),但至今未被合并到 QEMU 主线,状态仍为 New。

2.3 报错调用链

systemd.postinst
  ↓
pwconv (shadow-utils 包)
  ↓
libshadow.so → pw_lock()
  ↓
fcntl(F_OFD_SETLKW) → qemu-user-static 不支持 → 返回 EINVAL

注意:这是一个常见的认知误区。很多网上教程说"替换 /bin/systemd-sysusers 为 echo 可解决",但这个方案只适用于 WSL1 环境(报错来自 systemd-sysusers 本身)。在 qemu-user-static + chroot 场景下,报错来自 pwconv → libshadow.so,替换 systemd-sysusers 完全无效。

三、尝试过的无效方案(踩坑记录)

3.1 替换 /bin/systemd-sysusers 为 echo

操作:

cd /bin && mv -f systemd-sysusers systemd-sysusers.org && ln -s echo systemd-sysusers

结果:❌ 无效。报错来自 pwconv,不是 systemd-sysusers。该方案只适用于 WSL1 环境下 systemd-sysusers 自身报错的场景。

3.2 修改 postinst 脚本,在 systemd-sysusers 后添加 || true

操作:

find /var/lib/dpkg/info -name "*.postinst" -exec sed -i 's/systemd-sysusers/systemd-sysusers || true/g' {} \;

结果:❌ 无效。systemd.postinst 中 pwconv 在 systemd-sysusers 之前执行,脚本在 pwconv 行就报错退出了,根本跑不到 systemd-sysusers。

3.3 预创建 systemd 所需用户和组

操作:在 --customize-hook 中手动写入 /etc/group、/etc/passwd、/etc/shadow。

结果:❌ 无效。报错来自 pwconv → libshadow.so → pw_lock() → fcntl(F_OFD_SETLKW),预创建用户绕不过这个锁调用。

3.4 升级宿主机 QEMU 到 8.0.x(分场景有效)

Ask Ubuntu 上有用户报告通过 backports 升级 QEMU 到 8.0.x 解决了问题。但该方案有以下限制:

适用场景:

  • 宿主机直接 chroot 构建,文件系统为普通 ext4/btrfs 等

  • 宿主机 Ubuntu 20.04 通过 backports 升级到 8.0.x

不适用场景:

  • 宿主机 Ubuntu 版本无法通过 backports 获取 QEMU 8.0.x(如 Ubuntu 18.04 或更早版本)。

3.5 使用 multiarch/qemu-user-static --reset -p yes

操作:

docker run --rm --privileged multiarch/qemu-user-static --reset -p yes

结果:❌ 无效。该命令只修复 binfmt 注册(解决"找不到 arm64 解释器"的问题),不修复 QEMU TCG 中 struct flock 跨架构 ABI 转换的缺陷。该方案仅在 Docker 环境下被尝试,属于坑点之一。

3.6 使用 ischroot 技巧

操作:在 --essential-hook 中将 /usr/bin/ischroot 链接到 /bin/false。

结果:❌ 无效。systemd.postinst 没有用 ischroot 保护 pwconv 调用,ischroot 返回什么都无法阻止 pwconv 执行。

四、最终可行的方案

4.1 方案一:升级宿主机的 QEMU(✅ 本次采用,已成功)

在宿主机 Ubuntu 20.04 上,通过 backports 将 QEMU 升级到 8.0.x 版本。

4.1.1 方法一:通过 backports PPA 升级

sudo add-apt-repository ppa:canonical-server/server-backports
sudo apt-get update
sudo apt-get upgrade qemu-user-static
# 升级后重启 systemd-binfmt 服务
sudo systemctl restart systemd-binfmt.service
qemu-aarch64-static --version
# 显示还是之前的版本,升级版本未成功

方法一本次过程中未升级成功,使用的是方法二:手动安装定制版 deb 包。

4.1.2 方法二:手动安装 8.0.4 定制版 deb 包

  • 定制版 qemu-user-static 与 binfmt-support 包存在冲突。

  • binfmt-support 提供 SysVinit 启动脚本 /etc/init.d/binfmt-support,而定制版提供 systemd 服务单元 /lib/systemd/system/systemd-binfmt.service,两者执行顺序会导致 systemd 设置被覆盖。

  • 因此需要先移除 binfmt-support,再安装定制版。

# 1. 移除冲突的 binfmt-support
sudo apt-get purge binfmt-support -y

# 2. 下载 8.0.4 定制版 deb 包
wget https://archive.spacemit.com/qemu/qemu-user-static_8.0.4%2Bdfsg-1ubuntu3.23.10.1_amd64.deb

# 3. 安装 deb 包
sudo dpkg -i qemu-user-static_8.0.4+dfsg-1ubuntu3.23.10.1_amd64.deb

# 4. 重启 systemd-binfmt 服务,将 qemu-user-static 注册到内核
sudo systemctl restart systemd-binfmt.service

# 5. 验证安装
qemu-aarch64-static --version
# 应显示类似 8.0.4 的版本号

QEMU 官方 OFD 锁补丁(2020 年提交)从未被合并到 QEMU 主线,但升级到 8.0.x 后在实际测试中仍能解决此问题。

本次移植过程就是通过这个解决的! 升级宿主机的 QEMU

4.2 方案二:替换 pwconv(chroot + qemu-user-static 场景)

在 debootstrap --second-stage 执行之前,在宿主机上直接替换 chroot 内的 /usr/sbin/pwconv:

ROOTFS="$HOME/ubuntu_rootfs"

# 备份原 pwconv
sudo mv "$ROOTFS/usr/sbin/pwconv" "$ROOTFS/usr/sbin/pwconv.real"

# 替换为空操作脚本
sudo bash -c 'printf "#!/bin/sh\nexit 0\n" > '"$ROOTFS/usr/sbin/pwconv"
sudo chmod +x "$ROOTFS/usr/sbin/pwconv"

# 然后执行 debootstrap --second-stage
sudo chroot "$ROOTFS" /debootstrap/debootstrap --second-stage

原理:pwconv 被替换为空操作后,systemd.postinst 调用 pwconv 时直接返回成功,不会触发 F_OFD_SETLKW 锁。

代价:pwconv 永久返回 0,/etc/shadow 和 /etc/passwd 不同步。需要在目标系统首次启动后执行一次真实的 pwconv。

4.3 方案三:修改 systemd 源码

Launchpad Bug #2069555 中明确指出:

"The only real fix for this issue is a modified systemd package which changes the locking mechanism."

具体修改位置:src/basic/lock-util.c 中 fcntl_lock() 和 fcntl_unlockpp() 调用的 ofd 参数,从 true 改为 false。或者增加检测逻辑:检测到 F_OFD_SETLKW 不支持时,自动回退到 F_SETLKW。

适用场景:这个方案需要自行修改源码并重新编译 systemd 包,操作复杂但能根本解决问题。

4.4 方案四:改用完整虚拟机 qemu-system-aarch64

放弃 qemu-user-static,改用 qemu-system-aarch64 完整系统模拟。虚拟机内部运行完整的 ARM64 内核,原生支持 F_OFD_SETLKW,不存在模拟缺陷。这是最可靠但速度最慢的方案。

五、官方 Bug 追踪链接

来源链接状态
Ubuntu LaunchpadBug #2069555Confirmed
QEMUBug #1893010New
DebianBug #1126304fixed‑upstream
systemd GitHubIssue #29512公开讨论
Microsoft/WSLIssue #10397公开讨论
GitHub WorkaroundInfoXMax/linux‑apt‑fix‑broken‑issue社区方案

核心结论:该问题的根源是 systemd v254+ 硬性要求 F_OFD_SETLKW,而 qemu-user-static 不支持该锁。systemd 和 QEMU 两边都未修复此问题,只能通过 workaround 绕过。

本次采用的有效方案:升级宿主机的 QEMU 到 8.0.x 版本。

----------------------------------------------------------------------------------------

📝 后续补充内容优先同步至 GitHub,如有疏漏欢迎指正。

📌 全部相关技术笔记托管于 GitHub 仓库,欢迎访问。

🔗 GitHub仓库:kyshipit/tech‑notes

-----------------------------------------------------------------------------------------

内容概要:本文针对传统三电平并网逆变器在谐波抑制、电网不平衡适应性及动态响应方面的不足,提出一种基于有源中点箝位(ANPC)三电平拓扑的高性能并网控制策略。该策略深度融合双极性倍频脉宽调制(DPWMA)、正负序分离相技术与电网电压前馈控制,构建了“精准同步—扰动补偿—优质调制”三位一体的一体化控制体系。依托ANPC拓扑在开关损耗均衡、中点电位稳定和低谐波输出方面的硬件优势,结合DPWMA调制提升等效开关频率、正负序分离实现不平衡电网下的精确相、前馈控制克服闭环滞后等先进控制手段,显著改善了系统的稳态电能质量、动态响应速度与复杂工况适应能力。通过多工况仿真验证,该复合策略在稳态运行时可大幅降低总谐波畸变率,在电网不平衡与动态扰动工况下仍能维持并网电流对称、功率平稳及快速恢复能力,展现出优异的综合性能与工程应用潜力。; 适合人群:具备电力电子与电力系统基础知识,从事新能源并网、逆变器控制、微电网或相关领域研究的研发人员及研究生。; 使用场景及目标:① 提升高功率并网逆变器的电能质量与运行稳定性;② 解决电网电压不平衡、畸变等复杂工况下的并网难题;③ 优化动态响应性能,提升系统抗扰能力;④ 为ANPC拓扑与先进控制策略的工程化应用提供技术参考。; 阅读建议:建议结合仿真模型深入理解DPWMA调制、正负序分离相与前馈控制的实现细节,重点关注多工况下的性能对比分析,以掌握复合控制策略的设计逻辑与优化效果。
内容概要:本文针对海岛微电网中可再生能源出力波动与负荷需求不确定性的问题,提出了一种基于“空调-电动汽车”联合虚拟储能的优化调度方法。通过挖掘空调负荷的热舒适弹性与电动汽车充电的时空灵活性,构建联合虚拟储能模型,将其等效为可调度的储能资源参与系统能量平衡。研究建立了考虑多时间尺度协调、系统运行约束及经济性目标的优化调度模型,并采用Matlab进行仿真求解,实现了对海岛孤立微电网的日前-实时双层协同调度。该方法有效提升了系统对风光等分布式能源的消纳能力,降低了对传统物理储能的依赖,增强了微电网运行的经济性、稳定性与能源自给能力。; 适合人群:具备一定电力系统分析、优化算法理论及Matlab编程基础的科研人员或研究生,尤其适用于从事微电网能量管理、虚拟储能技术、需求侧响应、电动汽车与电网互动(V2G)等领域研究的专业技术人员。; 使用场景及目标:①应用于海岛、偏远地区等孤立电网环境,提升供电可靠性与能源利用效率;②为高比例可再生能源接入的微电网提供灵活调节资源,缓解功率波动;③探索空调与电动汽车等柔性负荷协同参与电网调度的潜力,推动需求侧资源由“被动消纳”向“主动支撑”转变;④实现微电网多时间尺度下的经济优化运行。; 阅读建议:建议结合文中所构建的数学模型与Matlab代码实现部分同步学习,重点理解虚拟储能的建模思路、目标函数的设计逻辑以及约束条件的处理方法,并可通过调整可再生能源出力、负荷水平及电动汽车渗透率等参数进行多场景仿真,深入掌握联合虚拟储能对系统调度性能的影响机制。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kyshipit

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值