首页 > 解决方案 > 程序可以检测它是否是通过 shell 启动的吗?

问题描述

如果设置为,该ls命令会给我一个不同的标准输出。这是为什么 ?shelltrue

是否有一个基本概念允许程序(ls在这种情况下)检测它是否通过 shell 启动?

我注意到两者在 Windowsp1p2共享相同的标准输出,但在 Linux 上却没有。

import subprocess

cmd = ['ls', '-la']
# Using shell
p1 = subprocess.run(executable=cmd[0], args=cmd[1:], shell=True, text=True, capture_output=True)
# Without using shell
p2 = subprocess.run(executable=cmd[0], args=cmd[1:], shell=False, text=True, capture_output=True)

print(p1.stdout)
print(p2.stdout)

Linux 上的输出

total 12
drwxr-xr-x  2 root root 4096 Feb 20 18:25 .
drwx------ 10 root root 4096 Feb 20 18:51 ..
-rw-r--r--  1 root root  269 Feb 20 18:57 test.py

test.py

标签: pythonpython-3.xshellsubprocess

解决方案


Python 文档很模糊,但行为无法从strace.

你的 Python 代码:

cmd = ['ls', '-la']
p1 = subprocess.run(executable=cmd[0], args=cmd[1:], shell=True, text=True, capture_output=True)
p2 = subprocess.run(executable=cmd[0], args=cmd[1:], shell=False, text=True, capture_output=True)

变成(strace -f -e execve python3 foo.py):

[pid 143557] execve("/bin/ls", ["ls", "-c", "-la"], 0x7fffc1235340 /* 34 vars */) = 0
[pid 143558] execve("/bin/ls", ["-la"], 0x7fffc1235340 /* 34 vars */) = 0

这相当于运行这些 shell 命令,即使两者都是从 shell 执行的,您也可以确认它们会给出相同的结果。

ls -c -la           # Generally equivalent to: ls -lca
( exec -a -la ls )  # Generally equivalent to: ls

由此我们可以推断出行为。

如果shell=Trueexecutable则调用 。参数列表是executable,后跟 shell 标准-c标志,然后是args. 这在 的情况下更有意义executable='bash', args=['ls -la']

如果shell=False,则调用可执行文件。参数列表是args。这模仿execve.

所以基本上没有,这里没有检测。这只是对 的两种不同调用ls,也不是您想要的。


推荐阅读