V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
爱意满满的作品展示区。
discrete
V2EX  ›  分享创造

GitLab 的惨剧让我造了个防 rm 的轮子: rm-protection

  •  
  •   discrete · 2017-02-03 22:11:49 +08:00 · 6473 次点击
    这是一个创建于 2637 天前的主题,其中的信息可能已经有所发展或是发生改变。

    rm-protection logo

    rm-protection

    PyPi Downloads PyPiversion Wheel python version

    GitLab 的惨剧想必大家都知道了:rm -rf了生产服务器上的数据库。常在河边走,哪能不湿鞋。即便是再认真,总是有失误的风险。

    现在网上已经流行了数种方法: rm -i , trash-cli 等等。rm -i 显然并不实用:想必没人能忍受每个文件都被问一次?况且就 GitLab 的情况,rm -i并不能起保护作用。trash-cli相当于启用了回收站,但是这又会带来一些小麻烦(比如在磁盘被 log 挤爆的情况下)。

    rm-protection 则采取了一种全新的思路:由用户自行设置一个安全问题来保护文件,在删除时询问相应的问题。想象一下,若 YP 在执行删除时突然被问一句:「 Which server are you on? 」,还会出现这样的惨剧吗?

    快速开始

    rm-protection 几乎完全兼容rm,因此可以作为 alias 使用。

    1. 从 PyPi 中安装并为 rm-p 创建 alias 。

      pip install rm-protection & alias rm="rm-p"

    2. 使用 protect 命令保护你想要保护的文件或者文件夹。

    3. Happy rm-ing!

    原理

    rm-protection 获取 arguments 后,会逐一检测是否存在 .<filename>.rm-protection 文件。若存在,则询问用户,否则将不再传递这个 argument 。安全的 argument 将被传递给 rm 进行删除。

    栗子:

    Basic usage

    它也能保护批量的递归删除:

    Recursive protection

    与其他工具的对比

    参见 GitHub 中的表格

    未来?

    若是这个工具能被推广使用,团队协作之间可以大有功用。在软件、文件分发时,分发者可以提前保护文件防止误删。在开发和部署时也可提前保护文件,防止在生产环境中的误删。

    贡献

    Github 欢迎 PR, 提 Issue 或者 Star :)

    第 1 条附言  ·  2017-02-04 09:28:24 +08:00

    FAQ

    使用栗子?

    rm -rf database
    「你删的是啥数据库」 
    「测试」 
    「滚!」
    

    简单问题复杂化?

    在特定的场合复杂化我觉得是有益的,比如 GitHub 会在你删除 repo 的时候让你确认 repo 的名字。 事实上 rm-protection 并不影响日常操作。只有当遇到你特定保护的文件时才会提示并提供尽可能的保护。

    rm -i 或者 alias rm="mv" 又或者 trash,下一题?

    每个文件都问,你受得了(当然取决于个人了,我是受不了)?那么你听说过「狼来了」的故事吗?yes | rm -i trash 类的方案并不能从源头上解决问题,当你想释放空间的时候,很容易随手就清空了垃圾桶。

    已经有 XXX 了,好处在哪?

    就我所知除了 Safe-rm 之外,没有类似机制的轮子出现。你也可以看看这里与其他机制的对比:https://github.com/alanzchen/rm-protection/blob/master/README.md#comparison-with-alternative-methods

    我去 Python 3? 你搞笑?

    嘛确实不太合适(逃。其实我完全不 care 到底有没有人用我的 implementation,唯一想做的是向社区提供这么一个机制的提案。

    若是社区能接受,这轮子很快可以被移植到任何语言或者任何平台,甚至被包括在 GNU coreutils 里。唯一需要统一的是,是否能够接受 .rm-protection 这样的保护机制。

    36 条回复    2017-02-05 14:59:28 +08:00
    qiuai
        1
    qiuai  
       2017-02-03 22:26:59 +08:00
    如果是为了服务器多的情况下准备的,为什么不直接设置问题为服务器的名字.
    比如提前在文件中定义服务器的名字为 Prod-1
    那么删除的时候要输入 Prod-1.如果要删除 2.那么不会去输入-1 吧?
    如果输入了-2..那就可以直接拒绝了嘛...

    弄一个问题上去,好像有点复杂?
    jingniao
        2
    jingniao  
       2017-02-03 22:40:03 +08:00 via Android
    其实我觉得如果给 rm 添加个功能,读取配置文件避开
    jingniao
        3
    jingniao  
       2017-02-03 22:40:37 +08:00 via Android
    重要文件,如果要删除,加个参数
    discrete
        4
    discrete  
    OP
       2017-02-03 22:40:38 +08:00
    @qiuai 你确实可以设置为问服务器的名字呀。问题和答案都是用户在保护文件时设定的。在 Prod-1 上你的回答应该是 Prod-1 ,在 Prod-2 上应该是 Prod-2 。

    与丢失重要文件的相比,我觉得问一个问题的时间挺值的。
    discrete
        5
    discrete  
    OP
       2017-02-03 22:42:43 +08:00
    @jingniao 这个轮子已经有了,叫 Safe-rm 。相比之下我觉得 rm-protection 的方式更加灵活一点。假定你不问问题的话,加个参数还不是顺手事情?(想象一下 YP 的状况。
    Akagi201
        6
    Akagi201  
       2017-02-03 22:44:20 +08:00
    建议用 bash 重写, 不依赖任何环境.
    discrete
        7
    discrete  
    OP
       2017-02-03 22:55:09 +08:00
    @Akagi201 这种轻量级的程序确实应该用 bash 写……不过现在哪台机器上没个 python 呢
    不过当然欢迎各种语言的 implementation 。只要 .rm-protection 这个格式互相能兼容就行。
    snnn
        8
    snnn  
       2017-02-03 22:55:12 +08:00 via Android
    然后硬盘爆了,数据库写入失败,挂掉了
    xuboying
        9
    xuboying  
       2017-02-03 23:46:39 +08:00
    300G 的数据复制一下,也没多久时间,关键还是要做好备份啊
    rm 再小心还是会有错误的时候。
    问题的关键点还是备份做的不好啊
    Doubear
        10
    Doubear  
       2017-02-04 01:40:22 +08:00   ❤️ 1
    which server are you on?

    ???

    [我不是在测试环境么???]

    > dev server

    ……

    [卧槽哪来那么多文件?!!糟糕这尼玛不是测试服……]

    《 MySQL 从删库到跑路》
    chuhades
        11
    chuhades  
       2017-02-04 02:02:42 +08:00
    ➜ ~ grep trash .zshrc
    alias trash='gvfs-trash'
    cuebyte
        12
    cuebyte  
       2017-02-04 02:16:42 +08:00
    @discrete 你好意思……你的是 python3
    yangqi
        13
    yangqi  
       2017-02-04 02:19:41 +08:00
    你这个显然解决不了类似这次 gitlab 的问题。人家不是误删文件,而且误以为自己在 slave 机器上,结果是在主机上。

    即使有了各种确认也没用
    em70
        14
    em70  
       2017-02-04 02:24:39 +08:00
    @yangqi 我觉得楼主的方案可以解决,因为会问你当前操作机器的名字,你以为在 slave,输入就是错的,不执行
    yangqi
        15
    yangqi  
       2017-02-04 02:40:42 +08:00
    @em70 那要看问题是什么了,如果你问了机器名字,下次我文件夹搞错了,误以为在别的文件夹咋办
    cxbig
        16
    cxbig  
       2017-02-04 03:32:54 +08:00
    我们家是在 PS1 上直接加机器代号, admin 、 backend 、 frontend-1~x 。根本不会弄混。
    WildCat
        17
    WildCat  
       2017-02-04 04:13:45 +08:00
    SharkIng
        18
    SharkIng  
       2017-02-04 06:53:29 +08:00
    显然这个也不能完全解决问题, Gitlab 的情况是程序员太累,以为自己在 db2 结果实际是 db1. 即使有这么个问题也有可能因为太累输错之类的。
    eccstartup
        19
    eccstartup  
       2017-02-04 06:56:26 +08:00
    叫 `rm-gitlab` (逃
    deamwork
        20
    deamwork  
       2017-02-04 07:42:55 +08:00 via Android
    loading
        21
    loading  
       2017-02-04 07:45:01 +08:00 via Android
    简单问题复杂化,大师级!
    discrete
        22
    discrete  
    OP
       2017-02-04 07:50:35 +08:00 via iPhone
    @SharkIng 当你必须输入 I'm going to delete production database 的时候难道还不会心里一惊 2333

    当然了不可能所谓完全解决问题,只是试图以最小的日常影响(比如与 rm -i 相比)做到最大的保护。
    ayayui
        23
    ayayui  
       2017-02-04 08:46:30 +08:00
    rm 列出要删除的文件,确认后才删除。
    phrack
        24
    phrack  
       2017-02-04 08:54:22 +08:00 via Android
    也许允许人犯一些错误更好,不然世界就少了乐趣和故事了。
    discrete
        25
    discrete  
    OP
       2017-02-04 09:06:27 +08:00
    @loading 在特定的场合复杂化我觉得是有益的,比如 GitHub 会在你删除 repo 的时候让你确认 repo 的名字。

    这个工具同理,不会影响你 rm 的日常操作,但是在删除极其重要的文件时提供尽可能的保护。
    discrete
        26
    discrete  
    OP
       2017-02-04 09:07:56 +08:00
    @cuebyte 嘛确实……(捂脸逃(其实当时不用 python2 只是因为 raw_input() 的问题,加个判断就兼容了。
    discrete
        27
    discrete  
    OP
       2017-02-04 09:09:09 +08:00
    @yangqi 所以最终还是要问对的问题,比如:
    「你删的是啥数据库」
    「测试」
    「滚!」
    lanxyou
        28
    lanxyou  
       2017-02-04 09:15:14 +08:00
    批量删除的时候会不会把保护文件先删除了?
    discrete
        29
    discrete  
    OP
       2017-02-04 09:16:43 +08:00
    @lanxyou 不会,会提前检索保护文件。
    gfexfizv
        30
    gfexfizv  
       2017-02-04 09:19:14 +08:00 via Android
    可以 alias rm 为 move ,移动到一个垃圾文件夹里面
    harry890829
        31
    harry890829  
       2017-02-04 09:21:09 +08:00
    用 alias 重定义 rm 啊,改为 move ,然后丢到垃圾文件夹,定期清理垃圾文件夹就好了
    finian
        32
    finian  
       2017-02-04 10:03:45 +08:00   ❤️ 1
    稍微有点复杂了,不如 trash 的方案来得简单。不过这些方案都无法彻底避免杯具,人和流程都是不可靠的,唯有使用自动化工具才能最大程度地避免失误
    sox
        33
    sox  
       2017-02-04 11:11:35 +08:00 via Android
    npm i -g trash-cli
    alias rm=“ trash ”
    discrete
        34
    discrete  
    OP
       2017-02-04 11:56:23 +08:00
    @finian
    @sox
    @gfexfizv

    trash 类方案确实是我之前见过最好的。
    但是 GitLab 让我想起了另外的情况:想象一下空间被 spam 挤爆(类似 GitLab ),大概是清空垃圾箱之后才 Oh shit 吧。在图形界面里,还不是有误删垃圾桶的情况发生?
    qianguozheng
        35
    qianguozheng  
       2017-02-05 14:39:16 +08:00
    例子中的 gif 图片用什么工具获得的?
    discrete
        36
    discrete  
    OP
       2017-02-05 14:59:28 +08:00 via iPhone
    @qianguozheng macOS 自带 QuickTime 录屏,然后 Google 里随便找了一个在线的视频转 gif 工具。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   5226 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 09:25 · PVG 17:25 · LAX 02:25 · JFK 05:25
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.