1 磁盘爆了
项目中一段逻辑不完善的代码,向一个目录不断上传图片文件,同时没有删除逻辑,当因为磁盘满了发现问题时,已经写了 200GB、600W+ 文件,并且还在继续。
其中有非常小一部分图片是有用、不能删的,大部分图片需要清理,于是有了本文的两种尝试(最后发现多绕了亿点弯路,但终究还是学习了几个 Linux 命令哈哈)。
本文没有详细介绍命令如何使用,网上相关的文章很多,可自行查找学习。
2 首先
重点中的重点,先修改有问题的代码,虽然新的图片文件还在上传,但被其替换的无用图片由新的逻辑控制主动删除。
混入防转防爬防抄袭声明:本文《Linux 从大量文件中找出部分文件并删除》首发且仅发布于没有名字的博客
3 找出文件
接下来要做的是找到要删除的文件,当然,目前目录下文件数量过多,实在是打印不出来,这些命令只是单独拿出来介绍和解释。
在这个问题中,通过查询数据库,得知了一些时间段的文件可以删,所以下面的命令都是按指定时间段查询符合条件的文件。
3.1 find 命令
find . -type f -mtime +9 -mtime -15 -print
or
touch -t 202208150000 t_start
touch -t 202209232359 t_end
find . -type f -newer t_start ! -newer t_end -print
第一种写法是用 -mtime
指定文件的修改时间在过去 10 到 15 天范围内,因为需要算天数,而且 +N 的计算还很奇怪(实际是 (n + 1) 天以前),再加上这个目录下有几百万文件,不太可能列出来看一遍再决定对不对,于是找到了第二种写法。
第二种是先使用 touch
命令创建两个时间戳文件,用 -newer
指定与这两个时间戳文件比较,得到符合条件的文件,这个写法就比较直观,touch
命令可以控制精确到秒的时间戳,所以尝试用此命令。
3.2 ls 命令
找到 find
命令后,在服务器(实际是 Docker 容器)中执行,提示没有此命令。。一阵无语,就随手搜一下其他方案,找到了 ls
命令的写法,虽然最后是在真实服务器上用 find
命令操作,但这个写法也挺有意思,于是记下来。
ls -f --full-time | grep -E "2022-08-15|2022-08-16|2022-08-17"
使用 --full-time
打印出完整的日期时间,再结合 grep
过滤找出相应日期的文件。
4 删除文件
结合上述两种查找命令,分别有各自的删除写法。
4.1 find 命令
find . -type f -mtime +9 -mtime -15 -exec rm -rf {} \;
or
find . -type f -mtime +9 -mtime -15 | xargs rm -rf
第一种是用 find
命令自带的 -exec
,用 {} 代替查找出的结果,同时这个 -exec
参数的末尾必须有空格,否则会报 find: 遗漏“-exec”的参数,所以就变成了接一个空格,再用 \;
结尾。
第二种是用管道的方式,接 rm
命令。
4.2 ls 命令
rm -rf $(ls --full-time | grep -E "2022-08-15|2022-08-16|2022-08-17" | awk '{print $9}')
or
ls -f --full-time | grep -E "2022-08-15|2022-08-16|2022-08-17" | awk '{print $9}' | xargs rm -rf
第一种是用 ls
的结果替换给 rm
执行,要注意后面的 awk
,使用 --full-time
后,输出的内容不仅仅是文件名,还包含其他列,所以使用 awk
只输出第 9 列,即文件名。
第二种同样是使用管道,接 rm
命令即可,同理,需要用到 awk
辅助。
5 兜圈子
借助 find
和 rm
,把确定的一些时间范围内的无用文件清理之后,发现还剩了 100W+ 图片文件,此时才开始反向思考一个问题,其实数据库保存的信息中有那些不需要删除的图片的名称,为什么不先把这些图片文件单独复制出来,再把目录清空,再将它们还原回来。。
于是,浪费了不少时间之后,最终还是采用了这样的最直接了当的方法,当然,学习尝试了几个以前没用过的命令也是个小收获。