【问题标题】:Configuring bash to prevent rm -rf * from being run without warning in ~/配置 bash 以防止 rm -rf * 在 ~/ 中无警告地运行
【发布时间】:2017-11-11 00:42:25
【问题描述】:

我正在运行最新的 Ubuntu Linux。

今天早上我运行了一个脚本,它做了很多事情。在做这些事情时,由于我还没有调查的原因,脚本回到了一个目录太多并做了一个 rm -rf * 在目录中 ~/ 显然不好;我花了 3 个小时来恢复和重新配置所有内容。

问题:.bashrc 中的函数是什么样子的 rm -rf ~/* 或者 rm -rf * while 在目录中 ~/

【问题讨论】:

  • 无论如何,已经有更全面的解决方案可用:使用支持快照的文件系统或块存储,这样您就可以查看您的文件,因为它们在之前的某个时间点存在。 btrfs 这样做,ZFS 这样做......哎呀,AFS 早在 90 年代就这样做了(以及之后的 OpenAFS)。
  • 顺便说一句,在未来,Unix & Linux 可能是解决此类问题的更好论坛,可以说更多的是关于交互式 shell 配置而不是软件开发。
  • 更改标准命令的默认界面时要小心。一旦管理员在我的所有用户配置文件中安装了alias rm=rm -i。有一天,我是 root 并想删除一些文件。我的 rm * 期望每个文件都得到确认,这是一个错误。
  • @Kes,我相信 Walter 的观点是,如果您基于只对自己的系统进行的自定义来养成习惯,那么您不想在使用时错误地做一些破坏性的事情。不同的机器/帐户,因为您养成的习惯不再适用。
  • @Kes,我是作为一个拥有数十年系统管理员经验的人发言(在转向更专注于开发的角色之前)——手指记忆依赖于机器本地定制是人们制作的一种方式错误,有时这些错误代价高昂。您可以随意忽略建议,但更容易避免亲身经历如此痛苦的经历。

标签: bash shell ubuntu


【解决方案1】:

您可以在您的PATH 中放置一个自定义rm 并使其调用/bin/rm,并将-i 作为最后一个选项强制放入其参数数组中,类似于(仅考虑POSIX 标志):

#!/bin/sh -eu
if [ "$PWD" != "$HOME" ]; then 
    exec /bin/rm "$@"
    exit 127
fi
opts=
while getopts 'fiRr' opt; do
    case $opt in [fiRr]) opts=$opts$opt;; *) exit 1;; esac
done; 
shift $((OPTIND-1))
/bin/rm -${opts}i "$@" < /dev/tty

【讨论】:

  • 这是否解决了问题的 only-in-$HOME 部分?
  • (它确实覆盖了我没有覆盖的东西,也就是说,通过确保 -i 出现在 last-f /i> 在选项中)。
  • @CharlesDuffy 谢谢。我在问题中错过了这一点。现已添加。
  • 非常有用,谢谢@PSkocik。你的编程技能远超我。你能围绕剧本说几句吗?今天我不太愿意执行任何我不完全理解的事情;否则我会在早上看它,因为它对我来说很有意义。现在是上午 130 点。
  • @Kes if 条件应该是明确的。 exec /bin/rm "$@" 将脚本的进程映像替换为 /bin/rm 的进程映像,如果此替换失败,则脚本将失败并返回 127(约定)。下一部分尝试解析 POSIX 标志 -f-i-R-r,将它们保存到 opts(不带连字符)中。 shift $((OPTIND-1)) 然后移动参数以便解析的标志移出。其余的在"$@"。然后将标志传递给 /bin/rm 并添加 i(以便它覆盖可能的 -f),然后是非标志参数。
【解决方案2】:

提示是防止这种情况发生的一种弱方法。每当您想删除某些内容而无需考虑太多时,很容易习惯于一直点击相同的响应。

最好实现一个可以从中恢复文件的垃圾箱。

您可以使用 mv 命令将 rm 别名为“垃圾箱”,您可以在其中安排 cron 作业以定期清理此垃圾箱。

也许别名 rm 类似于以下内容:

#!/usr/bin/env sh
mvargs=()
i=0
for arg in "$@"
do
    case "$arg" in

            -r|-R)
                shift;;

            -rf|-Rf |-R|-fr|-fR)
                mvargs[$i]="-f"
                ((++i))
                shift;;

            *)

                mvargs[$i]="$arg"
                ((++i))
                shift;;
    esac
done

mv "${mvargs[@]}" "/tmp/trashcan"

/tmp/trashcan 是一个可能的垃圾桶

【讨论】:

  • 我不是最擅长 bash 脚本,如果有人有任何关于如何更优雅地解析 -r 选项的 cmets,我愿意接受建议
  • 需要注意的是,这不会处理rm -- -r,它实际上会删除一个名为-r 的文件,而不是将字符串-r 作为选项处理。
  • 另外,mvargs+=( "$arg" ) 是一种更简单的附加到数组的方法(不需要维护计数器)。
猜你喜欢
  • 1970-01-01
  • 2011-02-28
  • 2021-04-09
  • 2017-09-06
  • 2013-01-10
  • 2017-09-17
  • 1970-01-01
  • 2013-07-31
  • 2012-05-13
相关资源
最近更新 更多