rm -rf不是原子的吗?


11

我刚抓到一个令人困惑的错误:

rm: cannot remove `xxx/app/cache/prod': Directory not empty

这是由以下命令引起的:

rm -rf $cache_dir/*

在哪里$cache_dir定义为xxx/app/cache

所以我看到它像:rm删除了cache/proddir中的所有内容,然后在尝试删除cache/prod目录之前-另一个程序在其中创建了一个文件/目录,从而导致rm失败。

我的假设正确吗?


7
您的假设是正确的- rm -r不是原子的。如果要确保rm -rf运行时在目录中没有创建更多文件,可以先重命名,然后删除重命名的目录。
约翰尼,

@Johnny:是的,那是我实际上已经实施的方法:-)
zerkms 2013年

尽管那也不是完全安全的。如果某个应用当前不在该目录下运行,它将随其移动并保持正常运行。
帕特里克

这与rm -rf线程安全无关:如果您在同一目录上同时运行多次,该目录将被删除。这是关于rm -r不是原子的。
吉尔(Gilles)'所以

@Gilles:它取决于:“如果一段代码仅以保证多个线程同时安全执行的方式操作共享数据结构,那么它就是线程安全的”。因此,如果我们将“线程”假定为rm调用,那么我们可以谈论线程安全性。但是无论如何,它什么都不会改变
zerkms 2013年

Answers:


7

给出的错误消息是“目录不为空”(ENOTEMPTY),鉴于您的假设听起来是正确的,这是一种竞争条件,程序在rm尝试删除目录之前会在该目录中创建一个文件,从而ENOTEMPTY从底层提供预期的错误rmdir(2)

注意:为了安全起见,您可以将目录移动/重命名为新名称,然后执行对该目录的删除。


2
这个答案是错误的,即使文件正在使用中,您也可以删除目录条目,然后删除目录。一项简单的测试mkdir x; cat > x/a &; tail -f x/a &; rm -r x显示,即使在使用文件时,也可以删除目录,而不管它们是为读取还是写入而打开的。
wingedsubmariner

1
是的,文件仍然存在,但这与删除目录失败的原因无关。您的答案中的该语句专门为false:“系统不会删除其中包含以读取/写入模式打开的文件的目录”。您的答案中有一些好东西,只是与问题
无关

1
另外,请注意不要将文件描述符与文件混淆。文件描述符永远不会删除,只会关闭。
wingedsubmariner

1
您的第一段可能也需要一些工作。您正确地说,当文件仍处于打开状态时,文件删除不会发生,只是从该目录取消链接文件后,它们就不会阻止该目录被删除。是的,这意味着UNIX允许存在任何目录中的文件,这乍看起来似乎很奇怪。
wingedsubmariner 2013年

1
我真的只能想到删除失败的两个原因,要么OP的直觉是正确的,然后创建了一个新文件,要么是权限错误。rm抱怨许可错误,所以我认为我们可以消除它。我没有足够的信心发布答案。
wingedsubmariner
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.