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

hyp*_*not 13 linux ubuntu filesystems ext4

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

mv cache cache.bak
mkdir cache
service nginx restart
Run Code Online (Sandbox Code Playgroud)

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

一个简单的rm -rf cache.bak垃圾服务器,即使是最简单的 HTTP 响应在 rm 运行时也需要 16 秒,所以我不能这样做。

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

我相信最好的解决方案是某种限制,就像 nginx 的内置缓存管理器所做的那样。

你会如何解决这个问题?有没有什么工具可以做到这一点?

Ubuntu 16.04 上的 ext4

Ter*_*nen 9

像这样制作一个 bash 脚本:

#!/bin/bash
rm -- "$*"
sleep 0.5
Run Code Online (Sandbox Code Playgroud)

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

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

然后,你可以运行

find cache.bak -print0 | xargs -0 -n 5 deleter.sh
Run Code Online (Sandbox Code Playgroud)

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

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


hyp*_*not 3

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

  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/
Run Code Online (Sandbox Code Playgroud)

现在 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 内置方法的简单性,但该解决方案取决于相对路径的长度。这不是一个大问题,因为大多数人都会通过反复试验找到正确的值。