如何防止意外 rm -rf /*?

Val*_*cev 171 linux bash command-line-interface safety rm

我只是rm -rf /*不小心跑了,但我的意思是rm -rf ./*(注意斜线后面的星星)。

alias rm='rm -i'并且--preserve-root在默认情况下不救我,那么,有没有这方面的任何自动进行保护?


我不是 root 并立即取消了该命令,但在某处或某处有一些宽松的权限,因为我注意到我的 Bash 提示已经坏了。我不想依赖权限而不是 root(我可能会犯同样的错误sudo),而且我不想因为系统中某处丢失一个文件而寻找神秘的错误,所以,备份和sudo是好的,但我想要更好的东西来处理这个特定的情况。


关于三思而后行。我实际上正在使用它!但我用它来解决一些涉及 10 种不同事物的复杂编程任务。我深深地沉浸在这个任务中,没有任何脑力来检查标志和路径,我什至不考虑命令和参数,我认为像“空当前目录”这样的动作,我大脑的不同部分将它们转换为命令,有时会出错。我希望计算机纠正它们,至少是危险的。

Sac*_*kar 227

我遵循的技巧之一是#在使用rm命令时放在开头。

root@localhost:~# #rm -rf /
Run Code Online (Sandbox Code Playgroud)

这可以防止rm在错误的文件/目录上意外执行。确认后,#从头开始删除。这个技巧是有效的,因为在 Bash 中,一个以 开头的单词#会导致该单词和该行上所有剩余的字符被忽略。因此该命令被简单地忽略。

或者

如果你想阻止任何重要的目录,还有一个技巧。

创建一个-i在该目录中命名的文件。怎么能创建这样一个奇怪的文件?使用touch -- -itouch ./-i

现在尝试rm -rf *

sachin@sachin-ThinkPad-T420:~$ touch {1..4}
sachin@sachin-ThinkPad-T420:~$ touch -- -i
sachin@sachin-ThinkPad-T420:~$ ls
1  2  3  4  -i
sachin@sachin-ThinkPad-T420:~$ rm -rf *
rm: remove regular empty file `1'? n
rm: remove regular empty file `2'? 
Run Code Online (Sandbox Code Playgroud)

这里*将扩展-i到命令行,因此您的命令最终会变成rm -rf -i. 因此命令会在删除前提示。你可以把这个文件在你的//home//etc/,等。

或者

使用--preserve-root作为一个选项rm。在rm包含在较新的coreutils软件包中,这个选项是默认的。

--preserve-root
              do not remove `/' (default)
Run Code Online (Sandbox Code Playgroud)

或者

使用安全-rm

摘自网站:

Safe-rm 是一种安全工具,旨在通过用包装器替换 /bin/rm 来防止意外删除重要文件,该包装器根据永远不应删除的文件和目录的可配置黑名单检查给定参数。

尝试删除这些受保护文件或目录之一的用户将无法这样做,而是会显示警告消息:

$ rm -rf /usr
Skipping /usr
Run Code Online (Sandbox Code Playgroud)

  • 安全 rm 很整洁。这也是 `-i` 文件的一个绝妙技巧。哈。愚蠢的打击。 (49认同)
  • 这是天才。巫术将是`touch -- -rf` (14认同)
  • safe-rm 看起来很不错,现在正在研究它...... (10认同)
  • @SachinDivekar 这个答案是如何获得如此高的投票的?`safe-rm` 和 `---preserve-root` 是不错的建议,但是在前面加上 `#` 似乎并不是那么有效。然而,我真正的抱怨是这种特殊的“-i”文件业务,很简单,**糟糕的建议**!用奇怪命名的文件乱扔你的文件系统真的没有帮助,特别是当有一个 [使用`find` 命令的简单、有效、通用的解决方案](http://serverfault.com/a/363816/93109) 来预览和然后删除:`find | less` 然后是`find -delete`。 (7认同)
  • 令人惊讶的是,在 unix 中做了什么样的诡计。 (6认同)
  • 名为 -i 的创建文件绝对是天才。大约一年前,当我不小心在 VPS 上运行 rm -rf /etc/* 时,我可以使用它......(幸运的是,我每晚拍摄快照,因此能够在 45 分钟内恢复)。 (4认同)
  • @SachinDivekar:您所说的“正则表达式”实际上是一个 glob。如果“/dir/*.conf”是一个正则表达式,它会匹配“/dir///.conf”和“/dirxconf”而不是“/dir/myfile.conf”。 (3认同)

Ste*_*ski 52

你的问题:

我只是不小心运行了 rm -rf /* ,但我的意思是 rm -rf ./* (注意斜线后面的星号)。

解决方案:不要这样做!作为练习,不要./在路径的开头使用。斜线对命令没有任何价值,只会引起混淆。

./*意思与 相同*,所以上面的命令最好写成:

rm -rf *

这是一个相关的问题。我经常看到以下表达式,有人认为它FOO设置为类似/home/puppies. 实际上,我今天刚刚在一家主要软件供应商的文档中看到了这一点。

rm -rf $FOO/

但是如果FOO没有设置,这将评估为rm -rf /,这将尝试删除系统上的所有文件。尾部斜杠是不必要的,所以作为练习,不要使用它。

以下将做同样的事情,并且不太可能损坏您的系统:

rm -rf $FOO

我通过艰难的方式学会了这些技巧。14 年前,当我拥有第一个超级用户帐户时,我不小心rm -rf $FOO/从 shell 脚本中运行并破坏了一个系统。其他 4 位系统管理员看着这个说,‘是的。每个人都这样做一次。现在这是您的安装介质(36 张软盘)。去修理它。

这里的其他人推荐解决方案,如--preserve-rootsafe-rm。但是,这些解决方案并非适用于所有 Un*xe 变体,并且可能不适用于 Solaris、FreeBSD 和 MacOSX。此外,还safe-rm要求您在使用的每个 Linux 系统上安装其他软件包。如果你依赖safe-rm,当你开始一份新工作而他们没有safe-rm安装时会发生什么?这些工具是一个拐杖,依靠已知的默认值并改善您的工作习惯要好得多。

  • 我的朋友告诉我他从不使用 `rm -rf *`。他总是先更改目录,然后使用特定的目标。原因是他经常使用shell的历史记录,他担心他的历史记录中有这样的命令可能会在错误的时间弹出。 (25认同)
  • @VictorSergienko,使用 bash,如何指定 `${FOO:?}`,如 `rm -rf ${FOO:?}/` 和 `rm -rf ${FOO:?}/${BAR:?} `. 它会阻止它被翻译成 `rm -rf /`。我在我的回答 [here](http://stackoverflow.com/a/22843897/832230) 中有更多关于此的信息。 (8认同)
  • 如果你需要 `rm -rf $FOO/$BAR`,`rm -rf $FOO` 将无济于事。`cd $FOO && rm -rf $BAR` 会有所帮助,尽管时间更长。 (6认同)
  • @VictorSergienko 如果 `$FOO` 为空且 `$BAR` 为 `.` 或 `/`,恭喜您获得新的空主目录。 (2认同)

Not*_*Now 34

由于这是在“Serverfault”上,我想这样说:

如果你有几十个或更多的服务器,有一个庞大的管理员/用户团队,有人会去rm -rfchown错误的目录。

您应该制定一个计划,以尽可能少的 MTTR 恢复受影响的服务。

  • 并且您应该使用虚拟机或备用设备来练习恢复 - 找出无效的方法并完善所述计划。我们每两周重新启动一次——因为我们的大楼已经停电了,而且每次都很痛苦。通过对所有机架进行一些有计划的关闭,我们已经将它从几天的运行时间减少到现在大约 3 小时 - 每次我们了解哪些位要自动化/修复 init.d 脚本等。 (5认同)

Gil*_*il' 24

最好的解决方案是改变你的习惯,不要rm直接使用。

一种方法是先运行echo rm -rf /stuff/with/wildcards*。检查通配符的输出是否合理,然后使用 shell 的历史记录执行不带echo.

另一种方法是将echo命令限制在您将要删除的内容非常明显的情况下。与其删除目录中的所有文件,不如删除该目录并创建一个新目录。一个好的方法是将现有目录重命名为DELETE-foo,然后创建一个foo具有适当权限的新目录,最后删除DELETE-foo. 这种方法的一个附带好处是,在您的历史记录中输入的命令是rm -rf DELETE-foo.

cd ..
mv somedir DELETE-somedir
mkdir somedir                 # or rsync -dgop DELETE-somedir somedir to preserve permissions
ls DELETE-somedir             # just to make sure we're deleting the right thing
rm -rf DELETE-somedir
Run Code Online (Sandbox Code Playgroud)

如果您真的坚持删除一堆文件,因为您需要保留该目录(因为它必须始终存在,或者因为您没有重新创建它的权限),请将文件移动到其他目录,然后删除该目录.

mkdir ../DELETE_ME
mv * ../DELETE_ME
ls ../DELETE_ME
rm -rf ../DELETE_ME
Run Code Online (Sandbox Code Playgroud)

(按那个Alt+.键。)

从内部删除目录会很有吸引力,因为rm -rf .它很短,因此打字错误的风险很低。不幸的是,典型的系统不允许您这样做。您可以rm -rf -- "$PWD"改为这样做,但拼写错误的风险更高,但其中大多数会导致不删除任何内容。请注意,这会在您的 shell 历史记录中留下一个危险的命令。

只要有可能,就使用版本控制。你不rm,你cvs rm或其他什么,这是可以撤销的。

Zsh 可以选择在运行之前rm使用列出目录中所有文件的参数来提示您:(rm_star_silent默认情况下打开)在执行之前提示rm whatever/*,以及rm_star_wait(默认情况下关闭)添加 10 秒延迟,在此期间您无法确认。如果您打算删除某个目录中的所有文件,这将是有限的,因为您已经在期待提示了。它可以帮助防止诸如rm foo *for 之类的拼写错误rm foo*

还有更多涉及更改rm命令的解决方案。这种方法的一个限制是,有一天你会在一台真实的机器上rm,你会自动调用rm,安全地期待确认......接下来你将恢复备份。


Naf*_*Kay 21

正如你提到的,你总是可以做一个别名:

what_the_hell_am_i_thinking() {
   echo "Stop." >&2
   echo "Seriously." >&2
   echo "You almost blew up your computer." >&2
   echo 'WHAT WERE YOU THINKING!?!?!' >&2
   echo "Please provide an excuse for yourself below: " 
   read 
   echo "I'm sorry, that's a pathetic excuse. You're fired."
   sleep 2
   telnet nyancat.dakko.us
}

alias rm -fr /*="what_the_hell_am_i_thinking"
Run Code Online (Sandbox Code Playgroud)

您还可以将其与命令行 twitter 客户端集成,以提醒您的朋友您rm -fr /*以 root 身份擦除硬盘几乎是如何羞辱自己。

  • -1 你不能用空格给命令加上别名,更不用说 /* 这是一个无效的名字 (4认同)
  • +1 telnet miku.acm.uiuc.edu (3认同)

acu*_*ich 17

防止意外的最简单方法rm -rf /*是避免所有使用rm命令!事实上,我一直想跑rm /bin/rm完全摆脱命令!不,我不是在开玩笑。

而是使用命令-delete选项find,但首先在删除文件之前,我建议预览您将删除的文件:

find | less
Run Code Online (Sandbox Code Playgroud)

请注意,在现代版本中,find如果您省略目录名称,它将隐式使用当前目录,因此上面的内容等效于:

find . | less
Run Code Online (Sandbox Code Playgroud)

一旦您确定这些是您要删除的文件,您就可以添加-delete选项:

find path/to/files -delete
Run Code Online (Sandbox Code Playgroud)

因此,不仅find 使用更安全,而且表现力更强,因此如果您只想删除目录层次结构中与特定模式匹配的某些文件,您可以使用这样的表达式进行预览,然后删除文件:

find path/to/files -name '*~' | less
find path/to/files -name '*~' -delete
Run Code Online (Sandbox Code Playgroud)

find除了更安全之外,还有很多很好的理由来学习和使用rm,所以如果你花时间学习使用find.


Sve*_*ven 16

是的:不要以 root 身份工作,并且在行动之前总是三思而后行。

另外,看看类似https://launchpad.net/safe-rm 的东西。


eve*_*nti 16

这个帖子中有一些非常糟糕的建议,幸运的是大部分都被否决了。

首先,当你需要成为 root 时,成为 root - sudo 和各种别名技巧会让你变得虚弱。更糟糕的是,他们会让你粗心大意。学会以正确的方式做事,停止依赖别名来保护你。有一天你会在一个没有训练轮的盒子上扎根,然后炸毁一些东西。

其次 - 当你有 root 时,把自己想象成驾驶一辆满是学童的公共汽车。有时你可以在收音机里听着这首歌摇摆不定,但有时你需要左右看,放慢速度,仔细检查你所有的镜子。

第三 - 你几乎从来没有真正需要rm -rf- 更有可能你想要mv something something.bakmkdir _trash && mv something _trash/

第四 -ls之前总是你的通配符rm- 在永远摧毁某物之前查看它并没有什么疯狂的。

  • +1 用于`ls`。 (3认同)
  • 我不明白 find 如何更简单或更安全,但我喜欢你的 `find 。-name '*~'` 示例。我的观点是,“ls”将列出“rm”将使用的相同 glob。 (2认同)

Dav*_*rtz 11

此问题的解决方案是定期备份。任何时候你生产的东西你不想冒失去的风险,备份它。如果您发现定期备份太痛苦,那么请简化该过程,使其不那么痛苦。

例如,如果您处理源代码,请使用诸如git镜像代码并将历史记录保存在另一台机器上的工具。如果您处理文档,请使用脚本将rsync您的文档传输到另一台机器。


Mad*_*ter 11

这是我的标准,专门针对 rm 上下文中的正则表达式,但在这种情况下它会救你。

我总是先做echo foo*/[0-9]*{bar,baz}*,看看正则表达式将匹配什么。获得输出后,我将返回命令行编辑并更改echorm -rf. 我从来没有rm -rf在未经测试的 regexp 上使用过

  • 这些你称之为“regexp”的东西实际上是 globs。这不是不同的正则表达式语法;它不是正则表达式。 (11认同)
  • 好的,我在找什么?您是否认为文件匹配的正则表达式语法与例如 perl 中使用的语法不同(有时以不同的名称调用)?或者我错过的其他一些点?我为我的缓慢思考道歉,这是周六早上的第一件事! (5认同)
  • 请比较:http://linuxmanpages.com/man3/regex.3.php http://linuxmanpages.com/man3/glob.3.php (3认同)
  • @MadHatter 另外,globbing 虽然在视觉上有些相似,但在语义上与正则表达式有很大不同。在正则表达式中,`*` 的含义有一个非常精确的定义,称为 [Kleene Star](http://en.wikipedia.org/wiki/Kleene_star),它是一个一元运算符,将集合中的零个或多个元素匹配到它被应用(在正则表达式的情况下,在 Kleene Star 之前的字符或字符集),而在 globbing 中,`*` 匹配后面模式中的任何内容。即使它们似乎具有相似的语法,它们在语义上也非常不同。 (2认同)

小智 7

似乎降低这种风险的最佳方法是像大多数 GUI 一样进行两阶段删除。也就是说,将 rm 替换为将内容移动到垃圾目录(在同一卷上)的内容。然后在足够的时间过去后清理垃圾以发现任何错误。

在 Unix StackExchange 上讨论了一个这样的实用程序,trash-cli,这里