PS:学习了自动化部署Django项目, 真香!!! 在这里记录一下过程和思路.
首先,查看项目的目录结构(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访问
[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
(pythonTDD-env) [root@bogon PythonTDD]# cd superlists/deploy_tools/
(pythonTDD-env) [root@bogon deploy_tools]# touch fabfile.py
#引用自: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')
(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.
完毕!!!