飞牛 fnOS 深度解析(三):系统目录结构与技术栈全览
本系列文章将对国产 NAS 系统飞牛 fnOS 进行全方位深度解析。本文是系列第三篇,聚焦系统目录结构与技术栈,详细解析 fnOS 的安装目录布局、100+ 自研程序分类、前端技术栈、配置文件体系,以及二次开发的目录布局参考。
阅读本文前,建议先阅读前两篇:
前言
前两篇我们解析了 fnOS 的系统基础、启动流程和存储架构,对系统的整体面貌有了认知。但如果要基于 fnOS 做二次开发,或者要快速解构另一台 NAS 设备,还需要搞清楚一个关键问题:
厂商的东西都放在哪?
Linux 发行版有标准的目录规范(FHS),但 NAS 厂商通常会把自己的自研程序、配置、前端文件、内核模块等放在一个统一的目录下,和系统自带的东西隔离开。找到这个目录,就找到了厂商的全部家当。
本文将带大家完整解析 fnOS 的安装目录 /usr/trim/,看看里面到底有什么、怎么组织的、用了哪些技术栈,以及对二次开发有什么参考价值。
测试环境:fnOS 1.2.0505,x86_64 平台。
一、fnOS 安装根目录总览
从启动流程的分析中我们已经知道,fnOS 的核心程序在 /usr/trim/bin/ 下。我们来看看整个 /usr/trim/ 目录的结构:
ls -la /usr/trim/输出:
drwxr-xr-x 12 root root 4096 Sep 3 08:03 .
drwxr-xr-x 14 root root 4096 Sep 3 08:00 ..
drwxr-xr-x 5 root root 4096 Sep 3 08:03 bin
drwxr-xr-x 2 root root 4096 Sep 3 07:59 config
drwxr-xr-x 7 root root 4096 Sep 3 08:03 etc
drwxr-xr-x 6 root root 4096 Sep 3 07:59 lib
drwxr-xr-x 3 root root 4096 Sep 3 08:03 logs
drwxr-xr-x 8 root root 4096 Sep 3 08:00 modules
drwxr-xr-x 13 root root 4096 Sep 3 08:03 nginx
drwxr-xr-x 6 root root 4096 Sep 3 07:59 share
drwxr-xr-x 11 root root 4096 Sep 3 07:59 var
drwxr-xr-x 9 root root 4096 Sep 3 08:03 www/usr/trim/ 下有 11 个子目录,整体布局参考了 Linux 的 FHS 标准,但做了简化和定制:
| 目录 | 作用 | 类比系统目录 |
|---|---|---|
bin/ | 所有自研程序和脚本(100+个) | /usr/bin/ |
etc/ | 服务级配置文件(40+个) | /etc/ |
lib/ | 库文件 | /usr/lib/ |
logs/ | 日志 | /var/log/ |
modules/ | 内核模块(多个版本) | /lib/modules/ |
nginx/ | 自编译 Nginx(独立目录) | — |
share/ | 共享文件 | /usr/share/ |
var/ | 各服务运行时数据 | /var/lib/ |
www/ | Web 前端文件 | — |
config/ | 运行时配置 | — |
logs/ | 日志 | — |
设计思路很清晰:把所有 fnOS 自研的东西统一放在 /usr/trim/ 下,和 Debian 系统自带的东西完全隔离。这样做的好处:
- 升级方便:系统升级时,直接替换
/usr/trim/目录就行,不会影响系统自带的文件 - 卸载干净:如果要移除 fnOS,删掉
/usr/trim/目录和相关的 systemd 服务就行 - 结构清晰:开发者一眼就能找到自研程序、配置、前端文件的位置
- 权限可控:可以对整个
/usr/trim/目录统一设置权限
下面我们逐个目录详细解析。
二、bin 目录:100+ 自研程序全览
bin/ 是 fnOS 最核心的目录,所有自研程序和脚本都在这里。
ls /usr/trim/bin/输出有 100+ 个文件,包括二进制程序和 shell 脚本。我们按功能分类整理:
2.1 核心基础设施
| 程序 | 作用 |
|---|---|
trim | 核心主进程(trim_main.service 执行的就是它) |
rpc_broker | RPC 消息代理(服务间通信的总线) |
triminit / triminitd | 系统初始化(一次性 + 常驻) |
trimacl | 飞牛自研 ACL 工具(跨文件系统统一权限) |
trimtools | 飞牛工具集 |
handlers | 事件处理器 |
2.2 Web 与 API
| 程序 | 作用 |
|---|---|
trim_http_cgi | HTTP CGI 接口 |
trim_open_gateway | 开放网关 |
uploadsrv / run_uploadserver.sh | 上传服务 |
trim-connect | 飞牛互联远程访问 |
trimdnsafe | DNS 安全 |
2.3 用户与权限
| 程序 | 作用 |
|---|---|
accountsrv | 账户服务 |
usersrv | 用户服务 |
useradd / groupadd | 飞牛自己的用户/组管理工具(不是系统的) |
check_perm / check_token | 权限/令牌校验 |
security_service | 安全服务 |
trim_tfa | 双因素认证 |
trim_license | 许可证管理 |
值得注意的是:fnOS 有自己的 useradd 和 groupadd,不是调用系统的。这说明 fnOS 的用户管理是完全自研的,Web 界面创建用户时,调用的是 /usr/trim/bin/useradd,而不是系统的 /usr/sbin/useradd。这也解释了为什么 Web 用户和系统用户的关系需要专门研究(我们将在第四篇详细解析)。
2.4 文件与存储
| 程序 | 作用 |
|---|---|
filestor_service | 文件存储服务 |
finder_service / filemanager | 文件查找/管理 |
share_service / share-management | 共享管理 |
trim_file_monitor | 文件监控 |
trashbind | 回收站 |
trim_sharelink | 分享链接 |
trim_nfusr / trim_mount_nfs | NFS 相关 |
extdev_service | 外部设备管理(U盘、移动硬盘等) |
diskpowerd / diskcheck | 硬盘电源管理/检测 |
2.5 文件协议
| 程序 | 作用 |
|---|---|
smbftpd / smbftpd-user | 飞牛自己的 FTP 服务(不是 vsftpd/proftpd) |
webdav | WebDAV 服务 |
wsdd2 | WSD 发现(Windows 网络邻居) |
minidlnad | DLNA 媒体服务器 |
cloud_storage_dav / trim_curlftpfs | 云存储挂载 |
又一个自研组件:fnOS 的 FTP 服务叫 smbftpd,不是常见的 vsftpd 或 proftpd。从名字看,它可能和 SMB 共享用户体系,或者是基于某个开源项目修改的。这个名字本身就值得研究。
2.6 网络服务
| 程序 | 作用 |
|---|---|
network_service / netdetect | 网络管理/检测 |
upnp_service / avahi_service | UPnP/零配置网络 |
ipblocker | IP 封禁 |
trim_nic_name_consistency | 网卡名称一致性(保证重启后网卡名不变) |
nic_performance_mode.sh | 网卡性能模式切换 |
2.7 AI 与媒体
| 程序 | 作用 |
|---|---|
ai_manager | AI 管理器(AI 相册的核心) |
imagesrv | 图像服务 |
mediasrv | 媒体服务 |
auto_thumbnailer | 自动缩略图生成 |
2.8 Docker 与应用
| 程序 | 作用 |
|---|---|
dockermgr / dsmgr | Docker 管理/流服务 |
trim_app_center | 应用中心 |
trim_sac | 系统应用控制(System Apps Control) |
trim_registry | 镜像仓库 |
docker-shutdown-containers.sh | Docker 关机时优雅停止容器的脚本 |
2.9 备份与下载
| 程序 | 作用 |
|---|---|
backup_service | 备份服务(总入口) |
backup_local / backup_remote / backup_cloud | 本地/远程/云备份 |
rapidrecovery | 快速恢复 |
dlcenter / multiple-downloads | 下载中心/多任务下载 |
trim-aria2c / trim-qbittorrent-nox | 下载工具(飞牛封装版) |
备份服务拆成了 local/remote/cloud 三个独立程序,说明飞牛的备份方案支持多种备份目标,架构上做了拆分。
2.10 系统管理
| 程序 | 作用 |
|---|---|
updatemgr / liveupdate | 系统升级/在线更新 |
sysdiag / sysinfo_service | 系统诊断/信息 |
sysrestore_service | 系统还原 |
system_startup.sh / system_shutdown.sh / system_umount.sh | 系统启停脚本 |
system_setgpio.sh / system_setled.sh / system_setmac.sh | 硬件设置脚本(GPIO/LED/MAC) |
resmon_service / eventlogger_service / logchecker | 资源监控/日志 |
show_startup_info.sh | 显示启动信息(可能是前面板屏幕) |
2.11 硬件与存储管理
| 程序 | 作用 |
|---|---|
pwm-fancontrol.sh | PWM 风扇调速 |
maligpu-fw-symlink | Mali GPU 固件(通用镜像,x86 上可能没用) |
mdadm | 飞牛自己的 mdadm(可能打了补丁或加了快速同步功能) |
fast_resync_md_raid / check_raid456_resync_status / init_resync_wait | RAID 同步管理(快速重建、状态检查、等待同步) |
resize-rootfs.sh | 首次开机自动扩容根分区 |
scrub_watch.json | ZFS scrub 监控(在 etc 目录下) |
又一个自研组件:fnOS 有自己的 mdadm,而且配套了 fast_resync_md_raid(快速 RAID 同步)。标准 mdadm 的 RAID 重建速度是有限制的,飞牛可能做了优化,加快重建速度。这也是一个技术亮点。
2.12 工具与其他
| 程序 | 作用 |
|---|---|
7zz | 压缩工具(7-Zip 的 Linux 版) |
benchmark / coremark | 性能测试工具 |
bpf | BPF(Berkeley Packet Filter)工具 |
dfree | 磁盘空间查询(Samba 用的) |
wait_trim_init.sh / run_trim.sh / trim_launch_tty.sh | 辅助脚本 |
upssched_cmd.sh | UPS 电源调度 |
2.13 bin 目录的重大发现总结
- 自研程度非常高:从核心主进程、用户管理、FTP 服务,到 mdadm、useradd 这些基础工具,fnOS 都有自己的版本,不是简单套用开源软件
- 微服务架构:100+ 个程序,每个负责一个小功能,通过 rpc_broker 通信,不是一个大而全的单体程序
- 脚本与二进制混合:既有编译好的二进制程序(trim、rpc_broker 等),也有大量 shell 脚本(.sh 结尾),用于系统启停、硬件设置等
- 硬件定制深入:GPIO、LED、风扇、MAC地址、UPS,都有专门的管理工具,说明飞牛对硬件层有较深的定制
三、www 目录:Web 前端文件与技术栈
www/ 是 Web 前端文件目录,也就是用户在浏览器里看到的管理界面的所有静态文件。
3.1 目录结构
ls /usr/trim/www/输出:
access-code apps assets favicon.ico index.html locales lottie modules robots.txt static| 目录/文件 | 作用 |
|---|---|
index.html | 入口页面 |
assets/ | 打包后的 JS/CSS 文件 |
locales/ | 多语言文件 |
modules/ | 前端模块 |
apps/ | 应用页面(可能是各个功能模块的入口) |
access-code/ | 访问码相关页面 |
lottie/ | Lottie 动画文件 |
static/ | 静态资源(图片、字体等) |
favicon.ico | 网站图标 |
robots.txt | 爬虫规则 |
这是一个典型的单页应用(SPA)结构:一个 index.html 入口 + 一堆打包后的 JS/CSS 文件 + 多语言文件。
3.2 前端技术栈分析
我们来看 index.html 的内容:
head -20 /usr/trim/www/index.html输出(关键部分):
<!doctype html>
<html class="light" lang="zh-CN">
<head>
<script type="module" crossorigin src="/assets/polyfills-UfQ5iIgP.js"></script>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover"/>
<style>
body,html{background:linear-gradient(110deg,#4a5568 .26%,#3a424f 97.78%)}
html.body--biz{--biz-bg-fallback:#F2F3F4}
...
.global-loading--biz{--biz-loading-fallback:#F2F3F4;background:var(--semi-color-bg-0,var(--biz-bg-fallback))}
...
</style>
<title>飞牛 fnOS</title>
<script type="module" crossorigin src="/assets/index-C9XPc7lT.js"></script>
<link rel="modulepreload" crossorigin href="/assets/rolldown-runtime-BM3Ffeng.js">
<link rel="modulepreload" crossorigin href="/assets/preload-helper-DgFuoWHe.js">
<link rel="modulepreload" crossorigin href="/assets/type-RT4QY32W.js">
<link rel="modulepreload" crossorigin href="/assets/domain-config-BzStsgMa.js">
<link rel="modulepreload" crossorigin href="/assets/constants-BTmVL42d.js">
<link rel="modulepreload" crossorigin href="/assets/namespace-CL4pj1vT.js">
<link rel="modulepreload" crossorigin href="/assets/url-B_xvWlNO.js">
<link rel="modulepreload" crossorigin href="/assets/zh_CN-mZPLn7er.js">
<link rel="modulepreload" crossorigin href="/assets/es-BdQV1tZe.js">
<link rel="modulepreload" crossorigin href="/assets/i18next-DI2VtEAE.js">
<link rel="modulepreload" crossorigin href="/assets/lodash-DktMXRmK.js">
<link rel="modulepreload" crossorigin href="/assets/lottie-react-BcWb8UXT.js">
<link rel="modulepreload" crossorigin href="/assets/bundle-mjs-Ds-GHEHy.js">
<link rel="modulepreload" crossorigin href="/assets/tslib.es6-C6_slaGn.js">
<link rel="stylesheet" crossorigin href="/assets/index-u7rXlhqt.css">
</head>从 index.html 引用的 JS 文件名,我们可以分析出完整的前端技术栈:
| 技术 | 证据 | 说明 |
|---|---|---|
| React | lottie-react.js | Lottie 的 React 绑定,说明用了 React |
| TypeScript | tslib.es6.js | TypeScript 运行时库,说明用了 TS |
| Semi Design | CSS 变量 --semi-color-bg-0 | 字节跳动开源的 React 组件库 |
| Rolldown | rolldown-runtime.js | 新一代 JavaScript 打包工具(基于 Rust,类似 Vite 的底层) |
| i18next | i18next.js | 国际化框架,支持多语言 |
| Lodash | lodash.js | JavaScript 工具库 |
| Lottie | lottie-react.js + lottie/ 目录 | 动画库,用于界面动画 |
| ES Modules | <script type="module"> | 原生 ES 模块,现代前端标准 |
结论:fnOS 的前端技术栈是 React + TypeScript + Semi Design(字节组件库),用 Rolldown 打包,i18next 做国际化。
几个值得注意的点:
- 用了字节的 Semi Design:Semi Design 是字节跳动开源的企业级 React 组件库,飞牛用它做 UI 组件,说明前端团队可能和字节有技术交流,或者就是偏好字节的技术栈
- 用了 Rolldown 打包:Rolldown 是一个比较新的打包工具(基于 Rust,由 Vite 团队开发),说明飞牛的前端技术栈比较新,跟进前沿工具
- 多语言支持:从
locales/目录和i18next来看,fnOS 支持多语言,至少有中文(zh_CN)和西班牙语(es) - 有 biz 主题:从
body--biz相关的 CSS 来看,fnOS 可能有"商业版"或"企业版"的主题,和普通版区分开
3.3 前端文件的权限与更新
www/ 目录下的文件都是打包后的静态文件,不是源码。这意味着:
- 不能直接修改源码:要改前端界面,需要有源码,用构建工具重新打包
- 可以直接替换打包后的文件:如果只是小改动(比如改个标题、换个图标),可以直接替换
www/下的对应文件 - 升级会被覆盖:系统升级时,
www/目录会被整体替换,自定义修改会丢失
对于二次开发来说,如果要加自己的前端页面,有两种思路:
- 在
www/下加静态文件:简单直接,但升级会被覆盖,且无法融入原有的菜单和路由体系 - 通过 Nginx 配置加独立路由:在 Nginx 配置里加一个 location,把某个路径指向自己的前端文件目录,这样和原系统隔离,升级不受影响
四、etc 目录:配置文件宝库
etc/ 是 fnOS 的服务级配置文件目录,有 40+ 个配置文件。
ls /usr/trim/etc/输出(分类整理):
4.1 版本与设备信息
| 文件 | 作用 |
|---|---|
version | fnOS 版本号 |
machine_id | 设备唯一标识 |
system_inited_timestamp | 系统初始化时间戳 |
fw.conf | 固件配置 |
gpu_device_info.json | GPU 设备信息 |
我们来看版本号:
cat /usr/trim/etc/version输出:
1.2.0505fnOS 的版本号是 1.2.0505。注意这个版本号不在 /etc/os-release 里(那里只有 Debian 12 的信息),而是在 fnOS 自己的 /usr/trim/etc/version 里。这也是找 NAS 系统版本号的一个通用方法:去厂商的安装目录下找 version 文件。
4.2 安全密钥与证书
| 文件 | 作用 |
|---|---|
rsa_private_key.pem | RSA 私钥 |
rsa_public_key.pem | RSA 公钥 |
ssl.crt | SSL 证书 |
ssl.key | SSL 私钥 |
ssl.csr | SSL 证书签名请求 |
trim.key.enc | 加密的密钥文件 |
download.key | 下载相关密钥 |
这些密钥和证书主要用于:
- 飞牛互联远程访问的加密通信
- Web 界面的 HTTPS
- 应用下载的签名验证
trim.key.enc 是加密的密钥文件,说明飞牛对核心密钥做了加密保护,不是明文存储。
4.3 网络配置
| 文件 | 作用 |
|---|---|
network_ssh.conf | SSH 配置 |
network_gateway_cert.conf | 网关证书配置 |
network_gateway_setting.conf | 网关设置 |
network_cert_all.conf | 网络证书(全部) |
network_nic_performance_mode.conf | 网卡性能模式 |
4.4 服务配置
| 文件 | 作用 |
|---|---|
rpc_broker.conf | RPC 消息代理配置 |
dockermgr.conf | Docker 管理配置 |
smbftp.conf | FTP 服务配置 |
webdav.conf | WebDAV 配置 |
mediasrv.conf | 媒体服务配置 |
minidlna.conf | DLNA 配置 |
resmon_service.conf | 资源监控配置 |
event_logger.conf | 事件日志配置 |
diskcheck.conf | 硬盘检测配置 |
trim_file_monitor.conf | 文件监控配置 |
trim_nic_name_consistency.conf | 网卡名称一致性配置 |
4.5 安全白名单
| 文件 | 作用 |
|---|---|
appcgi_notoken_whitelist | 不需要 Token 认证的 CGI 接口白名单 |
safe_code_whitelist.conf | 安全代码白名单 |
trim_nosig_whitelist | 不需要签名验证的白名单 |
这三个白名单文件很有意思,说明 fnOS 的安全机制:
- API 接口默认需要 Token 认证,白名单里的接口不需要
- 代码执行有安全校验,白名单里的代码可以直接运行
- 应用/文件默认需要签名验证,白名单里的不需要
这对二次开发很重要——如果要加自己的 API 接口或应用,可能需要加到对应的白名单里,否则会被安全机制拦截。
4.6 存储相关
| 文件 | 作用 |
|---|---|
storage/ | 存储配置目录(当前为空,可能运行时生成) |
scrub_watch.json | ZFS scrub(数据校验)监控配置 |
upgrade.conf | 系统升级配置 |
4.7 其他
| 文件 | 作用 |
|---|---|
cloud_storage_dav/ | 云存储 DAV 配置 |
network_cert_all.conf.old | 旧的网络证书配置(备份) |
五、nginx 目录:自编译 Nginx
fnOS 用的不是 Debian 自带的 Nginx,而是自己编译的,放在 /usr/trim/nginx/ 下。
ls /usr/trim/nginx/输出:
client_body_temp conf fastcgi_temp html logs modules
proxy_temp sbin scgi_temp test_js uwsgi_temp| 目录 | 作用 |
|---|---|
sbin/ | Nginx 二进制程序(/usr/trim/nginx/sbin/nginx) |
conf/ | Nginx 配置文件 |
html/ | 默认静态文件(可能不是主前端,主前端在 www/) |
logs/ | Nginx 日志 |
modules/ | Nginx 模块(自编译的模块) |
test_js/ | 测试用的 JS 文件 |
*_temp/ | 各种临时文件目录(client_body、fastcgi、proxy、scgi、uwsgi) |
从启动配置我们知道:
ExecStartPre=/usr/trim/nginx/sbin/nginx -t
ExecStart=/usr/trim/nginx/sbin/nginxNginx 启动前会先执行 nginx -t 测试配置文件,有语法错误就不启动,避免 Web 界面挂掉。
自编译 Nginx 的好处:
- 可以加自定义模块:
modules/目录说明飞牛可能编译了自己的 Nginx 模块 - 版本可控:不受 Debian 包管理器的版本限制,可以用最新版或特定版本
- 路径独立:和系统 Nginx 完全隔离,不会冲突
六、modules 目录:内核模块与多版本保留
modules/ 是内核模块目录,存放飞牛定制内核的模块文件。
ls /usr/trim/modules/输出:
6.18.18.c1032-trim 6.18.18.c788-trim 6.18.18.c877-trim
6.18.18.c938-trim 6.18.18.c952-trim 6.18.18-trim飞牛保留了 6 个内核版本的模块!
| 版本 | 说明 |
|---|---|
6.18.18.c1032-trim | 当前运行的版本 |
6.18.18.c952-trim | 上一个版本 |
6.18.18.c938-trim | 更早的版本 |
6.18.18.c877-trim | 更早的版本 |
6.18.18.c788-trim | 更早的版本 |
6.18.18-trim | 最早的版本(没有 c 后缀) |
这说明:
- 内核迭代非常频繁:从 c788 到 c1032,至少迭代了 5 个版本,说明飞牛对内核的更新很积极
- 支持升级回滚:保留旧版本的内核模块,系统升级后如果新内核有问题,可以回滚到旧版本
- 定制模块放在这里:trimafs2、zfs(飞牛定制版)这些自研内核模块,就放在对应版本的目录下
标准的 Linux 内核模块放在 /lib/modules/$(uname -r)/ 下,飞牛把自己的内核模块额外放在 /usr/trim/modules/ 下,可能是为了升级时方便整体替换,或者是因为他们的内核模块和标准内核模块有冲突,需要独立存放。
七、var 目录:各服务运行时数据
var/ 存放各服务的运行时数据,每个服务有独立的子目录。
ls /usr/trim/var/输出:
ai_manager backup_service downloadcenter minidlna trim_connect
auto_thumbnailer dockermgr eventlogger_service share_service| 目录 | 对应服务 | 存放内容 |
|---|---|---|
ai_manager/ | AI 管理器 | AI 模型缓存、推理临时数据 |
auto_thumbnailer/ | 自动缩略图 | 缩略图缓存 |
backup_service/ | 备份服务 | 备份任务状态、临时文件 |
dockermgr/ | Docker 管理 | Docker 相关状态 |
downloadcenter/ | 下载中心 | 下载任务状态、临时文件 |
eventlogger_service/ | 事件日志 | 事件日志数据 |
minidlna/ | DLNA | DLNA 媒体库索引 |
share_service/ | 共享服务 | 共享配置状态 |
trim_connect/ | 飞牛互联 | 远程连接状态、临时数据 |
这种"每个服务一个 var 子目录"的设计,和微服务架构是匹配的——每个服务独立管理自己的运行时数据,互不干扰,也方便清理和备份。
八、其他目录
8.1 lib 目录
lib/ 存放 fnOS 自研程序依赖的库文件。虽然我们没有详细列出内容,但从目录存在可以推断,飞牛的一些程序可能依赖了特定版本的库,为了不和系统库冲突,单独放在这里。
8.2 share 目录
share/ 存放共享文件,可能包括:
- 程序的资源文件(图标、模板、默认配置)
- 文档
- 示例文件
8.3 config 目录
config/ 存放运行时配置,和 etc/ 的区别可能是:
etc/是静态的、出厂默认的配置config/是运行时生成的、用户修改过的配置
我们看到 config/ 下有:
appcgi_notoken_whitelist gpu_device_info.json trim_nosig_whitelist这些和 etc/ 下的文件有重叠,可能是运行时从 etc 复制过来并修改的,或者是用户在 Web 界面修改后保存到这里。
8.4 logs 目录
logs/ 存放 fnOS 的日志。标准的系统日志在 /var/log/ 下,fnOS 把自己的日志单独放在 /usr/trim/logs/ 下,方便统一管理和清理。
九、二次开发的目录布局参考
基于以上分析,如果要基于 fnOS 做二次开发(比如加一个自己的存证功能),推荐的目录布局如下:
/usr/trim/ ← fnOS 原厂目录(升级会被覆盖,不要改)
├── bin/ ← 原厂程序
├── etc/ ← 原厂配置
├── www/ ← 原厂前端
└── ...
/opt/myapp/ ← 自己的程序放在这里(和原厂隔离,升级不影响)
├── bin/ ← 自己的程序二进制
├── etc/ ← 自己的配置
├── www/ ← 自己的前端页面
├── var/ ← 自己的运行时数据
└── logs/ ← 自己的日志
/etc/systemd/system/myapp.service ← 自己的 systemd 服务文件关键原则:不要修改 /usr/trim/ 下的任何文件。 因为系统升级时这个目录会被整体替换,你的修改会丢失。自己的东西放在 /opt/ 或 /usr/local/ 下,通过 systemd 服务和 Nginx 配置和原系统集成。
对于前端页面,可以通过修改 Nginx 配置(在 /usr/trim/nginx/conf/ 下加一个 conf 文件,或者在主配置里 include 自己的配置),把某个路径(比如 /myapp/)指向自己的前端目录,这样和原系统的前端完全隔离,升级不受影响。
十、系统解构方法论:怎么快速找到厂商的安装目录
分析完 fnOS 的目录结构,我们可以总结出一套通用的方法论——拿到任何一台新 NAS(或其他 Linux 设备),怎么快速找到厂商的安装目录和核心程序:
方法 1:从 systemd 服务入手
# 列出所有运行中的服务,找名字特殊的(不是 Debian 原生的)
systemctl list-units --type=service --state=running
# 看某个可疑服务的配置,找 ExecStart 路径
systemctl cat <服务名>服务的 ExecStart 指向的程序路径,通常就在厂商的安装目录下。比如 fnOS 的 trim_main.service 的 ExecStart=/usr/trim/bin/trim,一看就知道厂商目录是 /usr/trim/。
方法 2:从进程入手
# 看所有进程,找路径特殊的
ps aux | grep -v '/usr/bin\|/usr/sbin\|/bin\|/sbin'
# 或者看监听端口的进程
ss -tlnpWeb 服务、后端服务这些进程的可执行文件路径,通常就在厂商目录下。
方法 3:从常见位置找
NAS 厂商通常把自己的东西放在这些位置:
/usr/厂商名/(比如 fnOS 的/usr/trim/)/opt/厂商名//usr/local/厂商名//厂商名/(根目录下)
可以直接 ls /usr/、ls /opt/ 看看有没有可疑的目录。
方法 4:找版本号文件
# 在常见位置找 version 文件
find /usr /opt /etc -name "version" -o -name "VERSION" 2>/dev/null
# 或者找 os-release 的补充文件
cat /etc/*release* 2>/dev/null版本号文件通常在厂商的 etc 目录下,找到它也就找到了厂商目录。
方法 5:从前端文件入手
# 找 Nginx 配置,看 root 指向哪
find /etc /usr -name "nginx.conf" 2>/dev/null
# 或者直接看常见的前端位置
ls /var/www/ /usr/share/nginx/html/ 2>/dev/nullWeb 前端文件的位置,通常也在厂商目录下。
十一、总结
通过本文的解析,我们对 fnOS 的系统目录结构和技术栈有了完整的认知:
- 统一安装目录:所有 fnOS 自研的东西都在
/usr/trim/下,和 Debian 系统完全隔离,11 个子目录布局清晰 - 自研程度极高:100+ 自研程序,从核心主进程、用户管理(useradd)、FTP 服务(smbftpd),到 mdadm 这些基础工具都有自己的版本,不是简单套用开源软件
- 微服务架构:每个功能一个独立程序,通过 rpc_broker 通信,职责清晰,易于维护和扩展
- 前端技术栈现代:React + TypeScript + Semi Design(字节组件库)+ Rolldown 打包 + i18next 国际化,技术栈比较新
- 自编译 Nginx:独立目录、独立模块、启动前配置测试,和系统 Nginx 完全隔离
- 多版本内核保留:保留 6 个版本的内核模块,支持升级回滚,内核迭代频繁
- 配置体系完善:40+ 配置文件,涵盖版本、密钥、网络、服务、安全白名单等,安全机制严密
- 二次开发建议:不要修改
/usr/trim/下的文件,自己的东西放在/opt/下,通过 systemd 和 Nginx 配置集成
系列预告
下一篇《飞牛 fnOS 深度解析(四):文件服务与用户权限体系》,我们将详细解析:
- SMB/CIFS 服务的配置与认证机制(Samba 用什么认证后端?共享配置是动态生成的吗?)
- NFS、WebDAV、FTP 的实现方式(飞牛自己的 smbftpd 是什么?)
- 四种文件协议的对比与统一认证
- Web 用户和 Linux 系统用户的关系(/usr/trim/bin/useradd 做了什么?)
- 用户信息存在哪里(/etc/passwd?PostgreSQL?)
- 权限是 POSIX ACL 还是自研的 trimacl?
- 跨协议权限怎么保证一致?
敬请期待。
本文基于 fnOS 1.2.0505 版本实测,不同版本可能存在差异。
二次开发有风险,请勿在生产环境随意修改系统文件。