Python调用shell命令。什么类型的shell启动?

时间:2012-03-02 19:38:27

标签: python shell

我有以下python函数,它允许我从python脚本中运行shell命令:

import subprocess   

def run_shell_command(cmd,cwd=None):
      retVal = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, cwd=cwd);
      retVal = retVal.stdout.read().strip('\n');
      return(retVal);

这允许我做以下事情:

output = run_shell_command("echo 'Hello world'")

我的问题是:根据上面run_shell_command的定义,启动了哪种类型的shell? (例如login vs interactive)。

了解启动了哪个shell有助于了解在我的shell命令之前执行了哪些dot个文件(例如.bashrc.profile等。

3 个答案:

答案 0 :(得分:8)

POSIX上的/bin/sh。请参阅源代码subprocess.py(引用Python 2.7):

def _execute_child(self, args, executable, preexec_fn, close_fds,
                   cwd, env, universal_newlines,
                   startupinfo, creationflags, shell,
                   p2cread, p2cwrite,
                   c2pread, c2pwrite,
                   errread, errwrite):
    """Execute program (POSIX version)"""

    if isinstance(args, types.StringTypes):
        args = [args]
    else:
        args = list(args)

    if shell:
        args = ["/bin/sh", "-c"] + args
        if executable:
            args[0] = executable

    [...]

答案 1 :(得分:5)

运行什么shell?

Python subprocess documentation

中提到了这一点
  

可执行参数指定要执行的程序。它很少需要:通常,执行的程序由args参数定义。如果shell = True,则可执行参数指定要使用的shell。 在Unix上,默认shell为/bin/sh 。在Windows上,默认shell由COMSPEC环境变量指定。您需要在Windows上指定shell=True的唯一原因是您希望执行的命令实际内置于shell中,例如dir,copy。您不需要shell = True来运行批处理文件,也不需要运行基于控制台的可执行文件。

Linux / MacOSX上的

/bin/sh通常是bash(或bash兼容 - Debian使用短划线的新版本)的别名,而在像Solaris这样的Unix上,它可能是经典的Bourne Shell。

对于Windows,通常为cmdcommand.bat

是否通过popen登录shell?

我刚刚意识到我没有回答你的第二个问题 - 但设置shell=True会产生一个非登录shell(看看@AndiDog的源代码链接,shell分叉的方式会创建一个非登录shell)。


安全隐患

另请注意,使用shell=True,虽然它允许您使用shell基元和快捷方式,但可以also be a security risk,因此请务必检查可能用于进程生成的任何可能输入。

  

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

>>>
>>> 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...
  

shell=False禁用所有基于shell的功能,但不会受此漏洞影响;请参阅Popen构造函数文档中的注释,以获取有关获取shell = False的有用提示。

答案 2 :(得分:1)

它不是登录shell,所以你没有.login等。

如果由于任何原因你需要来初始化一个认为它是登录shell的shell,你需要自己执行shell(我相信这仍然是如何完成的)改变argv [0]的第一个字符,它看起来是一个“ - ”。