• 最近总在用 fabric,踩了一些坑, 分享一个实用函数


    最近一直在做的一个东西, 很多地方需要用到 shell 命令,
    同样的命令既要在本地运行, 也要放到远程,并获取远程的输出结果
    如果每个地方都要判断是在本地还是远程然后再去分别实例不同的对象,
    所以写了一个函数, 尽量减少一下重复代码

    加入了自己的一些理解

    def cmd_method(host, port=22, user=None, pwd=None):
    “”"
    执行远程或本地命令
    r = r"(?i)y|n|[y/d/n]|[y/n]|y/n"
    watcher = Responder(pattern=r, response=‘y ’)
    Responder 对象可以通过正则匹配对 stdout 做分析, 如果匹配到了,就向 stdin 写入 response
    完成命令的反复交互
    :param host: 主机 ip, 本地可以用 ‘localhost’ or ‘127.0.0.1’
    :param port: ssh 的端口
    :param user: 登陆远程主机的用户
    :param pwd: 远程登陆的密码
    :return: 正常输出和错误输出: (stdout, stderr)
    “”"

    from fabric import Connection
    from invoke import run, Responder
    from paramiko import AuthenticationException
    from paramiko.ssh_exception import NoValidConnectionsError, SSHException
    
    def local(command, interactive):
        watcher = Responder(
                pattern=interactive['pattern'],
                response=interactive['response']) if interactive else None
        res = run(command, watchers=[watcher], warn=True, hide=True)
        res = res.stdout.encode('utf8'), res.stderr.encode('utf8')
        return res
    
    def remote(command, interactive):
        if not ip_check(host):
            return 'host ip error'
        with Connection(host=host, port=port, user=user,
                        connect_kwargs={'password': pwd},
                        connect_timeout=10) as c:
            watcher = Responder(
                    pattern=interactive['pattern'],
                    response=interactive['response']) if interactive else []
            res = c.run(command, watchers=[watcher], warn=True, hide=True)
            res = res.stdout.encode('utf8'), res.stderr.encode('utf8')
            return res
    if host and host in ('localhost' or '127.0.0.1'):
        return local
    elif host and port and user and pwd:
        with Connection(host=host, port=port, user=user,
                        connect_kwargs={'password': pwd},
                        connect_timeout=10) as c:
            try:
                # 测试参数可用
                c.run('hostname', hide=True)
            except (AuthenticationException, NoValidConnectionsError,
                    SSHException) as e:
                return e.__str__()
        return remote
    else:
        return 'args error'
    

      

    因为 fabric 的 Connection 的 run 方法也是继承自 invoke, 所以参数作用基本都是一样的
    我最常用的是 warn 和 hide 还有 watchers
    warn 默认为 False, 默认情况下会因为 shell 命令的错误输出而抛错, 也就是直接抛出 stderr
    如果设为 True, 就会将 shell 命令的错误输出写到 Result 对象的 stderr 内

    hide 也是默认为 False, 默认情况下将远程的输出信息在当前命令行输出, 为 True 时, 则不会, 但不论是什么, 都不会影响 Result 对象的 stdout 和 stderr 结果, 还可以只隐藏 stdout 或 stderr

    watchers 参数, 传入的是一个包含诺干 Responder 实例的列表
    当需要运行交互式的命令时, 可以用 Responder 对象来匹配输出, 并写入输入, 做自动化部署时很实用

    还有一个 pty 参数, 这个参数, 默认是设为 True, 找文档时候发现很多人都是设为 True, 但在我踩过很多坑后,
    我发现当设为 True 时, 有时标准输出(stdout)和错误输出(stderr)会混乱, 不方便后面的逻辑判断, 所以最好别动

    还有 out_stream 和 err_stream, 可以将输出导到一个 write 模式打开的类 file 对象, 方便做记录。(作者 :giy.hkv,http://siligence.ai/column/index.php?page=1)

    原文:https://blog.csdn.net/luodoudoudou/article/details/90633868

  • 相关阅读:
    架构设计之NodeJS操作消息队列RabbitMQ
    如何搭建一个功能复杂的前端配置化框架(一)
    Web as a App(Web既APP)的概念可以提出吗?
    Bottle源码阅读笔记(二):路由
    Bottle源码阅读笔记(一):WSGI
    Python__slots__详解
    [译]如何在Web开发中使用Python
    C#中Internal关键字的总结
    [DataContract]引用
    分享一个与ABP配套使用的代码生成器源码
  • 原文地址:https://www.cnblogs.com/qbdj/p/10974638.html
Copyright © 2020-2023  润新知