我想删除一个 nginx 缓存目录,我通过以下方式快速清除它:
mv cache cache.bak
mkdir cache
service nginx restart
现在我有一个cache.bak
包含 200 万个文件的文件夹。我想删除它,但不影响服务器。
一个简单的rm -rf cache.bak
垃圾服务器,即使是最简单的 HTTP 响应在 rm 运行时也需要 16 秒,所以我无法这样做。
我试过了ionice -c3 rm -rf cache.bak
,但没用。服务器有一个 HDD,而不是 SSD,在 SSD 上可能不是问题。
我相信最好的解决方案是某种限制,就像 nginx 的内置缓存管理器那样。
您将如何解决这个问题? 有没有什么工具可以做到这一点?
Ubuntu 16.04 上的 ext4
答案1
编写如下 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 中所有文件的列表,并将五个文件名一次传递给删除脚本。
因此,您可以调整一次删除的文件数量,以及每次删除操作之间的延迟时间。
答案2
您应该考虑将缓存保存在单独的文件系统上,以便您可以挂载/卸载,正如评论中有人所说。在此之前,您可以使用这个一行程序,/usr/bin/find /path/to/files/ -type f -print0 -exec sleep 0.2 \; -exec echo \; -delete
假设您的 find 二进制文件位于 /usr/bin 下,并且您想在屏幕上查看进度。相应地调整睡眠时间,这样您就不会过度强调您的硬盘。
答案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
)
根据文件系统的不同,每次删除文件都可能导致重写整个目录。对于大型目录,这可能会造成很大影响。需要对 inode 表进行额外更新,并且可能需要更新可用空间列表。
如果文件系统有日志,则更改将写入日志、应用并从日志中删除。这会增加写入密集型活动的 I/O 要求。
您可能希望使用没有日志的文件系统进行缓存。
除了 ionice,您还可以使用 sleep 命令来限制操作的速率。即使 ionice 不起作用,这种方法也能奏效,但删除所有文件需要很长时间。
答案4
我在这里得到了很多有用的答案/评论,我想总结一下并展示我的解决方案。
是的,最好的办法是防止发生这种情况是为了将缓存目录保存在单独的文件系统上。删除/快速格式化文件系统最多需要几秒钟(也许几分钟),与文件系统上有多少文件/目录无关。
ionice
/解决方案nice
没有起到任何作用,因为删除过程实际上几乎没有造成 I/O。我认为造成 I/O 的原因是,当文件被删除过程删除得太快时,内核/文件系统级队列/缓冲区被填满。我解决问题的方法与 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 内置方法的简单性,但此解决方案取决于相对路径的长度。这不是什么大问题,因为大多数人都会通过反复试验找到正确的值。