我用子进程模块调用不同的进程。然而,我有一个问题。
在以下代码中:
callProcess = subprocess.Popen(['ls', '-l'], shell=True)
and
callProcess = subprocess.Popen(['ls', '-l']) # without shell
这两个工作。在阅读了文档之后,我知道shell=True意味着通过shell执行代码。也就是说,如果不存在,这个过程将直接启动。
那么对于我的情况,我应该选择什么呢?我需要运行一个进程并获得它的输出。从壳内或者壳外调用有什么好处呢?
不通过shell调用的好处是,您不会调用一个“神秘程序”。在POSIX上,环境变量SHELL控制作为“SHELL”调用的二进制文件。在Windows上,没有bourne shell的后代,只有cmd.exe。
因此调用shell调用用户选择的程序,并且依赖于平台。一般来说,避免通过shell调用。
通过shell调用确实允许您根据shell的通常机制展开环境变量和文件glob。在POSIX系统上,shell将文件glob扩展为一个文件列表。在Windows上,一个文件glob(例如,“*.*”)不会被shell扩展(但是命令行上的环境变量会被cmd.exe扩展)。
如果您想要环境变量扩展和文件glob,请研究1992-ish对通过shell执行子程序调用的网络服务的ILS攻击。示例包括涉及ILS的各种sendmail后门。
总之,使用shell=False。
不通过shell调用的好处是,您不会调用一个“神秘程序”。在POSIX上,环境变量SHELL控制作为“SHELL”调用的二进制文件。在Windows上,没有bourne shell的后代,只有cmd.exe。
因此调用shell调用用户选择的程序,并且依赖于平台。一般来说,避免通过shell调用。
通过shell调用确实允许您根据shell的通常机制展开环境变量和文件glob。在POSIX系统上,shell将文件glob扩展为一个文件列表。在Windows上,一个文件glob(例如,“*.*”)不会被shell扩展(但是命令行上的环境变量会被cmd.exe扩展)。
如果您想要环境变量扩展和文件glob,请研究1992-ish对通过shell执行子程序调用的网络服务的ILS攻击。示例包括涉及ILS的各种sendmail后门。
总之,使用shell=False。
上面的回答是正确的,但不够直接。
让我们使用ps命令看看会发生什么。
import time
import subprocess
s = subprocess.Popen(["sleep 100"], shell=True)
print("start")
print(s.pid)
time.sleep(5)
s.kill()
print("finish")
运行它,然后显示
start
832758
finish
你可以在完成前使用ps -auxf > 1,然后在完成后使用ps -auxf > 2。这是输出
1
cy 71209 0.0 0.0 9184 4580 pts/6 Ss Oct20 0:00 | \_ /bin/bash
cy 832757 0.2 0.0 13324 9600 pts/6 S+ 19:31 0:00 | | \_ python /home/cy/Desktop/test.py
cy 832758 0.0 0.0 2616 612 pts/6 S+ 19:31 0:00 | | \_ /bin/sh -c sleep 100
cy 832759 0.0 0.0 5448 532 pts/6 S+ 19:31 0:00 | | \_ sleep 100
看到了吗?而不是直接运行sleep 100。它实际上运行/bin/sh。它输出的pid实际上是/bin/sh的pid。如果你调用s.kill(),它会杀死/bin/sh,但sleep仍然存在。
2
cy 69369 0.0 0.0 533764 8160 ? Ssl Oct20 0:12 \_ /usr/libexec/xdg-desktop-portal
cy 69411 0.0 0.0 491652 14856 ? Ssl Oct20 0:04 \_ /usr/libexec/xdg-desktop-portal-gtk
cy 832646 0.0 0.0 5448 596 pts/6 S 19:30 0:00 \_ sleep 100
下一个问题是,/bin/sh能做什么?每个linux用户都知道它,听过它,并使用它。但我敢打赌,有很多人并不真正理解什么是壳。也许你也听说过/bin/bash,它们很相似。
shell的一个显著功能就是方便用户运行linux应用程序。由于sh或bash等shell程序,可以直接使用ls等命令,而不是/usr/bin/ls它将搜索ls的位置并为您运行它。
另一个函数是它将$后面的字符串解释为环境变量。您可以比较这两个python脚本来自己找出答案。
subprocess.call(["echo $PATH"], shell=True)
subprocess.call(["echo", "$PATH"])
最重要的是,它使linux命令可以以脚本的形式运行。如if else是由shell引入的。它不是原生的Linux命令