我想在 python 脚本中获取 (zsh) shell 提示符。只需使用
import os
prompt = os.environ['PS1']
似乎不是正确的方法,因为PS1
通常不会转发到子流程。以同样的方式env | grep PS
在 shell 中失败。
所以我得出的结论是,我应该启动一个交互式 shell 作为子进程并查询它的提示符。从外壳我可以做
zsh -c -i 'echo $PS1'
(必须是单引号,双引号失败)
我尝试从 python(2.7) 中执行相同的操作,如下subprocess
所示:
print subprocess.check_output(['-i','-c',r"'echo $PS1'"],executable="/bin/zsh")
这失败了
subprocess.CalledProcessError: Command '['-i', '-c', "'echo $PS1'"]' returned non-zero exit status 127
我认为这不是因为,$PS1
而是由于我提供 echo-part 作为参数的方式,因为以这种方式回显裸字符串也会失败。
来回尝试各种组合我最终得到了
prompt = subprocess.check_output("""zsh -c -i 'echo $PS1'""",shell=True,executable="/bin/zsh")
这似乎完成了这项工作,但对我来说似乎是错误的,因为这是启动一个 shell,并在该 shell 中使用 调用另一个 shell -c -i 'echo $PS1'
。
获取 shell 提示符的正确方法是什么?
答案1
print subprocess.check_output(['zsh','-i','-c','echo $PS1'])
从另一个 shell运行时zsh
,周围的引号echo $PS1
是必需的,以便整个字符串作为 后的单个参数传递-c
。他们必须是单身的引号是因为在双引号中,第一个 shell 会展开$PS1
。
在 Python 中,整个命令是单个字符串,因此它像任何其他字符串一样被引用。添加第二组就像键入'echo $PS1'
(带引号)一样zsh
- shell 会查找名为 的可执行文件,但找不到'echo $PS1'
。
答案2
我认为正确的方法是调用子进程,如下所示:
>>> prompt = subprocess.check_output("""echo $PS1""",shell=True,executable="/bin/zsh")
然后你可以通过以下方式检查结果>>> prompt
Enter
,或者你可以使用 call 直接查看结果:
>>> subprocess.call("""echo $PS1""",shell=True,executable="/bin/zsh")
所以你不需要调用zsh
命令本身。
Popen
可以使用以下方式进行交互通信:
>>> Popen(["/bin/zsh"], stdout=PIPE).communicate()[0]
SHELL_PROMPT% echo $PS1
SHELL_PROMPT% exit # exit to see the result of command
有关此内容的更多信息,请参阅子流程
shell=True
另请注意有关使用上面链接的警告:
警告:执行包含来自不受信任来源的未经处理的输入的 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 does not suffer from this vulnerability; the above Note may be helpful in getting code using shell=False to work.