Unix:用于清理日常构建的快速“删除目录”

Posted

技术标签:

【中文标题】Unix:用于清理日常构建的快速“删除目录”【英文标题】:Unix: fast 'remove directory' for cleaning up daily builds 【发布时间】:2010-12-20 04:53:15 【问题描述】:

有没有更快的方法来删除目录然后简单地提交

rm -r -f *directory*

?我问这个是因为我们每天的跨平台构建非常庞大(例如每个构建 4GB)。所以有些机器上的硬盘经常用完空间。

这就是我们的 AIX 和 Solaris 平台的情况。

也许这些平台上有用于目录删除的“特殊”命令?

粘贴编辑(将我自己的单独答案移到问题中):

我通常想知道为什么'rm -r -f' 这么慢。 'rm' 不只需要修改 '..' 或 '.'文件以取消分配文件系统条目。

类似

mv *directory* /dev/null

会很好。

【问题讨论】:

我不是似是而非;买更大的硬盘。在 TB 存储世界中,4GB 并不是那么大。 这是什么文件系统? 我听说过“滑稽”,但“似是而非”对我来说是一个新词。 +1:p >> GrzegorzOledzki 写道: 这是什么文件系统?在 AIX 上,它在 Linux 构建机器上是“jfs”,在 Solaris 构建机器上是“ext3”,它是???。我不知道。明天必须检查。 @Vokuhila-Oliba:这完全是 OT,但你的名字从何而来?没看懂,但是觉得挺好玩的作为德国人,我得到第一部分而不是第二部分? 【参考方案1】:

要从文件系统中删除目录,rm 是您最快的选择。 在 linux 上,有时我们在 ramdisk 中进行构建(几 GB),它具有非常令人印象深刻的删除速度 :) 您也可以尝试不同的文件系统,但在 AIX/Solaris 上您可能没有太多选择...

如果您的目标是让目录 $dir现在为空,您可以重命名它,并稍后从后台/cron 作业中删除它:

mv "$dir" "$dir.old"
mkdir "$dir"
# later
rm -r -f "$dir.old"

另一个技巧是你为 $dir 创建一个单独的文件系统,当你想删除它时,你只需重新创建文件系统。像这样的:

# initialization
mkfs.something /dev/device
mount /dev/device "$dir"


# when you want to delete it:
umount "$dir"
# re-init
mkfs.something /dev/device
mount /dev/device "$dir"

【讨论】:

"umount 'temp-fs' and re-create" 真是个好主意!我接受这是最佳答案! 这也与使用 LVM 从一些空闲空间分配新文件系统并在之后释放它非常吻合。或使用 LVM 的快照功能将您的新文件系统基于模板。【参考方案2】:

我忘记了这个技巧的来源,但它确实有效:

EMPTYDIR=$(mktemp -d)
rsync -r --delete $EMPTYDIR/ dir_to_be_emptied/

【讨论】:

来源(可能):quora.com/File-Systems/… 我很想了解为什么 rsync 方法要快得多 我不认为它更快,或者如果是,它高度依赖于文件系统和其他因素。我制作了 1000000 个文件并使用了rm -rf foo/,花了 3 分钟。然后我尝试了这个,但是当它占用了两倍的时间时就把它杀死了。 @MarkLopes 尝试来自 archive.org 的 WayBackMachine。 参见unix.stackexchange.com/questions/37329/…【参考方案3】:

至少在 AIX 上,您应该使用逻辑卷管理器 LVM。我们所有的系统都将所有物理硬盘驱动器捆绑到一个卷组中,然后从中创建一个大型 honkin 文件系统。

这样,您可以随意将物理设备添加到您的机器上,并将文件系统的大小增加到您需要的任何大小。

我见过的另一种解决方案是在每个文件系统上分配一个垃圾目录,并结合使用mvfind cron 作业来解决空间问题。

基本上,有一个cron 作业,每十分钟运行一次并执行:

rm -rf /trash/*
rm -rf /filesys1/trash/*
rm -rf /filesys2/trash/*

然后,当您希望回收该文件系统上的特定目录时,请使用以下内容:

mv /filesys1/overnight /filesys1/trash/overnight

并且,在接下来的十分钟内,您的磁盘空间将开始恢复。 filesys1/overnight 目录将立即可供使用,甚至在已开始删除已删除的版本之前。

垃圾目录与您要删除的目录位于同一文件系统上很重要,否则您需要进行大量的复制/删除操作,而不是相对快速的移动。

【讨论】:

【参考方案4】:

rm -r <em>directory</em> 通过深度优先向下递归目录,删除文件,并在备份途中删除目录。必须这样做,因为您不能删除非空目录。

冗长乏味的细节:每个文件系统对象都由文件系统中的一个 inode 表示,该文件系统具有文件系统范围内的平面 inode 数组。[1]如果您只是删除了 directory 而没有先删除其子级,则子级将保持分配状态,但没有任何指向它们的指针。 (fsck 在运行时会检查这种情况,因为它代表文件系统损坏。)

[1] 对于所有的文件系统来说,这可能并不完全正确,并且可能有一个文件系统按照您描述的方式工作。它可能需要像垃圾收集器这样的东西。但是,我所知道的所有常见的 act 对象,例如 fs 对象都归 inode 所有,而目录是名称/inode 编号对的列表。

【讨论】:

+1,这是我搜索并找到此问题时正在寻找的解释。【参考方案5】:

如果rm -rf 很慢,可能是您使用了“同步”选项或类似选项,这导致写入磁盘过于频繁。在具有普通选项的 Linux ext3 上,rm -rf 非常快。

一种适用于 Linux 并且可能也适用于各种 Unixen 的快速删除选项是使用循环设备,例如:

hole temp.img $[5*1024*1024*1024]  # create a 5Gb "hole" file
mkfs.ext3 temp.img
mkdir -p mnt-temp
sudo mount temp.img mnt-temp -o loop

“hole”程序是我自己编写的,它使用“hole”而不是在磁盘上分配的块来创建一个大的空文件,这要快得多,并且在您真正需要它之前不使用任何磁盘空间。 http://sam.nipl.net/coding/c-examples/hole.c

我刚刚注意到 GNU coreutils 包含一个类似的程序“truncate”,所以如果你有它,你可以使用它来创建图像:

truncate --size=$[5*1024*1024*1024] temp.img

现在您可以使用 mnt-temp 下的挂载映像来临时存储您的构建。完成后,执行以下操作将其删除:

sudo umount mnt-temp
rm test.img
rmdir mnt-temp

我想你会发现删除单个大文件比删除大量小文件要快得多!

如果你不想编译我的“hole.c”程序,你可以使用dd,但这会慢很多:

dd if=/dev/zero of=temp.img bs=1024 count=$[5*1024*1024]  # create a 5Gb allocated file

【讨论】:

这听起来像是一个“特殊”的解决方案。但如果它适用于 AIX/solaris,我可以试一试。对于 Linux,我没有这个问题,因为硬盘太大了,这不是问题。 您也可以使用dd 的“seek”命令和计数为零来创建有孔的文件。 您可以在任何支持循环设备或逻辑卷管理的操作系统上执行此类操作 - 在文件或 LvM 上创建一个临时文件系统,在其中完成您的工作,然后只需删除整个文件系统(删除文件),这应该几乎是瞬时的,例如从磁盘中删除大的 DVD 映像或任何内容。我给出的示例命令是针对 Linux 的,但在任何 *nix 工作上都应该可以实现相同的功能,它是 salt,甚至可能在 'doze 上。【参考方案6】:

我认为实际上除了您引用的“rm -rf”来删除您的目录之外别无他法。

为避免一遍又一遍地手动执行此操作,您可以每天 cron 一个脚本,如果它们“足够老”,则递归删除构建根目录的所有构建目录,例如:

find <buildRootDir>/* -prune -mtime +4 -exec rm -rf  \;

(这里 mtime +4 表示“任何超过 4 天的文件)

另一种方法是配置您的构建器(如果它允许这样的事情)以用当前构建粉碎先前的构建。

【讨论】:

【参考方案7】:

我也在研究这个。

我有一个包含 600,000 多个文件的目录。

rm * 会失败,因为条目太多。

find . -exec rm \; 很好,每 5 秒删除约 750 个文件。正在通过另一个 shell 检查 rm 速率。

所以,我写了一个简短的脚本来一次 rm 多个文件。每 5 秒获得约 1000 个文件。想法是将尽可能多的文件放入 1 个 rm 命令中以提高效率。

#!/usr/bin/ksh
string="";
count=0;
for i in $(cat filelist);do
    string="$string $i";
    count=$(($count + 1));
  if [[ $count -eq 40 ]];then
    count=1;
    rm $string
    string="";
  fi
done

【讨论】:

【参考方案8】:

使用 perl -e 'for()((stat)[9]http://www.slashroot.in/which-is-the-fastest-method-to-delete-files-in-linux

【讨论】:

【参考方案9】:

在 Solaris 上,这是我找到的最快的方法。

find /dir/to/clean -type f|xargs rm

如果您有奇怪路径的文件,请使用

find /dir/to/clean -type f|while read line; do echo "$line";done|xargs rm 

【讨论】:

我同意,刚刚使用 xargs 尝试了第一个命令,它比这里的任何其他命令都快得多,尤其是在慢速磁盘上运行时。【参考方案10】:

我编写了一个比 rm 更快的小型 Java 应用程序 RdPro(递归目录清除工具)。它还可以删除用户在根目录下指定的目标目录。适用于 Linux/Unix 和 Windows。它有命令行版本和 GUI 版本。

https://github.com/mhisoft/rdpro

【讨论】:

【参考方案11】:

我不得不在 Windows 中删除超过 3,00,000 个文件。我安装了cygwin。幸运的是,我拥有数据库中的所有主目录。创建了一个 for 循环并基于行条目并使用 rm -rf 删除

【讨论】:

【参考方案12】:

需要从 AWS EBS 1 TB 磁盘 (ext3) 上的数十个目录中删除 700 GB,然后将剩余部分复制到新的 200 GB XFS 卷。将该体积保持在 100%wa 需要数小时。由于磁盘 IO 和服务器时间不是空闲的,因此每个目录只需要几分之一秒。

在哪里 /dev/sdb 是任意大小的空卷

directory_to_delete=/ebs/var/tmp/

mount /dev/sdb $directory_to_delete

nohup rsync -avh /ebs/ /ebs2/

【讨论】:

【参考方案13】:

我只是在文件夹中使用find ./ -delete清空,它在大约10分钟内删除了620000个目录(总大小)100GB。

来源:本站评论https://www.slashroot.in/comment/1286#comment-1286

【讨论】:

以上是关于Unix:用于清理日常构建的快速“删除目录”的主要内容,如果未能解决你的问题,请参考以下文章

批量清理目录文件

在 Unix 中,如何删除当前目录及其下的所有内容?

Vagrant 快速生成Oracle 21c 数据库实验环境

Linux系统下/tmp目录下的临时文件怎么清理?

如何在Unix中为shell脚本锁定目录[重复]

linux清理文件