前言

树莓派买过来玩了一段时间之后就很久没碰过了, 当时说好的要用树莓派搭建 NAS 也因为种种原因不了了之, 不过由于 NAS 的功能对我来说确实还算比较有用, 因此开学之后找到空闲时间, 还是打算折腾一下.

经过一番搜寻(其实是很早之前保存过), 找到了一个相当不错的教程: 用树莓派搭建家庭NAS下载机, 配合我们之前研究的 使用frp实现内网穿透 足以实现一些更有趣的功能, 此外, 树莓派实现NAS家庭服务器(流媒体播放、文件共享及下载机) 一文还提及了 DLAN 流媒体服务器的搭建, 参考这两篇文章, 我们的工作如下.

材料准备

  • 一台树莓派
  • 一台有公网 IP 的 VPS, 用以实现内网穿透
  • 一块能使用 USB 接口的硬盘 (移动硬盘/硬盘盒皆可)
  • 一颗爱折腾的心

文中的大部分命令都需要管理员权限, 请事先确保你拥有相应权限.

NAS

挂载磁盘

这一部分各种教程都说的比较多, 很多教程都提到磁盘需要格式化为 ext4 格式, 否则容易出现兼容性问题, 但是由于我使用的移动硬盘里面的数据量还不少, 为了避免更改磁盘格式更大的麻烦, 只能使用一些曲线救国的办法, 例如使用一些软件读取 NTFS 格式的磁盘. 此外还要注意, 树莓派的 USB 接口输出电源可能不够, 你可能需要一个带有额外电源输入的 USB hub(或者是一个带有辅助供电的数据线).

首先新建一个磁盘挂载点并安装磁盘读取软件:

1
2
mkdir /mnt/samba
apt install fuse-utils ntfs-3g

配置磁盘挂载:

1
2
3
4
5
6
7
8
9
#加载内核模块
modprobe fuse # 此时 cat /proc/filesystems 输出结果中应当有 fuse

fdisk -l # 查看分区挂载情况, 找到硬盘分区, 例如 /dev/sda1.
mount -t ntfs-3g /dev/sda1 /mnt/samba # 测试挂载, 如果成功的话访问 /mnt/samba 就能看到磁盘文件了

#编辑 /etc/fstab 让移动硬盘开机自动挂载
#在最后一行添加如下内容
/dev/sda1 /mnt/samba ntfs-3g defaults 0 0

fstab 文件中:

  • 第一列表示磁盘分区名称
  • 第二列表示挂载点
  • 第三列是缺省设置, 一般使用 defaults 即可
  • 第四列表示是否备份: 0 表示不做 dump 备份; 1 表示要将整个 <file sysytem> 里的内容备份; 2 也表示要做 dump 备份, 但该分区的重要性比 1 小
  • 第五列表示检测顺序, 0 不进行检测; 根分区(/), 必须填写 1, 其它的都不能填写 1. 如果有分区填写大于 1 的话, 则在检查完根分区后, 从小到大依次检查下去

重启后使用 df -h 检查一下是否成功挂载, 这样就可以通过访问 /mnt/samba 来访问移动硬盘了.

安装与配置 samba

1
2
# 安装 samba
apt install samba samba-common-bin

在安装的时候如果报错:

1
2
3
The following packages have unmet dependencies:
samba : Depends: samba-common (= 2:3.6.6-6+deb7u13) but 2:4.5.8+dfsg-2+deb9u1 is to be installed
Depends: libwbclient0 (= 2:3.6.6-6+deb7u13) but 2:4.5.8+dfsg-2+deb9u1 is to be installed

卸载 samba-commonlibwbclient0 后重新安装即可, 有时你可能会遇到其他报错内容, 请到搜索引擎寻求帮助. 安装完成后配置 /etc/samba/smb.conf 文件:

1
2
3
4
5
6
7
# 在文件最后部分增加以下内容
[share] # 共享文件的名称,将在网络上以此名称显示
path = /mnt/samba # 共享文件的路径
valid users = root pi # 允许访问的用户,这里我用的是root 和 pi 两个用户
browseable = yes # 允许浏览
public = yes # 共享开放
writable = yes # 可写

接下来重启 samba 并添加用户 (请使用 root 权限运行命令):

1
2
3
4
service smbd restart   # 重启服务
# 如果是在其他系统, 使用 service samba restart 命令

smbpasswd -a pi # 增加可以访问 samba 的用户, 输入密码即可

这样 samba 的配置就完成了, 在 Windows 启用文件发现之后就能找到树莓派了, 输入刚刚设置的账号密码即可访问.

离线下载

下载! 下载! 下载! 似乎很多人买 NAS 都很看重离线下载的功能, 树莓派当然也能做到啦, 从此下载再也不用开机啦~

配置 Aria2

首先安装 aria2:

1
apt install aria2

/home/pi/.aria2/ 目录下新建 aria2 的配置文件(aria2.session 为空文件):

1
2
3
4
5
6
7
8
9
10
11
12
# aria2.conf(内容参考前文提到的链接中的文章, 注意把注释去掉)
dir=/mnt/samba/download # 文件保存目录
disable-ipv6=true # 关闭
enable-rpc=true # web管理界面需要启用rpc
rpc-allow-origin-all=true
rpc-listen-all=true
#rpc-secret=<TOKEN> # 设置访问令牌
#rpc-listen-port=6800
continue=true # 允许断点续传
input-file=/home/pi/.aria2/aria2.session # 进度保存文件
save-session=/home/pi/.aria2/aria2.session
max-concurrent-downloads=3 # 最大同时下载任务数

测试一下: aria2c --conf-path=/home/pi/.aria2/aria2.conf

新建一个 aria2 服务 vi /etc/init.d/aria2c, 内容为:

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
#!/bin/sh
### BEGIN INIT INFO
# Provides: aria2
# Required-Start: $remote_fs $network
# Required-Stop: $remote_fs $network
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Aria2 Downloader
### END INIT INFO

case "$1" in
start)

echo -n "Starting aria2c"
sudo -u pi aria2c --conf-path=/home/pi/.aria2/aria2.conf -D
;;
stop)

echo -n "Shutting down aria2c "
killall aria2c
;;
restart)

killall aria2c
sudo -u pi aria2c --conf-path=/home/pi/.aria2/aria2.conf -D
;;
esac
exit

更改权限并测试:

1
2
3
4
5
chmod 755 /etc/init.d/aria2c

/etc/init.d/aria2c start # 显示 Starting aria2c

update-rc.d aria2c defaults # 设为开机自启动

配置 web 界面

安装 apache 并配置权限:

1
2
3
apt install apache2

sudo visudo # 在最后一行添加 www-data ALL=(ALL) NOPASSWD: ALL

下载 webui-aria2 (update: 最终我选择了另外一个 web 前端: Aria-Ng):

1
2
cd /var/www
git clone https://github.com/ziahamza/webui-aria2

注意, 在国内使用请记得修改监听端口, 具体文件位置为 /etc/apache2/ports.conf/etc/apache2/sites-available/default, 包括虚拟端口, 修改完成后重启 apache 即可: service apache2 restart. 同时还需要对外网开放 aria2 的端口, 默认为 6800.

然后在你的浏览器中输入对应网址 (例如: http://树莓派IP:8080/webui-aria2/), 配置好相应的项目, 当提示已连接时, 就可以开始使用树莓派离线下载了.

配置远程文件共享

由于 HTTP 协议本质上就是下载服务器上的文件, 因此简单的一个想法就是在站点目录下新建一个 share 文件夹, 然后将要共享的文件软连接至目录下, 甚至你可以直接把外挂硬盘上的一个目录软连接至站点目录:

1
2
3
# 注意: 第三个参数中的 share 与 Windows 中的快捷方式类似, 本质上是一个指向某个目录的特殊文件, 并不是目录本身
# -s 参数即 symbolic 符号链接, 也称软连接, 不带 -s 参数就是硬链接, 硬链接只能是同一个分区下的文件, 是通过修改硬盘索引来实现的
ln -s /mnt/samba/share/ /var/www/html/share

硬盘休眠

使用 hdparm 或者是 hd-idle 来实现休眠, 但是我尝试了许多次, 都没有成功, 还把系统折腾崩一次, 等哪天有机会了再仔细研究研究吧…

update: 好吧, 无法安装的问题似乎得到了解决, 我之前使用的国内的软件源似乎发生了一个非常诡异的问题, 安装 hdparm 的时候会卸载 systemd, 这当然是安装不了的…所以…究竟怎么回事我也不知道, 因此如果你也遇到类似的问题可以尝试更换一下软件源, 不过这个问题能解决就行.

然而安装后, 发现硬盘不支持 hdparm, 网上找了一圈, 似乎是 usb-sata 控制器的问题, 先把休眠方法记录一下:

1
2
3
4
5
# 立刻让硬盘休眠
hdparm -Y /dev/sda1
# 设置硬盘自动休眠,数值/12 = 分钟,设置为120就是无操作10分钟后休眠
# 将这条命令写入 rc.local
hdparm -S 120 /dev/sda1

最终, 在 Raspberry Pi从零开始搭建低成本NAS(11)-硬盘功耗管理 找到了另外一个方案 sdparm, 同时参考 让OpenWRT下的空闲硬盘自动停转, 做了以下工作:

1
2
3
4
apt remove hdparm -y
apt install sdparm -y

sdparm --flexible --command=stop /dev/sda # 立即停止测试

写一个脚本 /usr/bin/spindown 并记得修改权限:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#!/bin/bash
DISKNAME='sda1'
a=0
for i in `seq 0 10`
do
b=`cat /proc/diskstats | grep $DISKNAME | awk '{print $(NF-2)}'`
a=`expr $a + $b`
sleep 1
done
echo $a
if [ $a == 0 ]
then
echo "No Activity"
sdparm -C stop /dev/sda # 我的硬盘必须先停止控制器才能休眠, 你可能并不需要这行代码
sdparm -C stop /dev/$DISKNAME
else
echo "Disk Active"
fi
exit 0

然后运行 crontab -e 在结尾加入:

1
*/20 * * * * bash /usr/bin/spindown >> /var/log/spindown.log

注意: 这里原文 bash 处为 sh, 但是运行脚本会报 /usr/bin/spindown: 11: [: 0: unexpected operator 错误, 因此修改为 bash, 参考 刚学习shell,碰到问题.执行时总出错:unexpected operator(转载).

这样就能实现每 20 分钟进行一次空闲检测, 如果空闲则自动休眠. (其实买个自带休眠功能的硬盘是才是最好的 #滑稽

总结

自此, 基本的功能搭建是完成了, 但是还有许多不完美之处, 但也勉强能用, 这次折腾应该到此为止, 就看我下次什么时候又心血来潮了.