公司文件服务器面向全部技术与市场人员,存在大量的相同文件。负责维护公司文件服务器的同事提出来希望能对相同文件进行删减,在删除文件的位置建立链接指向目标文件,这样既不影响正常使用,又可以大幅降低存储容量。
文件服务器采用 samba 搭建,存储空间 4T(已经使用了 2.7T)。采用脚本删除相同文件并建立软链接并不难,难点在于从大容量存储空间中实现相同文件的查找,根据此情况设计实现方案并进行优化。
1)初步实现:
* 删除空文件: find . -empty -type f -exec rm -f {} ;
* 查找相同的文件:find . -type f -printf “%sn” | sort -rn | uniq -d | xargs -I {} -n1 find . -type f -size {}c -print0 | xargs -0 md5sum | sort | uniq -w32 –all-repeated=separate | cut -c 35-
2)命令说明:
* find . -type f -printf “%sn”:查找文件并输出文件大小(注意 -printf “%sn” 的用法)
* sort -rn:按文件大小排序
* uniq -d:仅重复项输出,且只输出一次
* xargs -I {} -n1 find . -type f -size {}c -print0:使用 xargs 与 find 实现指定文件大小的查询
* xargs -0 md5sum:将前面的结果转化为输入(-0 实现特殊文件名)
* sort:排序
* uniq -w32 –all-repeated=separate:通过 uniq 实现分类输出
* cut -c 35-:截取 md5 校验码后面的部分(md5 校验码为固定位数)
3)以上命令在小存储空间测试无问题,但到 4T 空间使用时运行太慢,需要进行优化。分析原因为:该方案为先找到相同 size 文件,再在文件中寻找相同的 md5 校验码,每个 size 文件大小均要对全盘执行一次 find,共执行了多次 find 操作(后来测试证明大于3M的文件就执行8000+次),非常耗时。
4)调整思路为:先计算 md5 校验码,再对具有相同 md5 校验码的文件进行操作,全盘仅执行一次 find,大大缩短时间
* 最终方案:find . -type f -exec md5sum {} ; | sort | uniq -w32 –all-repeated=separate | cut -c 35-
5)优化前思路测试(时间太长,总时长为估算):
5.1 运行条件:Ubuntu20.04,4T USB 硬盘(USB3.0),实际使用 2.7T,全盘扫描,为节约时间仅处理大于 3M 的文件
5.2 time find . -type f -size +3M | sort | uniq # 全盘扫描并排列文件
* real:10m37s, sys:3m35s, user:0.4s
* 共有 8240 个文件 size
5.3 time find . -type f -size 28854272c # 针对特定文件大小进行一次搜索
* real:10m27s, sys:3m35s, user:0.5s
* 与 5.2 比较可见:find 使用时间基本相同
* 按照 8240 个不同文件 size 计算,时间为:8240 * 10m27s = 206h
6)优化后思路测试:
6.1 运行条件不变
6.2 time find . -type f -size +3M | wc -l # 全盘扫描文件
* real:10m23s, sys:3m31s, user:0.4s
* 满足条件文件 43129 个
* 再次说明 find 使用的时间基本相同
6.3 time find . -type f -size +3M -exec md5sum {} ; # 针对每个文件计算 md5 校验码
* real:203m, sys:19m26s, user:64m48s
* 由于文件数量太大(43129),造成计算 md5 校验码的时间较长
* 实现时间不到 4 小时,与旧方案相比时间大大缩短
最终方案:find . -type f -exec md5sum {} ; | sort | uniq -w32 –all-repeated=separate | cut -c 35- ;运行一晚上搞定!
声明:本站部分文章内容及图片转载于互联 、内容不代表本站观点,如有内容涉及侵权,请您立即联系本站处理,非常感谢!