2014-07-23 139 views
0

在linux中设置代理值的操作如下。如何设置代理值并在python中运行linux命令

proxy=http://$user:[email protected]:${NUM} 
http_proxy="$proxy" https_proxy="$proxy" ${COMMAND} 

出于安全原因,如果在子shell中运行此操作,则不会明确地让您的密码处于打开状态或日志中。这种方法的问题是,每次我想运行一个命令时,我都必须设置用户名和密码。

因此决定为它编写一个python代码。我有一个工作在C版本。只是想了解更多的Python。我找到了很好的方法来编码和解码我的密码,并且在大部分的hooplahs之后,我将它传递给这个函数来测试代理连接。

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) 

当我在使用suprocess的问题,我也明白,子进程不允许使用出口,因为它是不是一个真正的命令。 Subprocess module errors with 'export' in python on linux?

这是我实现

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) 

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

POST-答案编辑: Interaction between Python script and linux shell

ENV没有解决我的问题,但我也不得不参照纱线之上。我运行的一些命令是交互式的,因为它在线程中解释得很好,PIPE在交互式程序中无法正常工作。

+0

你只是在寻找['Popen']的'env'参数(https://docs.python.org/2/library/subprocess.html#subprocess.Popen)?或者你真的试图启动一个shell并直接在脚本中运行脚本而不是在子shell中,或者其他什么奇怪的东西? – abarnert

+0

同时,请给我们一个[MCVE](http://stackoverflow.com/help/mcve) - 特别是,请注意“完整”部分。不知道'http_proxy','https_proxy'和'bashCommand'中的内容,很难调试可能出错的东西。 (另外,是否有一个原因是你首先在命令中执行'call',然后用完全相同的命令创建一个'Popen'并调用''communicals'? – abarnert

+0

这并不是说“PIPE doesn' t可以在交互式程序中正常工作“(尽管在Python 3.2之前就是这样,你可能没有遇到过这种情况,如果是的话,可以安装'subprocess32' backport来解决这个问题),这就是一些交互式程序需要你改变缓冲区和其他人根本不和stdin交谈(例如,他们正在读密码而没有回应它,需要一个真正的tty,或者他们只是要求libpam为他们这样做,等等),所以管道到stdin不会没有任何好处。而且编写代码来交互式地通过管道进行交流而不会阻塞是很困难的。 – abarnert

回答

1

很难确定不知道你想要运行什么命令,但是我很确定你想在这里做什么只是为你的子进程设置环境,使用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) 

如果你想修改自己的环境,而不仅仅是子流程的环境中,只需修改os.environ到位。 (请参阅文档特定于平台的问题,以及如何处理它们。)


同时,你得到任何错误的原因很简单:

process = subprocess.Popen(finalCommand,stdout=subprocess.PIPE) 
out, err = process.communicate() 

如果你不这样做将stderr=subprocess.PIPE传递给Popen构造函数,它不捕获stderr,因此err最终为None

作为便笺,您几乎从不想检查== None。通常,只需if not err:就足够了。当它不是,几乎总是需要if err is not None:==是必要的,但不是不足的情况是非常小的。请参阅PEP 8中的Programming Recommendations了解更多细节。

还有一个方面说明:你可以写finalCommand.extend(x)list.extend方法与遍历迭代器和逐个元素循环相同,除了它更易读,更难以得到任何错误,更简洁和更快。

+0

感谢提示..我不得不自己挖掘出来,但设置一个env变量,不会显示在命令行的env变量里面.. – kmassada

+1

@kmassada:我不确定你的问题的意思。如果一个子进程(比如你的Python脚本)修改它的环境,或者使用不同的环境启动它自己的子进程,那么这不会影响父shell,更不用说其他任何正在运行的shell。但是,如果你用'subprocess.call(['/ bin/sh'],env = env')或其他东西启动一个shell,那么是的,'env'中的键将全部显示为你启动的shell的变量。 – abarnert