面料env.hosts

问题描述:

我有一个简单fabfile由名 env_fabfile.py面料env.hosts

# env_fabfile.py 
# makes use of fab env variables 

from fabric.api import env, run 
def login(): 
    env.hosts = ['[email protected]:1234', '[email protected]:2345'] 
    env.passwords = {'[email protected]:1234': 'pass1', '[email protected]:2345': 'pass2'} 
    env.parallel=True 

def run_lsb_release(): 
    run('lsb_release -a') 

现在我运行上面使用FAB命令:

fab -f env_fabfile.py login run_lsb_release

而且它运行完美(并行)并给出所需的输出

现在我想实际计算wh同一个脚本是以串行方式运行的,还是以并行方式运行。因此,要做到这一点,我写了下面的python脚本: timecal.py

# timecal.py 
# runs the fabfile once in serial and calculates the time 
# then runs the same file in parallel and calculates the time 

from fabric.api import env, run 
import time 

def login(): 
    print "in login" 
    env.hosts = ['[email protected]:1234', '[email protected]:2345'] 
    env.passwords = {'[email protected]:1234': 'pass1', '[email protected]:2345': 'pass2'} 

def parallel(status): 
    print "in parallel" 
    env.parallel=status 

def run_lsb_release(): 
    print "in run" 
    run('lsb_release -a') 

def do_serial(): 
    start_time = time.time() 
    parallel(False) 
    login() 
    run_lsb_release() 
    elapsed_time = time.time() - start_time 
    return elapsed_time 

def do_parallel(): 
    start_time = time.time() 
    parallel(True) 
    login() 
    run_lsb_release() 
    elapsed_time = time.time() - start_time 
    return elapsed_time 


if __name__ == '__main__': 
    print "Running in serial mode " 
    print "Total time taken ", do_serial() 

    print "Running in parallel mode" 
    print "Total time taken ", do_parallel() 

但是当我运行timecal.py作为

python timecal.py

我得到了下面的标准输出(除了打印在代码中的声明)

No hosts found. Please specify (single) host string for connection:

我不明白为什么?还怎么能脚本进行整流,这样我可以做到我想做的(如上面的问题说明)

如果我尝试不同的版本timecal.py的,如:

from fabric.api import run, settings, env 
import time 

def do_parallel(): 
    start_time = time.time() 
    env.hosts = ['[email protected]:1234', '[email protected]:2345'] 
    env.passwords = {'[email protected]:1234': 'pass1', '[email protected]:2345': 'pass2'} 
    env.parallel=True 
    run('lsb_release -a') 
    elapsed_time = time.time() - start_time 
    return elapsed_time 

def do_serial(): 
    start_time = time.time() 
    with settings(host_string='host1', port=1234, user='user', password='pass1'): 
     run('lsb_release -a') 
    with settings(host_string='host2', port=2345, user='user', password='pass2'): 
     run('lsb_release -a') 
    elapsed_time = time.time() - start_time 
    return elapsed_time 

if __name__ == '__main__': 
    try: 
     print "Running in parallel mode" 
     print "Total time taken ", do_parallel() 

     print "Running in serial mode " 
     print "Total time taken ", do_serial() 
    except Exception as e: 
     print e 

我得到以下错误:

Fatal error: Needed to prompt for the target host connection string (host: None), but input would be ambiguous in parallel mode

我不明白为什么是主机:无在这里?代码有什么问题?

简短的回答是,你不应该设置env.hosts值目前你正在做的方式,env.passowrds是超级粗略(也许坏了吗?),和it's recommended to use SSH key-based access,尤其是leveraging native SSH config files

下面是您的timecal.py脚本的修改版本,它可以按照预期工作,我会在下面列出一些差异。

# timecal.py 
# runs the fabfile once in serial and calculates the time 
# then runs the same file in parallel and calculates the time 

from fabric.api import env, run, execute, parallel 
import time 

env.use_ssh_config = True 
env.roledefs = { 
    "my_servers": ['server_1', 'server_2'] 
} 


def run_lsb_release(): 
    print "in run" 
    run('lsb_release -a') 


def do_task(task_func): 
    start_time = time.time() 
    execute(task_func, roles=['my_servers']) 
    elapsed_time = time.time() - start_time 
    return elapsed_time 


if __name__ == '__main__': 
    print "Running in serial mode " 
    print "Total time taken ", do_task(run_lsb_release) 

    print "Running in parallel mode" 
    print "Total time taken ", do_task(parallel(run_lsb_release)) 

的主要区别是使用env.roledefs和SSH配置文件,而不是主机&密码。这些值不能在并行执行模式下工作,因为这些任务是在单独的线程中执行的。 The docs有点瘦,但基本上这就是为什么你有这个问题。