概览

MoHand 为通用自动化处理工具,主要用于运维自动化。

灵感来自于 Python 下很经典的运维工具 Fabric ,故您在使用中会看到很多 Fabric 的影子。

最初开发 MoHand 是为了在公司自动化登录堡垒机,由于所在公司的业务较复杂, 故需要登录全国各地的堡垒机,然后跳到对应的私有云内,进行开发&调试工作。

考虑到高扩展性,同时也是因为深知自己能力有限不可多知多能,故在设计整体架构时, 参考了 Gulp 以及 PostCSS 的组件思想,通过 Python 的 stevedore 实现了高扩展性的插件系统,并自己实现了一个用于自动化登录堡垒机的插件 mohand-plugin-expect 。

如果您使用后觉得有意思,欢迎实现更多的插件分享给大家,我会及时在该文档中更新 plugin 列表, 供后来人参考&使用。若其足够优秀,我将考虑将其加入到 MoHand 的 install_requires 中!

安装方法

您可以通过 pip 进行安装,本包仅在 Python 3.X 下测试通过:

pip3 install mohand

提示

从 v1.0.1 版本开始,增加了对 Python 2.X 的支持,但由于我主要在 Py3 环境下使用,所以强烈建议您在 Py3 下使用。如果您在 Py2 环境下遇到任何异常, 可以及时提 Issues 给我,我会努力在搬砖的间隙进行修复。。。

注解

建议使用 virtualenv 来安装,避免与其他包产生依赖冲突。

如果您感兴趣的话,可以了解下 virtualenvwrapper ,用其来管理虚拟环境可谓丝般顺滑!

使用说明

安装成功后,您将获得 mohand 终端命令,该命令在调用前会加载当前路径下的 handfile.py 文件,若没有找到,则会递归向父级路径查找,直到根路径结束。若未找到该文件,则会返回信息如下:

$ mohand
[ERROR] 未找到 handfile 文件!

当其找到该文件后,会立即加载该文件,并停止继续递归。此处我们在当前路径创建该文件,然后再次执行:

$ touch handfile.py
$ mohand
Usage: mohand [OPTIONS] COMMAND [ARGS]...

  通用自动化处理工具

  详情参考 `GitHub <https://github.com/littlemo/mohand>`_

Options:
  --author   作者信息
  --version  版本信息
  --help     Show this message and exit.

此时 mohand 已经可以正常运行了,但是我们还没有可用于执行的子命令,接下来我们在 handfile.py 文件中实现一个子命令:

from mohand.hands import hand


@hand.general
def hello():
    """Hello World!"""
    print('Hello World!')

好,此时我们已经拥有了一个可执行的子命令,如何证明呢?再执行一次 mohand 看看吧:

$ mohand
Usage: mohand [OPTIONS] COMMAND [ARGS]...

  通用自动化处理工具

  详情参考 `GitHub <https://github.com/littlemo/mohand>`_

Options:
  --author   作者信息
  --version  版本信息
  --help     Show this message and exit.

Commands:
  hello  Hello World!

注意最后两行,现在已经多了一条子命令,其命令名即为我们之前实现的函数名,说明即该函数的 __doc__ 。 这里的 CLI 是基于 click 包实现的,故您基本感受不到其存在,相关逻辑已经被封装到 hand.general 这个装饰器中了。

接下来就是见证奇迹的时刻了,我们来执行以下这个子命令看看:

$ mohand hello
Hello World!

看我们实现的命令被执行了,打印出了 Hello World! 。

还记得我之前说过的循环递归查找 handfile.py 文件么?这个性质将很方便,比如将我们刚实现的 handfile.py 移到 ~ 下,这样我们在 ~ 目录下就都可以加载到这个文件中的子命令了。

注解

另外, mohand 还支持对 handfile 模块的加载,即您可以实现一个以 handfile 命名的 Python 包,并在其 __init__.py 中将想要被加载的命令导入,这样 mohand 就会对其进行加载处理,并注册为子命令。

高级用法

由于 mohand 的终端命令方案使用的是 click ,故您可以在实现子命令时灵活的增加命令参数, 继续以上述 hello 命令为例,为其添加一个终端参数:

@hand._click.option('--who', '-w', default='World', help='默认值为 `World` ')
@hand.general
def hello(who):
    """Hello World!"""
    print('Hello {}!'.format(who))

我们为 hello 命令增加了一个 who 的可选参数,该参数默认值为 World ,调用看看:

$ mohand hello --help
Usage: mohand hello [OPTIONS]

  Hello World!

Options:
  -w, --who TEXT  默认值为 `World`
  --help          Show this message and exit.

$ mohand hello
Hello World!

$ mohand hello -w MoHand
Hello MoHand!

我们通过传参定制了输出的结果,您可以通过这个方法获得一个强大的命令扩展系统。