🧩 问题背景
在我的 Ubuntu 系统中,无论是执行:
1 | sudo apt install <package> |
每次涉及 dpkg 调用时,系统都会在最后阶段报出相同的错误信息:
1 | Setting up openssh-server (1:8.2p1-4ubuntu0.13) ... |
表面上似乎只是 SSH 相关的警告,但它会导致 所有 apt/dpkg 命令退出码非 0,从而影响系统更新、软件安装、甚至 Docker 构建过程。
🧠 问题排查过程
一、确定 SSH 实际状态
首先查看 SSH 服务状态:
1 | systemctl status ssh |
结果显示:
1 | ● ssh.service - OpenBSD Secure Shell server |
可以确定——SSH 服务本身完全正常运行。
说明问题并不是服务启动失败,而是安装后脚本执行返回了错误状态。
二、查看 dpkg 后安装脚本
dpkg 的安装、配置流程中会调用 /var/lib/dpkg/info/<package>.postinst。
针对 openssh-server,我们打开:
1 | sudo nano /var/lib/dpkg/info/openssh-server.postinst |
在文件的末尾,找到类似这一行:
1 | invoke-rc.d ssh $_dh_action |
这里的 $_dh_action 一般是 restart、start 或 reload,
该行调用的是 /usr/sbin/invoke-rc.d,由它来执行 SSH 服务的重启。
而正是这一步返回了非零状态(exit code 1),导致 dpkg 报错。
🧰 解决方案
为了让 dpkg 在执行此处时即使失败也能继续正常返回,我们在命令后添加 || true:
1 | invoke-rc.d ssh $_dh_action || true |
这表示:
“即使前面的命令执行失败,也不要将整个脚本判定为失败。”
保存退出后,再执行:
1 | sudo dpkg --configure -a |
这一次输出正常,没有再出现报错。
再运行:
1 | sudo apt install -f |
或:
1 | sudo apt upgrade |
都能顺利完成。
✅ 验证结果
SSH 服务状态依旧正常:
1
systemctl status ssh
输出:
1
Active: active (running)
dpkg 状态干净:
1
dpkg -l | grep openssh-server
输出:
1
ii openssh-server 1:8.2p1-4ubuntu0.13 amd64 secure shell (SSH) server, for secure access from remote machines
apt/dpkg 不再受阻,系统升级恢复正常。
🧩 原因分析
这个问题实质上是由于:
/usr/sbin/invoke-rc.d脚本中的兼容性 bug(使用==等语法在 dash 下报错),- 或者某些运行环境中 systemd 启动 SSH 时返回状态非 0。
虽然服务本身成功运行,但 postinst 脚本没有忽略非零返回值,从而让 dpkg 误认为失败。
💡 为什么 “|| true” 是安全的
postinst 脚本的主要作用是在安装或升级时触发服务刷新。
即使 invoke-rc.d 返回失败:
- 不影响 SSH 本身(systemd 仍会自动管理服务),
- 不影响配置文件、密钥等资源,
- 只会让 dpkg 终止于非零状态。
加上 || true 后可以安全地忽略这种假性错误,
在确保系统完整性的同时恢复 dpkg 的正常运行逻辑。
🧾 总结
| 项目 | 说明 | ||
|---|---|---|---|
| 问题现象 | 所有 apt/dpkg 命令末尾都会因 openssh-server 报错而退出 | ||
| 服务状态 | SSH 实际运行正常 | ||
| 根本原因 | postinst 调用 invoke-rc.d 时返回 1 | ||
| 最终修复 | 修改 /var/lib/dpkg/info/openssh-server.postinst,将 invoke-rc.d ssh $_dh_action 改为 `invoke-rc.d ssh $_dh_action |
true` | |
| 修复效果 | dpkg 恢复正常,系统升级和安装不再出错 |
🧠 经验与启示
- apt/dpkg 的脚本错误并不一定意味着服务坏了,
很多时候只是“返回值不符合预期”。 - 可以通过修改
/var/lib/dpkg/info/<pkg>.postinst进行安全绕过。 - 如果未来系统更新覆盖此文件,可再次添加
|| true。 - 在容器(Docker)或无交互环境中尤其常见。
💬 结语
这个问题一开始看似 SSH 崩溃,
实则是 dpkg 对返回值“太认真”。
最终只是加上 || true,就让整个系统重新恢复了顺畅。
希望这篇记录能帮到你,也提醒未来的自己:
看清楚错误来源,不要慌,dpkg 只是有点“洁癖”。 😄