Debian 部署 Python3 + Flask + uwsgi + Nginx + Supervisor

永远不要逃避问题,有些问题你是逃不过去的,你现在逃避,你以后就会花十倍的精力去面对,因为时间不会给弱者任何回报 。

安装编译用的包

如果在 root 下就不用输入 sudo。在子用户下就在命令前加上 sudo。

  1. $ sudo apt-get install build-essential

  2. $ sudo apt-get install libncurses5-dev libncursesw5-dev libreadline6-dev

  3. $ sudo apt-get install libdb5.1-dev libgdbm-dev libsqlite3-dev libssl-dev

  4. $ sudo apt-get install libbz2-dev libexpat1-dev liblzma-dev zlib1g-dev

下载安装 Python3

  • 下载 Python3 包

$ wget --no-check-certificate

https://www.python.org/ftp/python/3.6.3/Python-3.6.3.tgz

'下载可能会出现证书无效问题,只要安装个 ca-certificates 或使用 --no-check-certificate 下载就可以避免下面的错误'

  • 进入下载目录
 $ cd 下载的目录下/
  • 解压包
 $ tar -zxf Python-3.6.3.tgz
  • 进入python3
 $ cd Python-3.6.3

编译安装

(1)解决 PIP 包管理器所需依赖包

 $ vim Modules/Setup.dist

(2)将下面 1 行取消注释,大概在文件的 361 行左右.修改后 esc:wq 保存并退出

 zlib zlibmodule.c -I$(prefix)/include -L$(exec_prefix)/lib -lz

自定义安装目录

(1)创建安装目录

$ mkdir -p /usr/local/python3.6.3

(2)进入 Python3 目录

 $ cd Python-3.6.3

(3)指定到安装目录

 $ ./configure --prefix=/usr/local/python3.6.3
 $ ./configure --enable-optimizations

(4)这里编译使用的是 make all 没有直接使用 make,all 参数会编译所有子模块。

 $ make all
 $ make install

把 Python3 添加到 PATH 里

(1)打开~/.bashrc 文件

(2)添加执行路径

 $ sudo vim ~/.bashrc
 export PATH=$PATH:/usr/local/python3.6.3/bin

添加新的别名信息来修改默认使用的Python版本

alias python='/usr/bin/python3.6.3'

(3)生效配置文件

$ source .bashrc

(4)查看版本:

因为上面已经添加了默认使用 Python3.6.3,所以直接输入 $ python -V 会出现

(-bash: /usr/bin/python3.6.3: No such file or directory)

报错。

查看 Python 版本输入以下:

 $ sudo vim ~/.bashrc
 export PATH=$PATH:/usr/local/python3.6.3/bin

安装 Nginx

(1)安装

$ sudo apt-get install nginx
# 查看版本
$ nginx -v

(2)启动 Nginx

$ sudo /etc/init.d/nginx start

浏览器访问:你的服务器ip地址 如:http://45.45.162.162

出现上图:表示成功

(3)停止 Nginx

 $ sudo nginx -s stop

安装 uWSGI

(1)因为已经安装 Python3 所以要使用 pip3 进行安装

 $ pip3 install uwsgi

(2)查看版本

 $ uwsgi --version

(3)安装方法二

下载:

 $ wget http://projects.unbit.it/downloads/uwsgi-latest.tar.gz

(4)解压:

 $ tar zxvf uwsgi-latest.tar.gz

测试

如果:有现成的项目可以把项目上传到服务器中,在 git 管理项目,只需要 git clone 一下就可以了。

如果:你需要从本地上传项目文件,可以用 scp 命令,这里就不啰嗦用法了。总之我们将项目文件放到服务器,然后就可以用 virtualenv 管理 Python 环境

virtualenv 就不多说了。这里直接用 flask demo 进行。

一、安装虚拟环境

$ pip3 install virtualenv

二、创建一个包

 $ mkdir myproject
 $ cd myproject

三、创建虚拟环境

 $ virtualenv env

(1)激活虚拟环境

 $ source env/bin/activate

(2)在虚环境中安装 flask

 $ pip3 install flask

(3)退出虚环境

 $ deactivate

(4)创建启动文件

 $ vim run.py

(5)写入一个 flask,端口自己进行设置。我这里用的 80 端口。

 from flask import Flask
 app = Flask(__name__)
 @app.route("/")
 def hello():
     return "Hello World!"
 if __name__ == "__main__":
     app.run(host='0.0.0.0', port=80)

(6)esc+wq 保存并且退出

四、运行这个 run.py 文件

(1)先停止 Nginx

 $ nginx -s stop

(2)打开你设置的端口(端口默认全部是关闭状态)端口自行设置。

 $ iptables -A INPUT -p tcp --dport 80 -j ACCEPT
 # 如果想关闭打开的端口:
 $ iptables -A INPUT -p tcp --dport 80 -j DROP

(3)启动 flask 程序

 $ cd myproject
 $ python3 run.py

五、用其他电脑和手机 4G 访问你的服务器 ip 地址+上端口。

如:http://45.32.122.555:80/

出现:Hello World! 那就成功了。

配置 Nginx

(1)进入

 $ cd /etc/nginx/sites-enabled/

(2)编辑 default

 $ vim default
------------------------------------
 # 或者直接配置 $ cd /etc/nginx 
 $ vim nginx.conf
 # 不过要根据其语法来配置其实最后nginx.conf还是会调用/etc/nginx/sites-enabled/default的配置。

(3)在最后写入后 : wq 保存并且退出

 server {
 listen  80;
 server_name 45.32.162.255; 
 charset      utf-8;
 client_max_body_size 75M;
 location / {
     include      uwsgi_params;
     uwsgi_pass   127.0.0.1:8000;  
     uwsgi_param UWSGI_PYHOME /root/myproject/venv;
     uwsgi_param UWSGI_CHDIR  /root/myproject; 
     uwsgi_param UWSGI_SCRIPT run:app; 
     }
 }

(4)解析

listen 80; # 服务器监听端口
server_name 45.32.162.255; # 这里写你的域名或者公网IP
charset utf-8; # 编码
client_max_body_size 75M; # 之前写的关于GET和POST的区别
include uwsgi_params; # 导入uwsgi配置
uwsgi_pass 127.0.0.1:8000; # 转发端口,需要和uwsgi配置当中的监听端口一致 (下面会配置uwsgi)
uwsgi_param UWSGI_PYTHON /root/myproject/venv; # Python解释器所在的路径(这里为虚拟环境)【路径按照自己具体的路径填写】
uwsgi_param UWSGI_CHDIR /root/myproject; # 项目根目录
uwsgi_param UWSGI_SCRIPT run:app; # 项目的主程序,即Flask app所在的位置【run是运行文件run.py文件(根据自己创建的文件名)app是falsk实例】

(5)测试一下配置文件是否正确,若检测配置文件失败,再好好检查下配置文件有没有疏漏。

$ nginx -t

表示测试成功

(6)此时访问 Nginx 服务器应该会得到 502 Bad Gateway 的提示,因为请求被 Nginx 转发了,但是并没有转发服务器来处理请求(还没有配置好 uwsgi)。

 $ service nginx start

配置 uwsgi

一、在项目文件根目录新建配置文件 uwsgi.ini(uwsgi 支持多种配置文件格式: xml, ini, json 等)

(1)进入项目根目录

 $ cd myproject

(2)创建 uwsgi 文件

 $ vim uwsgi.ini

(3)写入以下内容后 : wq 保存并退出

 [uwsgi]                                                     
 socket = 127.0.0.1:8000                         
 plugins = python                                        
 chidir = /root/myproject                                    
 wsgi-file = run.py                                       
 callable = app                  
# uwsgi的监听端口【要跟上面nginx配置里的端口一样】
# 这行一定要加上,不然请求时会出现-- unavailable modifier requested: 0 --错误提示
# 项目根目录【路径按照自己具体的路径填写】
# flask程序的启动文件【这里我命名为run.py】
# 程序变量名 【app是falsk实例变量】

二、启动测试

(1)启动 Nginx

 $ service nginx restart

(2)启动 uwsgi

注意要回到项目根目录下执行

 $ cd ~
 $ cd myproject
 $ uwsgi uwsgi.ini

若一切正常的话就可以在终端上看到 uwsgi 的启动信息了

(3)打开浏览器

访问你的 ip 加上端口

例:http://45.32.162.255:80

页面出现:Hello World!

说明 Nginx 和 uwsgi 配置成功了

但离真正项目上线还差一段,因为 uwsgi 是直接在前台启动的,当我们的连接终端跟服务器断开的时候 uwsgi 进程也被关闭了,所以我们需要 uwsgi 在后台运行。

解释一下上面这段话:我们在连接服务器启动项目后可以用浏览器访问成功。但是我们一但关闭与服务器的连接后再用浏览器访问就不行了.项目是运行在前台的也就是说.在关闭与服务器连接的同时也关闭了服务器的命令窗.运行在前台的项目也同时关闭。所以我们需要把项目运行在后台。

三、后台启动项目

(1)用 nohup 启动:不挂断运行命令,用"&"可以让你的命令在后台执行

(nohup 详细的命名参数请到官网查询)注意:别漏了 & 号。

 $ nohup uwsgi uwsgi.ini &

(2)关闭与服务器的连接,然后用浏览器访问你的 ip 地址:

显示:Hello World! 表示 ok 了!

(3)可以通过命令把这个项目从后台停止,查询 uwsgi 的进程( linux 命令不详细说了)

 $ ps -ef|grep uwsgi

找到 uwsgi 进程 uwsgi.ini:

root 7950 1 0 14:57 ? 00:00:00 uwsgi uwsgi.ini

进程 id 每个人都不一样 这里的 id 是 7950。

(4)杀掉后台的 uwsgi 进程 kill -9 后面加上进程的 id 或者 killall uwsgi 杀掉全部同名为 uwsgi 的进程。

 $ kill -9 7950
 $ killall uwsgi

(5)再用浏览器去访问 ip

浏览器页面显示: 502 Bad Gateway 表示停止掉 uwsgi 程序的运行

(6)项目根目录下会生成 nohup.out 记录日志

使用 Supervisor 进程监控

** Supervisor 是 Python2 写就的一款强大的运维工具。**

目前 Supervisor 还不支持 Python3。可以通过以下方法解决。

可通过 pip 安装.这里用的是 Python3 的 pip.所以会安装失败.使用以下.

(1)首先安装 supervisor (默认由自带的 python2.7 驱动)

 $ apt-get install supervisor

(2)进入默认配置文件(修改配置文件)

 $ cd /etc/supervisor/
 $ vim supervisord.conf

按 shift+G 跳到末尾

添加:files = /etc/supervisor/*.conf

esc:wq 保存

这样方便为每个 app 单独设置 conf 文件而不必全部写在全局设置里面

在启动 supervisorctl 须先启动 supervisord。

否则会出现

error:

<class 'socket.error'>, [Errno 99] Cannot assign requested address: file: /usr/lib/python2.7/socket.py line: 575错误

执行:(若不是在 root 下执行在最前面加上 sudo)

 $ supervisord -c /etc/supervisor/supervisord.conf
 $ supervisorctl -c /etc/supervisor/supervisord.conf
 # 这里补充以一下:每当修改完配置后如果出现
 error: <class 'socket.error'>, [Errno 2] No such file or directory: file: /usr/lib/python2.7/socket.
 # 请重新执行以上的两句命令

进入:supervisor shell 模式表示成功

退出:supervisor shell

supervisor> exit

(3)创建脚本文件,生成默认配置文件.

 $ cd /etc/supervisor/conf.d/
 新建app.conf文件(文件名自己定义)
 $ vim app.conf

(4)进入编辑模式添加配置

 [program:myproject]
 directory = /root/myproject/
 command= uwsgi --ini /root/myproject/uwsgi.ini
 autostart = true
 startsecs = 5
 autorestart = true
 startretries = 3
 user = root
 redirect_stderr = true
 stdout_logfile_maxbytes = 20MB
 stdout_logfile_backups = 20
 stdout_logfile = /tmp/app.log
 stopasgroup=false
 killasgroup=false

esc:wq 保存并退出

解析

[program:myproject]:# 项目的包名字(我的是myproject)

directory = /root/myproject/:# 程序的启动目录路径

command= uwsgi --ini /root/myproject/uwsgi.ini:#启动命令
(相当于直接启动 uwsgi uwsgi.ini一样只是加上了路径)

autostart = true:# 在 supervisord 启动的时候也自动启动
startsecs = 5: # 启动 5 秒后没有异常退出,就当作已经正常启动了
autorestart = true:# 程序异常退出后自动重启
startretries = 3:# 启动失败自动重试次数,默认是 3
user = root: # 使用哪个用户启动(我这里用的root)

redirect_stderr = true:# 把 stderr 重定向到 stdout,默认 false
stdout_logfile_maxbytes = 20MB:# stdout 日志文件大小,默认 50MB
stdout_logfile_backups = 20:# stdout 日志文件备份数

注意:

stdout 日志文件,需要注意当指定目录不存在时无法正常启动,所以需要手动创建目录( supervisord 会自动创建日志文件)别忘了配置之后创建下面继续。

stdout_logfile = /tmp/app.log

说下这两个有用的配置项 stopasgroup 和 killasgroup,如果我们用 Flask 等 Rest 服务,通常其会开启几个进程,那么如果 stopasgroup 不启用的话, supervisor 无法重启此服务(关闭主进程时其子进程没有关闭,再开启主进程时会提示端口被占用等错误信息)。

stopasgroup=false:

默认为 false,如果设置为 true,当进程收到 stop 信号时,会自动将该信号发给该进程的子进程。如果这个配置项为 true,那么也隐含 killasgroup 为 true。例如在 Debug 模式使用 Flask 时,Flask 不会将接收到的 stop 信号也传递给它的子进程,因此就需要设置这个配置项。

killasgroup=false:

默认为 false,如果设置为 true,当进程收到 kill 信号时,会自动将该信号发给该进程的子进程。如果这个程序使用了 python 的 multiprocessing 时,就能自动停止它的子线程。

 # 创建日志的文件夹
 $ cd ~
 $ cd /myproject/
 $ mkdir tmp

配置完成。

还有更多的配置参数请查阅官网

这里我们可以看出,虽然 supervisor 是 Python2 写的,但只要我们指定运行的 Python3 解释器去运行程序就行了。

(5)使配置生效(每当修改主配置文件或增改子配置文件都需要执行使它生效)

需要先进入 $ cd /etc/supervisor 目录或者项目的目录 cd myproject/ 才可以运行相关的命令如:supervisorctl reload 等相关命令

 $ supervisorctl update # 因为是python3执行该命令可能会报错
 # 可以使用以下命令:重新加载配置文件
 $ supervisorctl reload

(6)运行 supervisorctl,即可进入 shell 里面方便的操作,如 start app、restart app等。

 $ cd /etc/supervisor
 $ supervisorctl
 $ start myproject # 你的项目名称
 # 执行start后可以看到 myproject RUNNING pid 16758, uptime 0:02:58
 $ restart myproject # 重新启动
 $ stop myproject # 停止
 # 更多相关命令可以到官网上查阅这里不消息介绍

(7)以上我们只能在控制台查看运行.我们需要 web 界面上查看

 # 添加修改配置文件
 $ cd /etc/supervisor/
 $ vim supervisord.conf
 # 如果在 vim 模式下找到则对应修改
 # 如果没有 按 shift+G 跳至末尾添加

 # IP和绑定端口
 # 管理员名称
 # 管理员密码
 [inet_http_server]
 port = 45.32.111.111:9001   
 username = user 
 password = 666666
 # 如果不需要密码可以注释在最前面机上;号
 # ;username = user 
 # ;password = 666666
 # 重新加载配置文件使它生效
 $ cd /etc/supervisor
 $ supervisorctl reload
 # 最后你需要打开你的这个端口并且重启 supervisorctl
 $ iptables -A INPUT -p tcp --dport 9001 -j ACCEPT
 $ cd /etc/supervisor
 $ supervisorctl

(8)用浏览器启动

 # 输入你的 ip 和端口
 45.32.111.111:9001

看到上图界面表示已经成功,之后可以通过打开 Supervisor 端口去监控管理你的项目一键启动/停止你的项目。

有什么遗漏不足的请多多指导!!!

作者:[沙河顶战神]
原文链接:http://www.cnblogs.com/yangyuexiong/p/7825306.html

技术交流群:238757010

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342