如何让Fabric忽略env.hosts列表中的离线主机?

11 投票
4 回答
9307 浏览
提问于 2025-04-15 17:19

这和我之前提到的问题有关,但这是一个不同的问题。

我有以下的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列表里的其他服务器是什么情况。

我使用了设置“warn_only=True”,但可能我用得不太对。

我该如何修改这个行为,让它只打印错误信息,然后继续执行呢?

4 个回答

1

你并没有用错。你甚至可以在命令行中直接加上 --warn-only=true这是开发团队推荐的官方方法。

21

从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

别忘了也要明确设置超时时间。

15

根据Fabric文档中关于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

撰写回答