dkv*_*dkv 10 python linux bash shell subprocess
我正在使用Python的subprocess模块调用一些Linux命令行函数.文档解释了这个shell=True论点
如果是shell
True,则将通过shell执行指定的命令
有两个例子,从描述性的角度来看对我来说是相同的(即它们都调用了一些命令行命令),但是其中一个使用shell=True而另一个没有
>>> subprocess.call(["ls", "-l"])
0
>>> subprocess.call("exit 1", shell=True)
1
Run Code Online (Sandbox Code Playgroud)
我的问题是:
shell=Falsedo做什么运行命令shell=True?subprocess.call,check_call并且check_output所有人都必须通过shell执行参数.换句话说,它怎么可能不通过shell执行参数?得到一些例子也很有帮助:
shell=True可以完成的事情
shell=False以及为什么无法完成.shell=True或False为什么不要紧Cha*_*ffy 15
UNIX程序通过以下三个调用或其衍生物/等价物相互启动:
fork() - 创建自己的新副本.exec() - 用不同的程序替换自己(如果你是副本,请这样做!).wait() - 等待另一个进程完成(可选,如果没有在后台运行).因此,shell=False你做到这一点(如Python的语法如下的伪代码-排除wait()如果不是阻塞调用如subprocess.call()):
pid = fork()
if pid == 0: # we're the child process, not the parent
execlp("ls", "ls", "-l", NUL);
else:
retval = wait(pid) # we're the parent; wait for the child to exit & get its exit status
Run Code Online (Sandbox Code Playgroud)
而shell=True你用,你这样做:
pid = fork()
if pid == 0:
execlp("sh", "sh", "-c", "ls -l", NUL);
else:
retval = wait(pid)
Run Code Online (Sandbox Code Playgroud)
请注意,shell=False我们执行的命令是ls,而shell=True我们执行的命令是sh.
也就是说:
subprocess.Popen(foo, shell=True)
Run Code Online (Sandbox Code Playgroud)
与以下内容完全相同:
subprocess.Popen(
["sh", "-c"] + ([foo] if isinstance(foo, basestring) else foo),
shell=False)
Run Code Online (Sandbox Code Playgroud)
也就是说,您执行一个副本/bin/sh,并指示该副本/bin/sh将字符串解析为参数列表并执行ls -l自身.
那么,为什么会使用shell=True?
你正在调用一个内置的shell.
例如,该exit命令实际上是shell本身的一部分,而不是外部命令.也就是说,这是一组相当小的命令,并且它们很少在shell实例的上下文中有用,该实例仅在单个subprocess.call()调用期间存在.
你有一些shell构造(即重定向)的代码,没有它就很难模拟.
例如,如果您的命令是cat one two >three,则语法>three是重定向:它不是参数cat,而是stdout=open('three', 'w')在运行命令时设置shell 的指令['cat', 'one', 'two'].如果您不想自己处理重定向和管道,则需要shell来执行此操作.
一个稍微棘手的案例是cat foo bar | baz.要在没有shell的情况下执行此操作,您需要自己启动管道的两侧:p1 = Popen(['cat', 'foo', 'bar'], stdout=PIPE), p2=Popen(['baz'], stdin=p1.stdout).
你不会对安全漏洞发表任何看法.
......好吧,这是一个稍微有点过于强烈,但不是很大.使用shell=True是危险的.你不能这样做:Popen('cat -- %s' % (filename,), shell=True)没有shell注入漏洞:如果你的代码曾被一个filename包含调用$(rm -rf ~),那你将度过一个非常糟糕的一天.另一方面,['cat', '--', filename]对所有可能的文件名都是安全的:文件名纯粹是数据,不是由shell或其他任何东西解析为源代码.
这是可能的壳编写脚本的安全,但你必须要小心了.考虑以下:
filenames = ['file1', 'file2'] # these can be user-provided
subprocess.Popen(['cat -- "$@" | baz', '_'] + filenames, shell=True)
Run Code Online (Sandbox Code Playgroud)
该代码是安全的(以及-为让用户阅读他们想要的任何文件作为安全永远是),因为它是通过你的文件名外的带外脚本代码-但它是安全的,只是因为该字符串被传递到shell是固定和硬编码的,参数化内容是外部变量(filenames列表).即便如此,它只是在某一点上是"安全的" - 像Shellshock这样的bug 会在shell初始化时触发它会像其他任何东西一样影响它.
| 归档时间: |
|
| 查看次数: |
3534 次 |
| 最近记录: |