linux环境下利用rsync+find实现同步指定时间段文件

前言

这几天一直在处理shell脚本,作为服务器开发人员免不了要部署一些环境,数据备份和同步工作也是家常便饭,最近常搞的几个命令有 findrsyncsed 等,之前也写过一篇 《linux环境下使用rsync命令完成数据同步》,不过这次有新的需求了。

插曲

前段时间发现通过 rysnc 同步游戏版本数据时,在数据同步前有一个较长的等待时间,大概12G数据需要等待4分钟,多方面查找原因后定位到应该是 rsync-c 参数导致的,参数全称是 --checksum 打开校验开关,强制对文件传输进行校验,多次实验后发现只要把 -c 参数省略,这个检验所花的4分钟就能省掉,同步前校验只会根据修改的时间戳和文件大小来判断,这在大多数情况下足够了。

根据时间段同步

现在想同步日志文件,因为日志文件是每小时产生一个,之前的日志文件绝大多数情况也不会改动,所以再同步时没必要检测所有的日志文件,只需要同步最近一段时间的就可以了,这样可以减少文件比对的时间。

查询了 sync 命令的所有参数,没有找到指定同步时间段的参数,但是有个 --files-from=FILE 看起来能实现这个需求,man手册中是这样写的:

1
2
3
4
5
6
7
8
9
10
11
12
13
Using this option allows you to specify the exact list of files to transfer (as read from the specified FILE or - for standard input).  It also tweaks the default behavior of rsync to make transferring just the specified files and directories easier:

o The --relative (-R) option is implied, which preserves the path information that is specified for each item in the file (use --no-relative or --no-R if you want to turn that off).

o The --dirs (-d) option is implied, which will create directories specified in the list on the destination rather than noisily skipping them (use --no-dirs or --no-d if you want to turn that off).

o The --archive (-a) option’s behavior does not imply --recursive (-r), so specify it explicitly, if you want it.

o These side-effects change the default state of rsync, so the position of the --files-from option on the command-line has no bearing on how other options are parsed (e.g. -a works the same before or after --files-from, as does --no-R and all other options).

The filenames that are read from the FILE are all relative to the source dir -- any leading slashes are removed and no ".." references are allowed to go higher than the source dir. For example, take this command:

rsync -a --files-from=/tmp/foo /usr remote:/backup

基于参数的描述,我只要提供一个包含指定时间段的待同步的所有文件名的文件就可以了,比如将指定时间段需要同步的文件名放到 /tmp/foo 文件中,然后以 --files-from=/tmp/foo 形式来指定就行了。

其实还有一个方便的写法,就是直接在参数后面利用 find 写过滤文件的命令,比如只同步最近3天修改过的文件就可以写成:

1
rsync -avz --files-from=<(find /var/log/ -mtime -3) /usr remote:/backup

其中 find /var/log/ -mtime -3 命令的含义就是找出 /var/log/ 目录下最近3天修改的文件。

按时间过滤文件

有了上面的基础命令,想要同步不同时间段的文件只需要修改 find 命令参数就可以了,比较常用的参数就是 mtime 了。

使用 mtime 参数查找

mtime 表示文件的修改时间,用在 find 查找时是以天为单位的,最小间隔24小时,数字是几就表示几天前,带有 + 表示几天前之外,带有 - 表示今天前之内,下面举几个例子:

  • 查找修改时间在3天之前的文件(修改时间距今大于96小时)
1
find /var/log/ -mtime +3
  • 查找修改时间在3天之内的文件(修改时间距今小于72小时)
1
find /var/log/ -mtime -3
  • 查找修改时间在3天前当天的文件(修改时间距今大于72小时,小于96小时)
1
find /var/log/ -mtime 3

如果对mtime参数的使用有点疑惑,可以看一下下面的示意图:

除了上面提到的 -mtime 参数,还有类似的 -atime-ctime 参数,这三个参数的含义如下,使用时可根据定义来选择:

1
2
3
-atime:文件访问时间,文件被读取或执行的时间。
-ctime:属性改变时间,文件的inode被修改的时间
-mtime:内容修改时间

使用 newermt 进行更精确查找

find -newermt 的通用形式是find -newerXY reference,目的是找到一些X属性比variable的Y属性更早的文件,其中X代表find的目标文件属性,Y代表参照属性。X可选a,c,m,Y可选a,c,m,t,其中t代表客观绝对时间,只作为参照属性存在,具体详细的用法参照man手册:

1
2
3
4
5
6
7
8
9
10
-newerXY reference
Compares the timestamp of the current file with reference. The reference argument is normally the name of a file (and one of its timestamps is used for the comparison) but it may also be a string describing an absolute time. X and Y are placeholders for other letters, and these letters select which time belonging to how reference is used for the comparison.

a The access time of the file reference
B The birth time of the file reference
c The inode status change time of reference
m The modification time of the file reference
t reference is interpreted directly as a time

Some combinations are invalid; for example, it is invalid for X to be t. Some combinations are not implemented on all systems; for example B is not supported on all sys‐tems. If an invalid or unsupported combination of XY is specified, a fatal error results. Time specifications are interpreted as for the argument to the -d option of GNU date. If you try to use the birth time of a reference file, and the birth time cannot be determined, a fatal error message results. If you specify a test which refers to the birth time of files being examined, this test will fail for any files where the birth time is unknown.

如果要找到修改时间在2023-3-18 20:00:00 和 2023-3-18 22:00:00 之间的文件可以写成:

1
find /var/log -newermt '2023-3-18 20:00:00' ! -newermt '2023-3-18 22:00:00'

总结

  • rsync 命令本身不能指定同步的时间段,可搭配 find 命令来同步指定时间段的文件
  • rsync -avz --files-from=<(find /var/log/ -mtime -3) /usr remote:/backup 同步修改时间在3天内的文件
  • 使用 newermt 可按时间精确查找,形式如 find /var/log -newermt '2023-3-18 20:00:00' ! -newermt '2023-3-18 22:00:00'
  • 假设变量 KEY=birthday、FILE=myfile.log,查找KEY所在的行号可以使用 grep -rn $KEY" $FILE | awk -F ':' '{print $1}'
  • 还是在上面的假设 sed -n '/${KEY}=/' $FILE 无法获得行号,使用 sed -n '/birthday=/' $FILE 就可以
  • 上面这种sed命令中使用变量不生效的问题目前还没找到解决方法,有解决方案的大佬请指教
  • 不过 sed -e "${LINE},${LINE}s%$OLD_VAL%$NEW_VAL%g" $FILE 这种替换命令就支持变量,但sed不支持非贪婪模式,目前有点迷糊,还在探索中
==>> 反爬链接,请勿点击,原地爆炸,概不负责!<<==

不要规划孩子必须在哪一个领域取得成就,但只要她喜欢,就提供一个舞台,让她尽情去发挥~

2023-3-19 21:01:51

Albert Shi wechat
欢迎您扫一扫上面的微信公众号,订阅我的博客