首页 > 解决方案 > Python check_output 调用 eval(带参数)失败

问题描述

我正在使用check_output我的所有 SSH 和 GitHub 设置,并且我正在尝试执行eval $(ssh-agent),以启动代理并在我需要进程 ID 时解析输出。

from subprocess import check_output

out = check_output(["eval", "$(ssh-agent)"])
print(out)

但无论我如何逃避事情,我都会得到同样的错误。

Traceback (most recent call last):
  File "gitSetup.py", line 3, in <module>
    out = check_output(["eval", "$(ssh-agent)"])
  File "/usr/lib/python2.7/subprocess.py", line 216, in check_output
    process = Popen(stdout=PIPE, *popenargs, **kwargs)
  File "/usr/lib/python2.7/subprocess.py", line 394, in __init__
    errread, errwrite)
  File "/usr/lib/python2.7/subprocess.py", line 1047, in _execute_child
    raise child_exception
OSError: [Errno 2] No such file or directory

我想知道我是否没有正确地逃避或修剪我的论点;如果有人看到我的错误,我将不胜感激!

标签: pythonsubprocess

解决方案


即使您设法解决了表面的语法问题,一个成功运行的子进程也会在没有任何痕迹的情况下终止;它不会尝试(也不能,即使它想要)修改父 Python 进程的环境。这是一个常见的常见问题解答。

您可以eval在启动 Python 脚本的父进程中运行,或者可能弄清楚如何ssh-agent直接从 Python 进行通信。它的输出通常是一个简单的变量赋值序列,你可以自己解析。

from subprocess import check_output
from os import environ

eval_string = check_output(['ssh-agent'])
for line in eval_string.rstrip('\n').split('\n'):
    for expr in line.rstrip(';').split(';'):
        if expr.startswith((' export ', 'echo ')):
            continue
        var, value = expr.strip().split('=', 1)
        environ[var] = value

如果输出ssh-agent包含 shell 引用,您将需要对其执行额外的解析(基本上,修剪值字符串周围的引号)。但这已经相当笨重和脆弱,所以也许可以在启动 Python 之前恢复设置环境,而不是试图在这个杂物上添加一些复杂性。

更详细地说,ssh-agent其他一些宝贵的 shell 实用程序具有非常具体的设计,以便它们能够与其父进程通信。正是因为子进程无法对其父进程的环境进行任何更改,所以它改为打印一段代码供其父进程执行。默认情况下,它会打印sh如下代码:

SSH_AUTH_SOCK=/tmp/ssh-MUyniqn10506/agent.10506; export SSH_AUTH_SOCK;
SSH_AGENT_PID=10507; export SSH_AGENT_PID;
echo Agent pid 10507;

还有一个选项可以在csh语法中打印类似的代码(这是一个历史性的 shell,谢天谢地不再使用),但是,唉,没有生成 Python 代码的选项。(本身并不难ssh-agent做到这一点。)

(上面的输出示例复制/粘贴自http://blog.joncairns.com/2013/12/understanding-ssh-agent-and-ssh-add/其中包含更完整的解释。)


推荐阅读