从零开始搭建一个完整的web全栈开发环境并实现服务器部署(pycharm +Ubuntu+ django+uwsgi+nginx + neo4j/MySQL)
写在前面:这基本是我第一次着手去搭建一套开发环境,从软件到依赖包到服务器部署,代码同步调试,从零看着一大堆资料到搭建出一个基本的开发环境并成功运行,我觉得有必要把其中的过程和对我有帮助的资料重新整理linux操作:由于服务器系统大多在linux系统运行,所以熟练掌握linux的各种基本命令是非常重要的,但我觉得,单纯去学命令容易没有条理,可以跟着教程一步步做着去学,也能掌握每一步命令的用途...
写在前面:
这基本是我第一次着手去搭建一套开发环境,从软件到依赖包到服务器部署,代码同步调试,从零看着一大堆资料到搭建出一个基本的开发环境并成功运行,我觉得有必要把其中的过程和对我有帮助的资料重新整理
Mark Zuckberg —社交网络 2018
本文初稿完成于 19 年 8 月,例子和命令可能有些老旧,当时我才刚开始接触服务器端开发与部署,也算是边动手边整理,算是对我当时的思路的留念
基本配置:
开发机:
- 系统:win10
- IDE: Pycharm pro 2019
服务器环境:
- 系统: Ubuntu18.04
- Web服务器: nginx
- WSGI接口:uwsgi
- 开发框架:Django 2.2
- 后端语言:Python 3.7.3
- 数据库:MySQL 5.7
前端开发环境搭建
1.Chrome浏览器
由于我们开发的前端网页都是在浏览器中运行,而目前市场上的浏览器又是五花八门,存在不少兼容性问题,选择市场占有率最高,且方便开发调试的Chrome浏览器是开发前的首要工作
直接进入链接下载
https://www.google.cn/chrome/
Chrome 开发者工具
Chrome 开发者工具大大方便了网页调试,打开工具的方式是F12或者右键网页页面,选择检查
开发者工具由几个板块组成,他们的作用是
Network
网络面板,Network面板用于web抓包,记录了每条网络操作的相关信息
Chrome 插件
https://chrome.google.com/webstore/category/extensions
2.前端开发IDE
3. node.js运行环境
js的包管理工具依赖于node.js运行环境,我们先安装,直接进入官网,选择稳定LTS版本
https://nodejs.org
安装中需要选中ADD TO PATH,安装后打开cmd,运行node -v,成功即表明安装成功

4. 包管理工具安装
npm
npm 是node自带的包管理工具,安装node后默认安装
yarn
npm虽然是默认的js包管理工具,但有许多历史遗留的常见问题,为了对包管理的性能做出改进,yarn应运而生
官方对yarn的介绍
速度超快
Yarn 缓存了每个下载过的包,所以再次使用时无需重复下载。 同时利用并行下载以最大化资源利用率,因此安装速度更快。
超级安全
在执行代码之前,Yarn 会通过算法校验每个安装包的完整性。
超级可靠
使用详细、简洁的锁文件格式和明确的安装算法,Yarn 能够保证在不同系统上无差异的工作。
——————————————————————————————————————————
安装
npm install -g yarn
查看安装成功
webpack
eslint
准备篇
0.申请服务器
这一步不再赘述(之前是拿学校的云主机当例子但不具有普适性,所以删了),随便选一个云厂商把服务器买下来就好了
1.安装Xshell与Xftp
有了可以使用的云服务器,我们就需要对它进行操作,因此我们需要能与服务器建立会话并且能进行文件传输的工具,这就是Xshell与Xftp。
Xshell是一个强大的终端模拟软件,你可以通过Xshell在本地开发机上连接服务器进行远程控制,Xftp可以与服务器进行上传或下载文件的服务
这两个软件在官网上可以通过邮箱进行免费使用
https://www.netsarang.com/zh/free-for-home-school/
填入姓名与邮箱后,下载链接会发送到你的邮箱里

接着下载安装后打开Xshell,在左上角选择新建会话,输入一个名称和你主机的ip地址,点击确定并连接,接着会让你输入你的主机密码,可以在自己的电脑上点击记住密码,方便下次连接
打开Xftp,以同样的方式新建会话并连接,输入你主机的用户名(默认为root) 与密码
之后就形成了一个本地-服务器连接的工作区,可以上传下载文件,也可以通过命令行操作服务器
升级服务器
当服务器系统版本过旧,可以进行升级,一般当服务器可以升级时都会在连接时进行提示,如
输入
do-release-upgrade
之后会有很多让你选择的操作,全部输入y即可,安装之后会重启终端,系统就升级完毕了
更改主机名:主机名一般由云服务器厂商为你分配,如果想更改,按如下步骤:
vi /etc/cloud/cloud.cfg
修改preserve_hostname为true
vi /etc/hostname
将其中的字段改为你要设置的名称
vi /etc/hosts
在127.0.0.1 localhost 后加自己设置的主机名
随后重启服务器(不是重启Shell) 即可看到主机名称完成更改
2.linux操作
由于服务器系统大多在linux系统运行,所以熟练掌握linux的各种基本命令是非常重要的,但单纯去学命令容易没有条理,可以跟着教程一步步做着去学,也能掌握每一步命令的用途。
但一开始,熟悉一些必要的命令是有帮助的,我把一些在服务器中常用的linux命令和基本的linux常识列出(#是注释):
linux常识
linux相信大家不陌生,这是Linus Torvalds在1991年发布的一个基于UNIX内核的开源操作系统内核,尤其适合多用户、多任务、多线程和多cpu的网络作业,所以被广泛用于服务器操作系统
在linux内核的基础上又诞生出了不少发行版系统,可以分为两个系列redhat和Debian,分别衍生出了目前使用范围最广的两个操作系统CentOS与Ubuntu
sudo apt-get install XXX #安装XXX组件
find / -name 'XXX' #查找名为XXX的文件或文件夹
#cd 目录地址 :进入该目录
cd 或 cd~ #进入root文件夹
cd / #进入根文件夹
cd .. #退到上级目录
cd /home
ls 目录地址:列出该目录下的文件和文件夹
ls #列出当前目录的文件和文件夹
ls /etc
Tips: 在实际开发过程中肯定还是会碰到没见过的命令,好习惯是先查一下用法,不要乱用,linux的简单粗暴既是优点也是缺点,有时一行命令就能发生 清空数据库/删除系统文件/电脑开不了机…等等可怕的事情,在网上或书上看到的命令一定要结合自己机器的情况比如系统版本,具体的目录和文件名称,切忌照搬命令。
3.整体的架构
在了解配置环境之前,我们需要对所配置的环境的各个组件的作用作出了解,在实际配置时,不能一味跟着步骤走,否则如果有一步跟步骤的操作不一样就变得无从下手,为此,我绘制了两张图,一张是用户访问web应用的后台处理机制,一张是开发者开发测试的机制,跟着这两张图,一步一步配置整体的环境
本地篇
0.本地python的安装与配置
在官网下载最新版python到本地,在官网下载页选择 x86-64 executable(可执行版本)
https://www.python.org/downloads/release/python-373/
在安装时需要选中 Add python3.7 to PATH
安装完成后在cmd中输入
python -V
检查版本号,出现相关版本字样即表示安装成功
1. 本地Web测试环境的配置
有了python环境,就可以搭建一个本地的Web应用测试环境,只需要安装django框架并利用其内置的服务器即可
在开始搭建本地Web测试环境之前,我们先回顾几个基本的概念与命令
基本概念:
-
python解释器 (Interpreter):在每台计算机中都可以安装多个python版本,他们有着不同的地址,甚至也可以安装两个相同版本不同地址的python,每个python安装目录下都有一个python.exe,这被称为一个解释器,不同于编译器,解释器可以使得python边解释边执行,而不是像C一样整体编译。
-
python虚环境 (virtual environment):为了项目的依赖独立而创建出的python虚拟运行环境,解决不同项目之间包与解释器版本的依赖冲突问题,继承于一个python解释器,virtualenv在创建环境时会生成一个含有python解释器和依赖包的文件夹,虚环境解释器继承系统的解释器版本,在Scripts文件夹下,在虚环境中安装的包在Lib->site-packages文件夹下,这样便实现了包的隔离

现有成熟的虚环境工具有virtualenv,Anaconda,pyenv等 -
python包/模块 (Module):Python模块是一个 Python 文件,以 .py 结尾,包含Python 对象定义和Python语句,模块可以定义函数,类和变量,包含可执行的代码,能够通过import有逻辑地组织 Python 代码段,我们将会用到Django等python包
具体关系如下图所示
基本命令:
- python:在命令行中输入python命令会运行一个解释器,这个解释器的位置在windows系统中取决于系统的Path环境变量,在linux系统中取决于\bin下python指令的软链接所指的位置
- pip:pip是python自带的一个包管理工具,每个python解释器(包括虚环境的解释器)都含有一个pip工具,当系统使用一个python解释器时(由环境变量配置或者虚环境激活)进行pip install命令会将包装入该解释器文件夹下的Lib->site-packages文件夹
对于命令的一个约定俗成的规范是使用 **命令 help (–help等变体)**查看该命令的用法
如:

在cmd中可以用pip 快速进行python包的安装,以安装python虚环境为例,可以了解pip命令的基本用法
pip install virtualenv
在命令行当前目录下 (可以用cd命令实现目录跳转)创建virtualenv环境并建立同名文件夹
virtualenv testVenv
默认情况下新的环境会安装pip,setuptools等基本的包,如果还需要继承系统python解释器中的包,需要使用
virtualenv --system-site-packages testVenv
更多功能也可以用
virtualenv -h
查看,接下来激活环境,就在当前目录直接输入以下命令激活
testVenv\Scripts\activate

可以看到新的虚环境中只安装了必需的包,在该环境激活的状态下,使用pip命令会将包安装到该虚环境文件夹下
以同样方法执行
testVenv\Scripts\deactivate
即可使环境失效
在该环境下,我们安装django框架
pip install django
查看版本号,正常出现即安装成功
python
>>> import django
>>> django.VERSION
(2, 2, 3, 'final', 0)
在命令行当前目录下创建项目与应用:
django-admin startproject 项目名称
生成后可以看到工程文件的目录
可以看到在工程目录下有一个同名的文件夹,里面是一些基本的网站配置文件
我们所说的工程目录,就指的是你创建的django project的目录
例如你在 D:\Website\Django\ 目录下 startproject mysite
那么你的网站工程目录即为 D:\Website\Django\mysite
工程目录的确定很重要,决定了网站后续的URL配置
可以先测试一下django是否可以访问,使用django内置的web Server启动,命令行在工程目录输入
python manage.py runserver 0.0.0.0:8001
在工程目录下输入命令即你的命令行停留在工程目录时输入命令
打开浏览器,在地址栏输入 localhost:8001 若看到有django火箭,即说明成功,事实上,若在主机ip上开放端口,启动服务,在可路由的任何一台联网的机器上都可以通过ip:端口号对你开放的django服务进行访问
可以看到主机WLAN 的IPv4地址,再打开工程目录下同名文件夹下的 settings.py,将其中ALLOWED_HOSTS 改为[“ip”],ALLOWED_HOSTS表示当下这个Django站点可以提供的host/domain(主机/域名)。
在工程目录下启动服务器
python manage.py runserver ip:port
如下图所示

至此,完整的本地web测试环境已经搭建完毕,之后在服务器端部署后可以在本地进行开发,测试无误后再上传到服务器。
2.Pycharm 专业版安装与服务器部署配置
https://www.jetbrains.com/pycharm/download/#section=windows
选择下载Windows下的Pro版本
在本地安装,在激活时选择JetBrains Account,填入注册的账号密码

之后就可以使用Pycharm专业版了,选择New Project->Django
在Project Interpreter里选择项目和对应虚环境的地址,用Virtualenv可以很好的实现项目之间环境的隔离,避免包的版本冲突问题
在Base Interpreter里选择安装python3.7地址里的python.exe文件
pycharm还有一个非常强大的包管理功能,在File->Settings->Project Interpreter
中可以看到目前在这个环境中安装的所有包
并且点击右边的 + 按钮即可搜索并安装目前任意的公共python包,比pip命令更加直观
点击左下角的Install Package即可将这个包安装到当前的环境。
插话: 对于python的包和环境,很多人在一开始接触时容易理不清,可以画一张图来解释

而虚环境或者其他的所有环境都需要依赖于某个解释器(Base Interpreter),也就是一个解释器可以承载很多虚环境
而在每个虚环境中,都可以安装任意的(不冲突的)python包。
//说到底,造成python环境和包繁多的原因就是python是个开源语言,它的版本和开发者所开发的包以及包版本都太多了,为了方便开发者针对每个项目的管理,才有了虚环境这个中间层作连接,使得不同的包的集合封装在不同的虚环境中,并依附于某个python解释器,互相不影响。
配置pycharm的服务器部署功能
在之前我们已经申请过一个服务器,接下来需要在服务器上部署后台代码,来提供网站的服务,使用Pycharm的Deployment可以方便的实现
打开pycharm,打开Tools->Deployment->Configuration
点击选项卡左上角的 + 新建服务器,服务器名字自定义
随后在Host:一栏填入ip,User name: 和Password:按照服务器的配置填写用户名与密码
Autodetect一下root路径,如果显示为/root说明与服务器连接成功
接着点击Mappings,设置Deployment path为你的工程目录,接着点击OK
在界面右边栏点击
如果没有对应图标,点击Tools->Deployment->Browse Remote Host
即可看到工程文件与服务器的root目录
在工程目录里的每个文件与文件夹都可以右键在Deployment->Upload to XXX 上传到服务器,接着就可以把你本地的工程文件夹进行上传
部署完成后Tools->Deployment->Configuration会有很多选项,既可以上传也可以下载,如果希望自动上传,可以选择Automatic Upload,不过不建议这样做
理想的开发流程应该是,本地代码开发->本地服务器(localhost) 测试–(测试无问题)–>上传到服务器–>访问服务器ip再次测试
虽然可以用pycharm实现文件的上传与下载,但这只是在本地工程目录—服务器工程目录进行的,之前安装的Xshell和Xftp负责在任意目录上传下载文件并且实现对服务器的远程控制。
2.本地测试环境的部署与版本管理
在实际开发中,一般先在本地测试无误后再进行服务器部署,保证项目的安全稳定性,并且相当于一个本地备份,本地化测试和github上的版本分支管理与测试属于程序员的必备技能,就由这段教程进行演示
版本管理
VCS(Version Control System):版本控制系统,一种用于记录一个或多个文件内容变化,方便我们查阅特定版本修订情况的系统,早期的VCS有很多
本地版本控制系统 (LVCS):是将文件的各个版本以一定的数据格式存储在本地的磁盘,在一定程度上解决了手动复制粘贴的问题,但无法解决多人协作的问题
集中式版本控制系统(CVCS):单一的集中管理的服务器,保存所有文件的修订版本,而协同合作的开发人员都通过客户端连接到这台服务器,取出最新的文件或者提交更新
分布式版本控制系统 (DVCS):把代码仓库完整地镜像下来,相当于每个人的电脑都是一个完整的版本库,在没有网络的情况下也可以执行commit、查看版本提交记录、以及分支操作,在有网络的情况下可以发布到服务器
Git:是由linux作者linus开发的一个分布式版本控制系统,保存的是文件的完整快照,而不是差异变化或者文件补丁。
Git 基本概念:
仓库 (Repository):
分支 (Branch):master feature
提交 (Commit):
(Pull):
(Push):
(Clone):
Merge Collaboration
存放区域:工作目录,暂存区域,本地仓库,远程仓库
github与gitlab账户注册与仓库设置
github: 基于Git的全球最大的开源代码托管平台,GitHub 同时提供免费的公共仓库和付费的私有仓库
https://github.com
gitlab: 基于Git的免费私人仓库托管,适合团队内部协作开发,而且gitlab本身是作为一个gitlab上的开源项目,团体可以用它搭建自己的内网gitlab服务器
本地git安装配置
下载git: https://git-scm.com/download/win
按照默认提示安装完成
pycharm配置本地git连接
选择File -> Settings -> Version Control -> Git 将Git安装目录下的/cmd/git.exe路径写入Path to Git executable并点击OK
服务器篇
首先用Xshell登陆服务器命令行界面,准备进行环境配置
下载准备
在开始下载之前,我们需要把下载源更换一下,换成速度更快的国内源,系统中跟下载源有关的文件是 etc/apt/sources.list 在修改前作出备份
sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak
编辑下载源文件
vi /etc/apt/sources.list
以阿里云为例,由于服务器系统Ubuntu18的版本代号(Codename)为bionic (可用lsb_release -c命令查看版本代号),Ubuntu 14的版本代号为trusty,Ubuntu 16的版本代号为 xenial,相应的系统可以将下文中的bionic替换为相应版本代号
删除掉原有内容,并添加(Insert键)
deb http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe
multiverse deb-src http://mirrors.aliyun.com/ubuntu/ bionic main
restricted universe multiverse deb http://mirrors.aliyun.com/ubuntu/
bionic-security main restricted universe multiverse deb-src
http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted
universe multiverse deb http://mirrors.aliyun.com/ubuntu/
bionic-updates main restricted universe multiverse deb-src
http://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted
universe multiverse deb http://mirrors.aliyun.com/ubuntu/
bionic-backports main restricted universe multiverse deb-src
http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted
universe multiverse deb http://mirrors.aliyun.com/ubuntu/
bionic-proposed main restricted universe multiverse
之后Esc + :wq保存退出
再执行
sudo apt-get update
可能会出现的问题:
W: Failed to fetch
http://mirrors.aliyun.com/debian/dists/wheezy/InRelease Temporary
failure resolving ‘mirrors.aliyun.com’ W: Failed to fetch
http://mirrors.aliyun.com/debian/dists/wheezy-updates/InRelease
Temporary failure resolving ‘mirrors.aliyun.com’ W: Failed to fetch
http://mirrors.aliyun.com/debian-security/dists/wheezy/updates/InRelease
Temporary failure resolving ‘mirrors.aliyun.com’ W: Some index files
failed to download. They have been ignored, or old ones used instead.
产生原因:
下载源都是通过域名的形式进行访问,而现在系统的DNS解析没有配置,导致无法解析域名的源
解决方法:
在系统的网络配置文件里追加DNS服务器的ip
修改 :
vi /etc/resolv.conf
添加:
nameserver 8.8.8.8
nameserver 8.8.4.4
nameserver 198.153.192.1
nameserver 198.153.194.1
nameserver 208.67.222.222
nameserver 208.67.220.220
重启网络 :
sudo /etc/init.d/networking restart
修改:
sudo vim /etc/network/interfaces
添加:
dns-nameserver 8.8.8.8
dns-nameserver 8.8.4.4
dns-nameserver 198.153.192.1
dns-nameserver 198.153.194.1
dns-nameserver 208.67.222.222
dns-nameserver 208.67.220.220
重启虚拟机 :
linux里的apt-get命令可以用于获取源下的包,我们通过update命令更新源的更改
sudo apt-get update
问题解决
服务器优化
云服务器可能出现的问题是内存占用过高
我们在命令行中输入top命令可以看到内存的使用状况
top命令对于运维人员很重要,对其命令展现内容的关键参数解析如下:
top-:系统当前时间,当前登录用户个数以及系统负载。
Tasks:系统总进程数、运行中进程数、休眠、睡眠和僵尸进程数量。
%Cpu(s):CPU 当前使用情况。
KiB Mem:内存当前使用情况。
KiB Swap:Swap 空间当前使用情况。
下半部分以进程为维度显示资源的占用情况:
PID:进程 ID。
USER:进程所有者。
PR:进程优先级 NI:NICE 值,NICE 值越小,优先级越高。
VIRT:使用的虚拟内存大小,单位 KB。
RES:当前使用的内存大小,单位 KB。
SHR:使用的共享内存的大小,单位 KB。
S:进程状态。
%CPU:更新时间间隔内进程所使用的 CPU 时间的百分比。
%MEM:更新时间间隔内进程所使用的内存的百分比。
TIME+:进程使用的 CPU 时间,精确到 0.01s。
COMMAND:进程名称
知识补充:计算机存储与虚拟内存 Swap Space
了解计算机系统的人应该知道,计算机内部的存储器是有一定的层次结构的,需要被CPU快速访问的数据,指令,地址等放在最快读取的寄存器中(访问时间以纳秒计,存储量以位计),主机运行的应用程序的数据放在内存中,而由于CPU直接读取内存速度较慢,故在内存与寄存器间用静态存储器(SRAM)设立高速缓存,而实际上内存也可以看作本地磁盘的高速缓存,保存着本地磁盘取出的磁盘块。其实更进一步说,整个计算机的存储体系就是一个层级缓存体系,越需要被快速访问的代价是存储容量越小,而大存储容量的代价便是读写时间的变长,它们之间依次建立高速缓存使得计算机运算单元访问存储的时间和效率达到优化
所以我们知道直接从物理内存读写数据要比从硬盘读写数据要快的多,因此,我们希望所有数据的读取和写入都在内存完成,而内存是有限的,这样就引出了物理内存与虚拟内存的概念。
物理内存就是系统硬件提供的内存大小,是真正的内存,相对于物理内存,在Linux下还有一个虚拟内存的概念,虚拟内存就是为了满足物理内存的不足而提出的策略,它是利用磁盘空间虚拟出的一块逻辑内存,用作虚拟内存的磁盘空间被称为交换空间(Swap Space)。作为物理内存的扩展,Linux会在物理内存不足时,使用交换分区的虚拟内存,更详细的说,就是内核会将暂时不用的内存块信息写到交换空间,这样以来,物理内存得到了释放,这块内存就可以用于其它目的,当需要用到原始的内容时,这些信息会被重新从交换空间读入物理内存。
Linux的内存管理采取的是分页存取机制,为了保证物理内存能得到充分的利用,内核会在适当的时候将物理内存中不经常使用的数据块自动交换到虚拟内存中,而将经常使用的信息保留到物理内存。要深入了解Linux内存运行机制,需要知道下面提到的几个方面:Linux系统会不时的进行页面交换操作,以保持尽可能多的空闲物理内存,即使并没有什么事情需要内存,Linux也会交换出暂时不用的内存页面。这可以避免等待交换所需的时间。Linux进行页面交换是有条件的,不是所有页面在不用时都交换到虚拟内存,Linux内核根据”最近最经常使用“算法,仅仅将一些不经常使用的页面文件交换到虚拟内存,有时我们会看到这么一个现象:Linux物理内存还有很多,但是交换空间也使用了很多。其实,这并不奇怪,例如,一个占用很大内存的进程运行时,需要耗费很多内存资源,此时就会有一些不常用页面文件被交换到虚拟内存中,但后来这个占用很多内存资源的进程结束并释放了很多内存时,刚才被交换出去的页面文件并不会自动的交换进物理内存,除非有这个必要,那么此刻系统物理内存就会空闲很多,同时交换空间也在被使用,就出现了刚才所说的现象了。关于这点,不用担心什么,只要知道是怎么一回事就可以了。交换空间的页面在使用时会首先被交换到物理内存,如果此时没有足够的物理内存来容纳这些页面,它们又会被马上交换出去,如此以来,虚拟内存中可能没有足够空间来存储这些交换页面,最终会导致Linux出现假死机、服务异常等问题,Linux虽然可以在一段时间内自行恢复,但是恢复后的系统已经基本不可用
———————————————————————————————————
0. Python及相关的库管理
安装python3.7.3以及相关包并配置环境:
安装git,方便部署时的版本管理和下载git上的内容
sudo apt-get install git
首先安装python编译所需的依赖包 (也可以一行写下所有的包):
sudo apt-get install make build-essential wget curl llvm openssl
sudo apt-get install python-dev python-setuptools python-pip python-smbus
sudo apt-get install tk-dev xz-utils zlib1g-dev
sudo apt-get install libncurses5-dev libncursesw5-dev libgdbm-dev libsqlite3-dev
sudo apt-get install libssl-dev libffi-dev libbz2-dev libreadline-dev libc6-dev
sudo apt-get install libxml2-dev libxmlsec1-dev liblzma-dev
安装pyenv (python版本管理工具)和pyenv-virtualenv (python虚环境管理)并配置环境变量:
git clone https://github.com/pyenv/pyenv.git ~/.pyenv
git clone https://github.com/pyenv/pyenv-virtualenv.git ~/.pyenv/plugins/pyenv-virtualenv
echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bashrc
echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bashrc
echo 'eval "$(pyenv init -)"' >> ~/.bashrc
echo 'eval "$(pyenv virtualenv-init -)"' >> ~/.bashrc
exec $SHELL -l
git命令从github代码仓库中拉取pyenv文件到 ~/.pyenv文件夹(即 /root/.pyenv)
echo命令将后面引号中的字段写入 ~/.bashrc(即 /root/.bashrc ,相当于win系统下的环境变量配置文件),当你打开root/.bashrc文件时,结尾应该有如下代码
export PYENV_ROOT=$HOME/.pyenv
export PATH=${PYENV_ROOT}/bin:$PATH
eval "$(pyenv init -)"
eval "$(pyenv virtualenv-init -)"
exec命令重启shell进程完成环境变量更新的应用
exec $SHELL -l
用pyenv安装指定版本的python
pyenv install 3.7.3 -v
随后更新pyenv数据库
pyenv rehash
设置全局版本
pyenv global 3.7.3
查看全局python版本
root@MyCloudServer:~# python
Python 3.7.3 (default, May 23 2019, 09:10:34)
[GCC 7.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>
然后为项目创建虚环境,默认的python解释器版本为pyenv设置的全局版本,若需指定其他版本的解释器,需要在环境名称前加上版本号
pyenv virtualenv venv #版本为3.7.3
pyenv virtualenv 2.7.15 venv27 #版本为2.7.15
虚环境的文件夹地址为 .pyenv/versions/3.7.3/envs/venv
pyenv-virtualenv还有一个非常方便的地方,先前我们在.bashrc中写入过eval "$(pyenv virtualenv-init -)",这时,只要我们的项目文件夹下有一个.python_version文件,写有这个项目需要的环境名称,我们在进入项目文件夹后虚环境就会自动激活

至此我们在本地和服务器分别设置了一套python的版本与环境的管理系统,在本地利用pycharm的解释器设置与库管理工具,在服务器利用pyenv的版本管理与pyenv-virtualenv的环境管理和pip进行包安装。在实际开发中要保证本地与服务器的python版本和环境一致,方便开发与调试。
接下来要进行服务器的核心web系统的安装,包括:
- web服务器:nginx
- WSGI层 : uwsgi
- Python后端开发框架: Django
- 数据库: MySQL
成功的安装与实现各个组件的连接需要理解各个组件的工作方式以及组件之间的接口,同时需要一套测试规范,用一张图解来表达安装与测试的流程以及组件的合作方式:
1.安装Django
pip install django
查看版本号
python
>>> import django
>>> django.VERSION
(2, 2, 3, 'final', 0)
由于我们已经在本地创建了项目,只需要在pycharm中将其上传即可,右键点击本地工程文件,选择 Deployment->Upload to XXX
可以测试一下django是否可以访问,使用django内置的web Server启动,命令行进入工程目录输入
python manage.py runserver 0.0.0.0:8001

现在django就在8001端口访问了,在浏览器中输入ip:8001,可以看到如下界面
管理django站点
创建django管理员,在工程目录输入
python manage.py createsuperuser
接着按照提示输入用户名密码与邮箱就可以激活管理员账户了
访问ip/admin登陆并查看管理员界面
2. 安装uwsgi
pip install uwsgi
测试uwsgi:
在工程目录下
-新建一个python文件test.py,输入下面内容
def application(environ,start_response):
start_response('200 OK',[('Content-Type','text/html')])
return [b"Hello!"]
新建配置文件 uwsgi.ini (与test.py在同一目录下)
[uwsgi]
http=:9090 #在测试uwsgi时与浏览器通信的http端口
wsgi-file=test.py #指定一个服务器端程序test.py
之后在工程目录下启动(–ini表示以ini方式执行配置文件,除此之外还有xml方式)
uwsgi --ini uwsgi.ini

在浏览器中输入 ip:9090 即可看到 Hello!效果
这表明uwsgi单独测试是成功的
3. 配置uwsgi与django的连接并测试
更改uwsgi.ini配置文件
[uwsgi]
socket = 127.0.0.1:9090
#与nginx通信的内网socket
http=:8000
#在测试uwsgi与django连接时与浏览器通信的http端口
module=zxler.wsgi:application
#工程目录下的wsgi.py路径表示,如/zxler/wsgi/py表示为zxler.wsgi,使得uwgi与django进行通信
uid = root
#指定uwsgi用户user为root
gid = root
#指定uwsgi用户group为root
vacuum = True
chdir=/root/zxler
#项目根目录
py-autoreload=1
#当django文件作出更改时,重新加载uwsgi确保更改生效
在服务器端uwsgi.ini所在目录执行
uwsgi --ini uwsgi.ini
此时在浏览器中访问ip:8000端口,即可看到与python manage.py runserver开放的端口一样的效果
这表明uwsgi与django的连接测试成功
4.安装nginx并配置
直接在命令行输入命令安装
sudo apt-get install nginx
安装好即可用浏览器访问你的ip地址查看nginx的欢迎页面
5 .配置nginx与uwsgi的连接
这步使得网站基本架构完成,并且比较容易出问题
首先我们需要知道nginx的配置文件在哪个文件夹
nginx -t
这行命令可以检测配置文件的语法,也可以显示出配置文件的地址
我们可以看到,nginx的配置文件在 /etc/nginx 文件夹,我们进入并列出目录
cd /etc/nginx
ls

nginx配置文件状况如下
- 全局配置文件: /etc/nginx/nginx.conf
- 站点配置文件–可用配置文件: /etc/nginx/sites-available/XX.conf (默认: /default)
- 站点配置文件–已启用配置文件: /etc/nginx/sites-enabled/XX.conf (默认: /default)
全局配置文件 (关键部分):
#user www-data; #运行nginx的用户,修改为root
user root;
worker_processes auto; #nginx进程数,设置与系统CPU一样的数值,auto自动设置
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
events {
worker_connections 768; #每个nginx进程允许的最大客户端连接数
# multi_accept on;
}
http {
##
# Basic Settings
##
upstream django #upstream是nginx的负载均衡,多站配置时需要用到,后面跟一个任意的名字
{
server 127.0.0.1:9090; #与uwsgi服务器进行内网通信的端口,要与uwsgi.ini里的socket参数保持一致
}
sendfile on; #允许文件上传
tcp_nopush on; #防止网络阻塞
tcp_nodelay on;
keepalive_timeout 65; #允许客户端连接的最大秒数
types_hash_max_size 2048; #nginx散列表大小,值越大,占用内存越多,路由速度越快
# server_tokens off;
# server_names_hash_bucket_size 64;
# server_name_in_redirect off;
include /etc/nginx/mime.types;
default_type application/octet-stream;
access_log /var/log/nginx/access.log; #访问日志文件路径
error_log /var/log/nginx/error.log; #错误日志文件路径
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*; #加载已启用的站点配置文件
}
站点配置文件
站点配置文件的conf文件放在nginx目录的sites-available中,并与sites-enable建立符号链接,通过include加载至全局配置文件,这样使得一个nginx服务器可以运载不同站点并可以分别管理,
sites-available中默认只有一个default文件,使用vi命令创建自己站点的配置文件
vi /etc/nginx/sites-available/zxler.conf
写入以下内容
server{
listen 80; #站点的监听端口,默认为80
server_name 10.1.134.142; #站点监听的ip地址,更改为自己的主机ip;
root /root/zxler/templates/; #配置HTTP根页面目录
index index.html index.htm; #配置HTTP根页面目录中的默认页面
charset utf-8;
location /static{ #nginx的静态请求与动态请求是分开的,所以需要配置静态文件目录
alias /root/zxler/static; #一般配置到工程目录的static文件夹
}
location /media{
alias /root/zxler/media; #上传的文件的目录
}
location /{
include /etc/nginx/uwsgi_params;
uwsgi_pass 127.0.0.1:9090; #与uwsgi连接的内网端口 ,与uwsgi.ini里的socket保持一致
}
}
接下来,我们需要在sites-enabled文件夹中创建这个站点配置文件的符号链接,标志这个站点已启用,注意应当用绝对路径的写法,ln -s创建链接文件,如果原始文件路径时相对路径,其相对路径的基准路径为链接文件的路径,即以链接文件的路径为当前路径进行寻址,容易发生错误,故可以采用绝对路径定位的方法避免错误
ln -s /etc/nginx/sites-available/zxler.conf /etc/nginx/sites-enabled/zxler.conf
nginx与uwsgi都配置完毕,我们启动这两个服务
service nginx reload
uwsgi --ini /root/zxler/uwsgi.ini
之后,在浏览器中输入ip:80端口,就可以看到django的小火箭
注意:这里我们三次看到了这个火箭,但每一次的意义是不同的,
- :8001 用django内置的web服务器进行的,但因为其效率不高,只作测试使用
- :8000 用uwsgi内置的WSGI server启动,实现了uwsgi与django的连接
- :80 用nginx进行启动(:80端口是一种最为广泛的HTTP端口,在浏览器中会直接转向ip地址而 省略),实现了nginx与uwsgi的连接
这一步也很有可能出现问题,对于几种常见的问题这里列出解决方法:
nginx启动失败 Job for nginx.service failed

原因分析:nginx的配置文件中出现语法错误,使用 nginx -t 命令查看错误原因
如果成功,会出现
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successfu
否则,会提示你错误原因,按照错误原因去修改配置文件后重启nginx
很常见的一个问题就是绑定端口失败,用service nginx status查询状态信息时会出现
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
nginx.service: control process exited, code=exited status=1
nginx: [emerg] still could not bind()
使用ps -ef | grep 80 查看80端口的进程占用情况
用kill -s 9 <pid>将所有占用端口的进程kill掉,其中< pid >为占用端口的进程idservice nginx restart重启nginx服务
Internal Server Error
这个错误也容易遇到,往往nginx和uwsgi都启动正常,然后访问网站时却只得到一行小字"Internal Server Error"
这时由于nginx成功加载,问题最大可能出在uwsgi或者django上
首先,进入django工程目录
python manage.py runserver 0.0.0.0:8002
在浏览器访问 ip:port 查看能否正常访问,如果无法正常访问,那么基本上是django的问题,首先查看工程目录里各文件格式与语法是否正确,在DEBUG = TRUE 时django会给出你的错误原因,按照原因进行排查
如果能够正常访问,则是uwsgi的问题,由于在uwsgi的配置文件中将日志地址设在工程目录下,我们打开其中的uwsgi.log文件查看日志
最常见的问题还是端口绑定,被另一个uwsgi进程绑定
probably another instance of uWSGI is running on the same address (127.0.0.1:9091).
bind(): Address already in use [core/socket.c line 769]
依照相似的方法,我们用ps aux | grep uwsgi查看uwsgi占用的端口
用 kill -9 < pid > 将工程目录下的uwsgi进程kill掉
重启uwsgi后就可以了
—————————————————————————————————————
目前我们完成了一套nginx+uwsgi+django环境的基本搭建,但是还有一些地方有问题
nginx的静态文件需要单独加载(保证了效率),所以当我们访问ip/admin查看管理员界面时,发现是没有静态文件(css ,js文件等)的,我们只能看到简陋的文字
我们需要在django加载静态文件
上一步在nginx的站点配置文件中,我们已经配置了站点的静态文件目录
location /static{
alias /root/zxler/static;
}
我们进入工程目录,创建static文件夹,并修改其权限使得其能够读写
sudo chmod 777 static
打开工程目录下同名文件夹下的settings.py文件,文件最后有
STATIC_URL = '/static/'
但有可能出现相对路径解析失败的问题,可以补充STATIC_ROOT设置:
STATIC_ROOT = os.path.join(BASE_DIR, 'static/')
之后用manage.py自带的命令收集需要的static文件
python manage.py collectstatic

在目录中可以看到css样式和js文件被添加到了static文件夹的admin目录中
重新启动nginx与uwsgi
service nginx restart
uwsgi --ini uwsgi.ini
再访问ip/admin即可看到加载了CSS样式的admin页面
6.使网站访问html页面并用pycharm实现实时前端开发
目前为止,我们访问的页面都是在安装django与nginx时安装好的默认页面,对于网站当然要开发网站自己的html页面,这就需要用到前端的知识了,为了方便项目的管理,应该html文件放在工程目录下的文件夹中,并在django中设置,打开django的settings.py文件,找到TEMPLATES列表,内容如下
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')] #新增
,
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
其中‘DIRS’中的BASE_DIR在前面也有给出
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
而os.path.join则是把两个参数和一,即起到目录拼接的作用
os.path.join(BASE_DIR, 'templates')
BASE_DIR就是我们所说的工程目录,我们在TEMPLATES下 ‘DIRS’ 中规定的模板目录是工程目录下的templates文件夹,由于现在目录中没有,我们就创建一个templates文件夹(你也可以将’DIRS’中的templates改为其他的名字并且创建这样一个文件夹),新建一个index.html文件
之后对于url的配置和view层的渲染将在下一节4.2中介绍
6.安装数据库
MySQL
安装并配置
sudo apt-get install mysql-server
sudo mysql_secure_installation
按照提示输入密码后
systemctl status mysql.service
检测MySQL的安装情况
建立django与MySQL的连接
首先用MySQL创建一个数据库
mysql -u root -p
默认密码为空,可以直接回车进入mysql命令行
接着在命令行中输入(其中myproject替换为你为数据库起的名字)CHARACTER SET 指定字符集为utf-8 使数据库可以进行中文的存取
CREATE DATABASE myproject CHARACTER SET UTF8;
创建数据库用户 (myprojectuser替换为你起的用户名,password替换为一个符合要求的密码)
CREATE USER myprojectuser@localhost IDENTIFIED BY 'password';
给予数据库用户对数据库所有的访问权力
GRANT ALL PRIVILEGES ON myproject.* TO myprojectuser@localhost;
使改变生效
FLUSH PRIVILEGES;
值得注意的是mysql的默认用户名为root,默认密码为空,如果想用默认的root使用mysql在实际运行时为保证数据库安全必须设置密码,使用如下命令进行更改:
use mysql;
update mysql.user set authentication_string=password('*XXX') where user='root';
flush privileges;
其中use mysql 启用mysql的系统数据库进行编辑
然后更新root用户的密码;
最后flush是改变生效;
退出
exit;
接着配置django与MySQL的连接
先安装mysqlclient使得django可以对MySQL进行操作
sudo apt-get install libmysqlclient-dev
pip install django mysqlclient
django默认的数据库是sqlite,我们需要在settings.py文件中把它切换为MySQL
在settings.py中找到DATABASES字段,改为(替换同上)
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'myproject',
'USER': 'myprojectuser',
'PASSWORD': 'password',
'HOST': 'localhost',
'PORT': '',
}
}
保存退出,进入工程目录,使用如下命令生成数据移植文件
python manage.py makemigrations
python manage.py migrate

测试mysql的连接
migrate之后,mysql中就有了django的一些初始化数据库,如管理员日志和授权信息等,可以进行查看,直接在命令行输入mysql进入数据库,如果更改了数据库的密码,则需要用
mysql -u root -p
在输入密码后进入数据库
mysql> show databases; #查看数据库
mysql>use myproject; #使用刚才创建的数据库
mysql>show tables; #列出表格
+----------------------------+
| Tables_in_myproject |
+----------------------------+
| auth_group |
| auth_group_permissions |
| auth_permission |
| auth_user |
| auth_user_groups |
| auth_user_user_permissions |
| django_admin_log |
| django_content_type |
| django_migrations |
| django_session |
+----------------------------+
可以看到现在表中以及有了django的用户信息和管理员日志等表格,说明django连接mysql成功,接下来如果在django中创建了新的表单,在migrates后都会进入数据库中
建立本地pycharm与mysql的连接
打开pycharm,点击最右端的Database选项卡,选择左上角的+
选择 Data Source -> MySQL ,Driver选择 MySQL for 5.1
点击OK后就可以看到数据库已经连接,打开schemas中的数据库就可以查询了
neo4j
首先安装Java jdk8 选择linux版本
https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html
上传到服务器并解压(我将其上传到/root目录并重命名)
tar -xzvf jdk-8.tar.gz
配置环境变量
vim ~/.bashrc
在最后添加
export JAVA_HOME=/root/jdk-8 #jdk的解压路径
export JRE_HOME=${JAVA_HOME}/jre
export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
export PATH=${JAVA_HOME}/bin:$PATH
:wq 保存退出并执行
source ~/.bashrc
调用
java -version
查看版本确保安装成功
在官网上下载neo4j 的 linux community 版本
https://neo4j.com/download-center/#releases
下载后上传服务器并解压安装
配置环境变量使其操作可以直接通过neo4j命令执行
vim /etc/profile
在最后加入下面语句
NEO4J_HOME=/root/neo4j #neo4j解压后的文件夹名称,需要根据个人情况更改
PATH=$PATH:$NEO4J_HOME/bin
export NEO4J_HOME PATH
更改后执行文件
source /etc/profile
更改neo4j的配置文件使其可以远程访问(本地浏览器读写服务器数据库)
vi /root/neo4j/conf/neo4j.conf
找到着一行,在INSERT模式下对其取消注释(删掉前面的#)
接着就可以执行
neo4j console
使neo4j正式工作
接着就可以通过 ip:7474端口访问neo4j数据库,初次登陆默认密码为neo4j,修改密码后就可用Cypher语言对数据库进行增删改查了
7. 为网站配置域名并解析DNS
由于ip地址不易记忆,故我们访问一个网站需要用域名访问,我们也可以为自己的主机解析域名,通过几个步骤:
- 如果你仅为实验用途,想获得免费域名方便记忆,联系我们 申请 .hoc.ccshu.net 域名
教室:D502
教师:单子鹏
- 如果你希望申请一个.com域名用于测试或运营,我们可以从世界上最大的域名注册商godaddy注册域名
访问官网:godaddy.com
注册一个账户,在搜索框中输入你想注册的域名,域名只能由字母,数字和 - 组成
一般一个未被注册的.com域名使用费用为第一年58¥,添加到购物车以后就可以用支付宝或者银联卡进行购买了
购买以后就可以将域名解析到你的主机了,在我的账户->我的产品->你需要配置的域名中选择DNS

在记录中点击添加
选择A型,主机为@,指向你的域名,点击保存
几分钟后,在你的主机的命令行输入host和你的域名,就可以查看它的解析地址
host www.XXX.com

发现它的adress与你主机的ip地址相同,便标志着DNS解析成功,你可以在浏览器中访问你的域名,可以看到效果
但此时域名仅仅连接到了ip的首页,没有与uwsgi与django建立联系,如果我们访问管理员界面或者app会提示404,我们需要做两件事将域名与nginx绑定并可以访问django
- 将域名添加到nginx可用站点配置文件的 server_name中
vi /etc/nginx/sites-available/zxler.conf
将server{}中的server_name 添加域名
server_name zxler.com www.zxler.com 10.1.134.142;

接着打开django工程目录里的settings.py文件,在ALLOWED_HOSTS中添加
ALLOWED_HOSTS = ['localhost', '10.1.134.142','zxler.com','www.zxler.com',]

由于之前在uwsgi.ini设置的
py-autoreload=1
当django项目中的py文件修改时uwsgi便会自动重载,随后访问 域名/admin即可看到管理员登陆界面,输入之前设置的django管理员用户密码,管理员界面被正常加载
8. nginx配置多域名多站点
当我们拥有多个域名时,我们也可以把它们配置到一台服务器上,用nginx实现负载均衡,并且配置到不同的后端程序进行处理,有利于服务器资源的利用
在申请域名后,依然像上一节一样将其DNS解析到你的服务器的IP上
先创建工程文件
django-admin startproject newsite
打开nginx的主配置文件
vi /etc/nginx/nginx.conf
将upstream字段添加新的server,确保与uwsgi通信的端口不重复
upstream django
{
server 127.0.0.1.9090;
server 127.0.0.1.9091;
}
按照nginx站点配置,在sites-available文件夹下新建文件
cd sites-available
cp oldsite.conf newsite.conf #将已有配置文件复制一份,名称自行替换
vi newsite.conf
在server字段中把域名改为新站点域名,下面的文件夹名称也更改
server{
listen 80;
server_name newsite.com www.newsite.com;
root /root/newsite/templates/;
index index.html index.htm;
charset utf-8;
location /static{
alias /root/newsite/static;
}
location /media{
alias /root/newsite/media;
}
location /{
include /etc/nginx/uwsgi_params;
uwsgi_pass 127.0.0.1:9091;
}
}
在django工程文件中的settings.py的ALLOWED_HOSTS字段加上新的域名
在工程目录下同样创建uwsgi配置文件
[uwsgi]
socket = 127.0.0.1:9091
module=newsite.wsgi:application
uid = root
gid = root
vacuum = True
chdir=/root/newsite
pidfile=uwsgi.pid
daemonize=uswgi.log
py-autoreload=1
之后重启nginx服务并启动uwsgi配置文件
service nginx reload
uwsgi --ini /root/newsite/uwsgi.ini
在浏览器访问域名就可以看到新站点了
9.Nginx 配置HTTPS 与HTTP2访问
网站
免费证书颁发网站:
Symantec: https://console.bce.baidu.com/cas/#/cas/apply/create~brand=SYMANTEC&certType=DV
特点:免费,单域名,一年,(测试可用)
Cerbot: https://certbot.eff.org/lets-encrypt/
特点:免费,需要连接公网
申请,完善信息后将进入待验证状态,需要前往域名注册商添加TXT解析记录
为域名添加TXT类型的DNS解析,按照设置值进行设置,保存,
之后等待验证通过,通过后下载证书并解压,将证书上传至服务器

目前我们打开检查,刷新网页,在Network板块中的Protocol还是显示为http/1.1的协议连接,我们的网站配置了ssl后,可以进一步配置http/2连接
之后修改需要设置的站点的可用配置文件(sites-available文件夹下)
server{
listen 80; #http监听
server_name mysite.com www.mysite.com;
rewrite ^(.*) https://$host$1 permanent; #将http请求重定向为https
}
server{
listen 443 ssl http2; #监听443端口https请求,并启用http2协议;
server_name mysite.com www.mysite.com; #域名
root /root/mysite/templates/;
index index.html index.htm;
charset utf-8;
ssl on;
ssl_certificate /../../mysite.crt; #证书上传至服务器的绝对路径
ssl_certificate_key /../../mysite.key; #密钥上传至服务器的绝对路径
ssl_session_timeout 5m;
ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2; #ssl协议
ssl_ciphers "HIGH:!aNULL:!MD5 or HIGH:!aNULL:!MD5:!3DES"; #ssl套件
ssl_prefer_server_ciphers on;
location /static{
http2_push_preload on; #配置静态资源通过http2预加载
alias /root/mysite/static;
}
location /media{
alias /root/mysite/media;
}
location /{
include /etc/nginx/uwsgi_params;
uwsgi_pass 127.0.0.1:9090;
}
}
之后保存退出,nginx -t 检查无误后重启nginx服务
nginx -s reload
之后访问自己的域名就自动转到https连接了
在打开检查刷新网页,就可以看到Network中的Protocol显示的为http/2连接
Update:现在看来,Let’s Encrypt 肯定是更方便的证书申请方式
更多推荐
所有评论(0)