高效清理文件系统大量文件的方法
线上环境找出大量消耗inode的文件目录,我们需要有一个快速清理文件的方法。
参考 Delete only files older than 7 days: -mtime and find
find /tmp/exec -maxdepth 1 -mtime +1 -type f -delete如果要检查文件而不是删除,可以将 -delete 改成 -print
find /tmp/exec -maxdepth 1 -mtime +1 -type f -print但是发现不行
#df -i | grep vda
/dev/vda1        2621440 2618372      3068  100% /
[root@server-1.example.com /root]
#find /tmp/exec -maxdepth 1 -mtime +1 -type f -delete
[root@server-1.example.com /root]
#df -i | grep vda
/dev/vda1        2621440 2564624     56816   98% /也就是说都是一天内生成的文件
参考 find -mtime files older than 1 hour [duplicate] 改成一小时
原先案例:
find /var/www/html/audio -daystart -maxdepth 1 -mmin +59 -type f -name "*.mp3" \
    -exec rm -f {} \;如果要在删除前先验证可以使用echo命令加入
... -exec echo rm -f '{}' \;
          ^^^^ Add the 'echo' so you just see the commands that are going to get
               run instead of actual trying them first.我执行:
find /tmp/exec -maxdepth 1 -mmin +59 -type f -exec rm -f {} \;不过,这个命令执行起来超级慢。我测试了一下,如果要删除200w+文件,需要大约1.5小时。用watch每2秒检查一下文件清理速度,似乎每秒钟只清理350~400个文件。(计算了一下,每秒400个文件的话,1.5小时确实只能删除 216万 个文件)
为了加快清理速度,我找到 Efficiently delete large directory containing thousands of files
有以下一些推荐方法:
- 较快的删除目录文件方法是使用 - rsync对一个空目录和需要删除文件目录进行同步,可以快速清理掉目录下的文件
mkdir empty_dir
rsync -a --delete empty_dir/ yourdirectory/但是,这个方法对于我的案例不适用
此外,更快的方法是使用perl,但是我不熟悉perl,没有把握使用这个命令
cd yourdirectory
perl -e 'for(<*>){((stat)[9]<(unlink))}'- 有推荐使用 - find命令的- -delete参数,据说比标准的- -exec rm -f {} \;要快。但是这个命令不是所有平台通用(GNU find才支持- -delete),并且也是递归方式删除
- 可以通过 - xargs来加速删除,因为- xargs可以并发删除文件,也就是你可以一次传递多个文件给xargs,执行一条删除命令:
find /path/to/folder -name "filenamestart*" -type f -print0 | xargs -0rn 20 rm -f
这里
xargs的参数-0表示输入项是以null字符结束而不是空白,并且引号和反斜杠不指定。这个参数适合输入项可能包含空格,引号和反斜杠情况。
-r, --no-run-if-empty通常即使没有输入也会运行一次,GNU扩展的这个参数在没有包含任何非空白,就不运行
-n 20表示最大参数20个上述参数结合起来就是表示输入给xargs的一次处理参数是20个,也就是20个并发删除。你可以调整大这个参数以便更大并发。
不过,根据
man xargs手册提示,xargs能够自动根据平台计算出缓存大小,来决定尽可能大的参数,所以可以不用加-n 20而是让xargs自动判断取最大并发。所以可以改为| xargs -0r rm -f
对于我这个案例可以修订脚本命令
find /tmp/exec -maxdepth 1 -mmin +59 -type f | xargs -0r rm -f测试对比
- 先创建一个目录下50w文件 
mkdir test1
cd test1
for i in $(seq 1 500000); do echo testing >> $i.txt; done大约15秒就可以创建好500w文件
- 删除测试常规rm 
time find . -type f -exec rm {} \;完成时间
real    10m51.132s
user    1m56.469s
sys    8m49.892s再次测试
real    11m36.329s
user    1m37.385s
sys    9m53.831s- 测试find的 - -delete
time find . -type f -delete神奇,达到了xargs的效率
real    0m10.493s
user    0m0.692s
sys    0m5.105s- 测试删除: xargs并发20个文件 
time find . -type f | xargs -0rn 20 rm -f实测不行,传递参数过长,导致报错
xargs: argument line too long
但是可以改成 find 加上 -print0 参数
time find . -type f -print0 | xargs -0rn 20 rm -f删除效率也有很大提高,仅26秒钟,虽然比不上让xargs自动选择buffer的方式
real    0m26.355s
user    0m8.334s
sys    0m15.133s- 测试删除: xargs自动使用buffer并发删除文件 
time find . -type f | xargs -0r rm -f实测不行,传递参数过长,导致报错
xargs: argument line too long
time find . -type f -print0 | xargs -0r rm -f神奇的效率,仅仅12秒钟就可以完成删除
real    0m11.995s
user    0m0.984s
sys    0m5.603s批量处理
如果有大量的服务器需要检查inode消耗,我们可以使用 pssh 工具:
- 例如对于案例,执行 - pssh -ih hosts 'df -i | grep vda1'输出到日志文件- check_disk.log如下:
192.168.6.172:/dev/vda1        2621440 2613825      7615  100% /
192.168.6.239:/dev/vda1        2621440 2614148      7292  100% /- 过滤日志进行处理 
cat check_disk.log | awk '{print $1","$5}'获得类似输出
192.168.6.192:/dev/vda1,96%
192.168.6.200:/dev/vda1,5%
192.168.6.202:/dev/vda1,84%- 再进行数据整理 
cat check_disk.log | awk '{print $1","$5}' | awk -F"[:,%]" '{print $1","$3}'就获得了如下格式
192.168.6.183,5
192.168.6.165,82
192.168.6.168,6
...
192.168.6.192,96
192.168.6.200,5
192.168.6.202,84现在进行判断参考 print line only if number in third field is greater than X [duplicate] 或者参考我之前的实践记录 awk搜索字符串
cat check_disk.log | awk '{print $1","$5}' | awk -F"[:,%]" '{print $1","$3}' | awk -F, '$2>10 {print $1}'awk 支持先判断,然后执行打印 参考 get all rows having a column value greater than a threshold
所以执行
cat check_disk.log | awk '{print $1","$5}' | awk -F"[:,%]" '{print $1","$3}' | awk -F, '$2>10 {print $1}' | tee ip_clean- 现在我们可以开始批量清理了 
pssh -t 0 -ih ip_clean 'sudo find /tmp/exec -maxdepth 1 -mmin +10 -type f -delete'参考
- Which is the fastest method to delete files in Linux - 有详细对比不同命令的删除时间,不过没有对比 - xargs命令
Last updated
Was this helpful?