在 使用 Nginx 和 Gunicorn 部署 Django 博客 中,我们通过手工方式将代码部署到了服务器。整个过程涉及到十几条命令,输了 N 个字符。一旦我们本地的代码有更新,整个过程又得重复来一遍,这将变得非常繁琐。
使用 Fabric 可以在服务器中自动执行命令。因为整个代码部署过程都是相同的,只要我们用 Fabric 写好部署脚本,以后就可以通过运行脚本自动完成部署了。
安装 Fabric
Fabric 目前仅支持 Python2,如果你的系统中只有 Python3 版本,请先安装一个 Python2 的版本,推荐安装 Python 2.7。Python3 和 Python2 可以共存于一个系统,所以不用担心同时安装两个版本的 Python 会发生冲突。
接下就可以简单地通过 pip 命令安装 Fabric 了。注意要使用 Python2 环境下的 pip,这样才能把 Fabric 安装到 Python2 环境下。
pip install fabric
部署过程回顾
在写 Fabric 脚本之前,我们先来回顾一下当我们在本地开发环境下更新了代码后,在服务器上的整个部署过程。
- 远程连接服务器。
- 进入项目根目录,从远程仓库拉取最新的代码。
- 如果项目引入了新的依赖,需要执行
pip install -r requirement.txt
安装最新依赖。 - 如果修改或新增了项目静态文件,需要执行
python manage.py collectstatic
收集静态文件。 - 如果数据库发生了变化,需要执行
python manage.py migrate
迁移数据库。 - 重启 Nginx 和 Gunicorn 使改动生效。
整个过程就是这样,把每一步操作翻译成 Fabric 对应的脚本代码,这样一个自动化部署脚本就完成了。
编写 Fabric 脚本
Fabric 脚本通常位于 fabfile.py 文件里,因此先在项目根目录下建一个 fabfile.py 文件。
根据上述过程编写的脚本代码如下:
blogproject/fabfile.py
from fabric.api import env, run
from fabric.operations import sudo
GIT_REPO = "you git repository" ①
env.user = 'you host username' ②
env.password = 'you host password'
# 填写你自己的主机对应的域名
env.hosts = ['demo.zmrenwu.com']
# 一般情况下为 22 端口,如果非 22 端口请查看你的主机服务提供商提供的信息
env.port = '22'
def deploy():
source_folder = '/home/yangxg/sites/zmrenwu.com/django-blog-tutorial' ③
run('cd %s && git pull' % source_folder) ④
run("""
cd {} &&
../env/bin/pip install -r requirements.txt &&
../env/bin/python3 manage.py collectstatic --noinput &&
../env/bin/python3 manage.py migrate
""".format(source_folder)) ⑤
sudo('restart gunicorn-demo.zmrenwu.com') ⑥
sudo('service nginx reload')
① 你的代码托管仓库地址。
② 配置一些服务器的地址信息和账户信息,各参数的含义分别为:
- env.user:用于登录服务器的用户名
- env.password:用户名对应的密码
- env.hosts:服务器的 IP 地址,也可以是解析到这个 IP 的域名
- env.port:SSH 远程服务器的端口号
③ 需要部署的项目根目录在服务器上的位置。
④ 通过 run
方法在服务器上执行命令,传入的参数为需要执行的命令,用字符串包裹。这里执行了两条命令,不同命令间用 &&
符号连接:
- cd 命令进入到需要部署的项目根目录
- git pull 拉取远程仓库的最新代码
⑤ 对应上述部署过程中 3-5 的几条命令。因为启用了虚拟环境,所以运行的是虚拟环境 ../env/bin/
下的 pip 和 python
⑥ 重启 Gunicorn 和 Nginx,由于这两条命令要在超级权限下运行,所以使用了 sudo
方法而不是 run
方法。
注意全部的脚本代码要放在 deploy 函数里,Fabric 会自动检测 fabfile.py 脚本中的 deploy 函数并运行。
由于脚本中有登录服务器的用户名和密码等敏感信息,不要把 fabfile.py 文件也上传到公开的代码托管仓库。
执行 Fabric 自动部署脚本
进入 fabfile.py 文件所在的目录,在 Python2 的环境下用 fab 命令运行这个脚本文件。
比如我的是 Windows 环境,Python2 安装在 C:\Python27 下,那么运行:
C:\Python27\Scripts\fab deploy
这时 Fabric 会自动检测到 fabfile.py 脚本中的 deploy 函数并运行,你会看到命令行输出了一系列字符串,如果在最后看到
Done.
Disconnecting from zmrenwu.com... done.
说明脚本运行成功。
而如果看到
Aborting.
Disconnecting from zmrenwu.com... done.
说明脚本运行中出错,检查一下命令行输入的错误信息,修复问题后重新运行脚本即可。以后当你在本地开发完相关功能后,只需要执行这一个脚本文件,就可以自动把最新代码部署到服务器了。
总结
本章节的代码位于:Step15: deploy automatically using fabric。
如果遇到问题,请通过下面的方式寻求帮助。
- 在下方评论区留言。
- 将问题的详细描述通过邮件发送到 djangostudyteam@163.com,一般会在 24 小时内回复。
- 在 Pythonzhcn 社区的新手问答版块 发布帖子。
-- EOF --
https://blog.csdn.net/qq_41854273/article/details/83344255
我是通过这个教程安装fabric3的
最后Done.
Disconnecting from 114.55.92.22... done.也成功了,,为啥出现不了博客页面,是哪里出问题了
博主我在跑sudo python3 manage.py makemigrations
import markdownImportError: No module named 'markdown'
会找不到markdown模块
但是用pip安装又会提示Requirement already satisfied: markdown in /home/luzihai/sites/yimo.pro/env/lib/python3.5/site-packages (3.0.1)
你有激活虚拟环境吗?
采用pip3 install fabric3
其他操作没什么变化:
参考
https://blog.csdn.net/qq_41854273/article/details/83344255
回复上面那条,我自己搜索到怎么用密钥文件登陆了
把 env.password 替换为 env.key_filename 即可,如下所示
env.key_filename = '/path/to/key'
替换为你自己的 key 路径即可。
另外我按照博主教程写网站已经上线了 http://blog.mintin.me,自己重写了 CSS,大家互相参考下。
非常感谢博主的教程。
AWS 的服务器用的是密钥文件登录,应该怎么搞哦
博主你好,执行fab deploy 出现这种问题是怎么回事呢?
out: django.core.exceptions.ImproperlyConfigured: You're using the staticfiles app without having set the STATIC_ROOT setting to a filesystem path.
知道错哪里了。。
还有个细节:
还记得在 ubuntu16 下,自动启动 gunicorn 的脚本是不同于博主的,所以gunicorn的重启命令这里也要换掉:
你好,sudo('systemctl restart lenkenlau.service')这里的lenkenlau是什么呀
.service文件应该是你的配置信息,lenkenlau 只是我自定义的名字而已
env.hosts 填域名会报错:查找该域名失败
换成IP地址就好了...不清楚为什么?
能不能写个shell 脚本实现上面的功能
自动部署拉取什么文件的代码?blog等应用里的?
我用 supervisor 更方便。
使用密码不安全的话,fab 脚本 可以考虑使用SSH公私钥登陆。步骤是把本机公钥放到deploy 机器的 .ssh/authorized_keys 文件中。
实测需要先把git仓库文件提交到 github 以后再fab deploy 以后本地的修改才能生效。
out: templates/base.html.bak | 189 ------------------------------------------------------------------------------------------------------- out: 1 file changed, 189 deletions(-)
out: delete mode 100644 templates/base.html.bak
……………………
Done.Disconnecting from www.demonhunter07.com... done.
博主,这个提示是指我的本地仓库与远程仓库没合并还是什么原因? 我记得是已经上传到Github上的了
[www.lhyaiwh.top] out: error: Your local changes to the following files would be overwritten by merge:[www.lhyaiwh.top] out: templates/base.html
[www.lhyaiwh.top] out: Please, commit your changes or stash them before you can merge. [www.lhyaiwh.top] out: Aborting
[www.lhyaiwh.top] out: Fatal error: run() received nonzero return code 1 while executing!
Requested: cd /home/liuhanyu/sites/demo.lhyaiwh.top/blogproject && git pullExecuted: /bin/bash -l -c "cd /home/liuhanyu/sites/demo.lhyaiwh.top/blogproject && git pull" Aborting.
Disconnecting from www.lhyaiwh.top:29490... done.
看来是你pull代码的时候出的问题咯,不好确定,确定脚本没错的话多试几次。
请教杨大!!运行fabfile报错,我在本地添加了服务器上的仓库地址,仍然显示git仓库权限有问题。服务器上的git密钥之前在部署环节就生成好了,请问是怎么回事呢!!
fatal: Could not read from remote repository.
out: Please make sure you have the correct access rights
out: and the repository exists.
out:Fatal error: run() received nonzero return code 1 while executing!
显然是远程仓库出了问题,有可能是权限问题,也可能是网络问题,不好说。
博主我报错如下 我是python2的环境下
C:\Users\zmy\blogo\blogproject>fab deploy
[zhongminyong.tech] Executing task 'deploy'
[zhongminyong.tech] run: cd /home/zmy/sites/zhongminyong.tech/gitskills && git pull
Fatal error: No existing session
Underlying exception:
No existing sessionAborting.
根据异常信息谷歌一下,看不出问题。
一直遇到权限问题,不得不把`run('cd %s && git pull' % source_folder)`改成`sudo('cd %s && git pull' % source_folder)`,我想问下po,怎么在Fabric3切换用户。
我执行`run('su - user')`老是要手动输入密码,然后就不能继续执行了
查一下fabric的文档的,我对这个也不是很清楚。
我将部署过程写进python脚本,然后在服务器上用cron定时任务定期执行该脚本,实现了自动部署,部署结果通过邮件发送到指定邮箱。
有兴趣的可以看看:cron + python 实现自动部署
Greate job!学习了。
进去看了下,python3可以使用fabric3
直接pip install fabric3就可以了
原来如此,知道的晚了
请问层主,去看了你的博客,可以冒昧问一下,前端是用什么工具写的吗,更想做这个风格简约的。
你说的是这个博客吗?github 搜索 mobi.css 即可,一个微软大佬写的微型css库
fabric3,坐等大佬更新博客。
博主你好,我的网站部署之后nginx经常挂掉,可能是什么原因?
服务器不稳定吧。
cd { } 是什么意思
进入 cd 后的目录。
format函数了解一下,这个 {} 与上面的 % 作用基本一样
Traceback (most recent call last): File "/Library/Frameworks/Python.framework/Versions/3.6/bin/fab", line 11, in <module> load_entry_point('Fabric==1.14.0', 'console_scripts', 'fab')() File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/pkg_resources/__init__.py", line 565, in load_entry_point return get_distribution(dist).load_entry_point(group, name) File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/pkg_resources/__init__.py", line 2631, in load_entry_point return ep.load() File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/pkg_resources/__init__.py", line 2291, in load return self.resolve() File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/pkg_resources/__init__.py", line 2297, in resolve module = __import__(self.module_name, fromlist=['__name__'], level=0) File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/fabric/main.py", line 13, in <module> from operator import isMappingTypeImportError: cannot import name 'isMappingType'
这个是怎么回事啊
# 安装fabric
$ sudo apt-get install fabric
怎么执行那个脚本,没有看懂
现在可以用pip3 install fabric3安装依赖在python3环境下运行,我的py2文件夹找不到fab,用这个方法测试脚本成功。
有点没看明白,请问具体是怎么运行的`fab deploy`
博主问个问题,我每次自动化部署之后,数据库是不是就清空了啊?
不会的。
好的,谢谢,
博主你好;
我打算在生产环境下用Mysql数据库;那么每次部署都要修改settings.py文件的数据库配置和DEBUG模式。
是不是太麻烦了,有更好的办法吗?
当然有,在百度或者 google 上搜索会有答案。
以前我学ruby on rails的配置文件就可以分别配置开发环境,测试环境,生产环境的设置。我也百度过,diango的设置貌似有点麻烦。
基本思路也是一样的,把配置文件拆分成生产环境、开发环境两个配置文件,在不同环境下使用不同的配置文件。
好的,谢谢。
我是不把setting.py加入git,即在.gitignore里加入setting.py,手动在服务器上vim setting.py。
这样每次上传代码就不会更新setting.py,本地和服务器就可以同时使用不同setting。
不过如果setting有需要改动的话还得手动登录服务器去修改。
用shell自动化部署也可以把?
用sudo pip install fabric按照fabric 的时候报如下错误:
Command python setup.py egg_info failed with error code 1 in /tmp/pip_build_root/pynaclStoring debug log for failure in /root/.pip/pip.log
博主写得还是很清楚的,自动化部署成功了。
这个脚本不能重复使用吧,不然git pull 那里会报错啊
把 git 的仓库地址改成自己仓库的应该就可以。
../env/bin/pip install -r requirements.txt &&
../env/bin/python3 manage.py collectstatic --noinput &&
../env/bin/python3 manage.py migrate
建议使用绝对路径来写,/home/user/sites/env/bin/*,我用相对路径..执行的时候会报错,换成绝对路径执行就没问题了。
这时 Fabric 会自动检测到 fabfile.py 脚本中的 deploy 函数并运行。貌似不对吧,应该得到"fabfile.py"所在目录执行:fab deploy,是不是?
是的,我的表述可能不够准确,不过我相信你能理解我的意思。
我服务器上是ubuntu系统,这个操作实在服务器上完成还是本地完成?应该在什么环境下输入fab deploy呢?求赐教,这部分有点看不明白~
我自己搞明白了,谢谢哈,本地就可以运行这个fabfile.py~
这条 sudo('restart gunicorn-tianjigo.com') 就出错了
Requested: restart gunicorn-tianjigo.com
Executed: sudo -S -p 'sudo password:' /bin/bash -l -c "restart gunicorn-tianjigo.com"
是不是使用系统第一次sudo,还要把密码输进去呢?
是用的 ubuntu 么?
服务器系统是Ubuntu,本地是win7
有没有在脚本指定密码?看着像是你的 bash 有一些问题,具体问题我也不太清楚,我对 linux 了解也不多。
老铁,你把sudo换成run试一下,如果出现了restart:unknown instance的话那就把restart换成start.
run可以不用验证密码了。
报错
Unable to connect to system bus: Failed to connect to socket /var/run/dbus/system_bus_socket: No such file or directory
用sudo apt-get install dbus解决了
但是又出现了 Rejected send message, 1 matched rules; type="method_call", sender=":1.11" (uid=1000 pid=2280 comm="restart gunicorn-www.ftc300.pub ") interface="com.ubuntu.Upstart0_6.Job" m
ember="Restart" error name="(unset)" requested_reply="0" destination="com.ubuntu.Upstart" (uid=0 pid=1 comm="init")的错误了
so sad~
我只能在心里默默的祝福你了....手动笔芯~
是你的Ubuntu 服务器没有启动 gunicorn-tianjigo.com, 所以不能restart。
需要先在Ubuntu服务器上执行 sudo start gunicorn-tianjigo.com,
然后运行本地 fab deploy
其实你的报错信息应该是 Fatal error: sudo() received nonzero return code 1 while executing!