【问题标题】:Python: subprocess call with shell=False not workingPython:使用 shell=False 的子进程调用不起作用
【发布时间】:2014-10-17 09:51:18
【问题描述】:

我正在使用 Python 脚本来调用 Java 虚拟机。以下命令有效:

subprocess.call(["./rvm"], shell=False)  # works
subprocess.call(["./rvm xyz"], shell=True) # works

但是,

subprocess.call(["./rvm xyz"], shell=False) # not working

不起作用。 Python documentation 建议避免 shell=True

【问题讨论】:

    标签: python shell subprocess


    【解决方案1】:

    不要使用文件名目录,而是在其前面添加单词python,前提是您已将python 路径添加到环境变量中。如果您不确定,您可以随时重新运行 python 安装程序,只要您有新版本的 python。

    这就是我的意思:

    import subprocess
    subprocess.Popen('python "C:/Path/To/File/Here.py"')
    

    【讨论】:

      【解决方案2】:

      您需要将命令拆分为单独的字符串:

      subprocess.call(["./rvm", "xyz"], shell=False)
      

      shell=True 时可以使用字符串,但 shell=False 时需要 args 列表

      shlex 模块对更复杂的命令和处理输入更有用,但值得学习:

      import shlex
      
      cmd = "python  foo.py"
      subprocess.call(shlex.split(cmd), shell=False)
      

      shlex tut

      【讨论】:

      • 这个答案也解决了我的问题。您能否详细说明为什么“当 shell=True 时字符串可以工作,但当 shell=False 时您需要 args 列表”是?我听说shell=True 在有输入时非常危险,所以我试图避免它。
      • @Tommy,通常最好避免使用 shell=True,如果您完全控制正在运行的内容,但几乎所有可以使用的东西都可以使用它,这并不是世界末日shell=True 你可以用 shell=False 来做。当您至少在 unix 上传递 args 列表时,第一个 arg 是要执行的命令,其余的是该命令的 args,如果您使用 shell=True ,则必须完全按照传递命令的方式传递命令shell,shell=True 可以允许的示例docs.python.org/2/library/…
      • 我认为基于另一个布尔参数(Shell = True)改变一个参数的结构(这里是 arg 列表或命令)是一个奇怪的 API。这应该在子进程内部处理,以便无论shell如何,都可以传递相同的参数。
      【解决方案3】:

      如果你想使用shell=True,这是合法的,否则它会从标准库中删除。文档并没有说要避免它,它says

      执行包含来自不受信任来源的未经处理的输入的 shell 命令会使程序容易受到 shell 注入的攻击,这是一个严重的安全漏洞,可能导致任意命令执行。因此,在命令字符串由外部输入构造的情况下,强烈建议不要使用shell=True

      但在您的情况下,您不是从用户输入构造命令,您的命令是恒定的,因此您的代码不会出现 shell 注入 问题。您可以控制 shell 将执行的内容,如果您的代码本身不是恶意的,那么您是安全的。

      shell 注入示例

      为了解释为什么shell注入如此糟糕,这是documentation中使用的示例:

      >>> from subprocess import call
      >>> filename = input("What file would you like to display?\n")
      What file would you like to display?
      non_existent; rm -rf / #
      >>> call("cat " + filename, shell=True) # Uh-oh. This will end badly...
      

      编辑

      使用您提供的其他信息来编辑问题,请坚持Padraic 的答案。您应该仅在必要时使用shell=True

      【讨论】:

        【解决方案4】:

        除了 Enrico.bacis 的回答外,还有两种调用程序的方法。使用shell=True,给它一个完整的命令字符串。用shell=False,给它一个列表。

        如果您使用*.jpg2> /dev/null 之类的shell 技巧,请使用shell=True;但总的来说,我建议shell=False——正如 Enrico 所说,它更耐用。

        来源

        import subprocess
        subprocess.check_call(['/bin/echo', 'beer'], shell=False)
        subprocess.check_call('/bin/echo beer', shell=True)
        

        输出

        beer
        beer
        

        【讨论】:

          猜你喜欢
          • 2014-10-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-06-04
          • 2016-05-04
          • 2018-12-06
          • 2017-04-08
          相关资源
          最近更新 更多