NFS传输协议
NFS的工作原理
NFS:Network File System 网络文件系统,基于内核的文件系统。Sun 公司开发,通过使用 NFS,用户和程序可以像访问本地文件一样访问远端系统上的文件,基于RPC(Remote Procedure CallProtocol 远程过程调用)实现
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LRUzbYoZ-1660549766839)(F:\Documents\ImageDB\image-20220725221625812.png)]
RPC采用C/S模式,客户机请求程序调用进程发送一个有进程参数的调用信息到服务进程,然后等待应答信息。在服务器端,进程保持睡眠状态直到调用信息到达为止。当一个调用信息到达,服务器获得进程参数,计算结果,发送答复信息,然后等待下一个调用信息,最后,客户端调用进程接收答复信息,获得进程结果,然后调用执行继续进行
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pGgnnHnD-1660549766840)(F:\Documents\ImageDB\image-20220725223522286.png)]
NFS优势:节省本地存储空间,将常用的数据,如:/home目录,存放在NFS服务器上且可以通过网络访问,本地终端将可减少自身存储空间的使用
NFS软件包说明
- 软件包:nfs-utils包括服务器和客户端相关工具,CentOS8 最小化安装时默认没有安装)
- 相关软件包:rpcbind(必须),tcp_wrappers
- Kernel支持:nfs.ko
- 端口:2049(nfsd), 其它端口由portmap(111)分配
- 日志:/var/lib/nfs/
- 配置文件
- /etc/exports
- /etc/exports.d/*.exports
NFS服务主要进程
- rpc.nfsd 最主要的NFS进程,管理客户端是否可登录
- rpc.mountd 挂载和卸载NFS文件系统,包括权限管理
- rpc.lockd 非必要,管理文件锁,避免同时写出错
- rpc.statd 非必要,检查文件一致性,可修复文件
- CentOS 6 开始portmap进程由rpcbind代替
NFS共享配置文件格式
NFS共享文件格式
共享路径 主机(权限) 主机(权限)
/dir host-1(opt1,opt2) host-2(opt1,opt2)...
格式说明:
-
以#开始的行为注释
-
主机格式
anonymous:表示使用*通配所有客户端 单个主机:ipv4,ipv6,FQDN IP networks:两种掩码格式均支持 172.18.0.0/255.255.0.0 172.18.0.0/16 wildcards:主机名通配,例如:*.magedu.com,IP不可以 netgroups:NIS域的主机组,@group_name
-
每个条目指定目录导出到的哪些主机,及相关的权限和选项
默认选项:(ro,sync,root_squash,no_all_squash) ro,rw 只读和读写 async 异步,数据变化后不立即写磁盘,先写入到缓冲区中,过一段时间再写入磁盘,性能高,安全性低 sync(1.0.0后为默认)同步,数据在请求时立即写入共享存储磁盘,性能低,安全性高 root_squash (默认)远程root映射为nfsnobody,UID为65534,CentOS8 为nobody,CentOS 7以前的版本为nfsnobody no_root_squash 远程root映射成NFS服务器的root用户 all_squash 所有远程用户(包括root)都变成nfsnobody,CentOS8 为nobody no_all_squash (默认)保留共享文件的UID和GID anonuid和anongid 指明匿名用户映射为特定用户UID和组GID,而非nobody,可配合all_squash使 用
NFS常用工具
rpcinfo
功能
- 查看RPC相关信息
例:
#查看注册在指定主机的RPC程序
rpcinfo -p hostname
#查看RPC注册程序
rpcinfo -s hostname
[root@nfs_server ~16:46]$rpcinfo 192.168.213.122
program version netid address service owner
100000 4 tcp6 ::.0.111 portmapper superuser
100000 3 tcp6 ::.0.111 portmapper superuser
100000 4 udp6 ::.0.111 portmapper superuser
100000 3 udp6 ::.0.111 portmapper superuser
100000 4 tcp 0.0.0.0.0.111 portmapper superuser
100000 3 tcp 0.0.0.0.0.111 portmapper superuser
100000 2 tcp 0.0.0.0.0.111 portmapper superuser
100000 4 udp 0.0.0.0.0.111 portmapper superuser
100000 3 udp 0.0.0.0.0.111 portmapper superuser
100000 2 udp 0.0.0.0.0.111 portmapper superuser
100000 4 local /var/run/rpcbind.sock portmapper superuser
100000 3 local /var/run/rpcbind.sock portmapper superuser
exportfs
功能
- 用于管理NFS导出的文件系统
常用选项
-v #查看本机所有NFS共享
-r #重读配置文件,并共享目录
-a #输出本机所有共享
-au #停止本机所有共享
showmount
功能
- 查看远程主机的共享
常用选项
-a或--all #以 host:dir 这样的格式来显示客户主机名和挂载点目录。
-d或--directories #仅显示被客户挂载的目录名。
-e或--exports #显示NFS服务器的输出清单。
-h或--help #显示帮助信息。
-v或--version #显示版本信。
--no-headers #禁止输出描述头部信息。
例:
#查看远程主机发布的NFS共享目录列表
showmount -e hostname
mount.nfs
功能:
- 客户端NFS挂载
格式:
mount -t 类型 -o 挂载选项 共享IP:/共享路径 /挂载点
开机自动挂载
功能:
- 开机自动挂载NFS共享
- 可能会导致无法开机,需要删除fstab里挂载选项后重启
格式:
共享IP:/共享路径(可使用showmount -e查询) /挂载点/ 挂载类型(nfs) 挂载选项(_netdev) 0 0
NFS相关的挂载选项:man 5 nfs:
fg #(默认)前台挂载
bg #后台挂载
hard #(默认)持续请求
soft #非持续请求
intr #和hard配合,请求可中断
rsize #和wsize 一次读和写数据最大字节数,rsize=32768
_netdev #无网络服务时不挂载NFS资源
vers #指定版本,客户端centos8默认4.2 ,centos7默认4.1 centos6默认4.0
wsize #每个WRITE命令字向服务器写入文件的最大字节数。实际数据小于或等于此值。resize必须是1024倍数的正整数,小于1024时自动设为4096,大于1048576时自动设为1048576。默认时,服务器和客户端进行协商后设置
async/sync # 【参数说明】同步、异步挂载,客户端默认异步(async)。对于异步挂载,客户端下发的写数据会先缓存在内存中,达到一定大小或者其他条件(与客户端设置,状态有关),再一起发往服务端。而同步挂载,每次下发的写数据马上发到服务端。
acregmin/acregmax #设置NFS客户端缓存普通文件属性的最短时间和最长时间,单位为秒。超过此时间后对其进行更新。默认最短时间是3s,最长时间是60s
acdirmin/acdirmax #设置NFS客户端缓存目录属性的最短时间和最长时间,单位为秒。超过此时间后对其进行更新。默认最短时间是3s,最长时间是60s。
sharecache/nosharecache #设置客户端并发挂载同一文件系统时数据缓存和属性缓存的共享方式。设置为sharecache时,多个挂载共享共享同一缓存。设为nosharecache时,每个挂载各有一个缓存。默认为sharecache
resvport/noresvport #设置连接服务器是否使用保密源端口。默认的resvport设置保密端口,noresvport设置为非保密端口。内核2.6.28及以后版本支持。
proto=n #客户端向服务器发起传输请求使用的n协议,可以为UDP或者TCP。未指定时,mount命令选择服务器支持的协议
port=n #指定服务器NFS服务端口。如果NFS服务端口不在port上,则mount请求失败。未指定或设为0,mount命令根据服务器的rpcbind服务选择服务端口
mountproto=n #客户端向服务器发起MNT请求时和UMNT使用的协议,可以为udp或者tcp。该参数用于防火墙屏蔽特定的协议也能正常mount到服务器
mountvers=n #设置连接服务器mountd时的RPC版本号。未指定时使用与请求的NFS版本相适应的版本号。该参数用于多个NFS服务运行于同一远程主机上
lock/nolock #选择是否使用NLM协议在服务器上锁文件。当选择nolock选项时,锁对于同一主机的应用有效,对不同主机不受锁的影响。默认为lock
acl/noacl #设置是否在挂载时使用NFSACL协议。NFSACL协议不属于标准NFS协议,而是Solaris上的实现。未指定时,客户端与服务器协商检查服务器是否支持,如果支持则使用NFSACL
提示:基于安全考虑,建议使用nosuid,netdev,noexec 挂载选项
NFS_Server安装脚本
#!/bin/bash
#软件列表
software_list="nfs-utils
rpcbind
autofs"
#配置文件:*.exports
nfs_config="/etc/exports.d/nfs_1.exports"
#共享主机/网段
ShareHost="192.168.213.124"
ShareHost_segment="${ShareHost%.*}.0"
shareHost_list="/root/sharelist.nfs"
IP_mask=24
#共享目录
ShareDir="/var/nfs"
#远端挂载
ssh_host=192.168.213.124
ssh_pass="redhat"
#挂载目录
Mount_dir="/mnt/nfs_dir"
#本机IP
local_IP=$(ip addr|sed -rn "s/.*inet (${ShareHost%.*}.*)\/.*/\1/p")
#映射用户与组
Nfs_user="xiang"
Nfs_group="xiang"
#
function env_info()
{
echo "开始检查环境.................."
Cn=1
#软件包检查
for i in $software_list;do
if ! rpm -qa |grep "^$i";then
uninstalled[$Cn]=$i
(( Cn++ ))
echo "包: $i 未安装"
fi
done
#创建映射账户
groupadd -g 65533 $Nfs_group
useradd -s /sbin/nologin -u 65533 -g $Nfs_group $Nfs_user
#判断是否安装
read -r -p "是否补全环境(y/n):" Option_1
case $Option_1 in
y|yes|Yes)
env_install
;;
N|n|no)
return
;;
esac
}
function env_install()
{
#包补全
if [ ! -e "${uninstalled[*]}" ];then
yum -q -y install "${uninstalled[@]}" || { echo "安装失败,请检查yum配置.....";exit; }
fi
#目录检查
[ -d $Mount_dir ] || { mkdir $Mount_dir;chmod 700 $Mount_dir;setfacl -m u:$Nfs_user:rwx $Mount_dir; }
[ -d $ShareDir ] || { mkdir $ShareDir;chmod 700 $ShareDir;setfacl -m u:$Nfs_user:rwx $ShareDir;}
#文件检查
[ -f $nfs_config ] || { touch $nfs_config;chmod 700 $nfs_config; }
[ -f $shareHost_list ] || tee $shareHost_list << EOF
#第一列共享目录,第二列共享主机。请用空格隔开
EOF
}
function nfs_conf()
{
read -r -p "单个主机或主机段或列表:(sin/mul/list)" Option_2
case $Option_2 in
sin|singel)
echo "$ShareDir $ShareHost(rw,sync,root_squash,no_all_squash)" >>$nfs_config
;;
mul|multi)
echo "${ShareHost_segment}/${IP_mask} ${ShareHost}(rw,sync,root_squash,all_squash,anonuid=65533,anongid=65533)" >>$nfs_config
;;
list)
echo "请填写共享设置";sleep 3
vim "$shareHost_list"
while read -r line_1 line_2;do
[ -e "$line_1" ] && [ -e "$line_2" ] && { echo "文件:$shareHost_list未写入配置";exit; }
echo "$line_1 $line_2" >>$nfs_config
done <<< "$(awk 'NR>1{print $0}' "$shareHost_list")"
;;
*)
echo "结束"
exit
;;
esac
systemctl enable --now nfs-server.service
systemctl start rpcbind
exportfs -r
echo "当前共享目录如下:"
exportfs -v
}
function mount_nfs()
{
exportfs -v
#包安装
rpm -qa|grep -q "sshpass" || yum -q -y install sshpass
#远程主机包安装
sshpass -p "$ssh_pass" ssh root@"$ssh_host" "yum -y install nfs-utils"
sshpass -p "$ssh_pass" ssh root@"$ssh_host" "[ -d $Mount_dir ] || mkdir $Mount_dir"
while read -r line_1 line_2;do
sshpass -p "$ssh_pass" ssh -n root@"$ssh_host" "
echo ""$local_IP":"$line_1" $Mount_dir nfs sync,vers=3 0 0" >> /etc/fstab"
done <<< "$(showmount -e "$local_IP" |awk 'NR>1{print $0}'|grep "$ShareHost")"
sshpass -p "$ssh_pass" ssh -n root@"$ssh_host" "mount -a"
}
env_info
nfs_conf
mount_nfs