在Linux(CentOS7)中使用Fabric自动部署Django项目

PS:学习了自动化部署Django项目, 真香!!! 在这里记录一下过程和思路.

文章目录

  • 准备工作
  • 1.安装Fabric
  • 2.创建fabric.py
  • 3.编写脚本
  • 5.运行脚本

准备工作

首先,查看项目的目录结构(GitHub远程仓库中的目录结构等同)

ps:使用命令tree -L 3生成

PythonTDD
├── database
│   └── db.sqlite3
├── requirements.txt
├── static
│   ├── admin
│   │   ├── css
│   │   ├── fonts
│   │   ├── img
│   │   └── js
│   ├── base.css
│   └── bootstrap
│       ├── css
│       └── js
└── superlists
    ├── deploy_tools
    │   ├── gunicorn-systemd.template.service
    │   └── nginx.template.conf
    ├── functional_tests
    │   ├── __pycache__
    │   └── tests.py
    ├── geckodriver
    ├── geckodriver.log
    ├── __init__.py
    ├── lists
    │   ├── admin.py
    │   ├── apps.py
    │   ├── migrations
    │   ├── models.py
    │   ├── __pycache__
    │   ├── static
    │   ├── templates
    │   ├── tests.py
    │   ├── urls.py
    │   └── views.py
    ├── manage.py
    └── superlists
        ├── asgi.py
        ├── __init__.py
        ├── __pycache__
        ├── settings.py
        ├── urls.py
        └── wsgi.py

默认已经在服务器中配置过GitHub的SSH访问

1.安装Fabric

[tu@bogon root]$ pip3 install wheel		#提前安装依赖
[tu@bogon root]$ pip3 install fabric3
[tu@bogon deploy_tools]$ fab -V		#检查fab命令是否可用
Fabric3 1.14.post1
Paramiko 2.7.1

ps:如果fab命令不可用,注意检查在系统环境变量中是否设置Python环境变量

[tu@bogon deploy_tools]$ vim /etc/profile

#Python Path
export PYTHON_HOME=/opt/python3.7
export PATH=$PATH:$PYTHON_HOME/bin

2.创建fabric.py

(pythonTDD-env) [root@bogon PythonTDD]# cd superlists/deploy_tools/
(pythonTDD-env) [root@bogon deploy_tools]# touch fabfile.py

3.编写脚本

#引用自:https://github.com/hjwp/book-example/blob/chapter_11/deploy_tools/fabfile.py

from fabric.contrib.files import append,exists,sed
from fabric.api import env,local,run
import random

REPO_URL='https://github.com/FireFreedomK/PythonTDD.git'

def deploy():
    site_folder = '/home/%s/sites/%s' % (env.user, env.host)        #用于放置项目的文件夹
    source_folder = site_folder + '/source'                         #用于防止项目源代码的文件夹
    _create_directory_structure_if_necessary(site_folder)           #在服务器中创建项目的目录结构
    _get_latest_source(source_folder)                               #从GitHub中拉取源代码到服务器中
    _update_settings(source_folder, env.host)                       #更新项目的settings.py,设置DEBUG=False,设置允许访问项目的IP
    _update_virtualenv(source_folder)                               #创建或更新项目环境
    _update_static_files(source_folder)                             #创建或更新项目静态文件
    _update_database(source_folder)                                 #迁移或更新项目数据库

def _create_directory_structure_if_necessary(site_folder):
    for subfolder in ('database','static','virtualenv','source'):
        run(f'mkdir -p {site_folder}/{subfolder}')

def _get_latest_source(source_folder):
    if exists(source_folder + '/.git'):
        run('cd %s && git fetch' % (source_folder,))
    else:
        run('git clone %s  %s' % (REPO_URL, source_folder))
    current_commit = local("git log -n 1 --format=%H", capture=True)
    run('cd %s && git reset --hard %s' % (source_folder, current_commit))

def _update_settings(source_folder,site_name):
    settings_path=source_folder+'/superlists/superlists/settings.py'
    sed(settings_path,"DEBUG=True","DEBUG=False")
    sed(settings_path,
        'ALLOWED_HOSTS=.+$',
        f'ALLOWED_HOSTS=["{site_name}"]'
        )
    secret_key_file=source_folder+'/superlists/secret_key.py'
    if not exists(secret_key_file):
        chars='qazwsxedcrfvtgb1234567890-='
        key=''.join(random.SystemRandom().choice(chars) for _ in range(50))
        append(secret_key_file,f'SECRET_KEY="{key}"')
    append(settings_path,'\nfrom .secret_key import SECRET_KEY')

def _update_virtualenv(source_folder):
    virtualenv_folder=source_folder+'/../virtualenv'
    if not exists(virtualenv_folder+'/bin/pip'):
        run(f'python3.7 -m venv {virtualenv_folder}')

    run(f'{virtualenv_folder}/bin/pip install -r {source_folder}/requirements.txt')

def _update_static_files(source_folder):
    run('cd %s && ../virtualenv/bin/python  ./superlists/manage.py collectstatic --noinput' % (
        source_folder,
    ))

def _update_database(source_folder):
    run(f'cd {source_folder}'
        ' && ../virtualenv/bin/python ./superlists/manage.py migrate --noinput')    

5.运行脚本

(ps:自动化真爽,看着一行一行的代码无误差的刷屏,真的太赞了)

[tu@bogon deploy_tools]$ fab deploy:host=tu@localhost
deploy:host=tu   #是服务器中的用户名
localhost		#站点名称,我这里用的是localhost

会提示你输入用户密码

[tu@localhost] Executing task 'deploy'
[tu@localhost] run: mkdir -p /home/tu/sites/localhost/database
[tu@localhost] Login password for 'tu':

[tu@localhost] run: mkdir -p /home/tu/sites/localhost/static
[tu@localhost] run: mkdir -p /home/tu/sites/localhost/virtualenv
[tu@localhost] run: mkdir -p /home/tu/sites/localhost/source
[tu@localhost] run: git clone https://github.com/FireFreedomK/PythonTDD.git  /home/tu/sites/localhost/source
[tu@localhost] out: 正克隆到 '/home/tu/sites/localhost/source'...
[tu@localhost] out: remote: Enumerating objects: 483, done.
[tu@localhost] out: remote: Counting objects:   0% (1/483)
[tu@localhost] out: remote: Counting objects:   1% (5/483)
[tu@localhost] out: remote: Counting objects:   2% (10/483)
[tu@localhost] out: remote: Counting objects:   3% (15/483)
[tu@localhost] out: remote: Counting objects:   4% (20/483)
[tu@localhost] out: remote: Counting objects:   5% (25/483)
[tu@localhost] out: remote: Counting objects:   6% (29/483)
[tu@localhost] out: remote: ...............................
[tu@localhost] out: remote: Compressing objects: 100% (227/227)
[tu@localhost] out: remote: Compressing objects: 100% (227/227), done.
[tu@localhost] out: 接收对象中:   0% (1/483)
[tu@localhost] out: 接收对象中:   1% (5/483)
[tu@localhost] out: 接收对象中:............................   
[tu@localhost] out: 接收对象中: 100% (483/483), 1.04 MiB | 18.00 KiB/s
[tu@localhost] out: 接收对象中: 100% (483/483), 1.06 MiB | 18.00 KiB/s, done.
[tu@localhost] out: 处理 delta 中:   0% (0/244)
[tu@localhost] out: 处理 delta 中:   1% (3/244)
[tu@localhost] out: 处理 delta 中:   2% (5/244)
[tu@localhost] out: 处理 delta 中:.........................   
[tu@localhost] out: 处理 delta 中: 100% (244/244)
[tu@localhost] out: 处理 delta 中: 100% (244/244), done.
[tu@localhost] out:

[localhost] local: git log -n 1 --format=%H
[tu@localhost] run: cd /home/tu/sites/localhost/source && git reset --hard 0ef54a43adbd6a10ef9ff5c3f433f04c53cd2188
[tu@localhost] out: HEAD 现在位于 0ef54a4 在database下添加.gitkeep文件
[tu@localhost] out:

[tu@localhost] run: sed -i.bak -r -e 's/DEBUG=True/DEBUG=False/g' "$(echo /home/tu/sites/localhost/source/superlists/superlists/settings.py)"
[tu@localhost] run: sed -i.bak -r -e 's/ALLOWED_HOSTS=.+$/ALLOWED_HOSTS=["localhost"]/g' "$(echo /home/tu/sites/localhost/source/superlists/superlists/settings.py)"
[tu@localhost] run: echo 'SECRET_KEY="=1f1882gvq-b=52z6cag78s67=2czg80bt4d94d22e6wa495e7"' >> "$(echo /home/tu/sites/localhost/source/superlists/secret_key.py)"
[tu@localhost] run: python3.7 -m venv /home/tu/sites/localhost/source/../virtualenv
[tu@localhost] run: /home/tu/sites/localhost/source/../virtualenv/bin/pip install -r /home/tu/sites/localhost/source/requirements.txt
[tu@localhost] out: Collecting asgiref==3.2.7 (from -r /home/tu/sites/localhost/source/requirements.txt (line 1))
[tu@localhost] out:   Using cached https://files.pythonhosted.org/packages/68/00/25013f7310a56d17e1ab6fd885d5c1f216b7123b550d295c93f8e29d372a/asgiref-3.2.7-py2.py3-none-any.whl
[tu@localhost] out: Collecting Django==3.0.5 (from -r /home/tu/sites/localhost/source/requirements.txt (line 2))
[tu@localhost] out:   Using cached https://files.pythonhosted.org/packages/a9/4f/8a247eee2958529a6a805d38fbacd9764fd566462fa0016aa2a2947ab2a6/Django-3.0.5-py3-none-any.whl
[tu@localhost] out: Collecting pytz==2019.3 (from -r /home/tu/sites/localhost/source/requirements.txt (line 3))
[tu@localhost] out:   Using cached https://files.pythonhosted.org/packages/e7/f9/f0b53f88060247251bf481fa6ea62cd0d25bf1b11a87888e53ce5b7c8ad2/pytz-2019.3-py2.py3-none-any.whl
[tu@localhost] out: Collecting selenium==3.141.0 (from -r /home/tu/sites/localhost/source/requirements.txt (line 4))
[tu@localhost] out:   Using cached https://files.pythonhosted.org/packages/80/d6/4294f0b4bce4de0abf13e17190289f9d0613b0a44e5dd6a7f5ca98459853/selenium-3.141.0-py2.py3-none-any.whl
[tu@localhost] out: Collecting sqlparse==0.3.1 (from -r /home/tu/sites/localhost/source/requirements.txt (line 5))
[tu@localhost] out:   Using cached https://files.pythonhosted.org/packages/85/ee/6e821932f413a5c4b76be9c5936e313e4fc626b33f16e027866e1d60f588/sqlparse-0.3.1-py2.py3-none-any.whl
[tu@localhost] out: Collecting urllib3==1.25.8 (from -r /home/tu/sites/localhost/source/requirements.txt (line 6))
[tu@localhost] out:   Using cached https://files.pythonhosted.org/packages/e8/74/6e4f91745020f967d09332bb2b8b9b10090957334692eb88ea4afe91b77f/urllib3-1.25.8-py2.py3-none-any.whl
[tu@localhost] out: Installing collected packages: asgiref, pytz, sqlparse, Django, urllib3, selenium
[tu@localhost] out: Successfully installed Django-3.0.5 asgiref-3.2.7 pytz-2019.3 selenium-3.141.0 sqlparse-0.3.1 urllib3-1.25.8
[tu@localhost] out: WARNING: You are using pip version 19.2.3, however version 20.1 is available.
[tu@localhost] out: You should consider upgrading via the 'pip install --upgrade pip' command.
[tu@localhost] out:

[tu@localhost] run: cd /home/tu/sites/localhost/source && ../virtualenv/bin/python  ./superlists/manage.py collectstatic --noinput
[tu@localhost] out:
[tu@localhost] out: 130 static files copied to '/home/tu/sites/localhost/source/static', 21 unmodified.
[tu@localhost] out:

[tu@localhost] run: cd /home/tu/sites/localhost/source && ../virtualenv/bin/python ./superlists/manage.py migrate --noinput
[tu@localhost] out: Operations to perform:
[tu@localhost] out:   Apply all migrations: admin, auth, contenttypes, lists, sessions
[tu@localhost] out: Running migrations:
[tu@localhost] out:   Applying contenttypes.0001_initial... OK
[tu@localhost] out:   Applying auth.0001_initial... OK
[tu@localhost] out:   Applying admin.0001_initial... OK
[tu@localhost] out:   Applying admin.0002_logentry_remove_auto_add... OK
[tu@localhost] out:   Applying admin.0003_logentry_add_action_flag_choices... OK
[tu@localhost] out:   Applying contenttypes.0002_remove_content_type_name... OK
[tu@localhost] out:   Applying auth.0002_alter_permission_name_max_length... OK
[tu@localhost] out:   Applying auth.0003_alter_user_email_max_length... OK
[tu@localhost] out:   Applying auth.0004_alter_user_username_opts... OK
[tu@localhost] out:   Applying auth.0005_alter_user_last_login_null... OK
[tu@localhost] out:   Applying auth.0006_require_contenttypes_0002... OK
[tu@localhost] out:   Applying auth.0007_alter_validators_add_error_messages... OK
[tu@localhost] out:   Applying auth.0008_alter_user_username_max_length... OK
[tu@localhost] out:   Applying auth.0009_alter_user_last_name_max_length... OK
[tu@localhost] out:   Applying auth.0010_alter_group_name_max_length... OK
[tu@localhost] out:   Applying auth.0011_update_proxy_permissions... OK
[tu@localhost] out:   Applying lists.0001_initial... OK
[tu@localhost] out:   Applying lists.0002_item_text... OK
[tu@localhost] out:   Applying lists.0003_list... OK
[tu@localhost] out:   Applying lists.0004_item_list... OK
[tu@localhost] out:   Applying sessions.0001_initial... OK
[tu@localhost] out:


Done.
Disconnecting from localhost... done.

完毕!!!

你可能感兴趣的:(Python测试驱动开发,Django,CentOS)