关于fabric
fabric是一款python库,可以在执行本地或者远端服务器上执行shell命令,一般用于远程部署应用或者运维工作。
你要注意的事
由于fabric的作者更新了代码,python2.x和python3.x使用方式有所不同,所以在使用之前,请睁开眼睛看看你的环境中的fabric是哪个版本,$ pip show fabric。
我当时安装的时候是默认版本,2.4。
如果你的1.x版本,就不要往下看了。这有1.x的基础教程:传送门。
安装
怎么快怎么来,一条命令即可:pip install fabric。
如果你的项目是在虚拟环境中,不要忘了开启虚拟环境再安装哦。
使用
fabric默认的任务路径是fabfile/init.py,也可以是fabfile.py。
比如说,我建了个项目叫"nzh_project",我想在这里执行fabric任务,那么你就把fabfile.py文件建在这里。
打开fabfile.py,并输入如下代码:
from invoke import task
@task
def hello(c):
print("Hello Fabric")
然后在pycharm编译器中的terminal中输入fab hello,就能看到输出结果。
如果报错了
那么你看看是不是以下问题:
1.路径错误,你必须切换到fabfile.py所在的路径。
2.pycharm解释器不对,有的同学可能和我一样用的是虚拟环境,虚拟环境是独立的,不会受到系统环境的影响,所以如果没有切换pycharm的python解释器也会报错,在你import fabric的时候就会报错。
再废话一句,怎么切换python解释器
在1处搜索“interpreter”,选中project interpreter,在下拉框中查看是否有你的虚拟环境解释器,如果没有的话,点击4处的齿轮,选择add local。
在Exist environment中选择你的虚拟环境中/bin/python3.6。我是3.6,你用的什么就选什么。
回来继续说正题
fabric 2.x需要使用task装饰器来标识函数,这个被标识的函数被称为fabric任务。
这个任务要被执行,必须标注@task。
再说一下为什么hello函数要传个参数c,如果不传就会报TypeError错误。
说是缺少一个初始化上下文参数,随便传一个即可。
如何调用task
任务(@task标识的函数)我们写完了,那么接下来就要知道如何调用。
回到终端,输入 fab --list,查看task列表.
我们可以看到,里面有个可用任务hello,不正是我们写的hello函数么。
继续在终端中输入,fab hello,完成调用。
在远程服务器执行shell命令
fabric的强大在于你可以通过SSH在远程服务器执行shell命令。
那么,我们可以写一个简单的“查看当前路径所有文件的命令”,这个命令是在远程服务器上执行的。
from invoke import task
from fabric import Connection
@task
def hello(c):
# c.run("echo ‘hello fabric‘")
print("Hello Fabric")
@task
def show_files(r):
c = Connection('xx.xx.xx.xx', user='root', port=22, connect_kwargs={'password': '密码'})
c.run('ls')
show_files(r)里的参数r是随便写的,因为我也不知道它是干啥的。
要连接远程服务器必须有IP地址(或者域名),账号,密码,端口号。
所以我们要先从fabric导入Connection类,初始化时传入这些参数。
c就是一个连接实例,可以理解为sqlalchemy中操作数据库的游标cursor。
你对远程服务器操作都写在run函数中。
比如我想在服务器上执行ls命令,那么把ls传入到run函数中即可。
注意
再次查看可执行任务时,发现show_files函数名字变了,变成了show-files。
如果不注意,你在终端输入fab show_files时会发现,提示“No idea what 'show_files' is!”,也许是命名规则的问题吧,所以注意规避就好了。
执行的时候要输入fab show-files。
那应用程序分布在多台服务器上时
很有可能遇到这样的情况,你的应用托管到多台服务器上,我们总不能每台服务器都写个脚本吧?这种情况有两种解决办法。
1.如果这些服务器的账号密码都一样,给hostname传入一个ip地址的list。(这种方法没试过。)
2.如果每台服务器账号密码不一样,那就对每台服务器都建立一个Connection。
c1 = Connection('xx.xx.xx.xx', user='xxx', port=22, connect_kwargs={'password': 'xxxx'})
c2 = Connection('xx.xx.xx.xx', user='xxx', port=22, connect_kwargs={'password': 'xxxx'})
c3 = Connection('xx.xx.xx.xx', user='xxx', port=22, connect_kwargs={'password': 'xxxx'})
for i in [c1, c2, c3]:
i.run('ls')