步骤/目录:
0.Samba的陷阱
1.树莓派下载安装samba
2.配置samba
3.为samba绑定系统用户
4.其他客户端连接到共享文件夹
    (1)linux
    (2)Windows
    (3)安卓手机
    (4)投影仪、电视
    附:ES文件浏览器 连接Samba
5.frp+samba
6.加快读写速度
    (0)分析瓶颈、测试硬盘
    (1)网线直连
    (2)换路由器
    (3)修改smb.conf
    (4)其他
    (5)后续
    (6)总结
7.自动挂载硬盘
8.使用qBittorrent离线下载
附录:小米手机开启FTP服务器

本文首发于个人博客https://lisper517.top/index.php/archives/16/,转载请注明出处。
本文的目的是使用树莓派搭建NAS,可以远程访问云硬盘上的文件,并可进行离线下载。
本文实验日期为2022年2月19日。使用的是树莓派4B(内存8G版),系统为Pi OS 32位桌面版(2022年1月28日更新,镜像名 2022-01-28-raspios-bullseye-armhf.img )。frps运行在阿里云服务器(系统镜像Ubuntu 20.04)。
本文使用Samba搭建NAS,而且并没有涉及UPS电源、RAID等,属于入门级NAS,感兴趣的可自行深造。Samba可以替换为FTP,或者懒得自建NAS也可以购买群晖等现成NAS。

0.Samba的陷阱

当你在windows中打开 我的电脑 ,此时打开的东西叫文件管理器(Windows Explorer)。从文件管理器向其它地方拷贝东西,WE会要求目标硬盘先创建一个同等大小的空镜像(内容全部为0的镜像),再填充数据;Samba会调用 ftruncate() 函数来创建,而该函数在FAT文件系统上运行奇慢,需要花很长时间才能创建好空白镜像,WE以为Samba卡死了,最终会返回0x8007003B错误( 参考回答 )。

FAT文件系统创建空镜像这么慢,归根结底是不支持sparse file(稀疏文件),所以它创建空镜像时真的会在硬盘上挨个写入0;而支持sparse file的,直接指定空镜像文件的头尾区块、存在metadata中即可,不用管这些区块上原本是1还是0。

在Samba的设置中有一项隐藏的默认值 strict allocate = no ,如果改成yes,当单个文件大小超过500MB,Samba自己就会要求先生成空镜像再填充数据(参考 wiki-SambaSMB/SMB2 write activities 一节)。

综上所述,不需要改Samba的配置,只要保证Samba挂载的不是FAT文件系统(exFAT、FAT32)而是ext4、NTFS就行了( 参考回答 )。先创建空镜像再写入,本意是好的,只是FAT执行坏了。

1.树莓派下载安装samba

输入apt install samba即可。一共安装了16个包(如果没有samba-common-bin则需手动下载):

attr libcephfs2 liburing1 python3-dnspython python3-gpg python3-markdown
  python3-requests-toolbelt python3-samba python3-tdb python3-yaml
  samba-common samba-common-bin samba-dsdb-modules samba-vfs-modules tdb-tools

2.配置samba

samba的配置文件为/etc/samba/smb.conf。在其中底部添加:

[shared]
   path = /home/samba_user/shared #共享文件夹目录
   valid users = samba_user
   writable = yes
   read only = no
   create mask = 0755 #创建文件时,权限为755(测试时发现不管改成什么,创建的文件都是755)
   directory mask = 0755 #创建目录权限为755(同上)
   #browseable = yes #无权限的人可看到资源名称

另外在[global]下添加:

security = user #设定安全等级

保存退出,使用testparm检测samba设置有无语法错误。
关于samba配置更多信息可参考这篇文章。安全方面,还可用hosts allow设置允许访问的主机、write list设置仅哪些用户可进行写操作。

3.为samba绑定系统用户

创建用户的命令可以参考 提升树莓派安全性 。这里新建一个用户samba_user,并创建共享文件夹:

mkdir -p /home/samba_user/shared
useradd -d /home/samba_user samba_user
passwd samba_user
chown -R samba_user:samba_user /home/samba_user

然后为samba指定该用户及设置该用户的SMB密码,激活该用户,并重启服务:

smbpasswd -a samba_user #后面更改SMB密码也用这个命令
smbpasswd -e samba_user #-d可disable指定SMB用户
service smbd restart #服务名也可能不叫smbd。service --show-all查看所有服务

注意SMB密码和用户的系统密码可能不同,连接到samba共享文件夹只需要SMB密码。但是添加其他SMB用户时,还需要先创建一个同名的系统用户(否则 smbpasswd 时会提示 Failed to add entry for user),即需要添加SMB用户时,要先添加一个系统用户,然后添加同名SMB用户,设置SMB密码,连接时用SMB密码。增加用户的范例:

useradd -d /dev/null -s /sbin/nologin samba_user2

如上设置的samba_user2系统用户,没有家目录,也无法登录,只是为了添加SMB用户而创建,安全性好一点。然后用 smbpasswd 添加SMB用户即可。
最后使用ufw打开samba使用的445端口:ufw allow 445

4.其他客户端连接到共享文件夹

(1)linux

以树莓派为例(这里顺便测试一下刚才的Samba设置),在资源管理器的地址栏输入 smb://树莓派ip ,按回车键后出现两个文件夹:print$与shared,其中shared就是刚才设置的共享文件夹,print$则是samba设置文件自带的。双击shared文件夹后提示需要输入密码,选择已注册用户,用户名为samba_user,密码为SMB密码,下面可以选是否记住密码、记住多久,然后即可进入共享文件夹。接下来插上u盘模拟硬盘,将u盘挂载到shared文件夹下:

df -h
#输出结果
#/dev/sda1  ......  /media/pi/xxxxx
umount /media/pi/xxxxx
cd /home/samba_user/shared
mkdir usb_1
mount -o uid=samba_user,gid=samba_user /dev/sda1 usb_1 #指定挂载后文件夹所属用户及组

用root身份时会默认挂载到root:root下,这里指定挂载到samba_user下才可对共享文件夹有rwx的权限(默认755)。
然后在资源管理器中查看,可以成功看到u盘里的文件,也可修改、删除、新增文件。
最后这里说明一下samba的权限问题:用smbpasswd -a 用户名可添加一个SMB用户,该用户必须是系统用户。读写权限有两个地方受到限制,一是登录SMB的系统用户对共享文件夹有无rwx权限,二是在smb.conf里设置共享文件夹的读写权限(writable = yesread only = no都是可写入)。所以挂载硬盘时要挂载到SMB用户同名的系统用户下(要不然就在挂载时设置权限为xx7),且[shared]里面要指定可以读写共享文件夹。

如果在命令行下,也可以挂载,但是要安装一些samba客户端或扩展。以CentOS为例:

yum install -y cifs-utils
mkdir /mnt/shared
mount -t cifs -o username="用户名",password="密码" //树莓派ip/共享名 /mnt/shared #如 //192.168.1.190/shared
cd /mnt/shared
ls -al

可以看到挂载成功。还可以设置开机自动挂载,比如在 /etc/rc.local 中加入一行:

mount -t cifs -o username="用户名",password="密码" //树莓派ip/共享名 /mnt/shared

即可。或者也可以加到fstab里。但是笔者实验时,fstab和rc.local开机时运行的时间比较靠前,可能因为没有网络连接而挂载不上,所以建议可以用crontab,加上自己写一个小脚本:

mkdir -p ~/mybash
vim ~/mybash/mount_samba

内容如下:

#/bin/bash
mounted=`ls -l /mnt/shared | wc -l`
if [ $mounted -eq 1 ]; then
        mount -t cifs -o username="用户名",password="密码" //树莓派ip/共享名 /mnt/shared
        exit 0
fi
exit 0

然后如下操作:

chmod +x ~/mybash/mount_samba
crontab -e

加上一行:

* * * * * /root/mybash/mount_samba

即可每分钟检查一次,没有挂载时自动挂载,算是退一步的选择。或者你也可以写一个service,在网络连接后才运行,就是比较复杂。
在Ubuntu上也一样,唯一不同是yum换成apt-get。

(2)Windows

在资源管理器的 此电脑 界面(就是显示C盘和其他盘符的界面),左上角点击 计算机-映射网络驱动器-映射网络驱动器 ,驱动器随便选,文件夹 写\\树莓派局域网ip\shared,点击连接,需要输入凭证。输入samba_user和对应的SMB密码后成功登录,也可增、删、改文件。
如果windows上无法连接,可试试打开SMB功能:在设置中搜 启用或关闭Windows功能 ,找到 SMB 1.0/CIFS 文件共享支持 ,勾选上后确定,等组件下载完(带客户端、服务器端、自动删除),重启。但是这个可能是1.0的Samba协议,不知道对读写速度有无影响。笔者测试时没有开启此功能也可连接到共享文件夹。
测试速度:树莓派4B无线连接,接口和u盘都支持usb3.0,百兆路由器,写入速度5-6MB/s(不含创建镜像的时间),读取速度5-6MB/s。这里使用的是exFAT格式的u盘,写入大文件时会花较长的时间生成镜像,再写入数据;写入10GB的大文件时,由于镜像迟迟未创建完毕,windows上还出现了0x8007003B错误。下一节中尝试加快读写速度。

(3)安卓手机

可用 ES文件浏览器 。但是据说其可能使用老的Samba协议,导致传输速度低。
其他应用也有能连samba的。
另外,有的手机自带ftp服务器,也可以方便地与电脑传输文件,详见附录。

(4)投影仪、电视

在投影仪、电视自带的应用市场一般也能找到 ES文件浏览器,下载即可。另外,据说SMB在播放高码率视频时,不时卡顿,不如NLDA,笔者没有进行比较。

附:ES文件浏览器 连接Samba

以安卓手机为例,选择 网络-局域网-新建, 服务器 填 树莓派ip:445,用户名、密码填SMB用户名、密码即可。

5.frp+samba

frps和frpc的初始搭建参考 frp+云服务器搭建能从外网访问的redis、mysql。这里默认已经配置好了frps、frpc,仅在frpc.ini增加一项映射。
samba默认使用445端口,在树莓派的frpc.ini中添加:

[pi4B-samba-server-1]
type = tcp
local_ip = localhost
local_port  = 445
remote_port = 44550

之后树莓派上重启frpc:service frpc restart,然后到frp服务器的防火墙打开44550端口(云服务器不要用ufw打开)。
在树莓派上,资源管理器输入 smb://frp服务器ip:44550 ,即可看到print$和shared两个文件夹;但点开shared时显示 挂载windows共享失败 : 连接超时,可能是由于云服务器的带宽只有5Mbps(640KB/s)。
在windows上,映射网络驱动器 不能写\\云服务器ip:44550\shared,只能用默认的445端口。不过可以使用netsh命令将云服务器的44550端口接到本地的端口445(参考文章)。打开cmd,输入:

netsh interface portproxy add v4tov4 listenaddress=127.0.0.1 listenport=445 connectaddress=云服务器ip connectport=44550
netsh interface portproxy show all #查看一下
#最后使用netsh interface portproxy delete v4tov4 listenaddress=127.0.0.1 listenport=445即可删除这条端口转接设置

确认无误后,在 映射网络驱动器 的 文件夹 一栏直接填\\127.0.0.1\shared即可。可能由于云服务器带宽问题,测试时一直卡在尝试连接界面。

注意,以上流程稍微有些问题,具体参考新的文章:
Samba, ftp与webdav

6.加快读写速度

(0)分析瓶颈、测试硬盘

首先测试一下瓶颈可能在哪里。从windows机器到树莓派,数据需要经过:硬盘读写->树莓派内存->树莓派网卡->有线时通过网线,无线通过无线网卡->路由器->有线或无线->客户端(暂不考虑客户端变化)。可以控制的地方主要有:
硬盘或u盘读写速度;
硬盘或u盘是否通过usb3.0连到树莓派;
树莓派内存是否够用(本文中是8G版,测试时内存消耗不大);
网线传输速度/树莓派网卡速度;
路由器网口是百兆还是千兆。

首先测试一下u盘。安装hdparm(apt install hdparm),输入下面的命令:

hdparm -Tt /dev/sda1
#输出结果
 Timing cached reads:   1688 MB in  2.00 seconds = 844.54 MB/sec
 Timing buffered disk reads: 342 MB in  3.01 seconds = 113.62 MB/sec

可以看出u盘的读取还是很快的(hdparm更详细的教程见runoob-hdparm)。
然后使用dd命令测试u盘写入速度:

cd /home/samba_user/shared/usb_1
dd if=/dev/zero of=./testwritefile bs=4KB count=131072 #写入5GB的文件,测试前要确保有这么大的空间
# 输出结果
...
5242880000字节(5 GB,4.9 GiB)已复制,178.29 s,29.4 MB/s
#rm testwritefile

写入速度为30MB/s左右。
更多关于dd命令测试硬盘的内容可参考这篇文章

(1)网线直连

用买路由器送的免费网线直连树莓派到路由器,写入速度提升到11.5MB/s,已经达到路由器百兆上限(12.5MB/s),提升明显。

(2)换路由器

测试时的路由器只有百兆网口,换成千兆网口后估计速度可进一步提升;换成千兆网口后理论上支持125MB/s读写,但u盘的读写只有113 / 30 MB/s,将成为新的瓶颈。

(3)修改smb.conf

[global]下添加:

   read raw = yes
   write raw = yes
   aio read size = 0 #关闭异步读取
   aio write size = 0 #关闭异步写入
   large readwrite = yes

由于测试时瓶颈是路由器,修改samba配置后读写速度还是11.5MB/s。

(4)其他

挂载的硬盘最好不用NTFS格式,若用的是NTFS注意使用ntfs-3g挂载(据说树莓派默认即ntfs-3g)。树莓派上格式化设备为指定格式:mkfs -t 格式 /dev/sdxx,也可以用其他工具。windows上可试试DiskGenius
据说换网线也可提升速度。当然,前提是瓶颈在网线;若路由器只支持百兆,换网线应该也没用。
另外,有些设备可能用的还是比较老的samba协议,若要添加对老samba协议的支持,可以在smb.conf中的[global]下添加:

min protocol = NT1

NT1为Samba v1,SMB2、SMB3分别是v2、v3。
最后,从windows10机器上向共享文件夹拷贝文件时会先生成等大的镜像,再写入数据;写入10GB的大文件时,由于镜像迟迟未创建完毕,windows上还出现了0x8007003B错误。所以目前还不能从windows机器上写入大文件。

(5)后续

使用希捷硬盘(exFAT格式),通过带USB3.0的硬盘盒连接到树莓派的USB3.0接口,树莓派和windows电脑都通过网线直连到路由器的1000M网口,smb.conf的[global]下添加相应内容。测试读写速度为80-100MB/s,写入单个文件、高峰时可达113MB/s,已经达到硬盘写入速度极限。

(6)总结

使用samba共享树莓派挂载的硬盘,可以实现Pi OS、windows间共享文件(android未测试),进行一些设置后甚至可达硬盘读写速度上限。但是从windows向硬盘写入10G以上的大文件时会报错(因为linux系统下写入一般是先创建空白镜像,而windows系统在这段时间内无法得到反馈,误以为写入操作卡死),算是一个缺陷。

7.自动挂载硬盘

修改/etc/fstab文件,添加一行:

设备名          挂载点                    硬盘格式                    设置                               是否备份    是否检测及检测顺序
/dev/sdxx   /home/samba_user/shared/1     exfat      defaults,uid=1003,gid=1004,nofail,auto,noatime       0           0

(这里的挂载点为/home/samba_user/shared/1,而smb.conf中设置的是path = /home/samba_user/shared,两处不一致会导致windows下显示共享盘的大小为派的sd卡大小而不是硬盘大小,但是对实际使用几乎没问题。如果只有一张NAS硬盘就可以把两处改一样)
其中uid和gid可通过id samba_user查看;
设备名推荐换成UUID=xxxxxx,不会挂错地方。硬盘的UUID可插上硬盘后通过 blkidls -l /dev/disk/by-uuid 查看;
关于nofail,auto,noatime的解析参考浅析 fstab 与移动硬盘挂载方法
最后,使用raspbian带桌面的系统,会发现系统识别到存储介质时会自动挂载,一般是在/media/pi/目录下,所属用户和组都是pi。若要关闭这个功能,需要以pi用户的身份登录桌面,在文件管理器中,左上角 编辑-偏好设置-卷管理 ,第一个选项是开机自动挂载,第二个选项是插入移动存储时自动挂载。

8.使用qBittorrent离线下载

也可以用aria2代替,但是据说aria2没有公网ip时下载较慢。以下参考了利用树莓派进行挂机下载

apt install qbittorrent qbittorrent-nox

(下载qBittorrent-Enhanced-Edition可自动封禁迅雷吸血鬼ip,见上述参考文章)
下载完成后,使用qbittorrent-nox即可开启qBittorrent的Web UI,在 树莓派ip:8080 可访问到网页qBittorrent,十分方便。默认用户密码为admin和adminadmin,在 设置-Web UI 中修改。
接下来把qbittorrent-nox注册到开机自启:

nano /etc/systemd/system/qbittorrent-nox.service

服务文件中写入以下内容:

[Unit]
Description=qBittorrent-nox_WebUI
After=network.target

[Service]
User=root
Type=simple
RemainAfterExit=yes
ExecStart=/usr/bin/qbittorrent-nox -d
ExecStop=/bin/kill $MAINPID
Restart=on-failure
RestartSec=5
StartLimitInterval=0

[Install]
WantedBy=multi-user.target

允许自启,并开启qBittorrent-nox:

systemctl enable qbittorrent-nox
systemctl start qbittorrent-nox

附录:小米手机开启FTP服务器

在 文件管理器-分类-远程管理 中可开启FTP服务器,设置里还可以修改连接的用户名和密码。开启后手机显示 ftp://手机ip:2121 ,在windows的资源管理器输入 ftp://手机ip:2121 、用户名密码 即可查看手机文件。测试了一下,写入速度1.9-2.5MB/s,读取速度3MB/s,勉强能用。
后续:更换为千兆路由器后,写入速度在16-40MB/s,提升明显。

标签: frp, 树莓派, NAS, samba

添加新评论