如何在不干扰服务器的情况下删除数百万个文件


11

我想删除一个nginx缓存目录,我通过以下方法快速清除了该目录:

mv cache cache.bak
mkdir cache
service nginx restart

现在,我有一个cache.bak包含200万个文件的文件夹。我想删除它,而不会打扰服务器。

一个简单的操作会rm -rf cache.bak破坏服务器,即使在运行rm时,即使最简单的HTTP响应也要花费16秒,所以我无法做到这一点。

我尝试过ionice -c3 rm -rf cache.bak,但是没有帮助。服务器具有HDD,而不是SSD,可能在SSD上可能不是问题。

我相信最好的解决方案将是某种限制,例如nginx的内置缓存管理器是如何做到的。

您将如何解决?有没有什么工具可以做到这一点?

Ubuntu 16.04上的ext4


1
您是如何从“ rm -rf cache.bak”中恢复的?当您重命名时,nginx似乎正在运行,因此它可能维护了文件描述符,甚至切换到了新目录。我认为您需要完全关闭Nginx,删除缓存,然后重新启动。
Jan Steinman

6
将来,请将缓存保留在单独的文件系统上。这样,您可以简单地核对该文件系统,这比尝试删除数百万个文件要快得多。几年前,它通过一个包含数十亿个文件的hylafax假脱机目录来艰难地学习了此方法。
Dennis Kaarsemaker '16


尝试rsync快速删除-类似情况的答案-unix.stackexchange.com/questions/37329/…–
kawu

感谢所有评论,我总结了我的发现以写出答案。
hyperknot

Answers:


9

制作如下的bash脚本:

#!/bin/bash
rm -- "$*"
sleep 0.5

deleter.sh例如,保存名称。运行chmod u+x deleter.sh使其可执行。

该脚本删除作为参数传递给它的所有文件,然后休眠0.5秒。

然后,您可以运行

find cache.bak -print0 | xargs -0 -n 5 deleter.sh

此命令检索cache.bak中所有文件的列表,并将五个文件名一次传递给删除脚本。

因此,您可以调整一次删除多少个文件,以及每次删除操作之间的延迟时间。


感谢您提供此解决方案,我已将其包含在我的整体文章中。但是,一个问题是,这如何处理大ns?我通常在大型目录中遇到*字符时会遇到错误,这不是吗?
hyperknot

xargs了解命令行的最大大小,并且默认情况下尽量不超过该大小。此限制具有一次最多不超过5条路径的附加限制。
BowlOfRed

1
请注意,以每秒10个文件的速度,删除200万个文件将花费55个小时。
安德鲁·亨利

4

您应该考虑将缓存保存在一个单独的文件系统上,您可以按照注释中的说明进行挂载/卸载。在执行此操作之前,您可以使用此衬纸,/usr/bin/find /path/to/files/ -type f -print0 -exec sleep 0.2 \; -exec echo \; -delete前提是您的查找二进制文件位于/ usr / bin下,并且您希望在屏幕上看到进度。相应地调整睡眠时间,以免使硬盘过分紧张。


-print0这里不需要一个,因为您没有管道find任何地方的输出。
Tero Kilkanen '16

您可能对rm-ing感兴趣。称它为偏执狂,但我始终想确保自己删除了正确的文件。
亚历克斯

是的,我没有正确解码命令,这很糟糕。
Tero Kilkanen '16

3

您可能想在使用find命令输出的脚本上尝试ionice。类似于以下内容:

ionice -c3 $(
for file in find cache.bak -type f; do
    rm $file
done
for dir in find cache.bak -depthe -type d -empty; do
    rmdir $dir
done
)

根据文件系统的不同,每个文件的删除都可能导致重写整个目录。对于大型目录,这可能会很受欢迎。索引节点表还需要其他更新,并且可能还有可用空间列表。

如果文件系统有日志,则将更改写入日志;否则,将更改写入日志。应用 并从日记中删除。这增加了写入密集型活动的I / O要求。

您可能要使用没有日志的文件系统作为缓存。

您可以使用sleep命令来代替动作,以限制动作的速率。即使ionice无效,也可以使用,但是删除所有文件将花费很长时间。


2

我在这里得到了许多有用的答案/评论,在此我也想总结一下,并展示我的解决方案。

  1. 是的,防止此类情况发生的最佳方法是将缓存目录保留在单独的文件系统上。核对/快速格式化文件系统最多最多需要几秒钟(也许是几分钟),这与文件系统上存在多少文件/目录无关。

  2. ionice/ nice解决方案没有做任何事情,因为删除过程实际上造成几乎没有I / O。导致I / O的原因是,我相信当删除过程过快地删除文件时,内核/文件系统级队列/缓冲区会填满。

  3. 我解决该问题的方法与Tero Kilkanen的解决方案相似,但是不需要调用shell脚本。我使用rsync的内置--bwlimit开关来限制删除速度。

完整的命令是:

mkdir empty_dir
rsync -v -a --delete --bwlimit=1 empty_dir/ cache.bak/

现在,bwlimit以千字节为单位指定带宽,在这种情况下,带宽适用于文件名或文件路径。通过将其设置为1 KBps,它每小时删除约100,000个文件,或每秒删除27个文件。文件具有相对路径,例如cache.bak/e/c1/db98339573acc5c76bdac4a601f9ec1e,长度为47个字符,因此它每秒可以提供1000/47〜= 21个文件,因此有点类似于我每小时估计有100,000个文件。

现在为什么--bwlimit=1呢?我尝试了各种值:

  • 10000、1000、100->系统变慢
  • 10->系统在一段时间内运行良好,但每分钟左右会产生部分速度下降。HTTP响应时间仍小于1秒。
  • 1->完全没有系统速度下降。我并不着急,因此可以在不到1天的时间内删除200万个文件,所以我选择了它。

我喜欢rsync内置方法的简单性,但是此解决方案取决于相对路径的长度。这不是一个大问题,因为大多数人会通过反复试验找到正确的价值。


现在我很好奇,如果您执行“ mv cache.dir-old / dev / null”之类的操作,磁盘的影响将是什么
ivanivan '16
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.