Linux大文件删除
通常,要在 Linux 终端删除一个文件,我们使用 rm 命令(删除文件)、shred 命令(安全删除文件)、wipe 命令(安全擦除文件)。
如果我们想要删除超大的文件/文件夹,比如大概 100-200GB,在删除文件(I/O 调度)所花费的时间以及 RAM 占用量方面,就没有那么简单。
为啥不用rm
rm命令大量调用了lstat64和unlink,可以推测删除每个文件前都从文件系统中做过一次lstat操作。过程:正式删除工作分三阶段。
第一阶段,需要通过getdirentries64调用,分批读取目录(每次大约为4K),在内存中建立rm的文件列表;
第二阶段,lstat64确定所有文件的状态;
第三阶段,通过unlink执行实际删除。
这三个阶段都有比较多的系统调用和文件系统操作。
清空内容来释放空间
通过重定向到 Null 来清空文件内容清空或者让一个文件成为空白的是最简单方式。
通过重定向到 Null 来清空文件内容
1 | # > access.log |
使用 ‘true’ 命令重定向来清空文件
1 | # : > access.log |
使用 cat/cp/dd 实用工具及 /dev/null 设备来清空文件
在 Linux 中, null
设备基本上被用来丢弃某个进程不再需要的输出流,或者作为某个输入流的空白文件,这些通常可以利用重定向机制来达到。
所以 /dev/null
设备文件是一个特殊的文件,它将清空送到它这里来的所有输入,而它的输出则可被视为一个空文件。
另外,你可以通过使用 cat 命令 显示 /dev/null
的内容然后重定向输出到某个文件,以此来达到清空该文件的目的。
1 | # cat /dev/null > access.log |
同理,使用 cp 命令 复制 /dev/null
的内容到某个文件来达到清空该文件
1 | cp /dev/null access.log |
使用 echo 命令清空文件
使用 echo 命令 将空字符串的内容重定向到文件中
1 | # echo "" > access.log |
要将 null 做为输出输入到文件中,你应该使用 -n
选项,这个选项将告诉 echo 不再像上面的那个命令那样输出结尾的那个新行。
1 | # echo -n "" > access.log |
使用 truncate 命令来清空文件内容
truncate
可被用来将一个文件缩小或者扩展到某个给定的大小。
你可以利用它和 -s
参数来特别指定文件的大小。要清空文件的内容,则在下面的命令中将文件的大小设定为 0。
1 | # truncate -s 0 access.log |
rsync快速删除文件
假如你有一些特别大的文件要删除,比如nohup.out这样的实时更新的文件,动辄都是几十个G上百G的,也可以用rsync来清空大文件,而且效率比较高。
1)创建空文件
1 | # touch/data/blank.txt |
2)用rsync清空文件
1 | # rsync -a --delete-before --progress --stats /root/blank.txt /root/nohup.out |
rsync 也可以用来清空目录
1 | # mkdir /data/blank/ |
其中–delete-before 接收者在传输之前进行删除操作。
rsync所做的系统调用很少:没有针对单个文件做lstat和unlink操作。命令执行前期,rsync开启了一片共享内存,通过mmap方式加载目录信息。只做目录同步,不需要针对单个文件做unlink。
另外,在其他人的评测里,rm的上下文切换比较多,会造成System CPU占用较多——对于文件系统的操作,简单增加并发数并不总能提升操作速度。
总结:频繁做减法不如直接从头来过把文件系统的目录与书籍的目录做类比,rm删除内容时,将目录的每一个条目逐个删除(unlink),需要循环重复操作很多次;rsync删除内容时,建立好新的空目录,替换掉老目录,基本没开销。
速度对比
有人对此进行过测试:
rm 文件数量太多,不可用
find with -exec 50万文件耗时43分钟
find with -delete 9分钟
Perl 16s
Python 8分钟
rsync with -delete 16s