# 0x00 前言

当大家还在纠结 Python2 与 Python3 的时候,我其实早就入了 python3 的门了。

后来

  • 我总算学会了如何去爱。
  • 我喜欢的工具陆陆续续支持了 Python3
  • Scrapy 支持了 Python3
  • Ansible 支持了 Python3

只有 Fabric 这个工具,死撑着没有支持 Python3 的的迹象。

2018-05-08 的时候,Fabric 悄悄升级了 2.0 版本。

而就在前两天,我升级网站的时候,突然发现 fabric (1.14 版本) 不能用了。

查了一下版本,发现 fabric 更新到了 2.0 版本,支持了 python3.4

在发现这个问题之后,火速刷了一波官方文档,把手头 Fabric 1.14 版本的脚本做了一些升级。

# 从 V1 到 V2

Fabric v2 基于 invoke 和 paramiko 两个库构建而成。

  • invoke 库提供了 subprocess command execution 和 command-line
  • paramiko 提供了 ssh 协议实现

在这两者的基础上,做了一些扩展。

甚至,如果你只用其中的本地功能,你都完全不需要使用 fabric, 直接用 invoke 即可。没错,我已经打算把我的本地脚本全部使用 invoke Python3 化了。

v1 版本和 v2 版本初步用起来,个人觉得 v1 用起来 API 更加符合直觉一些。

这东西怎么用呢?

我们先定义 fabfile

# fabfile.py
from invoke import task

def expand_path(c, path):
    return '"$(echo %s)"' % path

def exists(c, path):
    cmd = 'stat %s' % expand_path(c, path)
    return c.run(cmd, warn=True, hide=True).ok

@task
def deploy(c):
    c.local("youcmd")
    c.put()
    c.get()
    c.run()
    c.run("sudo youcmd")
    ......

@task
def other_stuff(c):
    ......

需要注意的是,invoke 里面默认的 replace_env 设置为了 False ,fabric 里面给 runner 设置了 replace_env 为 True , 这也就意味着默认情况下,执行 c.local 的时候会找不到自定义的环境变量,这意味着:

  1. 你的 PATH 被重置了,这意味着你用 brew 安装的软件可能已经完全找不到了。
  2. 你的环境变量 LANG 并不一定是 en_US.UTF-8 了

于是设置一下。

# ~/.fabric.py
#!/usr/bin/env python
# encoding: utf-8

run = {
    "replace_env": False
}

当我要部署的时候直接执行

fab -H webserver01,webserver02,webserver03,webserver04 deploy

到这里大家基本上看出来了,我并没有在文件中 import fabric 只是简单了配置了一个配置文件和执行一下 fab 命令。

这个 v2 版本的 fabric 相当于 invoke 的包装。但我们也可以显式的 import fabric 里面的东西进行更加进阶的操作。