[TOC] > [官网](https://www.osgeo.cn/fabric/getting-started.html#a-note-about-imports) ## 概述 * 存在多个版本,如果语法错误,检测版本 * Fabric 是一个被广泛应用的自动化工具库 * 可通过 ssh 方式远程远程执行命令 * 也可进行交互式操作 ## 安装 `pip intall fabric` 查看版本 ``` > fab -V Fabric 2.5.0 Paramiko 2.7.1 Invoke 1.4.1 ``` ## 语法 ``` --prompt-for-login-password:令程序在命令行中输入 SSH 登录密码(上例在代码中指定了 connect_kwargs.password 参数,若用此选项,可要求在执行时再手工输入密码) --prompt-for-passphrase:令程序在命令行中输入 SSH 私钥加密文件的路径 -H 或 --hosts:指定要连接的 host 名 -i 或 --identity:指定 SSH 连接所用的私钥文件 -S 或 --ssh-config:指定运行时要加载的 SSH 配置文件 ``` ### Connection 函数 ``` con = Connection(host_ip, user_name, connect_kwargs={'password': password}) ``` ## 教程 ### 简单例子:远程获取 date ``` # 可使用任意的文件名 from fabric import Connection host_ip = '192.168.1.4' # 服务器地址 user_name = 'idcpj' # 服务器用户名 password = '123' # 服务器密码 cmd = 'date' # shell 命令,查询服务器上的时间 con = Connection(host_ip, user_name, connect_kwargs={'password': password}) result = con.run(cmd, hide=True) # result = con.local(cmd, hide=True) # result = con.sudo(cmd, hide=True) print(result.stdout) # Fri Feb 14 15:33:05 CST 2020 print(result.exited) # 0 print(result.ok) # True print(result.failed) # False print(result.command) # date print(result.connection.host) #192.168.1.4 ``` 1. 如果需要用管理员权限,则需替换成 sudo() 方法。 2. 如果要在本地执行 shell 命令,则需替换成 local() 方法 ### 在命令函执行 注意 文件名必须为`fabfile.py`执行时候必须在当前目录执行 <details> <summary>fabfile.py</summary> ``` from fabric import Connection from fabric import task host_ip = '192.168.1.4' # 服务器地址 user_name = 'idcpj' # 服务器用户名 password = '123' # 服务器密码 cmd = 'date' # shell 命令,查询服务器上的时间 @task def test(c): """ Get date from remote host. """ con = Connection(host_ip, user_name, connect_kwargs={'password': password}) result = con.run(cmd, hide=True) print(result.stdout) # 只打印时间 ``` </details> <br /> 运行 ``` > fab -l Available tasks: test Get date from remote host. > fab test Tue Feb 25 23:07:06 CST 2020 ``` ### 交互式操作 a.py ``` from invoke import Responder from fabric import Connection host_ip = '192.168.43.192' # 服务器地址 user_name = 'idcpj' # 服务器用户名 password = '123' # 服务器密码 cmd = 'sudo who' # shell 命令,查询服务器上的时间 c = Connection(host_ip, user_name, connect_kwargs={'password': password}) sudopass = Responder( pattern=r'\[sudo\] password:', response='123\n') result = c.run(cmd, pty=True, watchers=[sudopass]) print(result) # idcpj console Feb 22 10:50 ... ``` 运行 ``` > python a.py Password: //输入 123 idcpj console Feb 22 10:50 idcpj ttys000 Feb 25 22:14 (192.168.1.4) ``` ### 传输文件 ``` from fabric import Connection host_ip = '192.168.1.4' # 服务器地址 user_name = 'idcpj' # 服务器用户名 password = '123' # 服务器密码 cmd = 'sudo who' # shell 命令,查询服务器上的时间 c = Connection(host_ip, user_name, connect_kwargs={'password': password}) # 拉去远程文件当本地 c.get('/Users/idcpj/Desktop/1.txt', '2.txt') # 发送到远程文件 c.put('1.txt', '/Users/idcpj/Desktop/2.txt') ``` 第二个参数是要传输的目的地,可以指定成文件名或者文件夹(为空或 None 时,使用默认路径) `get()` 方法的默认存储路径是`os.getcwd`(项目当前目录),而 `put()` 方法的默认存储路径是 home 目录 ### 服务器批量操作 方式一:循环执行(同步) ``` host_ip = '192.168.1.4' user_name = 'idcpj' password = '123' cmd = 'date' if __name__ == '__main__': for host in ('192.168.1.4', '192.168.1.4', '192.168.1.4'): result = Connection(host_ip, user_name, connect_kwargs={'password': password}).run('uname -s') ``` 方法二:group 方法(异步) ``` from fabric import SerialGroup host_ip = '192.168.1.4' user_name = 'idcpj' password = '123' cmd = 'date' if __name__ == '__main__': group = SerialGroup('192.168.1.4', '192.168.1.4', user_name, connect_kwargs={'password': password}) group.get('/Users/idcpj/Desktop/1.txt', '3.txt') group.run('uname -s') ``` ### 配置 系统级的配置文件:`/etc/fabric.yml` 用户级的配置文件:`~/.fabric.yml`(Windows 在 C:\Users\xxx 下) 项目级的配置文件:`/myproject/fabric.yml` <details> <summary>fabric.yml</summary> ``` user: idcpj connect_kwargs: password: 123 # 若用密钥,则如下 # key_filename: # - your_key_file ``` </details> <br /> <details> <summary>fabfile.py</summary> ``` from fabric import Connection from fabric import task host_ip = '47.xx.xx.xx' # 服务器地址 cmd = 'date' # shell 命令,查询服务器上的时间 @task def test(c): """ Get date from remote host. """ con = Connection(host_ip) result = con.run(cmd, hide=True) print(result.stdout) ``` </details> <br /> 运行 ``` > fab test Tue Feb 18 10:33:38 CST 2020 ``` ### 网络网关 如果远程服务是网络隔离的,无法直接被访问到(处在不同局域网),这时候需要有网关/代理/隧道,这个中间层的机器通常被称为跳板机或堡垒机 ``` from fabric import Connection c = Connection('internalhost', gateway=Connection('gatewayhost')) ```