Fabric部署、维护
Fabric的应用范围是自动化运维,可以让以往需要ssh链接到远程服务器执行的部署、更新命令写入脚本中自动完成,大大降低项目部署、维护的成本, 官方文档:http://www.fabfile.org/。
指定hosts
:
from fabric.api import *
env.hosts = ['dreamgo@192.168.1.102:22', ]
env.passwords = {
'dreamgo@192.168.1.102:22': 'dreamgo',
}
# >fab -H dreamgo@192.168.1.10:22 host_type
@hosts('dreamgo@192.168.1.102:22')
def host_type():
with cd('/django/SchoolMS_Server/SchoolMS'):
run('uname -s')
run('service apache2 reload')
指定roles
:
from fabric.api import *
env.roledefs = {
'test_server': ['dreamgo@192.168.1.102:22'],
}
env.passwords = {
'dreamgo@192.168.1.102:22': 'dreamgo',
}
# >fab -R test_server host_type
@roles('test_server')
def host_type():
with cd('/django/SchoolMS_Server/SchoolMS'):
run('uname -s')
run('service apache2 reload')
Django
刷新程序命令:
from fabric.api import *
from contextlib import contextmanager as _contextmanager
env.roledefs = {
'test_server': ['dreamgo@192.168.1.102:22'],
}
env.passwords = {
'dreamgo@192.168.1.102:22': 'dreamgo',
}
env.directory = '/django/SchoolMS_Server/'
env.activate = 'source environment/bin/activate'
@_contextmanager
def virtualenv():
with cd(env.directory):
with prefix(env.activate):
yield
@roles('test_server')
def update():
with virtualenv():
run('git pull origin master')
run('python manage.py makemigrations')
run('python manage.py migrate')
run('deactivate')
run('service apache2 reload')
执行结果:
(environment) C:\django\SchoolMS\SchoolMS>fab update
[dreamgo@192.168.1.102:22] Executing task 'update'
[dreamgo@192.168.1.102:22] run: git pull origin master
[dreamgo@192.168.1.102:22] out: 来自 https://git.coding.net/name/xxxx.git
[dreamgo@192.168.1.102:22] out: * branch master -> FETCH_HEAD
[dreamgo@192.168.1.102:22] out: 更新 94bdffc..6e43223
[dreamgo@192.168.1.102:22] out: Fast-forward
[dreamgo@192.168.1.102:22] out: SchoolMS/fabfile.py | 30 ?[32m++++++++++++++++++++++++++++++?[m
[dreamgo@192.168.1.102:22] out: requirements.txt | 3 ?[32m++?[m?[31m-?[m
[dreamgo@192.168.1.102:22] out: 2 files changed, 32 insertions(+), 1 deletion(-)
[dreamgo@192.168.1.102:22] out: create mode 100644 SchoolMS/fabfile.py
[dreamgo@192.168.1.102:22] out:
[dreamgo@192.168.1.102:22] run: python manage.py makemigrations
[dreamgo@192.168.1.102:22] out: No changes detected
[dreamgo@192.168.1.102:22] out:
[dreamgo@192.168.1.102:22] run: python manage.py migrate
[dreamgo@192.168.1.102:22] out: ?[36;1mOperations to perform:?[0m
[dreamgo@192.168.1.102:22] out: ?[1m Apply all migrations: ?[0madmin, auth....
[dreamgo@192.168.1.102:22] out: ?[36;1mRunning migrations:?[0m
[dreamgo@192.168.1.102:22] out: No migrations to apply.
[dreamgo@192.168.1.102:22] out:
[dreamgo@192.168.1.102:22] run: deactivate
[dreamgo@192.168.1.102:22] run: service apache2 reload
[dreamgo@192.168.1.102:22] out: * Reloading web server apache2
[dreamgo@192.168.1.102:22] out: *
[dreamgo@192.168.1.102:22] out:
Done.
Disconnecting from dreamgo@192.168.1.102... done.
创建数据库的两种方法:
run('echo "drop database if exists {};"|mysql --batch --user=root --password'.format(env.db), pty=True)
run('echo "create database {} default character set utf8;"|mysql --batch --user=root --password'.format(env.db),
pty=True)
run('mysql -uroot -p -e "drop database if exists {}"'.format(env.db))
run('mysql -uroot -proot -e "CREATE DATABASE {} DEFAULT CHARACTER set utf8"'.format(env.db))
常用命令:
小技巧:
- passwords指定为''时运行命令时会提示输入密码。
- 远程服务器为
python2
和python3
共存,以python3
为默认python
的服务器,使用命令python2 -m pip install Fabric
来安装。本地服务器只有python3
环境,使用命令pip install Fabric3
来安装。 - Fabric3 的
requirements.txt
应写为Fabric3==1.13.1.post1
。 - 只需要本地安装Fabric即可,不要求远程也安装Fabric(所以无需把
Fabric3==1.13.1.post1
写入requirements.txt
文件)。
Django常用的部署、更新脚本
fabfile.py(推荐放置在
manage.py`所在的根目录):
from fabric.api import *
from fabric.contrib import django, files
from contextlib import contextmanager as _contextmanager
django.settings_module('NingTe.settings')
from django.conf import settings
_ = settings.INSTALLED_APPS
env.roledefs = {
'test_server': ['dreamgo@192.168.1.102:22'],
}
env.passwords = {
'dreamgo@192.168.1.102:22': '',
}
# 项目存放目录
env.directory = '/django/portal/'
# 虚拟环境目录 从项目根目录算起 environment为默认的虚拟环境文件夹名称
env.activate = 'source environment/bin/activate'
# git仓库地址
env.repo = ''
env.db = settings.DATABASES['default']['NAME']
@_contextmanager
def virtualenv():
with cd(env.directory):
with prefix(env.activate):
yield
# 数据库、目录、克隆代码、环境安装、插件安装、迁移数据库、创建超管
# >fab create 一键部署
@roles('test_server')
def create():
run('mysql -uroot -p -e "drop database if exists {}"'.format(env.db))
run('mysql -uroot -p -e "create database {} default character set utf8"'.format(env.db))
run('rm -rf {}'.format(env.directory))
run('mkdir {}'.format(env.directory))
run('git clone {} {}'.format(env.repo, env.directory))
with cd(env.directory):
run('virtualenv environment')
with virtualenv():
run('pip install -r requirements.txt -i https://pypi.douban.com/simple')
run('python manage.py makemigrations')
run('python manage.py migrate')
run('python manage.py createsuperuser --username=username --email=ykh@dreamgo.tech')
run('deactivate')
# 拉取代码、迁移数据库、重载Apache
# >fab update 一键维护
@roles('remote_server')
def update():
with virtualenv():
run('git stash')
run('git pull')
run('git stash pop')
run('pip install -r requirements.txt -i https://pypi.douban.com/simple')
run('python manage.py makemigrations')
run('python manage.py migrate')
run('deactivate')
run('service apache2 reload')
# 创建并配置Apache的conf文件 server_name-域名或IP environment为默认的虚拟环境文件夹名称
# >fab apache_conf 一键配置Apache设置
@roles('test_server')
def apache_conf():
directory = env.directory.rstrip('/')
run('chmod -R 777 {}'.format(env.directory))
file_path = '/etc/apache2/sites-available/'
filename = 'portal.conf'
with cd(file_path):
run('rm -f {}'.format(filename))
run('touch {}'.format(filename))
server_name = 'blog.dreamgotech.com'
apache_template = \
'<VirtualHost *:8001>\n' \
' ServerName {server_name}\n' \
' ServerAdmin ykh@dreamgo.tech\n' \
' DocumentRoot {document_root}\n' \
' \n' \
' Alias /static {document_root}/static \n' \
' <Directory {document_root}/static>\n' \
' Require all granted\n' \
' </Directory>\n' \
' \n' \
' Alias /media {document_root}/media\n' \
' <Directory {document_root}/media> \n' \
' Require all granted\n' \
' </Directory>\n' \
' \n' \
' <Directory {document_root}/Portal>\n' \
' <Files wsgi.py>\n' \
' Require all granted\n' \
' </Files>\n' \
' </Directory>\n' \
' \n' \
' WSGIPassAuthorization On\n' \
' WSGIDaemonProcess {server_name} python-path={document_root} python-home={document_root}/environment \n' \
' WSGIProcessGroup {server_name}\n' \
' WSGIScriptAlias / {document_root}/Portal/wsgi.py\n' \
' \n' \
' ErrorLog {document_root}/log/error.log\n' \
'</VirtualHost>\n'.format(server_name=server_name, document_root=directory)
files.append(filename, apache_template)
run('sudo a2dissite {}'.format(filename))
run('sudo a2ensite {}'.format(filename))
run('service apache2 reload')
# usage:fab cmd:"service apache2 reload"
@roles('test_server')
def cmd(cmd_str=''):
run(cmd_str)