2009-12-24 23 views
11

这与我的previous question有关,但是与此不同。如何使织物忽略env.hosts列表中的脱机主机?

我有以下fabfile:

from fabric.api import * 

host1 = '192.168.200.181' 
offline_host2 = '192.168.200.199' 
host3 = '192.168.200.183' 

env.hosts = [host1, offline_host2, host3] 
env.warn_only = True 

def df_h(): 
    with settings(warn_only=True): 
     run("df -h | grep sda3") 

,输出是:执行打脱机服务器

[192.168.200.199] run: df -h | grep sda3 

Fatal error: Low level socket error connecting to host 192.168.200.199: No route to host 

Aborting. 

后,系统会立即中止,不论在包膜中的其他服务器。主机列表。

我已经使用了env设置“warn_only = True”,但也许我使用不当。

如何修改此行为,以便它只会打印错误并继续执行?

回答

15

按照Fabric documentation on warn_only

env.warn_only“指定是否警告,而不是中止,当时run/sudo/local遇到错误条件。

这将不利于在服务器关闭的情况,因为执行前SSH尝试期间发生故障run/sudo/local

一个解决方案是创建一个函数,在执行任务之前检查每个服务器是否启动。以下是我使用的代码。

from __future__ import print_function 
from fabric.api import run, sudo, local, env 
import paramiko 
import socket 

host1 = '192.168.200.181' 
offline_host2 = '192.168.200.199' 
host3 = '192.168.200.183' 

env.hosts = [host1, offline_host2, host3] 

def df_h(): 
    if _is_host_up(env.host, int(env.port)) is True: 
     run("df -h | grep sda1") 


def _is_host_up(host, port): 
    # Set the timeout 
    original_timeout = socket.getdefaulttimeout() 
    new_timeout = 3 
    socket.setdefaulttimeout(new_timeout) 
    host_status = False 
    try: 
     transport = paramiko.Transport((host, port)) 
     host_status = True 
    except: 
     print('***Warning*** Host {host} on port {port} is down.'.format(
      host=host, port=port) 
     ) 
    socket.setdefaulttimeout(original_timeout) 
    return host_status 
+1

我用类似的方式来做到这一点,但太天真了 - 我用ping子命令打包了子进程模块-_-“ 我应该看看你已经使用过的模块更多。谢谢,伙计 – 2010-04-02 02:56:07

+0

@ jevonearth的回答通过在函数中使用--skip-bad-hosts标志或env.skip_bad_hosts = True来建议结构> = v1.4。 – sreenivas 2017-02-01 11:30:38

1

您没有正确使用它。你甚至可以在命令行上提供--warn-only=trueIt's the documented method suggested by the development team.

+1

参数应该是“ - 仅限注册”。但是,运行“fab --warn-only df_h”会输出相同的错误消息。看起来连接失败不包含在“warn_only”设置中。 – 2009-12-24 06:06:22

1

基于马修的答案,我想出了实现只是一个装饰:

from __future__ import with_statement 
from paramiko import Transport 
from socket import getdefaulttimeout, setdefaulttimeout 
from fabric.api import run, cd, env, roles 


roledefs = { 
    'greece': [ 
     'alpha', 
     'beta' 
    ], 
    'arabia': [ 
     'kha', 
     'saad' 
    ] 
} 

env.roledefs = roledefs 


def if_host_offline_ignore(fn): 
    def wrapped(): 
     original_timeout = getdefaulttimeout() 
     setdefaulttimeout(3) 
     try: 
      Transport((env.host, int(env.port))) 
      return fn() 
     except: 
      print "The following host appears to be offline: " + env.host 
     setdefaulttimeout(original_timeout) 
    return wrapped 


@roles('greece') 
@if_host_offline_ignore 
def hello_greece(): 
    with cd("/tmp"): 
     run("touch hello_greece") 


@roles('arabia') 
@if_host_offline_ignore 
def hello_arabia(): 
    with cd("/tmp"): 
     run("touch hello_arabia") 

当你有多个主机和角色这是非常有用的。