【Linux】聊聊删文件的那些破事

前言

在操作系统的日常运维中,我们经常会做文件的创建、删除、修改操作,尤其是删除,无论是定期清理日志文件,还是做完一个操作以后删除临时文件,这都是非常常见的操作,如果你运维的服务器是非常小型的,而且业务量并不多,那也许你永远不会遇到在文件删除时产生的性能问题;但是如果你需要运维临时文件产生巨多或者日志产生巨多或者其他会产生大量文件的服务器,你也许会遇到删除文件时的瓶颈问题,其中最常见的就是/bin/rm: Argument list too long;如果还没有遇到,可以随便找一个目录,创建一个测试文件夹,并生成随机的文件,然后尝试rm所有文件:

mkdir file_test
cd file_test
for i in $(seq 1 500000); do echo testing >> $i.txt; done
rm -rf *

相信很快你就会遇到上述的问题,从这个问题出发,我们聊聊删除文件的这些破事。

正文

在Linux中,虽然不同的文件系统在数据删除上的具体实现有所不同,但均是对inode进行操作,更改文件的元数据信息,就和HDFS一样,你能否找到数据取决于NameNode里有没有存对应块的元数据信息。

找到几个博文解释ext各文件系统的数据删除原理,放在这里,感兴趣可以看看:
ext4文件系统文件删除解析
ext2和ext3文件系统文件删除解析

rm命令

rm命令虽然是最常用的用来删除文件的命令,但是正如我上文所说,当文件数过多的时候就会无法执行,这种情况下,常见的方式是通过一些关键字做文件的筛选删除,尽量保证每批删除的文件数量在rm允许的范围内,比如按照文件所带的日期或者按照字母开头来筛选:

rm -rf *20220921*
rm -rf a*

当然,在报错/bin/rm: Argument list too long的时候,删除操作是没有进行的,所以无论执行多少次,文件都没被删除。

find命令

当通过一些关键字做筛选无法满足我们的运维要求时,就要寻求别的方式了,比如文件名没有明显的特征,或者需要按照文件的生成日期进行删除等场景,大部分人会使用类似以下的命令进行删除:

find $path -mtime +3 -name "*" -type f -exec rm -rf {} \;

原先我也使用这个命令去做文件删除,但是耗时非常久,这是因为find结合rm -rf命令的原理是对于所有搜索出来满足条件的文件,都执行一次rm -rf命令。

一个更好的替代方式是以下的命令格式:

find $path -mtime +3 -name "*" -type f -delete

以下是两种方式删除相似体量的文件耗时的对比:
在这里插入图片描述
在这里插入图片描述

能够看出来明显的区别,所以下次再使用find删除文件的时候还是尽量使用delete,性能能够提升很多;

当然,如果你能用rm来实现的时候,还是用rm会好一些:
在这里插入图片描述

perl方式

除了上述两种方式,还有一种使用很少的方式,那就是用perl脚本来做文件删除,从我的测试来看,之所以知道这个也是因为之前看到网上的大佬说perl的性能比find delete还要高,但是在我的测试下并不是这样,性能最好的还是find delete,以下是删除10w个文件和50w个文件的性能对比:

10w文件删除对比

perl方式
在这里插入图片描述
find delete方式
在这里插入图片描述

50w文件删除对比

perl方式
在这里插入图片描述
find delete方式

在这里插入图片描述

100w文件删除对比

perl方式
在这里插入图片描述
find delete方式
在这里插入图片描述
当然了,在进行筛选的情况下我没有实际做过测试,我估计在极大数据量的情况下,性能差距不会太大的,如果有朋友有兴趣测试可以继续下去,并给我留言,附上我的清理脚本,这个脚本会在给定目录下再遍历一层进行数据删除:

#!/usr/bin/perl

use File::Find;
use File::Spec;

my $path="/home/test";

opendir DH, $path or die "cannot chdir to $path : $!";

for my $p (readdir DH) {
    next if $file eq "." or $file eq "..";
    my $sonpath=File::Spec->catdir($path,$p);
    opendir SH, $sonpath or die "cannot chdir to $sonpath : $!";
        for my $file (readdir SH) {
            next if $file eq "." or $file eq "..";
            next if $file =~ /^\./;
            my $abspath=File::Spec->catdir($sonpath,$file);
            my @s=stat("$abspath");
            if ((time()-$s[8]) > (60*60*24*2)){
                print "delete file $abspath\n";
                unlink $abspath;
            }
        }
    closedir SH;
}
closedir DH;

结语

一直以来都只是简单的使用rm命令做数据删除,这次因为业务上的需要,参与到大量文件的清理工作中,想要找到在linux下最高效的数据清理方式,也正是在这些目标的驱动下,了解到更多的文件清理方法,希望在以后的不断学习中能够探索到更高效的方法。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Meepoljd

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值