# 缘起

关于为什么要买 nas 这件事,我个人认为只有以下几种原因:

  • 存储不够
  • 重视数据隐私和安全
  • 单纯拿来折腾

很不幸,我全中了。再加上我计划之前攒的一套主机没有点亮,迫使我需要找一个一体化的 nas 解决方案,插上硬盘就可以用的那种。而且我还需要利用到我闲置的 3.5 英寸硬盘,说起这个硬盘,我原本是打算给我的 PS3 由 120g 扩容到 500g 的,但是当时我以为 PS3 用的是 3.5 英寸的硬盘,结果买到手才发现 PS3 用的是 2.5 英寸的硬盘,我买的那个根本放不下去,于是就闲置了。这下得利用起来了。

虽然说我有一台骁龙 8gen3 16+512 的一加 Ace3 Pro,而且我还有大大小小的 U 盘和移动硬盘,再加上我还有两个 5tb 的 e5 ,理论上来说我不应该买一个 nas 吧?

但是我的数据太多了以至于分散在各处,而且万一 e5 续订不成功怎么办?以至于我无法统一我现有的所有设备。在这些因素的驱使下我买了一个单盘位的 nas

# 初探

这是关于我买的这一套 nas 的配置:

  • CPU: Intel(R) Celeron(R) Processor 1037U @ 1.80GHz
  • MEM: 4G DDR3 1333MHz
  • HARDDISK: Seagate Barracuda 7200.14(AF) ST500DM002-1BD142
  • HARDDISK: FASTDISK 32G SSD
  • POWER: 12V 5A DC

总价不带硬盘是 110R.

后来我有看到卖家上了一个双盘位 1037U 的 nas 才贵 10R,我有点后悔买早了,不过早买早享受嘛。

让后就是插好电源,网线,hdmi 线,开机进 PE 查看下情况。

(No Picture)

接下来就是装系统了,我这里试了好几个系统:

  • DSM: 一开始用 RR 编译引导失败,然后用网上的二合一整合包能启动但是卡 booting the kernel 且群晖助手没有扫到 ip 地址,作罢。
  • OMV 7: 装完之后没有 IP 地址,用 Debian 手动安装后在创建存储空间时突然卡死重启后就找不到 IP 了,作罢
  • FnOS: 很顺利啊装完之后就可以直接用了,不过还是遇到了一点小麻烦。

# 遇到的问题

# 关于 fnos 自带虚拟机的问题

  • 创建虚拟机时无法识别网卡
    需要在设置 > 网络选项里开启 ovs

  • 打开 ovs 重启后没有 IP
    解决方法:参考该帖子下面的回复,这个问题我在实体机遇到了,但是虚拟机没有。

  • ui 体验对手机不友好
    这个目前无解。我一般情况下是下了个手机客户端来解决大部分情况的,少部分需要登 ssh 解决,极少数情况需要登 webui.

而且 fnos 官方虚拟机前端是 novnc, 也不支持调整 vnc 端口,就没有用。

但是我又想体验虚拟机,因为 fnos 是基于 debian 12 深度魔改,理论上我们就可以使用 qemu 来实现虚拟机的要求,虽然可以使用 systemd 来开机自启动,但是我装了三个虚拟机有时候要启动别的所以就没有这样做:

alpine.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
#!/bin/bash

# Enable debug output
set -eu

# Configuration
VM_MEMORY=2048
VM_CPUS=1
ISO_PATH="/vol1/1000/1/debian-12.9.0-amd64-netinst.iso"
DISK_PATH="/vol1/1000/1/vms/debian.qcow2"
VNC_DISPLAY=
VM_NAME="qemu-vm-$(date +%s)"
LOG_FILE="/var/log/qemu-vm.log"

# Logging function
log() {
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
echo "[${timestamp}] $1" | tee -a "${LOG_FILE}"
}

# Check VM status
check_vm_status() {
if pgrep -f "qemu-system-x86_64.*${DISK_PATH}" >/dev/null; then
return 0 # VM is running
else
return 1 # VM is not running
fi
}

convert() {
TEMP_DISK=/tmp/$(openssl rand -base64 8).qcow2
if ! check_resources; then
log "系统资源不足,压缩可能会影响系统性能"
read -p "是否仍然继续?(y/N) " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
log "用户取消压缩"
return 1
fi
fi
log "开始压缩磁盘 ${DISK_PATH},压缩后文件临时存放到 ${TEMP_DISK}"
sudo qemu-img convert -p -c -O qcow2 ${DISK_PATH} ${TEMP_DISK}
if [ ! -f ${TEMP_DISK} ]; then
log "转换失败!"
rm -rf ${TEMP_DISK}
return 1
fi
if cp ${TEMP_DISK} ${DISK_PATH} ; then
log "覆盖成功"
rm -rf ${TEMP_DISK}
log "已删除临时文件"
else
log "覆盖失败!"
rm -rf ${TEMP_DISK}
return 1
fi
}

# Get VM information
get_vm_info() {
local pid=$(pgrep -f "qemu-system-x86_64.*${DISK_PATH}")
if [ -n "$pid" ]; then
echo "VM Status: Running"
echo "VM PID: $pid"
echo "VM Runtime: $(ps -o etime= -p $pid)"
echo "Memory Usage: $(ps -o rss= -p $pid | awk '{printf "%.2f GB\n", $1/1024/1024}')"
echo "CPU Usage: $(ps -p $pid -o %cpu=)%"
echo "VNC Display: :${VNC_DISPLAY}"
else
echo "VM Status: Stopped"
fi
}

# Check system resources
check_resources() {
local total_mem=$(free -g | awk '/^Mem:/{print $2}')
local free_mem=$(free -g | awk '/^Mem:/{print $4}')
local cpu_usage=$(top -bn1 | grep "Cpu(s)" | awk '{print $2}')

if [ ${free_mem} -lt 2 ]; then
log "警告: 系统内存不足 (可用: ${free_mem}GB)"
return 1
#fi

if [ $(echo "${cpu_usage} > 90" | bc -l) -eq 1 ]; then
log "警告: CPU 负载过高 (使用率: ${cpu_usage}%)"
return 1
fi

return 0
}

# Function to start VM
start() {
if check_vm_status; then
log "虚拟机已经在运行中"
get_vm_info
return 1
fi

if ! check_resources; then
log "系统资源不足,启动可能会影响系统性能"
read -p "是否仍然继续?(y/N) " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
log "用户取消启动"
return 1
fi
fi

log "正在刷新系统资源"
sync
sh -c "echo 3 > /proc/sys/vm/drop_caches"
sync
log "系统资源刷新完成"

if [ ! -f "${DISK_PATH}" ]; then
log "错误: 磁盘镜像不存在: ${DISK_PATH}"
return 1
fi

log "正在启动虚拟机..."
sudo qemu-system-x86_64 \
-name "${VM_NAME}" \
-m ${VM_MEMORY} \
-smp ${VM_CPUS} \
-netdev user,id=net0 \
-device virtio-net-pci,netdev=net0 \
-device virtio-scsi-pci,id=scsi0 \
-drive file=${DISK_PATH},format=qcow2,if=virtio,id=hd0 \
-vga qxl \
-bios /usr/share/qemu/OVMF.fd \
-vnc :${VNC_DISPLAY} \
-accel kvm \
-daemonize -M q35 -cpu max

sleep 1
if check_vm_status; then
log "虚拟机启动成功"
get_vm_info
else
log "虚拟机启动失败"
return 1
fi
}

# Function to stop VM
stop() {
if ! check_vm_status; then
log "虚拟机未在运行"
return 1
fi

local pid=$(pgrep -f "qemu-system-x86_64.*${DISK_PATH}")
log "正在停止虚拟机 (PID: ${pid})..."

# Try to stop vm
kill -TERM $pid

# Waiting vm stop
for i in {1..30}; do
if ! check_vm_status; then
log "虚拟机已成功停止"
return 0
fi
echo -n "."
sleep 1
done

# Force close if still running
log "虚拟机未能正常停止,正在强制关闭..."
kill -9 $pid 2>/dev/null || true

if ! check_vm_status; then
log "虚拟机已被强制停止"
else
log "错误: 无法停止虚拟机"
return 1
fi
}

# Get vm status
status() {
log "正在获取虚拟机状态..."
get_vm_info
}

# Main function
main() {
# Check if running as root
if [ "$(id -u)" -ne 0 ]; then
log "错误: 请使用root权限运行此脚本"
exit 2
fi

# Create log directory if it doesn't exist
mkdir -p "$(dirname ${LOG_FILE})"

# Check for arguments
if [ $# -eq 0 ]; then
echo "用法: $0 [-s|-e|-v|-h|-i]"
exit 1
fi

# Process arguments
case "$1" in
-s)
start
;;
-e)
stop
;;
-i)
status
;;
-v)
echo "Version: 1.1.0"
;;
-c)
convert
;;
-h)
echo "用法: $0 [-s|-e|-v|-h|-i|-c]"
echo " -s 启动虚拟机"
echo " -e 停止虚拟机"
echo " -i 显示虚拟机状态信息"
echo " -v 显示版本信息"
echo " -h 显示此帮助信息"
echo " -c 动态调整虚拟机磁盘大小"
;;
*)
log "错误: 未知选项 '$1'"
echo "使用 '$0 -h' 查看帮助信息"
exit 1
;;
esac
}

# Run main function with all arguments
main "$@"

然后就可以通过 vnc 连接了。

# 散热

虽然 1037U 只有双核双线程,但是单核心暴打 J1900 和 N3150,多核心基本持平,但是代价就是:

    1. tdp 高达 17w
  • 2. 机器自带一个小风扇,开机后比被动散热的 J1900 吵。

这两个我暂时没有解决方法。目前在 bios 里找不到风扇选项

# 远程访问

如果家里有公网 IP 可以考虑一下,如果不是公网 IP 可以考虑 frp 穿透出去或者注册一个飞牛账号然后使用 fn connwct 进行远程访问。

我试了几个方法:

  • frp 穿透:目前只穿透了一个 ssh 端口,通过 systemd 进行开机自启动:

    /etc/systemd/system/frpc.service
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    [Unit]
    Description=Frp Client Service
    Wants=network.target
    After=systemd-user-sessions.service

    [Service]
    Type=simple
    ExecStart=/etc/frpc/frpc -c /etc/frpc/frpc.ini
    KillMode=process

    [Install]
    WantedBy=multi-user.target

    然后在 ssh 里 (需要在设置里打开) 执行:
    1
    2
    3
    $ sudo systemctl daemon-reload
    $ sudo systemctl enable frpc.service
    $ sudo systemctl start frpc.service

    然后就可以通过提供的 ip 和端口进行远程访问了:
    1
    $ ssh -p <port> <username>@<address>

    frpc 可以穿透多个端口,前提是这些端口都指定一个隧道,多个隧道不同端口我还在研究

  • fn connect
    通过手机号注册飞牛账号后就可以在设置里启用了,目前我试过只能访问 webui,ssh 和 vnc 是无法访问的。

  • v6 公网
    虽然机器获取的 v6 地址是 2409 开头的,但是流量完全无法访问,可能跟这个有关?我也不太清楚。

# 无法网盘自动备份

由于是单盘位无法组 raid,所以硬盘坏了就是真的 g 了。

而 fnos 也没有退出类似 dsm 的 cloudsync 那样的。

只能等官方更新咯。

# 内存虚标

具体表现为 fnos app 和 htop 剩余内存不一样。

我也不知道是不是故意这样设计的,总之我看着觉得比较膈应。

目前还是先把 zram 打开:

1
2
3
$ echo "zram" > /etc/modules-load.d/zram.conf
$ echo 'KERNEL=="zram0", ATTR{comp_algorithm}="zstd", ATTR{disksize}="3G" RUN="/sbin/mkswap /dev/zram0", TAG+="systemd"' > /etc/udev/rules.d/99-zram.rules
$ echo -e "\n/dev/zram0 none swap defaults,pri=200 0 0" >> /etc/fstab

以上命令会将最大 3G 内存用以内存 zram,如果需要使用更多的内存用以 zram,可以自行修改。
尽量留 1G 的物理内存剩余空间,避免出现不必要的麻烦。

开启 zram 后,可以将部分内存压缩使用,令小内存能发挥更大的力量。

但这种力量也是有限的。如果占用过高还是发动钞能力,给 nas 加内存吧。

# 核显摸鱼

主要表现为播放视频是核显不工作,但是 app 里能看到核显显存占用,/dev/dri 也不为空,我觉得应该需要 ffmpeg 指定 intel 解码器才能工作?

尝试 ffmpeg 指令:

1
$ ffmpeg -hwaccel qsv -c:v hevc_qsv -i input_file.mkv -c:v h264_qsv -c:a aac output_file.mp4

但是报错:
log
1
2
3
4
5
6
Device creation failed: -542398533.
[hevc @ 0x55fdc6f62280] No device available for decoder: device type qsv needed for codec hevc.
Stream mapping:
Stream #0:0 -> #0:0 (hevc (native) -> h264 (libx264))
Stream #0:1 -> #0:1 (flac (native) -> aac (native))
Device setup failed for decoder on input stream #0:0 : Generic error in an external library

查看视频信息:
log
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
user@fnnas:~$ ffprobe /vol1/1000/1/\[UHA-WINGS\&VCB-Studio\]\ Eromanga\ Sensei\ \[01\]\[Ma10p_1080p\]\[x265_flac\].mkv
ffprobe version 5.1.4-0+deb12u1 Copyright (c) 2007-2023 the FFmpeg developers
built with gcc 12 (Debian 12.2.0-14)
configuration: --prefix=/usr --extra-version=0+deb12u1 --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --arch=amd64 --enable-gpl --disable-stripping --enable-gnutls --enable-ladspa --enable-libaom --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libcodec2 --enable-libdav1d --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libglslang --enable-libgme --enable-libgsm --enable-libjack --enable-libmp3lame --enable-libmysofa --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse --enable-librabbitmq --enable-librist --enable-librubberband --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libsrt --enable-libssh --enable-libsvtav1 --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libx265 --enable-libxml2 --enable-libxvid --enable-libzimg --enable-libzmq --enable-libzvbi --enable-lv2 --enable-omx --enable-openal --enable-opencl --enable-opengl --enable-sdl2 --disable-sndio --enable-libjxl --enable-pocketsphinx --enable-librsvg --enable-libmfx --enable-libdc1394 --enable-libdrm --enable-libiec61883 --enable-chromaprint --enable-frei0r --enable-libx264 --enable-libplacebo --enable-librav1e --enable-shared
libavutil 57. 28.100 / 57. 28.100
libavcodec 59. 37.100 / 59. 37.100
libavformat 59. 27.100 / 59. 27.100
libavdevice 59. 7.100 / 59. 7.100
libavfilter 8. 44.100 / 8. 44.100
libswscale 6. 7.100 / 6. 7.100
libswresample 4. 7.100 / 4. 7.100
libpostproc 56. 6.100 / 56. 6.100
Input #0, matroska,webm, from '/vol1/1000/1/[UHA-WINGS&VCB-Studio] Eromanga Sensei [01][Ma10p_1080p][x265_flac].mkv':
Metadata:
encoder : libebml v1.3.4 + libmatroska v1.4.5
creation_time : 2017-07-08T03:34:59.000000Z
Duration: 00:23:42.09, start: 0.000000, bitrate: 3945 kb/s
Chapters:
Chapter #0:0: start 0.000000, end 190.982000
Metadata:
title : Chapter 01
Chapter #0:1: start 190.982000, end 578.036000
Metadata:
title : Chapter 02
Chapter #0:2: start 578.036000, end 1305.179000
Metadata:
title : Chapter 03
Chapter #0:3: start 1305.179000, end 1395.227000
Metadata:
title : Chapter 04
Chapter #0:4: start 1395.227000, end 1409.992000
Metadata:
title : Chapter 05
Chapter #0:5: start 1409.992000, end 1422.090000
Metadata:
title : Chapter 06
Stream #0:0(jpn): Video: hevc (Main 10), yuv420p10le(tv, bt709/unknown/unknown), 1920x1080, SAR 1:1 DAR 16:9, 23.98 fps, 23.98 tbr, 1k tbn (default)
Metadata:
BPS : 2631829
BPS-eng : 2631829
DURATION : 00:23:42.088000000
DURATION-eng : 00:23:42.088000000
NUMBER_OF_FRAMES: 34096
NUMBER_OF_FRAMES-eng: 34096
NUMBER_OF_BYTES : 467836589
NUMBER_OF_BYTES-eng: 467836589
_STATISTICS_WRITING_APP: mkvmerge v13.0.0 ('The Juggler') 64bit
_STATISTICS_WRITING_APP-eng: mkvmerge v13.0.0 ('The Juggler') 64bit
_STATISTICS_WRITING_DATE_UTC: 2017-07-08 03:34:59
_STATISTICS_WRITING_DATE_UTC-eng: 2017-07-08 03:34:59
_STATISTICS_TAGS: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES
_STATISTICS_TAGS-eng: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES
Stream #0:1(jpn): Audio: flac, 48000 Hz, stereo, s32 (24 bit) (default)
Metadata:
BPS : 1311765
BPS-eng : 1311765
DURATION : 00:23:42.090000000
DURATION-eng : 00:23:42.090000000
NUMBER_OF_FRAMES: 16666
NUMBER_OF_FRAMES-eng: 16666
NUMBER_OF_BYTES : 233181058
NUMBER_OF_BYTES-eng: 233181058
_STATISTICS_WRITING_APP: mkvmerge v13.0.0 ('The Juggler') 64bit
_STATISTICS_WRITING_APP-eng: mkvmerge v13.0.0 ('The Juggler') 64bit
_STATISTICS_WRITING_DATE_UTC: 2017-07-08 03:34:59
_STATISTICS_WRITING_DATE_UTC-eng: 2017-07-08 03:34:59
_STATISTICS_TAGS: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES
_STATISTICS_TAGS-eng: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES

查看信息后发现核显不支持 h265 解码,他妈的。

# DLNA

挂载的本地存储还是工作的,主要说一下 webdav 方面。

因为我懒得下载在上传到盘里,虽然 app 里有一个自动下载的功能但是 nas 的主要用途又不是影视盘,于是找了个挂载上去,通过 dlna 在电视上观看。

但是不知道为什么加载非常慢,而且播放几秒后就强制退出了,我也不知道为什么。

但是在 PS3 上就可以看了,虽然隔几分钟就卡一下,但是总比一播放就闪退要好的多,但是很可惜 PS3 不支持 hevc 视频。

手机上也是可以看的,但是没有办法选择字幕。

后来又挂了一个小雅,但是官方应用商店的小雅是不能用的,只能手动安装,用 GitHub 上的安装脚本安装就可以了。但是有一点需要注意网络模式一定要改成 host 否则无法联网。

折腾了这么久,终于上享受到满屏电影墙的快感了,虽然我本地也没有资源,虽然加载慢,虽然电视播放不了,虽然我不一定能有时间看。

感觉年纪轻轻染上刮削也不是什么好事(笑)

# 用途

  • docker 挂小雅和青龙面板
    现在这台 nas 上面在跑的服务:
  • ftp,smb
  • 装了三个虚拟机,一个 alpine 用来挂 telegram 和 QQ,一个 Windows8 build 8400 骨头版 32 位用来玩 Galgame,一个 WindowsXP 32 位用来玩玩老游戏,例如双星物语,可以勉强 30 帧游玩,虽然有时候会掉到 15 帧以下。
    可能会跑的一些服务:
  • qb 下载(有 v6 公网但是防火墙关不了有什么用呢?)
  • 搭一个本地音乐服务器在线听歌也说不定,因为我用的落雪音乐的音乐源经常失效加载不出来。

感觉 fnos 体验还是挺不错的,这台机器目前放在了卧室旁边的储物柜底下,和路由器共用一个插线板,有线网络直连路由器,有点吵 (但是 PS3 一打开基本上就可以忽略不计了),但是基本上是可以忍受的 (如果是那种对噪音很敏感的建议买一个 J1900 然后挂几个固态组集群(),。后期可能会考虑加购个 UPS,突然断电很伤 HDD(虽然我没有遇到过,而且我这里几乎没有突然停电的历史)。

至于还有其他什么的到时候再说吧。可能到时候升级下硬盘和内存也说不定?毕竟 4g 内存挂虚拟机还是有点捉襟见肘的。

更新于 阅读次数