如何在 python 中设置代理值并运行 linux 命令

kma*_*ada 1 python linux shell proxy curl

在 Linux 中,要设置代理值,请执行以下操作。

proxy=http://$user:$password@proxy.server.com:${NUM}
http_proxy="$proxy" https_proxy="$proxy" ${COMMAND}
Run Code Online (Sandbox Code Playgroud)

出于安全原因,如果您在子 shell 中运行此命令,则不会明确将您的密码公开或记录在日志中。这种方法的问题是,每次我想运行命令时都必须设置用户名和密码。

因此决定为其编写一段python代码。我有一个 C 语言的工作版本。只是想了解更多 Python 知识。我找到了编码和解码密码的好方法,在经历了大部分的麻烦之后,我将其传递给这个函数来测试代理连接。

def test_connection(creds,proxy_url):
    import pycurl
    import cStringIO

    buf = cStringIO.StringIO()
    test_url="http://www.google.com"

    c = pycurl.Curl()
    c.setopt(c.URL, test_url)
    c.setopt(c.WRITEFUNCTION, buf.write)
    c.setopt(c.PROXY, proxy_url)
    c.setopt(c.PROXYPORT, 8080)
    c.setopt(c.PROXYTYPE, c.PROXYTYPE_HTTP) 
    c.setopt(c.PROXYAUTH, c.HTTPAUTH_NTLM) 
    c.setopt(c.PROXYUSERPWD, creds) 
    c.perform()
    buf.close()
    return c.getinfo(c.RESPONSE_CODE)
Run Code Online (Sandbox Code Playgroud)

我遇到问题的地方是使用 suprocess,我确实知道 subprocess 不允许您使用导出,因为它并不是真正的命令。Linux 上的 python 中的“导出”子进程模块错误?

这是我的实现

finalCommand = ["/bin/sh", "-c"]
finalCommand.append(http_proxy)
finalCommand.append(https_proxy)
for x in bashCommand:
    finalCommand.append(x)

print subprocess.call(finalCommand)
process = subprocess.Popen(finalCommand,stdout=subprocess.PIPE)


out, err = process.communicate()

print "Output ... \n %s" % (out)

if err == None: 
    print "No errors"
else: 
    print "Errors ... \n %s" %(err)
Run Code Online (Sandbox Code Playgroud)

不幸的是,经过多次测试,我的程序总是没有返回任何输出,也没有错误。我已经打印了curl 的输出,所以我知道解码、编码或代理不是问题。有什么建议么?

答案后编辑: Python 脚本和 linux shell 之间的交互

env 确实解决了我的问题,但我还必须参考上面的线程。我运行的一些命令是交互式命令,正如它在线程中很好地解释的那样,PIPE 无法与交互式程序正常工作。

aba*_*ert 5

如果不确切知道您要运行哪些命令,则很难确定,但我很确定您在这里要做的只是使用以下参数为子进程设置env环境Popen

env = dict(os.environ)
env['http_proxy'] = proxy
env['https_proxy'] = proxy
for command in commands:
    out = subprocess.check_output(command, env=env)
Run Code Online (Sandbox Code Playgroud)

如果您想修改自己的环境,而不仅仅是子流程的环境,只需os.environ就地修改即可。(请参阅文档了解特定于平台的问题以及如何处理这些问题。)


同时,您没有收到错误的原因很简单:

process = subprocess.Popen(finalCommand,stdout=subprocess.PIPE)
out, err = process.communicate()
Run Code Online (Sandbox Code Playgroud)

如果您不传递stderr=subprocess.PIPEPopen构造函数,它不会捕获 stderr,因此err最终为None.

附带说明一下,您几乎不想检查== None. 通常,仅仅if not err:就足够了。如果不是,则if err is not None:几乎总是需要的。必要但不充分的情况==极少。有关(稍微)更多详细信息,请参阅PEP 8 中的编程建议。

还有一个旁注:你可以只写finalCommand.extend(x). 该list.extend方法的作用与循环迭代并逐一解析每个元素相同append,只不过它更具可读性,更难出错,更简洁且更快。