【问题标题】:Bash - Hiding command (preventing from bad manipulations)Bash - 隐藏命令(防止不良操作)
【发布时间】:2010-08-18 10:51:39
【问题描述】:

我想知道它们是否是一种防止某些命令被执行的方法,以防止有时出现错误的操作(例如,当你想执行“rm *.py”时,你执行“ rm *.pyc" 或类似的东西)。

人们会说检查他的输入是用户的责任,这是正确的,但无论如何我想知道是否有办法。

对于“基本”的东西,我们可以在 bashrc 中使用别名,例如:

alias apt-get="echo 'We use aptitude here !'"
alias sl="echo 'Did you mean ls ?'"

但是对于像“rm -f *.py”(或“rm -Rf /”)这样的参数,这个简单的技巧不起作用。 当然,我只想要一个防止执行确切命令的基本方法(相同的空格和相同的参数排序将是一个好的开始)。

非常感谢您的回答。

【问题讨论】:

  • 请注意,扩展这些通配符的是外壳程序,因此您的程序或函数永远不会真正看到 *.py。它所看到的只是 globbing *.py 的结果,即匹配该模式的文件列表。 (如果没有,则为文字*.py,如果shopt -s nullglob,则为空字符串。)
  • 依赖同名替换来代替rm 是个坏主意。所需要的只是让它不可用一次,然后 Bam!你的文件不见了,因为没有安全网。如果您想使用网络,您应该使用不同的名称(例如“saferm”)。
  • @Dennis Williamson :是的,您是对的,使用不同的名称可能更好,但实际上并非出于您的原因(至少如果您像原始命令一样使用“rm”命令(不直接利用诸如“rm * 不会删除我的源代码,所以我可以随时使用它”))。但问题可能更多的是 Makefile 或安装不知道您的“rm”不是标准脚本的脚本,并且您可能会产生巨大的副作用......
  • 我的意思是,例如,如果你做alias rm=rm -i,然后做rm *,想着“有什么害处——它会先问我”,然后你就开始依赖那个安全网——有一天,别名将不存在,您将没有机会说“Y”或“N”,一切都会消失。
  • 问题是问题,答案是答案。请您将您的解决方案放在自己的答案中,而不是在问题中。

标签: shell configuration bash


【解决方案1】:

好吧,您可以使用历史悠久的方法,将您自己的路径组件之一放在所有其他组件的前面:

PATH=~/safebin:$PATH

然后,在~/safebin 中,您放置“更安全”的脚本,例如rm:

#!/bin/bash

for fspec in "$@" ; do
    if [[ "${fspec: -3}" = ".py" ]] ; then
        echo Not removing ${fspec}, use /bin/rm if you really want to.
    else
        echo Would /bin/rm "${fspec}" but for paranoia.
    fi
done

该脚本为rm * 输出:

Would /bin/rm chk.sh but for paranoia.
Would /bin/rm go but for paranoia.
Would /bin/rm go.sh but for paranoia.
Would /bin/rm images but for paranoia.
Would /bin/rm images_renamed but for paranoia.
Would /bin/rm infile.txt but for paranoia.
Would /bin/rm jonesforth.S but for paranoia.
Would /bin/rm jonesforth.f but for paranoia.
Would /bin/rm mycode.f but for paranoia.
Would /bin/rm num1.txt but for paranoia.
Would /bin/rm num2 but for paranoia.
Would /bin/rm num2.txt but for paranoia.
Would /bin/rm proc.pl but for paranoia.
Would /bin/rm qq but for paranoia.
Would /bin/rm qq.c but for paranoia.
Would /bin/rm qq.cpp but for paranoia.
Would /bin/rm qq.in but for paranoia.
Not removing qq.py, use /bin/rm if you really want to.
Would /bin/rm qq.rb but for paranoia.
Would /bin/rm qq.s but for paranoia.
Would /bin/rm qq1 but for paranoia.
Would /bin/rm qq2 but for paranoia.
Would /bin/rm qqq but for paranoia.
Would /bin/rm rm but for paranoia.
Would /bin/rm source.f90 but for paranoia.
Would /bin/rm test.txt but for paranoia.
Would /bin/rm xx but for paranoia.
Not removing xx.py, use /bin/rm if you really want to.

现在显然"${fspec: -3}" = ".py" 是一个简单的和一个黑名单。我可能更希望有一个允许我删除并拒绝其他所有内容的白名单。


还有一个基于正则表达式的白名单版本:

#!/bin/bash

for fspec in "$@" ; do
    del=0
    if [[ ! -z "$(echo "${fspec}" | grep 'a.e')" ]] ; then
        del=1
    fi
    if [[ ! -z "$(echo "${fspec}" | grep '\.[Ss]$')" ]] ; then
        del=1
    fi

    if [[ ${del} -ne 1 ]] ; then
        echo "Not removing ${fspec}, use /bin/rm if you want."
    else
        echo "    Removing ${fspec}"
        #/bin/rm "${fspec}
    fi
done

哪个输出:

Not removing chk.sh, use /bin/rm if you want.
Not removing go, use /bin/rm if you want.
Not removing go.sh, use /bin/rm if you want.
    Removing images
    Removing images_renamed
Not removing infile.txt, use /bin/rm if you want.
    Removing jonesforth.S
Not removing jonesforth.f, use /bin/rm if you want.
Not removing mycode.f, use /bin/rm if you want.
Not removing num1.txt, use /bin/rm if you want.
Not removing num2, use /bin/rm if you want.
Not removing num2.txt, use /bin/rm if you want.
Not removing proc.pl, use /bin/rm if you want.
Not removing qq, use /bin/rm if you want.
Not removing qq.c, use /bin/rm if you want.
Not removing qq.cpp, use /bin/rm if you want.
Not removing qq.in, use /bin/rm if you want.
Not removing qq.py, use /bin/rm if you want.
Not removing qq.rb, use /bin/rm if you want.
    Removing qq.s
Not removing qq1, use /bin/rm if you want.
Not removing qq2, use /bin/rm if you want.
Not removing qqq, use /bin/rm if you want.
Not removing rm, use /bin/rm if you want.
Not removing source.f90, use /bin/rm if you want.
Not removing test.txt, use /bin/rm if you want.
Not removing xx, use /bin/rm if you want.
Not removing xx.py, use /bin/rm if you want.

【讨论】:

  • 感谢您的回答。毕竟这可能是最好的解决方案!我可能会考虑在 python 中编写一些脚本以获得更高的可读性(如果我松开 python,直接使用 /bin/rm)但是你的 bash 脚本似乎做得很好!
【解决方案2】:

你可能想看看这个http://code.google.com/p/safe-rm/

【讨论】:

    【解决方案3】:

    您也可以使用鲜为人知的命令“command”(类似于“内置”命令)来创建限制性 rm 包装器:

    help builtin command | less
    
    # test example using ls instead of rm
    function ls() {
       for ((i=1; i<=$#; i++ )); do
          arg="${@:i:1}"
          echo "arg ${i}: ${arg}"
          [[ "${arg}" == \*.py ]] && { echo "Not allowed: ${arg}"; return 1; }
       done
       command ls "${@}"
       return 0
    }
    
    ls -a
    
    ls -a *.py
    

    【讨论】:

    • 您可能需要使用builtin command ls "${@}",以防命令被别名或被函数覆盖
    【解决方案4】:

    更正我的 ls 函数示例:

    [[ "${arg}" != \*.py ]] && [[ "${arg}" == *.py ]] && \
       { echo "Not allowed: ${arg}"; return 1; }
    

    然后:

    ls -a *.py
    
    # ... and also play with modified shell wildcard expansion behaviour ...
    ( shopt -s nullglob; ls -a *.py )
    

    【讨论】:

      【解决方案5】:

      ThR37 说:

      这是一个简短的 python 脚本,它基于简单地包装命令,如“rm”。 Bash 包装器可能是一个更好的主意,但我喜欢 python :) :

      #!/usr/bin/python
      # coding=UTF-8
      
      import getopt, sys
      import subprocess
      import re
      
      exprs=[]
      exprs.append(re.compile(".*\.py$"));
      exprs.append(re.compile(".*\.cpp$"));
      exprs.append(re.compile(".*\.hpp$"));
      exprs.append(re.compile("\*$"));
      
      
      def main():
              try:
                  opts, args = getopt.getopt(sys.argv[1:], "Rrfiv", ["interactive","no-preserve-root","preserve-root","recursive","verbose","help","version"])
              except getopt.GetoptError, err:
                  # print help information and exit:
                  print str(err)
                  usage()
              optsString = "".join([opt[0]+opt[1]+" " for opt in opts]);
              for arg in args:
                  tab = [expr.match(arg) for expr in exprs];
                  if  tab.count(None)!=len(tab):
                       print "Not removing "+str(arg);
                  else
                      cmd = ["/bin/rm"]+[opt[i] for opt in opts for i in range(2) if not opt[i]=='']+[str(arg)];
                      rmfile = subprocess.Popen(cmd)
      
      if __name__=="__main__":
          main();
      

      【讨论】:

        猜你喜欢
        • 2015-05-14
        • 2013-08-06
        • 2020-06-09
        • 1970-01-01
        • 2015-06-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多