最暴力的 rm -rf 命令居然删除目录失败了!为什么?

当我们在Linux系统中卸载软件或清理数据时,经常会使用rm -rf命令去删除某个目录,例如删除/tmp/tektea目录:

[code lang=”shell”]# rm -rf /tm/tektea[/code]

rm命令的-r和-f这两个参数的man含义如下:

-r, -R, –recursive
remove directories and their contents recursively

-f, –force
ignore nonexistent files, never prompt

所以-r和-f分别表示可递归删除目录和强制删除文件,组合起来就是我们在Linux系统中所熟知的、最暴力的强制删除某个目录的命令了,即便目录下文件正在被读写,也依然会干干净净的删除掉该目录,因为有-f参数,听起来合情合理。但你现在已经看了本文的标题,你开始迷惑了吧?

没关系,下面我们通过一些测试来验证下这个暴力的 rm -rf 命令,看看它是不是真的那么生猛,可以破坏一切目录。

用例1:使用cp命令持续往/tmp/tektea目录下拷贝文件,然后rm -rf /tmp/tektea,测试代码如下

[code lang=”shell”]# cat test1.sh
#!/bin/bash

i=1
while true
do
cp /tmp/testfile /tmp/tektea/$i
let i++
done

# cat /tmp/testfile
hi[/code]

验证结果:执行bash test1.sh后,rm -rf /tmp/tektea删除成功

用例2:使用dd命令持续往/tmp/tektea目录下写文件,然后rm -rf /tmp/tektea,测试代码如下

[code lang=”shell”]# cat test2.sh
#!/bin/bash

while true
do
dd if=/dev/zero of=/tmp/tektea/ddfile bs=1024 count=1000000000
let i++
done[/code]

验证结果:执行bash test2.sh后,rm -rf /tmp/tektea删除成功

用例3:使用echo命令持续往/tmp/tektea目录下的文件写数据,然后rm -rf /tmp/tektea,测试代码如下

[code lang=”shell”]# cat test3.sh
#!/bin/bash

while true
do
echo hi >>/tmp/tektea/echofile
done[/code]

验证结果:执行bash test3.sh后,rm -rf /tmp/tektea删除失败,且有以下报错:

# rm -rf /tmp/tektea/
rm: cannot remove `/tmp/tektea’: Directory not empty

通过上面的验证,首先我们可以得出这条结论:使用rm -rf命令删除目录时,如果该目录下的文件正在被写入,那么会存在删除失败的可能

那么,以上三个用例都是在往/tmp/tektea目录写入数据,为什么仅仅是第三个场景会失败呢?

各种迹象都把根因指向到了 rm 命令(有兴趣的朋友可以下载Linux中rm命令的源码走读下),rm命令在-r -f强制删除目录时,其逻辑是这样的:

1)从被删除目录的最里层递归删除文件;
2)当最里层目录A的文件被删除完以后,再删除该层文件夹A;
3)在删除文件夹A前,再检查目录A下是否还有文件,如果有则报错Directory not empty(编外:注意这里了

现在再来回答这个问题——“为什么仅仅是第三个场景会失败呢?”,不过在回答前,我先给大家展示两个数据:

1. 用例1使用cp往/tmp/tektea目录拷贝数据,15秒大约生成了8600个文件,每秒约573文件,相当于每秒573次写入
2. 用例3使用echo往/tmp/tektea/echofile写数据,15秒大约在echofile中写入了59万行,每秒约40000次写入

所以结合rm的实现和几个用例差异可以清楚的知道——在删除某个目录时,若有进程往该目录写入数据,则需要先停止该进程的服务(或kill掉该进程),所以我们的一些Shell代码在卸载或删除目录时就存在失败的可能。

网友评论comments

发表评论

电子邮件地址不会被公开。 必填项已用*标注

  1. Sec007小编说道:

    改版后,速度快了不少啊!

  2. ibusybox说道:

    第三个例子删不掉的原因是这里用的echo是bash内嵌的命令,你可以换成/bin/echo效果应该就和前面例子一样了。前面例子用的都是进程调用, 第三个例子是进程内调用频率不一样而已, 这两种并没有一直锁住这个目录, 所以即便是使用bash内嵌命令也会出现竞争,反复多次rm -rf还是可以删掉的。可以验证例子:这样bash cpu直接飚上去while truedo echo “aaa”done这样bash cpu并不会很高while truedo /bin/echo “aaa”done

    • Sec007说道:

      我记得以前就有人做过这样的实验,并做了详细说明,rm -rf很危险!只是很久没玩Linux了,忘的差不多了吧!

Copyright © 2012-2017 YUNWEIPAI.COM - 运维派 - 粤ICP备14090526号-3
扫二维码
扫二维码
返回顶部