青蛙小白
博客 / 2025/04

折腾飞牛fnOS的笔记

2025/04/02 · — 字 · 阅读约 — 分钟 ·
目录

系统安装

fnOS启动盘制作(MacOS下)

列出磁盘,找到U盘的盘符

diskutil list

/dev/disk4 (external, physical):
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:      GUID_partition_scheme                        *15.5 GB    disk4

取消U盘的挂载:

diskutil unmountDisk /dev/disk4

Unmount of all volumes on disk4 was successful

执行下面的命令导入fnOS镜像:

sudo dd if=./fnos-<version>-<version>.iso of=/dev/disk4 bs=4m

关于dd命令:

  • if:input file,输入文件(这里是ISO镜像)
  • of:output file,输出设备(这里是 /dev/disk4
  • bs=5m:block size 每次读写的块大小(一般u盘设置为1~4m)

Lucky

已放弃使用Lucky,改为使用docker部署nginx

对于 Linux 老手而言,通过配置 fnOS 自带的 Nginx 或新装一个,也完全能实现上述功能。使用 lucky 纯粹是为了省事。

用了几天发现飞牛应用中心里Lucky不带稳定,而且Lucky比较臃肿带了很多我现在用不到的功能,我当前的需求只是要将把飞牛NAS上的Web应用(包括飞牛NAS自己)以域名的形式暴露到公网上,一个nginx足以。

首先尝试使用fnOS自带的nginx,发现最新版本的fnOS已经不支持/usr/trim/nginx/conf/conf.d/增加自定义的配置,重启后会导致该目录中的文件恢复成默认状态。fnOS官方在论坛里给的解释是: “新版nginx防护功能,不允许用户自行修改nginx配置。后面也不会放开控制了。”

fnOS自带的nginx备份文件在/usr/trim/share/.restore/目录,重启系统时会使用此目录还原自带的nginx:

ls /usr/trim/share/.restore/
ng.conf.zip  ng.zip  www.zip

退而求其次,docker起了一个nginx。

主要用Lucky来把飞牛NAS上的Web应用(包括飞牛NAS自己)以域名的形式暴露到公网上,lucky的其他功能暂时未用到。

允许lucky监听80,443等低端口:

先停用lucky,再执行下面的命令:

sudo setcap 'cap_net_bind_service=+ep' /vol1/@appcenter/Lucky/bin/lucky

IPv6公网IP

在路由器上添加防火墙规则,允许所有外部 IPv6 主机访问 NAS 443 端口

[ -n "$(command -v ip6tables)" ] && ip6tables -I FORWARD -p tcp -d <NAS IPv6公网IP> --dport 443 -j ACCEPT

示例:

ip6tables -I FORWARD -p tcp -d 2409:abcd:1234:5678:aaaa:bbbb:cccc:dddd --dport 443 -j ACCEPT

允许所有转发(经过路由器)到 IPv6 地址 2409:abcd:1234:5678:aaaa:bbbb:cccc:dddd 的 TCP 443 端口的数据包,通过防火墙。

  • IPv4:大多使用 NAT,内网主机没有公网 IP → 需要端口映射 才能被外网访问。
  • IPv6:每台主机都有全球唯一公网地址 → 不需要端口映射,只要防火墙允许,外网就能直接访问。

PostgreSQL数据库故障排查与修复

问题背景

在某次突然断电,重启后出现远程挂载服务(阿里云盘、百度云、115网盘等)无法连接的问题。通过root账户查看日志发现数据库损坏,cloud_storage_dav 服务启动失败。

故障现象

  • 服务名称: cloud_storage_dav

  • 错误日志:

    failed migrate database: ERROR: expected "[" to start datum ...
    CONTEXT: SQL function "_pg_truetypmod" during inlining
  • 影响范围: 数据库迁移、ORM 元数据读取失败

原因分析

PostgreSQL 系统 schema information_schema 中的函数 _pg_truetypmod(a pg_attribute, t pg_type) 定义损坏,导致访问 information_schema.columns 时触发解析错误。

任何 ORM 或迁移工具在读取表结构元数据时都会调用该函数,因此报错中断。

排查步骤

1. 验证数据库环境

SELECT version();
SELECT * FROM pg_extension WHERE extname='vector';

确认无 pgvector 扩展,数据库版本为 PostgreSQL 15.13

2. 确认错误来源函数

SELECT n.nspname, p.proname
FROM pg_proc p
JOIN pg_namespace n ON n.oid=p.pronamespace
WHERE p.proname='_pg_truetypmod';

函数位于 information_schema

3. 创建诊断查询

创建临时 prepared statement 用于检测元数据读取问题(仅存于当前会话内存,会话结束会自动销删除):

PREPARE q(text) AS
SELECT
  c.column_name,
  c.is_nullable = 'YES',
  c.udt_name,
  c.character_maximum_length,
  c.numeric_precision,
  c.numeric_precision_radix,
  c.numeric_scale,
  c.datetime_precision,
  8 * typlen,
  c.column_default,
  pd.description,
  c.identity_increment
FROM information_schema.columns AS c
JOIN pg_type AS pgt ON c.udt_name = pgt.typname
LEFT JOIN pg_catalog.pg_description AS pd
  ON pd.objsubid = c.ordinal_position
 AND pd.objoid = (
       SELECT oid FROM pg_catalog.pg_class
       WHERE relname = c.table_name
         AND relnamespace = (
             SELECT oid FROM pg_catalog.pg_namespace
             WHERE nspname = c.table_schema))
WHERE table_catalog = current_database()
  AND table_schema = current_schema()
  AND table_name = $1;

执行诊断:

EXECUTE q('users');
EXECUTE q('storage');

确认问题触发点即为 _pg_truetypmod

修复方案

方案一:临时安全替代(应急)

创建稳定只读实现用于快速恢复服务:

CREATE OR REPLACE FUNCTION information_schema._pg_truetypmod(
  a pg_catalog.pg_attribute,
  t pg_catalog.pg_type
)
RETURNS integer
LANGUAGE sql
IMMUTABLE
STRICT
PARALLEL SAFE
AS $
  SELECT a.atttypmod
$;
此函数仅返回列修饰符值,避免解析逻辑,确保 introspection 不报错。

方案二:恢复官方标准版本(推荐)

查看官方标准定义:

cat /usr/share/postgresql/15/information_schema.sql | grep pg_truetypmod -A 100

应用官方实现:

CREATE OR REPLACE FUNCTION information_schema._pg_truetypmod(
  a pg_catalog.pg_attribute,
  t pg_catalog.pg_type
)
RETURNS int4
LANGUAGE sql
IMMUTABLE
PARALLEL SAFE
RETURNS NULL ON NULL INPUT
RETURN CASE WHEN t.typtype = 'd' THEN t.typtypmod ELSE a.atttypmod END;
已按照官方标准版本恢复,暂时未出现问题。

验证修复

1. 验证函数定义

SELECT pg_get_functiondef(
  'information_schema._pg_truetypmod(pg_catalog.pg_attribute, pg_catalog.pg_type)'::regprocedure
);

2. 验证元数据访问

SELECT column_name, data_type, character_maximum_length
FROM information_schema.columns
WHERE table_schema='public' AND table_name='users';

3. 验证服务启动

systemctl restart cloud_storage_dav
tail -n 50 /var/log/cloud_storage_dav/error.log

修复结果总结

项目状态
_pg_truetypmod已恢复为官方标准版
information_schema正常可访问
cloud_storage_dav服务启动正常
数据完整性未修改任何业务表数据
各种结果的远程挂载服务恢复正常
评论