外观
执行 apt upgrade 之后无法登录、打不开管理界面
典型经过是这样的:开启 SSH,登录进去,看到熟悉的 Debian 提示符,顺手敲了一句 apt update && apt full-upgrade。命令跑完,SSH 断开——然后网页管理界面再也打不开了,手机 App 也登录不上。
这是 fnOS 上最常见的一类自损事故。本页说明它为什么会发生、能不能救,以及怎么避免。
先停下来,不要做这三件事
不要重装系统——在确认清楚之前,重装可能让你失去本来能救回来的配置。 不要格式化任何硬盘,也不要对存储空间做任何操作。 不要凭搜索到的命令随手往下敲——特别是带 rm、dd、mkfs 的命令。
好消息是:这类故障通常只破坏了系统盘上的软件环境,数据盘上的文件多半完好。你的目标是在不碰数据的前提下恢复系统。
为什么会这样
fnOS 的底座是 Debian,但它不是一个普通的 Debian 系统。
官方源里的系统组件是配套发布的:管理界面、授权服务、数据库、Web 服务器、内核,这些东西的版本经过一起测试,彼此之间有明确的依赖关系。
apt upgrade 做的事情是:把系统里所有能升级的包,升级到上游 Debian 仓库里的最新版本。这会撞上几类问题:
| 被替换的东西 | 后果 |
|---|---|
| PostgreSQL | fnOS 的授权等服务连不上数据库,管理界面返回 502 或「系统内部错误」 |
| nginx 等 Web 组件 | 管理界面端口不再监听,浏览器直接连不上 |
| systemd、glibc 等基础库 | 多个 fnOS 服务启动失败,症状五花八门 |
| 内核 | 最严重——存储相关模块不匹配,可能开不了机,或者开机了但存储空间挂不上 |
所以「无法登录」和「打不开管理界面」往往不是同一个原因,而是多个服务同时挂掉的综合表现。
这也是升级 fnOS 本身会失败的原因
手动动过底层环境的系统,在之后执行 fnOS 官方版本更新时也容易失败。飞牛官方论坛有专门的更新失败问题处理合集,其中包含修复脚本,见下方参考资料(需要论坛账号访问)。
第一步:判断故障到哪一层
按这个顺序确认,每一步的答案决定下一步做什么。
机器还能开机吗
接上显示器和键盘,看能不能进到系统的本地控制台。
- 能进 → 系统内核和基础启动流程还在,多半只是服务层面的问题,继续往下。
- 黑屏或卡在引导 → 内核可能被换掉了,这种情况自行修复的难度很高,直接跳到什么时候该重装。
SSH 还能连上吗
sh
ssh 你的用户名@NAS地址- 能连 → 这是最好的情况,你有完整的排查手段。
- 连不上但能开机 → 用本地控制台(接显示器键盘)操作,下面的命令同样适用。
网页界面是哪种打不开
这两种表现指向不同的方向:
| 现象 | 含义 |
|---|---|
| 浏览器提示无法连接 / 连接被拒绝 | Web 服务没在监听,端口是空的 |
| 页面能打开但卡在登录页,或提示 502、「系统内部错误」 | Web 服务活着,但它依赖的后端服务挂了 |
第二种反而更容易修——说明系统大体健康,只是某个服务没起来。
第二步:找出哪些服务挂了
登录后先看全局:
sh
systemctl --failed这条命令列出所有启动失败的服务单元。这是整个排查里信息量最大的一条命令,先看它,再做任何猜测。
然后看具体服务的状态:
sh
systemctl status postgresql
systemctl status nginx以及端口有没有在监听:
sh
ss -tlnp-t 只看 TCP、-l 只看监听状态、-n 不解析域名、-p 显示对应进程。管理界面的端口如果不在列表里,说明服务确实没起来。
再看日志:
sh
journalctl -p err -b | tail -50
journalctl -xeu 服务名 --no-pager | tail -30-p err 按错误级别过滤,-b 限定本次启动;第二条看某个具体服务的详细日志。日志里几乎总会写清楚它为什么起不来,比如缺少某个库、配置文件格式不认识、或者端口被占用。
一个真实案例:数据库端口被占用
社区里有一个被反复引用的排查记录,症状是登录页卡住、浏览器控制台显示授权相关请求返回 502,根源是授权服务依赖的 PostgreSQL 没能启动——数据库端口被一个残留进程占着。
排查过程大致是这样(命令来自该记录,版本号和端口以你实际看到的为准):
sh
pg_lsclusters # 查看数据库集群状态,down 表示没跑起来
pg_ctlcluster 15 main start # 尝试启动,看它报什么错
journalctl -xeu postgresql@15-main.service --no-pager | tail -30如果日志里出现类似 could not bind ... Address already in use,说明端口被占用:
sh
ss -tulnp | grep :5432 # 找出占用 5432 端口的进程和 PID结束进程和删除文件之前,先看清楚
后续步骤涉及强制结束进程和删除 PID 文件。动手之前确认你看到的进程确实是残留的数据库进程,而不是正在正常工作的其他服务。
kill -9 是强制终止,不给进程保存数据的机会。对数据库执行它,有造成数据损坏的可能。只在进程已经卡死、常规方式停不掉时才用,并且先确认这个数据库里的内容有没有备份。
删除 PID 文件同理:删错文件可能让服务的状态更混乱。每一条命令执行前,先读懂它操作的是哪个路径。
确认无误后,清理残留并重新启动集群,再启动依赖它的服务,最后确认这些服务设置了开机自启——否则重启一次问题就会复现。
这是社区方案,不是官方修复步骤。 你的版本号、服务名和实际原因都可能不同,把它当作「排查思路的示例」,而不是照抄的脚本。
第三步:能不能自己修好
到这里做个判断:
| 情况 | 建议 |
|---|---|
| 只有一两个服务失败,日志里原因明确 | 值得尝试修复 |
systemctl --failed 列出一长串 | 修复的性价比很低,考虑重装 |
| 内核被替换、开不了机 | 直接重装 |
| 你已经折腾了两小时还没缩小范围 | 停手,走重装 |
修复的目标不是「修好」,而是「进得去」
如果你能让管理界面重新打开,第一件事不是继续修,而是:把配置导出、把重要数据确认一遍、把容器的 compose 文件备份走。拿到这些东西之后,重装是一个轻松的选项。
什么时候该重装
出现下列任一情况,重装比继续修划算:
- 内核被替换,系统起不来。
- 大量服务启动失败,日志指向基础库版本不匹配。
- 你不确定自己之前还动过什么。
重装之前必须做的事
重装会清空系统盘
安装程序会重建目标盘的分区。最稳妥的做法是:断电,把所有数据盘的数据线拔掉,只留系统盘,装完再把数据盘接回去。
这比在安装界面里靠型号辨认要可靠得多——辨认错一次,代价是全部数据。
顺序是这样:
- 如果还能进系统,先把配置和 compose 文件导出备份。
- 确认重要数据在别处还有一份,见3-2-1 原则。
- 断电,拔掉数据盘的数据线。
- 按安装 fnOS重装到系统盘。
- 关机,把数据盘接回去,开机。
- 让系统识别已有的存储空间。
- 重建共享文件夹权限、容器和定时任务。
官方也提供了系统恢复相关的功能,见下方参考资料,可以在重装之前先了解一下它能做到什么程度。
重装之后
把这次的经历变成两件事:
- 记录下你的配置:存储空间结构、共享文件夹与权限、容器 compose 文件、定时任务。下次重建时它能省掉几天,见开发者工作流里用 Git 管理 compose 的做法。
- 检查备份是不是真的可用,见恢复演练。这次没丢数据是运气好,不是体系可靠。
怎么避免再次发生
记住这条边界
| 操作 | 结论 |
|---|---|
| 查看状态、读日志、排查问题 | 放心用命令行 |
apt install 装个 htop 之类的小工具 | 一般可以,但要接受系统升级后可能失效 |
apt upgrade / apt full-upgrade | 不要 |
apt 升级内核、systemd、数据库等基础组件 | 不要 |
| 直接改存储、共享、用户的底层配置 | 不要,用网页端 |
完整讨论见SSH 与命令行。
需要装东西时,优先用容器
想跑一个服务、试一个工具,用容器而不是往宿主机上装。容器有自己的依赖环境,装坏了删掉重来,不会影响系统本身。这是自托管场景下最重要的一条习惯,见Docker 入门。
系统更新走官方渠道
fnOS 自身的版本更新在网页端完成,那是经过配套测试的。apt 拉来的是 Debian 上游的版本,两者不是一回事。
动手之前留一条退路
在做任何底层改动之前:
- 导出一份系统配置。
- 把容器的 compose 文件备份走。
- 如果存储空间是 Btrfs,确认快照策略在跑。