文件共享服务

补充知识:iSCSI

概括的说,iSCSI 是一种存储设备远程映射技术,它可以将一个远程服务器上的存储设备映射到本地,并呈现为一个块设备(大白话就是磁盘)。从普通用户的角度,映射过来的磁盘与本地安装的磁盘毫无差异。

这种映射方式基于是基于 SCSI 协议的,SCSI 协议是计算机与外围设备(例如硬盘、光盘等)通信的协议。而 iSCSI 则是通过 TCP 协议对 SCSI 进行封装的一种协议,也就是通过以太网传输 SCSI 协议的内容。

存储类型

存储类型分为三类:

  • 直连式存储:Direct-Attached Storage,简称 DAS

  • 网络附加存储:Network-Attached Storage,简称 NAS

  • 存储区域网络:Storage Area Network,简称 SAN

    FC:Fibre Channel 光纤

三种存储比较

三种存储应用场景

  • DAS 虽然比较古老了,但是还是很适用于那些数据量不大,对磁盘访问速度要求较高的中小企业
  • NAS 多适用于文件服务器,用来存储非结构化数据,虽然受限于以太网的速度,但是部署灵活,成本低
  • SAN 则适用于大型应用或数据库系统,缺点是成本高、较为复杂

FTP 服务

文件传输协议:File Transfer Protocol,基于 C/S 结构

数据传输格式:二进制(默认)和文本

双通道协议:命令和数据传输使用不同的端口

两种模式:从服务器角度命令 主动被动 模式

  • 主动模式:Port Style

    windows 连接 FTP 服务器默认使用主动模式

  • 被动模式:PASV Style

FTP 服务状态码:

1
2
3
4
5
1XX:信息   125:数据连接打开
2XX:成功类状态 200:命令OK 230:登录成功
3XX:补充类 331:用户名OK
4XX:客户端错误 425:不能打开数据连接
5XX:服务器错误 530:不能登录

用户认证:

1
2
3
匿名用户:ftp、anonymous,对应Linux用户ftp
系统用户:Linux用户、用户/etc/passwd,密码/etc/shadow
虚拟用户:特定服务的专用用户、独立的用户/密码文件

常见 FTP 相关软件:

  • FTP 服务器端软件

    Wu-ftpd、Proftpd、Pureftpd、Filezilla Server、Serv-U、Wing FTP Server、IIS

    vsftpd:Very Secure FTP Daemon,CentOS 默认 FTP 服务器

  • 客户端软件

    ftp、lftp、lftpget、wget、curl

vsftpd

1

pureftpd

1

NFS 服务

工作原理

Network File System:网络文件系统,基于内核的文件系统。通过 NFS,用户和程序可以像访问本地文件一样去访问远端系统上的文件,基于 RPC(Remote Procedure Call Protecol)实现。

上图中的 portmap,自 centos6 之后就被 rpcbind 代替了

优点:节省本地存储空间,将常用的数据,如:/home 目录,存放在 NFS 服务器上且可以通过网络访问,本地终端将可减少自身存储空间的使用

缺点:1. 占用带宽;2. 端口号比较多,而且不固定,防火墙不太好配;所以 nfs 一般不用在互联网,都是用在局域网

nfs 软件介绍

软件包:nfs-utils(包括服务器和客户端相关工具)

相关软件包:rpcbind(必须)、tcp_wrappers

kernel 支持:nfs.ko

端口:2049(nfsd),其他端口由 portmap 分配

nfs 服务主要进程:

  • rpc.nfsd:最主要的 NFS 进程,管理客户端是否可登录
  • rpc.mountd:挂载和卸载 NFS 文件系统,包括权限管理
  • rpc.lockd:非必要,管理文件锁,避免同时写出错
  • rpc.statd:非必要,检查文件一致性,可修复文件

日志:/var/lib/nfs

配置文件:/etc/exports 和 /etc/exports.d/*.exports

nfs 配置文件

1
/dir host1(opt1,opt2)	host2(opt1,opt2)
  • host 格式:支持通配符 *、ipv4、ipv6、FQDN(全域名)、NIS 域的主机组

  • opt 格式:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    默认选项:(ro,sync,root_squash,no_all_squash)
    ro:只读
    rw:可读可写
    async:异步,数据变化后不立即写磁盘,先写入到缓冲区中,过一段时间再写入磁盘,性能高,安全性低
    sync:1.0.0后为默认,同步,数据在请求时立即写入共享存储磁盘,性能低,安全性高
    root_squash:默认,远程root映射为nobody(CentOS7以前的版本为nfsnobody),UID为65534
    no_root_squash:远程root映射成NFS服务器的root用户,squash的意思是压榨
    all_squash:所有远程用户(包括root)都被压榨
    no_all_squash:默认,保留共享文件的UID和GID,即不压榨
    anonuid和anongid:指明匿名用户映射为特定用户UID和组GID,而非nobody,可配合all_squash使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

默认把root用户压榨成nobody用户,普通用户不压榨,anonuid和anongid可以设置默认压榨成哪个用户

范例:

​```bash
# vim /etc/exports

/data/script 10.0.0.0/24(ro,async)
/data/script 10.0.0.0/24(rw,async,root_squash,anonuid=1000,anongid=1000,all_squash)

/myshare server.example.com
/myshare *.example.com
/myshare server?.example.com
/myshare server[0-20].example.com
/myshare 172.25.11.10
/myshare 172.25.0.0/16
/myshare 2000:472:18:b51:c32:a21
/myshare 2000:472:18:b51::/64
/myshare *.example.com 172.25.0.0/16
/myshare desktop.example.com(ro)
/myshare desktop.example.com(ro) server[0-20].example.com(rw)
/myshare diskless.example.com(rw,no_root_squash)

nfs 工具

fpcinfo

rpcinfo 工具可以查看 RPC 相关信息

1
2
3
4
5
# 查看注册在指定主机的RPC程序
rpcinfo -p hostname

# 查看RPC注册程序
rpcinfo -s hostname

范例:

1
2
3
4
[root@centos8 ~]#rpcinfo -p
[root@centos8 ~]#rpcinfo -s
[root@centos7 ~]#rpcinfo -p 10.0.0.8 # 查看远程主机
[root@centos7 ~]#rpcinfo -s 10.0.0.8

exportfs

用于管理 NFS 导出的文件系统

1
2
3
4
5
6
exportfs [-avi] [-o options,..] [client:/path ..]
exportfs -r [-v]
exportfs [-av] -u [client:/path ..]
exportfs [-v]
exportfs -f
exportfs -s
  • -v:查看本机所有 NFS 共享
  • -r:重读配置文件,这个选项可以避免重启服务
  • -a:输出本机所有共享
  • -au:停止本机所有共享

showmount

常见用法:查看远程主机的 nfs 共享

1
showmount -e hostname

范例:

1
2
3
[root@centos7 ~]#showmount -e 10.0.0.8
Export list for 10.0.0.8:
/data/wordpress *

monut

客户端 nfs 挂载

1
mount [-fnrsvw] -t nfs [-o options] device dir

options:

  • nfsvers=n
  • vers=n
  • soft / hard

范例:

1

自动挂载 autofs

使用 autofs 服务按需要挂载外围设备,NFS 共享等,并在空闲 5 分钟后后自动卸载

配置文件:/etc/auto.master

案例:

10.0.0.1(ubuntu):nfs server,共享/data/wwwroot/script 目录

10.0.0.71(centos):nfs client

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
# 10.0.0.1
# 安装nfs服务端软件
lujinkai@Z510:~$ sudo apt -y install nfs-kernel-server
# 修改exports共享设置文件
lujinkai@Z510:~$ vim /etc/exports
/data/wwwroot/script 10.0.0.0/24(rw,async,root_squash,anonuid=1000,anongid=1000,all_squash)
# 重新加载配置文件
lujinkai@Z510:~$ sudo exportfs -r

# 10.0.0.71
# 安装autofs,并设置开机自启
[root@c71 ~]$yum -y install autofs
[root@c71 ~]$systemctl enable --now autofs.service
# 查看10.0.0.1共享的目录
[root@c71 ~]$showmount -e 10.0.0.1
Export list for 10.0.0.1:
/data/wwwroot/script 10.0.0.0/24
# 修改auto.master,注意格式,`man auto.master`可以查看格式
[root@c71 ~]$vim /etc/auto.master
...
/root/www /etc/auto.www
# 编辑/root/www指定的配置文件
[root@c71 ~]$vim /etc/auto.www
script -fstype=nfs 10.0.0.1:/home/lujinkai/www/script
# 重启autofs
[root@c71 ~]$systemctl restart autofs.service
# 查看是否挂载成功
[root@c71 ~]$cd ~/www/
[root@c71 www]$ll # 没有任何东西
总用量 0
[root@c71 www]$df -Th ./
文件系统 类型 容量 已用 可用 已用% 挂载点
/etc/auto.www autofs 0 0 0 - /root/www
[root@c71 www]$cd script # 直接进入,就会自动挂载
[root@c71 script]$ll
总用量 48
-rwxrwxrwx 1 lujinkai lujinkai 688 11月 13 21:54 demo.sh
drwxrwxrwx 2 lujinkai lujinkai 4096 11月 12 10:09 etc
drwxrwxrwx 4 lujinkai lujinkai 4096 11月 12 16:30 include
drwxrwxrwx 2 lujinkai lujinkai 4096 11月 12 19:34 ini
drwxrwxrwx 2 lujinkai lujinkai 4096 11月 11 11:08 init.d
-rwxrwxrwx 1 lujinkai lujinkai 3750 10月 31 20:11 install.sh
-rwxrwxrwx 1 lujinkai lujinkai 2051 10月 31 15:52 magedu.sh
-rwxrwxrwx 1 lujinkai lujinkai 1462 10月 28 15:58 scp_list.sh
-rwxrwxrwx 1 lujinkai lujinkai 1744 11月 11 10:54 scp_sh.sh
-rwxrwxrwx 1 lujinkai lujinkai 1440 10月 13 21:57 sftp-config.json
drwxrwxrwx 3 lujinkai lujinkai 4096 11月 11 11:03 src
-rwxrwxr-x 1 lujinkai lujinkai 1211 11月 11 10:55 u_scp_sh.sh
[root@c71 script]$df -Th ./
文件系统 类型 容量 已用 可用 已用% 挂载点
10.0.0.1:/home/lujinkai/www/script nfs4 117G 37G 74G 34% /root/www/script

/etc/fstab 和 autofs

/etc/fstab 设置开机自动挂载,系统开机会去读取这个文件,用于挂载本地固定设备,如硬盘

autofs 设置自动挂载,只有当访问挂载点的时候,autofs 才会挂载,过一段时间没有访问,autofs 就会自动卸载设备,用于挂载动态的设备,如光盘、nfs、smb 等文件系统

SAMBA 服务

官网:https://www.samba.org/

相关包:

  • samba 提供 smb 服务器端
  • samba-client 客户端软件
  • samba-common 通用软件
  • cifs-utils smb 客户端工具
  • samba-winbind 和 AD 相关

相关服务进程:

  • smbd 提供 smb(cifs)服务 TCP:139、445
  • nmbd NetBIOS 名称解析 UDP:137、138,如果不使用计算机名来访问,这个就没用

主配置文件:/etc/samba/smb.conf

语法检查: testparm [-v] [/etc/samba/smb.conf]

客户端工具:smbclient、mount.cifs

samba 服务器配置

/etc/samba/smb.conf 是主配置文件,ini 格式,来自 samba-common 包

分为全局配置[global] 和特定的共享设置,例如[homes]、[printers]等\

smb.conf 中的宏定义

1
2
3
4
5
6
7
8
9
10
11
%m 客户端主机的NetBIOS名
%M 客户端主机的FQDN
%H 当前用户家目录路径
%U 当前用户的用户名
%g 当前用户所属组
%h samba服务器的主机名
%L samba服务器的NetBIOS名
%I 客户端主机的IP,是i的大写字母
%T 当前日期和时间
%S 可登录的用户名
...

[global] 全局配置

  • workgroup:指定工作组名称

  • server string:主机注释信息

  • netbios name:指定 NetBIOS 名,可以被 SAMBA 客户端使用,但不支持 ping

    注意:netbios name 需要启动 nmb 服务

    范例:

    1
    2
    3
    [global]
    workgroup = workgroup
    netbios name = smbserver # 此设置需要启动nmb服务才可能生效
  • interfaces:指定服务侦听接口和 IP

  • hosts allow: 允许指定主机访问,可用逗号,空格,或 tab 分隔,默认允许所有主机访问,可以在其他共享独立配置,但是[global]中的设置会覆盖其他共享设置,可以是以下格式:

    1
    2
    3
    4
    172.16.0.0/24
    172.16.0.0/255.255.255.0
    desktop.example.com
    .example.com # 以example.com后缀的主机名
  • hosts deny:拒绝指定主机访问,格式和 hosts allow 相同

  • config file=/etc/samba/conf.d/%U:用户独立的配置文件

  • log file=/var/log/samba/log.%I:不同客户机采用不同日志

  • log level = 2:日志级别,默认为 0,不记录日志

    范例:

    1
    2
    3
    [global]
    Log file=/var/log/samba/log.%I
    log level = 2
  • max log size=50:日志文件达到 50K,将轮循 rotate,单位 KB

  • security=user:认证方式,有三种

    • user:samba 用户(采有 linux 用户,samba 的独立口令)
    • share:匿名(CentOS7 不再支持),已不建议使用
    • server:已不建议使用
  • passdb backend = tdbsam:密码数据库格式

特定共享目录配置

1
2
3
4
5
6
7
8
9
10
11
[共享名称]    # 远程网络看到的共享名称
comment # 注释信息
path # 所共享的目录路径
public # 能否被guest访问的共享,默认no,和guest=ok 类似
browsable # 是否允许所有用户浏览此共享,默认为yes,no为隐藏
writable=yes # 可以被所有用户读写,默认为no
read only=no # 和writable=yes等价,如与以上设置冲突,放在后面的设置生效,默认只读
write list # 可读写的用户,可设置为用户或者组,用空格或逗号分隔,用户组有两种格式:@组名、+组名;如果设置writable=no,那write list中的用户和组可读写
valid users # 规定合法用户,即能访问该共享的用户,用空格或逗号分隔,如为空,将允许所有
force group # 指定存取资源时须以此设定的群组使用者进入才能存取(用户名/@组名)
force user # 指定存取资源时须以此设定的使用者进入才能存取(用户名/@组名)

范例:

1
2
3
4
5
[share]
path = /data/dir
valid users=wang,@admins
writeable = no
browseable = no

samba 用户管理

smbpasswd 命令

smbpasswd 用于管理 samba 用户

添加用户:实际上是把把系统用户映射为 samba 用户,所以添加的用户首先必须是 linux 系统用户

1
2
smbpasswd -a <user>  # 交互式
pdbedit -a -u <user>

修改用户密码:

1
smbpasswd <user> # 交互式

删除用户和密码:

1
2
smbpasswd -x <user>
pdbedit -x -u <user> # 这个好像权限更大

查看 samba 用户列表:

1
pdbedit -L -v

范例:

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
# 为了方便配置,可以将用户指定同一个组
[root@c71 ~]$ groupadd -r smb
[root@c71 ~]$useradd -G smb -s /sbin/nologin smb1
[root@c71 ~]$useradd -G smb -s /sbin/nologin smb2

[root@c71 ~]$smbpasswd -a smb1
New SMB password:
Retype new SMB password:
[root@c71 ~]$smbpasswd -a smb2
New SMB password:
Retype new SMB password:
Added user smb2.

[root@c71 ~]$pdbedit -L
smb1:1001:
smb2:1002:
[root@c71 ~]$pdbedit -L -v
---------------
Unix username: smb1
NT username:
Account Flags: [U ]
User SID: S-1-5-21-540276018-2794668495-3753694806-1000
Primary Group SID: S-1-5-21-540276018-2794668495-3753694806-513
Full Name:
Home Directory: \\c71\smb1
HomeDir Drive:
Logon Script:
Profile Path: \\c71\smb1\profile
Domain: C71
Account desc:
Workstations:
Munged dial:
Logon time: 0
Logoff time: Wed, 06 Feb 2036 23:06:39 CST
Kickoff time: Wed, 06 Feb 2036 23:06:39 CST
Password last set: Sat, 14 Nov 2020 17:46:18 CST
Password can change: Sat, 14 Nov 2020 17:46:18 CST
Password must change: never
Last bad password : 0
Bad password count : 0
Logon hours : FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
---------------
Unix username: smb2
NT username:
Account Flags: [U ]
User SID: S-1-5-21-540276018-2794668495-3753694806-1001
Primary Group SID: S-1-5-21-540276018-2794668495-3753694806-513
Full Name:
Home Directory: \\c71\smb2
HomeDir Drive:
Logon Script:
Profile Path: \\c71\smb2\profile
Domain: C71
Account desc:
Workstations:
Munged dial:
Logon time: 0
Logoff time: Wed, 06 Feb 2036 23:06:39 CST
Kickoff time: Wed, 06 Feb 2036 23:06:39 CST
Password last set: Sat, 14 Nov 2020 17:46:24 CST
Password can change: Sat, 14 Nov 2020 17:46:24 CST
Password must change: never
Last bad password : 0
Bad password count : 0
Logon hours : FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF

案例:

实现不同 samba 用户访问相同的 samba 共享,实现不同的配置

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
# 10.0.0.71 服务端
[root@c71 ~]$yum -y install samba
[root@c71 ~]$groupadd -r smb
[root@c71 ~]$useradd -G smb -s /sbin/nologin smb1 # 注意这里是-G,而不是-g
[root@c71 ~]$useradd -G smb -s /sbin/nologin smb2
[root@c71 ~]$smbpasswd -a smb1
[root@c71 ~]$smbpasswd -a smb2
[root@c71 ~]$vim /etc/samba/smb.conf
#在workgroup下加一行
config file= /etc/samba/conf.d/%U
[share]
Path=/data/dir
Read only= NO
Guest ok = yes
write list=@wheel
#针对smb1和smb2用户创建单独的配置文件
[root@c71 ~]$vim /etc/samba/smb.conf/smb1
[share]
Path=/data/dir1
Read only= NO # 等价于writable = yes
Create mask=0644 # 说明:默认为744
[root@c71 ~]$vim /etc/samba/smb.conf/smb2
[share]
path=/data/dir2
Read only= NO
Create mask=0644
# 重启服务
[root@c71 ~]$systemctl restart smb.service

# 10.0.0.72 客户端
# 用户smb1,smb2访问share共享目录,看到目录是不同目录
[root@c72 ~]$yum -y install samba-client cifs-utils
[root@c72 ~]$smbclient //10.0.0.73/share -U smb1%123456
[root@c72 ~]$smbclient //10.0.0.73/share -U smb2%123456

# windows:文件管理器输入 \\10.0.0.73\share 回车,然后输入账号密码即可

数据的实时同步

实现实时同步的方法:

  • inotify + rsync
  • sersync:国人周洋在 inotify 基础上开发的,功能强大,只是已经不再更新了

inotify

异步的文件系统事件监控机制,利用事件驱动机制,而无须通过诸如 cron 等的轮询机制来获取事件,linux 内核从 2.6.13 起支持 inotify,通过 inotify 可以监控文件系统中添加、删除,修改、移动等各种事件

inotify+rsync 使用方式:

  1. 利用监控服务(inotify),监控同步数据服务器目录中信息的变化
  2. 发现目录中数据产生变化,就利用 rsync 服务推送到备份服务器上
  3. 利用脚本进行结合

inotify 内核参数

  • max_queued_events:inotify 事件队列最大长度,如值太小会出现 Event Queue Overflow 错误,默认值:16384, 生产环境建议调大,比如:327679
  • max_user_instances:每个用户创建 inotify 实例最大值,默认值:128
  • max_user_watches:可以监视的文件的总数量(inotifywait 单进程),默认值:8192,建议调大
1
2
3
4
5
6
7
8
9
10
11
[root@data-centos8 ~]#vim /etc/sysctl.conf
fs.inotify.max_queued_events=66666
fs.inotify.max_user_watches=100000
[root@centos8 ~]#sysctl
-p
fs.inotify.max_queued_events = 66666
fs.inotify.max_user_watches = 100000
[root@centos8 ~]#cat /proc/sys/fs/inotify/*
66666
128
100000

inotify-tools

1
2
3
4
5
6
7
8
[root@c71 ~]$yum -y install inotify-tools

[root@c71 ~]$rpm -ql inotify-tools
# 在被监控的文件或目录上等待特定文件系统事件(open、close、delete等)发生,常用于实时同步的目录监控
/usr/bin/inotifywait
# 收集被监控的文件系统使用的统计数据,指文件系统事件发生的次数统计
/usr/bin/inotifywatch
...
inotifywait
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
inotifywait [ options ] file1 [ file2 ] [ file3 ] [ ... ]

# 常用option
-m, --monitor: 始终保持事件监听
-d, --daemon: 以守护进程方式执行,和-m相似,配合-o使用
-r, --recursive: 递归监控目录数据信息变化
-q, --quiet: 输出少量事件信息
--exclude <pattern>: 指定排除文件或目录,使用扩展的正则表达式匹配的模式实现
--excludei <pattern>: 和exclude相似,不区分大小写
-o, --outfile <file>: 打印事件到文件中,相当于标准正确输出,注意:使用绝对路径
-s, --syslogOutput: 发送错误到syslog相当于标准错误输出
--timefmt <fmt>: 指定时间输出格式
--format <fmt>: 指定的输出格式;即实际监控输出内容
-e: 指定监听指定的事件,如果省略,表示所有事件都进行监听

--timefmt "%Y-%m-%d %H:%M:%S"
%Y # 年份信息,包含世纪信息
%y # 年份信息,不包括世纪信息
%m # 显示月份,范围 01-12
%d # 每月的第几天,范围是 01-31
%H # 小时信息,使用 24小时制,范围 00-23
%M # 分钟,范围 00-59
%S # 秒,范例 0-60

--format "%T %w%f event: %;e"
%T # 输出时间格式中定义的时间格式信息,通过 --timefmt option 语法格式指定时间信息
%w # 事件出现时,监控文件或目录的名称信息,相当于dirname
%f # 事件出现时,将显示监控目录下触发事件的文件或目录信息,否则为空,相当于basename
%e # 显示发生的事件信息,不同的事件默认用逗号分隔
%Xe # 显示发生的事件信息,不同的事件指定用X进行分隔

-e create,delete,moved_to,close_write,attrib
create #文件或目录创建
delete #文件或目录被删除
modify #文件或目录内容被写入
attrib #文件或目录属性改变
close_write #文件或目录关闭,在写入模式打开之后关闭的
close_nowrite #文件或目录关闭,在只读模式打开之后关闭的
close #文件或目录关闭,不管读或是写模式
open #文件或目录被打开
lsdir #浏览目录内容
moved_to #文件或目录被移动到监控的目录中
moved_from #文件或目录从监控的目录中被移动
move #文件或目录不管移动到或是移出监控目录都触发事件
access #文件或目录内容被读取
delete_self #文件或目录被删除,目录本身被删除
unmount #取消挂载

范例:

1
2
3
4
5
6
7
8
9
10
11
# 监控一次性事件
inotifywait /data/www

# 持续前台监控
inotifywait -mrq /data/www --exclude=".*\.swx|\.swp"

# 持续后台监控,并记录日志
inotifywait -o /root/inotify.log -drq /data/www --timefmt "%Y-%m-%d %H:%M:%S" --format "%T %w%f event: %e"

#持续前台监控特定事件
inotifywait -mrq /data/www --timefmt "%F %H:%M:%S" --format "%T %w%f event:%;e" -e create,delete,moved_to,close_write,attrib
inotifywatch
1
inotifywatch [ options ] file1 [ file2 ] [ ... ]

rsync

rsync 常用做镜像备份和同步数据,配合计划任务实现定时备份,配合 inotify 可以实现触发式的实时数据同步

官方网站: http://rsync.samba.org/

软件包:rsync、rsync-daemon(CentOS 8)

服务文件:/usr/lib/systemd/system/rsyncd.service

配置文件:/etc/rsyncd.conf

端口:873/tcp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 1. 源地址 和 目标地址 都在本机
rsync [OPTION]... SRC [SRC]... DEST

# 2. 通过远程shell连接
rsync [OPTION]... SRC [SRC]... [USER@]HOST:DEST # pull 推
rsync [OPTION]... [USER@]HOST:SRC [DEST] # push 拉

# 3. 连接到rsync守护进程
rsync [OPTION]... SRC [SRC]... [USER@]HOST::DEST # pull 推
rsync [OPTION]... SRC [SRC]... rsync://[USER@]HOST[:PORT]/DEST # pull 推
rsync [OPTION]... [USER@]HOST::SRC [DEST] # push 拉
rsync [OPTION]... rsync://[USER@]HOST[:PORT]/SRC [DEST] # push 拉

The ':' usages connect via remote shell, while '::' & 'rsync://' usages connect to an rsync daemon, and require SRC or DEST to start with a module name.

前两种的本质是通过本地或远程 shell,而第 3 种方式则是让远程主机上运行 rsyncd 服务,使其监听在一个端口上,等待客户端的连接

范例:备份服务器启动 rsync 的守护进程,然后数据服务器去连接,再进行数据的推送和拉取

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
# 备份服务器 10.0.0.71
[root@c71 ~]$systemctl start rsyncd.service
[root@c71 ~]$ss -ntl
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 5 *:873 *:*
LISTEN 0 5 [::]:873 [::]:*

[root@c71 ~]$vim /etc/rsyncd.conf
...
[backup] # bachup 模块
path = /data/backup # 备份路径
read only = no # 设置可写,默认只读

# 查看设置的模块
[root@c71 ~]$rsync 127.0.0.1::
backup
[root@c71 ~]$rsync rsync://127.0.0.1
backup

# 默认用户以nobody访问此目录,所以给nobody设置读写权限
[root@c71 ~]$setfacl -m u:nobody:rwx /data/backup/

# 数据服务器 10.0.0.1
lujinkai@Z510:~$ rsync rsync://10.0.0.71
backup
lujinkai@Z510:~$ rsync 10.0.0.71::
backup

# 推送,将本机的u_script目录备份到10.0.0.71的/data/backup目录(rsyncd.conf中backup模块设置)
lujinkai@Z510:~/www$ rsync -av ./u_script/ root@10.0.0.71::backup
lujinkai@Z510:~/www$ rsync 10.0.0.71::backup
drwxrwxr-x 4,096 2020/11/14 22:38:48 .
-rwxrwxr-x 319 2020/11/14 22:38:48 demo.sh
drwxrwxr-x 4,096 2020/11/09 14:52:39 include
# 拉取
lujinkai@Z510:~/www$ rsync -av root@10.0.0.71::backup ./u_script/

rsyncd.conf 的格式 参考 man rsyncd.conf 或者 https://linux.die.net/man/5/rsyncd.conf

上面的过程都是免密的,我们也可以设置认证

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 备份服务器 10.0.0.71
[root@c71 ~]$echo "rsyncuser:123456" > /etc/rsync.pas
[root@c71 ~]$chmod 600 /etc/rsync.pas
[root@c71 ~]$vim /etc/rsyncd.conf
...
[backup]
path = /data/backup
read only = no
auth users = rsyncuser # 默认anonymous可以访问rsync服务器,这里设置只能虚拟用户rsyncuser访问
secrets file = /etc/rsync.pas # 认证文件
...
[root@c71 ~]$systemctl restart rsyncd.service # 也可以不重启

# 数据服务器 10.0.0.1
# 将秘密写入到/etc/rsync.pas,也可以赋值给环境变量 export RSYNC_PASSWORD=123456
lujinkai@Z510:~/www$ echo 123456 > /etc/rsync.pas
# 测试,注意这里一定要指定用户名 rsyncuser
lujinkai@Z510:~/www$ rsync rsyncuser@10.0.0.71::backup
Password:
drwxrwxr-x 4,096 2020/11/14 22:38:48 .
-rwxrwxr-x 319 2020/11/14 22:38:48 demo.sh
drwxrwxr-x 4,096 2020/11/09 14:52:39 include

inotify+rsync+shell 脚本 实现实时数据同步

备份数据库是:10.0.0.71,inotifywait 监控文件变化,rsync 负责同步数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
SRC='/data/www/' #注意最后的/
DEST='rsyncuser@10.0.0.71::backup'
rpm -q rsync &>/dev/null || yum install rsync
inotifywait \
-mrq \
--exclude=".*\.swp" \
--timefmt '%Y-%m-%d %H:%M:%S' \
--format '%T %w %f' \
-e create,delete,moved_to,close_write,attrib ${SRC} |
while read DATE TIME DIR FILE; do
FILEPATH=${DIR}${FILE}
rsync \
-az \
--delete \
-password-file=/etc/rsync.pas $SRC $DEST &&
echo "At ${TIME} on ${DATE}, file $FILEPATH was backuped up via rsync" >>/var/log/changelist.log
done

sersync 实现实时数据同步

sersync 虽然快 10 年没更新了,但是还是比较好用的

sersync 项目地址: https://code.google.com/archive/p/sersync/
sersync 下载地址: https://code.google.com/archive/p/sersync/downloads

sersync 类似于 inotify,同样用于监控,但它克服了 inotify 的缺点

inotify 最大的不足是会产生重复事件,或者同一个目录下多个文件的操作会产生多个事件,例如,当监控目录中有 5 个文件时,删除目录时会产生 6 个监控事件,从而导致重复调用 rsync 命令。另外比如:vim 文件时,inotify 会监控到临时文件的事件,但这些事件相对于 rsync 来说是不应该被监控的

sersync 优点:

  • c++编写,速度快
  • 对 linux 系统文件系统产生的临时文件和重复的文件操作进行过滤,所以在结合 rsync 同步的时候,节省了运行时耗和网络资源
  • 配置很简单,其中提供了静态编译好的二进制文件和 xml 配置文件,直接使用即可
  • 使用多线程进行同步,尤其在同步较大文件时,能够保证多个服务器实时保持同步状态
  • 有出错处理机制,通过失败队列对出错的文件重新同步,如果仍旧失败,则按设定时长对同步失败的文件重新同步
  • 不仅可以实现实时同步,另外还自带 crontab 功能,只需在 xml 配置文件中开启,即也可以按要求隔一段时间整体同步一次,而无需再额外配置 crontab 功能
  • 可以二次开发

sersync 只有两个文件:

  • 二进制程序文件 sersync2

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    lujinkai@Z510:/usr/local/sersync$ ./sersync2 -h
    set the system param
    execute:echo 50000000 > /proc/sys/fs/inotify/max_user_watches
    sh: 1: cannot create /proc/sys/fs/inotify/max_user_watches: Permission denied
    execute:echo 327679 > /proc/sys/fs/inotify/max_queued_events
    sh: 1: cannot create /proc/sys/fs/inotify/max_queued_events: Permission denied
    parse the command param
    _______________________________________________________
    参数-d:启用守护进程模式
    参数-r:在监控前,将监控目录与远程主机用rsync命令推送一遍
    c参数-n: 指定开启守护线程的数量,默认为10个
    参数-o:指定配置文件,默认使用confxml.xml文件
    参数-m:单独启用其他模块,使用 -m refreshCDN 开启刷新CDN模块
    参数-m:单独启用其他模块,使用 -m socket 开启socket模块
    参数-m:单独启用其他模块,使用 -m http 开启http模块
    不加-m参数,则默认执行同步程序

  • 配置文件 confxml.xml

    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
    lujinkai@Z510:/usr/local/sersync$ vim confxml.xml
    <?xml version="1.0" encoding="ISO-8859-1"?>
    <head version="2.5">
    <host hostip="localhost" port="8008"></host>
    <debug start="false"/> # 是否开启调试模式
    <fileSystem xfs="false"/>
    <filter start="false"> # 是否开启文件过滤功能
    <exclude expression="(.*)\.svn"></exclude>
    <exclude expression="(.*)\.gz"></exclude>
    <exclude expression="^info/*"></exclude>
    <exclude expression="^static/*"></exclude>
    </filter>
    <inotify> # 监控的事件
    <delete start="true"/>
    <createFolder start="true"/>
    <createFile start="false"/>
    <closeWrite start="true"/>
    <moveFrom start="true"/>
    <moveTo start="true"/>
    <attrib start="false"/> # 修改此行为true,文件属性变化后也会同步
    <modify start="false"/>
    </inotify>

    <sersync> # rsync命令的配置段
    <localpath watch="/opt/tongbu"> # 同步的目录
    # name是远程rsyncd的模块名,如果下面ssh标签开启了start,name则为远程sehll方式运行的目标目录
    <remote ip="127.0.0.1" name="tongbu1"/>
    <!--<remote ip="192.168.8.39" name="tongbu"/>-->
    <!--<remote ip="192.168.8.40" name="tongbu"/>-->
    </localpath>
    <rsync>
    <commonParams params="-artuz"/> # 指定rsync选项
    <auth start="false" users="root" passwordfile="/etc/rsync.pas"/>
    <userDefinedPort start="false" port="874"/><!-- port=874 -->
    <timeout start="false" time="100"/><!-- timeout=100 -->
    <ssh start="false"/> # 默认使用rsync daemon运行rsync命令,true为使用远程shell模式
    </rsync>
    # 错误重传及日志文件路径,默认60分钟
    <failLog path="/tmp/rsync_fail_log.sh" timeToExecute="60"/>
    <crontab start="false" schedule="600"> # 定时,默认600分钟
    <crontabfilter start="false"> # 是否开启定时
    <exclude expression="*.php"></exclude>
    <exclude expression="info/*"></exclude>
    </crontabfilter>
    </crontab>
    <plugin start="false" name="command"/>
    </sersync>
    #####################################以下行不需要修改####################################
    <plugin name="command">
    <param prefix="/bin/sh" suffix="" ignoreError="true"/> <!--prefix /opt/tongbu/mmm.sh suffix-->
    <filter start="false">
    <include expression="(.*)\.php"/>
    <include expression="(.*)\.sh"/>
    </filter>
    </plugin>

    <plugin name="socket">
    <localpath watch="/opt/tongbu">
    <deshost ip="192.168.138.20" port="8009"/>
    </localpath>
    </plugin>
    <plugin name="refreshCDN">
    <localpath watch="/data0/htdocs/cms.xoyo.com/site/">
    <cdninfo domainname="ccms.chinacache.com" port="80" username="xxxx" passwd="xxxx"/>
    <sendurl base="http://pic.xoyo.com/cms"/>
    <regexurl regex="false" match="cms.xoyo.com/site([/a-zA-Z0-9]*).xoyo.com/images"/>
    </localpath>
    </plugin>
    </head>

基于 rsync daemon 实现 sersync

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 下载
lujinkai@Z510:~/www/script/src$ wget https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/sersync/sersync2.5.4_64bit_binary_stable_final.tar.gz
# 解压,可以看到,sersync只有两个文件:二进制程序文件和xml配置文件
lujinkai@Z510:~/www/script/src$ tar zxvf sersync2.5.4_64bit_binary_stable_final.tar.gz
lujinkai@Z510:~/www/script/src$ sudo mv GNU-Linux-x86/ /usr/local/sersync
# 添加到环境变量PATH,过程略...
# 修改配置文件
lujinkai@Z510:~/www/script/src$ cd /usr/local/sersync/
lujinkai@Z510:/usr/local/sersync$ vim confxml.xml # 过程略...
# 确认安装rsync客户端工具
lujinkai@Z510:/usr/local/sersync$ apt -y install rsync
# 创建连接rsynd服务器的用户密码文件,并必须修改权限
lujinkai@Z510:~$ echo 123456 > /etc/rsync.pas
lujinkai@Z510:~$ chmod 600 /etc/rsync.pas
# 以后台方式执行同步
lujinkai@Z510:~$ sersync2 -dro /usr/local/sersync/confxml.xml
# 如果同步失败,可以手动执行下面命令,观察过程
lujinkai@Z510:~$ cd /data/www && rsync -artuz -R --delete ./rsyncuser@10.0.0.71::backup --password-file=/etc/rsync.pas >/dev/null 2>&1

# sersync支持多实例,监控多个目录时,只需分别配置不同配置文件,然后使用sersync2指定对应配置文件运行
lujinkai@Z510:~$ sersync2 -rd -o /etc/sersync.d/nginx.xml

基于远程 shell 实现 sersync

1
2
3
4
5
6
7
8
9
# 首先配置ssh基于key的自动验证,过程略...
# 修改配置文件 confxml.xml
<localpath watch="/data/www">
<remote ip="备份服务器IP" name="/data/backup"/> #修改此行指定备份服务器地址和备份目标目录
</localpath>
...
<ssh start="true"/> # 开启ssh

# 不需要配置/etc/rsync.pas,其他步骤和上面一样