如何使Fabric忽略env.hosts列表中的脱机主机?

时间:2009-12-24 05:06:04

标签: python fabric

这与我的previous question有关,但与另一个有关。

我有以下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.hosts列表中的其他服务器如何,它都会立即中止。

我使用了env设置“warn_only = True”,但也许我使用它不正确。

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

4 个答案:

答案 0 :(得分:20)

从版本1.4开始,Fabric有一个--skip-bad-hosts选项,可以从命令行设置,也可以在fab文件中设置变量。

env.skip_bad_hosts = True

该选项的文档在这里: http://docs.fabfile.org/en/latest/usage/fab.html#cmdoption--skip-bad-hosts

不要忘记明确设置超时值。

答案 1 :(得分:15)

根据Fabric documentation on warn_only

  

env.warn_only“指定在run / sudo / local遇到错误情况时是否发出警告,而不是中止。

这对服务器关闭无效,因为在执行run / sudo / local之前SSH尝试期间发生了故障。

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

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

答案 2 :(得分:1)

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

答案 3 :(得分: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")

当您拥有多个主机和角色时,它尤其有用。

相关问题