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

发布于 2024-08-16 04:14:04 字数 757 浏览 4 评论 0原文

这与我的上一个问题,但又是另一回事。

我有以下 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”,但也许我使用不当。

如何修改此行为,使其仅打印错误并继续执行?

This is related to my previous question, but a different one.

I have the following 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")

And the output is:

[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.

After the execution hits the offline server, it aborts immediately, regardless of the other servers in the env.hosts list.

I have used the env setting "warn_only=True", but maybe I'm using it improperly.

How can I modify this behavior so that it will only prints the error and continue executing?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

一江春梦 2024-08-23 04:14:04

从版本 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

不要忘记显式设置超时值。

As of version 1.4 Fabric has a --skip-bad-hosts option that can be set from the command line, or by setting the variable in your fab file.

env.skip_bad_hosts = True

Documentation for the option is here:
http://docs.fabfile.org/en/latest/usage/fab.html#cmdoption--skip-bad-hosts

Don't forget to explicitly set the timeout value also.

如若梦似彩虹 2024-08-23 04:14:04

根据 有关 warn_only 的 Fabric 文档

env.warn_only “指定当run/sudo/local 遇到错误情况。


这对于服务器关闭的情况没有帮助,因为在执行 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

According to the Fabric documentation on warn_only,

env.warn_only "specifies whether or not to warn, instead of abort, when run/sudo/local encounter error conditions.

This will not help in the case of a server being down, since the failure occurs during the SSH attempt before executing run/sudo/local.

One solution would be to create a function to check if each server is up prior to executing your tasks. Below is the code that I used.

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
诗化ㄋ丶相逢 2024-08-23 04:14:04

你没有使用不当。您甚至可以只在命令行上提供 --warn-only=true这是开发团队建议的记录方法。

You're not using it improperly. You can even just provide --warn-only=true on the command line. It's the documented method suggested by the development team.

梨涡 2024-08-23 04:14:04

根据 Matthew 的回答,我想出了一个装饰器来实现这一点:

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")

当您有多个主机和角色时,它特别有用。

Based on Matthew's answer, I came up with a decorator that accomplishes just that:

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")

It is especially useful when you have multiple hosts and roles.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文