介绍

Fabric 是一个基于 Python 的开源工具库,主要用于简化远程服务器的自动化操作(如部署、管理、批量执行命令等)。它通过封装 SSH 协议,让开发者可以用 Python 代码定义 “任务”,并批量在多台远程服务器上执行,避免了手动登录服务器逐个操作的繁琐流程。

用代码替代 “手动 SSH 登录服务器 → 输入命令 → 等待结果” 的重复工作,尤其适合需要管理多台服务器的场景(如集群部署、批量配置等)。

特点

  • 基于 SSH 协议
  • 任务自动化
  • 支持多服务器与角色分组
  • 并行执行
  • Python 生态集成

应用场景

  • 批量部署应用:同时向多台 Web 服务器推送代码、安装依赖、重启服务。
  • 服务器监控:批量查看多台服务器的 CPU、内存、磁盘使用率。
  • 配置管理:统一在多台服务器上修改配置文件、创建用户、设置权限。
  • 日志收集:从多台服务器拉取日志文件到本地汇总分析。

版本说明

对比维度Fabric 1.X(官方旧版)Fabric 2.X(官方现代版)Fabric 3(非官方分支)
官方定位早期官方版本,已停止主动维护(仅安全补丁)官方推荐的当前版本(2.0+),又称 “现代版 Fabric”非官方分支(Fabric 1.X 的 Python 3 兼容补丁版)
Python 兼容性仅支持 Python 2.5-2.7(不支持 Python 3)原生支持 Python 3.4+,兼容 Python 2.7(官方建议优先用 3.x)仅支持 Python 3(解决 1.X 的 Python 3 基础兼容,无高版本适配)
安装方式pip install fabric==1.x(如 1.14.0)pip install fabric(默认 2.x+);迁移用别名:pip install fabric2pip install fabric3(PyPI 第三方包,无官方源)
核心架构依赖全局env对象(如env.hosts)管理配置,耦合度高模块化设计:拆分fabric(高层操作)、invoke(任务框架)、paramiko(SSH 底层);显式Connection对象管理连接,无全局状态完全继承 1.X 架构,保留全局env,无架构重构
任务定义与执行依赖@task装饰器,全局函数(如run/sudo)依赖env配置支持@task装饰器,任务需传入Connection对象;支持命令行参数灵活传递与 1.X 一致,无新特性,仅适配 Python 3 语法
并行任务支持依赖@parallel装饰器,稳定性差,无批量控制原生支持并行 / 串行(--parallel/--serial参数);SerialGroup/ParallelGroup类实现批量任务管理继承 1.X 的@parallel,稳定性无改善
配置管理仅通过全局env对象(如env.user/env.password支持Config对象、fabric.yaml配置文件、环境变量,实现多环境隔离仅支持全局env,无配置隔离能力
文件传输(上传 / 下载)put/get功能基础,无断点续传等优化增强put/get(支持断点续传、权限预设);支持远程目录递归操作与 1.X 一致,无功能优化
错误处理异常捕获能力弱,无明确的错误类型划分细分错误类型(如CommandFailed/ConnectionError);支持上下文管理器(with Connection(...))安全处理连接与 1.X 一致,无错误处理增强
维护支持官方停止迭代(最后更新 2017 年),仅修复严重安全漏洞官方持续维护(2024 年仍有版本更新),文档完善(官方文档社区个人维护,无官方支持,2020 年后基本停更
生产环境适配性不推荐(Python 2 终止支持,无安全更新保障)强烈推荐(稳定性高、安全更新及时、功能贴合生产需求)不推荐(无维护、隐性兼容性风险,仅临时过渡用)
官方态度已被 2.X 替代,建议迁移官方唯一推荐版本,明确 “升级到 2.X 是强烈建议”官方明确否定:“未授权的 fork,无官方 3.x 计划”

生产环境建议直接使用 Fabric 2.X,由于目前很多老的项目用是 Fabric 1.X 的版本,而且 Fabric 2.X 也兼容 1.X,所以下面我们先使用 Fabric 1.X 进行演示。

安装

  • Fabric 1.14.0
  • Paramiko 2.12.0
  • Python 2.7.5

确保当前使用的版本是 python 2,然后执行下面的命令

pip install 'fabric<2.0'

常用参数

# fab --help     查看帮助
  
 常用参数
-l  显示定义好的任务函数名
-f  指定fab入口文件,默认入口文件名为fabfile.py.. 即指定fabfile文件
-g  指定网关(中转)设备,即HOST逗号分隔要操作的主机, 比如堡垒机环境,填写堡垒机IP即可.
-H  指定目标主机,多台主机用‘,’号分隔
-p  远程账号的密码,fab执行时默认使用root账户
-P  以异步并行方式运行多主机任务,默认为串行运行
-R  指定role(角色),以角色名区分不同业务组设备
-t  设置设备连接超时时间(秒)
-T  设置远程主机命令执行超时时间(秒)
-w  当命令执行失败,发出警告,而非默认中止任务。
 
其他参数:
--set=KEY=VALUE,...     逗号分隔,设置环境变量
--shortlist             简短打印可用命令
-c PATH                 指定本地配置文件
-D                      不加载用户known_hosts文件
-i PATH                 指定私钥文件
-k                      不加载来自~/.ssh下的私钥文件
--port=PORT             指定SSH连接端口
-R ROLES                根据角色操作,逗号分隔
-s SHELL                指定新shell,默认是'/bin/bash -l -c'
--show=LEVELS           以逗号分隔的输出
--ssh-config-path=PATH  SSH配置文件路径
-T N                    设置远程命令超时时间,单位秒
-u USER                 连接远程主机用户名
-x HOSTS                以逗号分隔排除主机
-z INT                  并发进程数

常用方法

远程命令执行

方法说明
run(command)在远程服务器上以当前用户权限执行命令(非 sudo),返回命令结果对象。
sudo(command)在远程服务器上以 sudo 权限执行命令(需输入密码,可通过 env.password 预设)。
local(command)在本地机器执行命令(非远程),常用于本地预处理(如打包代码)。
prompt(message)在本地终端提示用户输入信息(如密码、版本号),返回用户输入的字符串。

文件传输

方法说明
put(local_path, remote_path)将本地文件 / 目录上传到远程服务器(remote_path 为目标路径)。
get(remote_path, local_path)将远程服务器文件 / 目录下载到本地(local_path 为本地保存路径)。

连接与环境配置

配置项说明
env.hosts远程服务器列表,如 env.hosts = ['user@host1', 'user@host2:port']
env.user登录远程服务器的用户名(默认使用本地当前用户)。
env.password远程服务器密码(或 sudo 密码),避免手动输入(明文不安全,建议用密钥)。
env.key_filenameSSH 私钥路径,如 env.key_filename = '~/.ssh/id_rsa'(密钥登录用)。
env.portSSH 端口号(默认 22,非默认端口需指定)。
env.timeout连接超时时间(秒),如 env.timeout = 30
env.parallel是否并行执行任务(默认 False,设为 True 可批量操作多服务器)。

上下文管理与装饰器

方法 / 装饰器说明
cd(path)上下文管理器,临时切换远程工作目录(仅在 with 块内生效)。
settings(**kwargs)临时覆盖 env 配置,如 with settings(user='root'): run('whoami')
prefix(command)为后续命令添加前缀(如激活虚拟环境:with prefix('source venv/bin/activate'))。
@task装饰器,标记函数为可通过 fab 命令调用的任务(如 @task def deploy(): ...)。
@roles(role_name)装饰器,指定任务仅在特定角色的服务器上执行(需先定义 env.roles)。

错误处理

方法 / 配置项说明
warn_only设为 True 时,命令执行失败不会终止任务(默认 False,失败即终止)。
abort(message)手动终止任务并输出错误信息,如 if not result.succeeded: abort('命令失败')
result.failed命令结果对象的属性,判断命令是否执行失败(run/sudo 返回的对象)。
result.succeeded判断命令是否执行成功。

快速开始

编写任务文件 fabfile.py
-f  指定fab入口文件,默认入口文件名为 fabfile.py

# 定义名为 hello 的任务
def hello():
    print("Hello from Fabric!") 

执行命令

fab hello

输出结果

Hello from Fabric!

带颜色的输出

fabric 为了让输出日志更具有可读性,对命令行中断的颜色输出进行了封装,使用print打印带有不同颜色的文本,这些颜色包含在fabric.colors中。

  • blue(text,blod=False)  蓝色
  • cyan(text,blod=False)  淡蓝色
  • green(text,blod=False)  绿色
  • magenta(text,blod=False)  紫色
  • red(text,blod=False)  红色
  • white(text,blod=False)  白色
  • yellow(text,blod=False)   黄色
from fabric.api import *
from fabric.colors import *
from fabric.contrib.files import exists

def hello():
    print("Hello from Fabric!")
    warn(yellow('----->warn'))
    print(green("green color"))
    print(green("green blod color", True))
    print(blue("blue color"))

带参数

def hello(name, value):
    print("Hello Fabric! %s %s." % (name, value))

执行

fab hello:name=Year,value=2025

收集动态参数 prompt

prompt(message) 是用于在本地终端向用户获取输入的方法(类似 Python 内置的 raw_input()),常用来收集动态参数(如版本号、确认信息等)。

from fabric.api import prompt, task

def deploy():
    # 提示用户输入部署版本
    version = prompt("请输入部署版本号: ")
    print("你输入的版本是: " + version)
    
    # 执行部署逻辑(示例)
    # run(f"deploy {version}")

def rollback():
    # 提示用户输入回滚版本,默认回滚到上一版本
    version = prompt("请输入回滚版本号(默认: previous): ", default="previous")
    print(f"将回滚到版本: {version}")

def is_positive_number(input_str):
    """验证函数:检查输入是否为正整数"""
    if input_str.isdigit() and int(input_str) > 0:
        return True  # 输入合法
    else:
        print("错误:请输入正整数!")
        return False  # 输入不合法,重新提示

def set_workers():
    # 提示用户输入 worker 数量,必须为正整数
    workers = prompt(
        "请输入进程数量(正整数): ",
        validate=is_positive_number  # 绑定验证函数
    )
    print(f"已设置进程数量: {workers}")

执行本地命令之 local 方法

在当前目录下创建一个文件 fab.out,并写入字符串到文件中

from fabric.api import local

def taskA():
    local('touch fab.out && echo "fabric" >> fab.out')

执行远程命令

from fabric.api import run, env

# env被称为环境字典,用来配置一些运行环境相关的信息
env.hosts = ['192.168.1.100', '192.168.1.101']
env.user = 'user'
env.password = 'passwd'

def taskA():
    run('cd /usr/local/webserver/php && ls -l')
    run('sudo /usr/local/webserver/nginx/sbin/nginx -t')

并行执行

Fabric 在多台机器上执行任务时默认情况下是串行的。Fabric支持在多台服务器上并行执行任务,并行可以有效的加快执行速度。开启并行执行有如下两个方法:

1. 在执行 fab 命令时加上-w参数

fab -P task

2. 设置env.parallel环境参数为True

from fabric.api import env
env.parallel = True

以上是对任务并行做一个全局控制。如果只想对某一个任务做并行的话,我们可以在任务函数上加上@parallel装饰器,这样即便全局并行未开启,被@parallel装饰的任务也会并行执行:

#-*- coding:utf-8 -*-
from fabric.api import env, run, parallel

env.hosts = ['10.216.224.65', '10.216.224.66']
env.key_filename = '~/.ssh/id_rsa'

@parallel
def taskA():
    run('echo "parallel"')

def taskB():
    run('echo "serial"')

假如全局并行已开启,我们想让某个任务串行执行,我们可以在任务函数上加上@serial装饰器,这样即便并行已开启,被@serial装饰的任务也会串行执行:

#-*- coding:utf-8 -*-
from fabric.api import env, run, serial

env.hosts = ['10.216.224.65', '10.216.224.66']
env.user = 'user'
env.key_filename = '~/.ssh/id_rsa_fabric'
env.parallel = True

def taskA():
    run('echo "parallel"')

@serial
def taskB():
    run('echo "serial"')

密码登录

env.hosts = ['10.10.10.01', '10.10.10.02']
env.user = 'user'
env.passwords = {
    'root@10.10.10.01:22':'******',
    'root@10.10.10.02:22':'******'
}

ssh 密钥登录

env.hosts = ['10.10.10.01', '10.10.10.02']
env.user = 'user'
env.port = 22 # 默认是 22
env.key_filename = '~/.ssh/id_rsa' # 私钥文件路径

服务器分组

env.roledefs = {
    # 操作一致的放一组,一组执行同一个操作
    'servers1':['10.10.10.01', '10.10.10.02'],
    # 第二组
    'servers2':['10.10.10.03', '10.10.10.04']
}
env.user = 'user'
env.port = 22 # 默认是 22
env.key_filename = '~/.ssh/id_rsa' # 私钥文件路径
env.parallel = True # 开启并行

def webtask():
    run('/usr/local/nginx/sbin/nginx')

def dbtask():
    run('uptime')

执行

fab -R servers1 webtask

部署案例

文件打包, 上传与校验

部署LNMP业务服务环境

生产环境代码包发布管理的配置

代码的自动化部署

总结

Fabric 是基于 Python 实现的 SSH 命令行工具,简化了 SSH 的应用程序部署及系统管理任务,它提供了系统基础的操作组件,可以通过 SSH 的方式与远程服务器进行自动化交互, 实现本地或远程 shell 命令,包括:命令执行、文件上传、下载及完整执行日志输出等功能。

相关链接

 Fabric 1.x 官方文档

官方文档

中文文档

https://www.cnblogs.com/kevingrace/p/5570240.html

https://www.cnblogs.com/xiao-apple36/p/9124292.html

https://zhuanlan.zhihu.com/p/104777654