zoukankan      html  css  js  c++  java
  • Django项目在Linux服务器上部署和躺过的坑

      引言

      在各方的推荐下,领导让我在测试环境部署之前开发的测试数据预报平台。那么问题来了,既然要在服务器上部署,

    就需要准备:

    1.linux服务器配置

    2.linux安装python环境搭建与配置

    3.项目依赖的库

    4.uwsgi安装与配置

    5.nginx安装与配置

      环境安装

    备注:以下所有操作都在root权限下进行,如果没有linux的root权限,找运维或者相关人员开通。

    1.更新系统软件包

    [root@localhost ~]# yum update -y

    2.安装软件管理包和可能使用的依赖

    [root@localhost ~]#  yum -y groupinstall "Development tools"
    [root@localhost ~]# yum install openssl-devel bzip2-devel expat-devel gdbm-devel readline-devel sqlite-devel psmisc libffi-devel

    敲黑板:centos安装python3.7时遇到如下问题,查阅知需要的openssl版本最低为1.0.2,但是centos 默认的为1.0.1,所以需要重新更新openssl

    import _ssl       # if we can't import it, let the error propagate
    ImportError: No module named _ssl

    3.安装依赖库

    [root@localhost ~]# yum install -y zlib zlib-dev openssl-devel sqlite-devel bzip2-devel libffi libffi-devel gcc gcc-c++

    4.安装最新版本的openssl 注意!openssl配置是用config,而不是configure,另外openssl编译安装依赖zlib动态库,所以一定要shared zlib 自行到官网查阅最新版本~

    wget http://www.openssl.org/source/openssl-1.1.1.tar.gz
    tar -zxvf openssl-1.1.1.tar.gz
    cd openssl-1.1.1
    ./config --prefix=$HOME/openssl shared zlib
    make && make install

    敲黑板:安装python前一定要先安装ssl,不然后面pip使用不了。

    5.设置环境变量LD_LIBRARY_PATH

    echo "export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$HOME/openssl/lib" >> $HOME/.bash_profile
    source $HOME/.bash_profile
    这一步一定要有!!LD_LIBRARY_PATH环境变量主要用于指定查找共享库(动态链接库)时除了默认路径之外的其他路径。当执行函数动态链接.so时,如果此文件不在缺省目录下‘/lib' and ‘/usr/lib',那么就需要指定环境变量LD_LIBRARY_PATH
    6.解压python3.7,并安装,一定要指定刚才安装的1.1.1版本的openssl!!!
    敲黑板:这里安装python后面一定要指定--with-openssl=$HOME/openssl ,其中$HOME就是/root目录
    tar -zxvf Python-3.7.0.tgz
    ./configure --prefix=$HOME/Py37 --with-openssl=$HOME/openssl
    make && make install
    echo $HOME

    7.至此python3.7就安装完了,来检验下ssl模块能否被导入吧:

    [root@test-bss-181 ~]# echo $HOME
    /root
    [root@test-bss-181 ~]# cd /root/Py37/
    [root@test-bss-181 Py37]# ls
    bin  include  lib  share
    [root@test-bss-181 Py37]# cd bin/
    [root@test-bss-181 bin]# ls
    2to3      easy_install-3.7  idle3.7  pip3    pydoc3    python3    python3.7-config  python3.7m-config  pyvenv      virtualenv
    2to3-3.7  idle3             pip      pip3.7  pydoc3.7  python3.7  python3.7m        python3-config     pyvenv-3.7
    [root@test-bss-181 bin]# ./python3
    Python 3.7.0 (default, Jan 12 2020, 03:54:25) 
    [GCC 4.4.7 20120313 (Red Hat 4.4.7-23)] on linux
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import ssl
    >>> import _ssl
    >>> 

    已经验证没有报错。

    如果没有按照步骤安装,将出现:

    >>> import ssl
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "D:Anacondalibssl.py", line 98, in <module>
        import _ssl             # if we can't import it, let the error propagate
    ModuleNotFoundError: No module named '_ssl'
    >>>

    最后使用pip安装其他包会出现:

    这里是个坑,所以在此讲一下,可能有人会遇到。接下来继续讲

    8.python安装好后,要创建软链接,你若要不知道python的位置在哪儿可以这样

    [root@izbp12am8wqrn7t6wzgmydz bin]# whereis python
    python: /usr/bin/python /usr/bin/python2.7 /usr/bin/python.bak /usr/lib/python2.7 /usr/lib64/python2.7 /etc/python /usr/include/python2.7 /usr/local/python /usr/share/man/man1/python.1.gz

    查看软链接指向

    [root@root ~]# cd /usr/bin/
    [root@root bin]# ll python*
    lrwxrwxrwx. 1 root root    7 2月   7 09:30 python -> python2
    lrwxrwxrwx. 1 root root    9 2月   7 09:30 python2 -> python2.7
    -rwxr-xr-x. 1 root root 7136 8月   4 2017 python2.7
    可以看到,python指向的是python2,python2指向的是python2.7,因此我们可以装个python3,然后将python指向python3,然后python2指向python2.7,那么两个版本的python就能共存了。
    添加python软链接
    将原来的链接备份
    mv /usr/bin/python /usr/bin/python.bak
    
    添加python3的软链接
    ln -s /root/Py37/bin/python3.7 /usr/bin/python
    
    测试是否安装成功了
    python -V

    添加pip软链接

    ln -s /root/Py37/bin/pip3.7 /usr/bin/pip
    
    [root@test-bss-181 bin]# ll pip*
    lrwxrwxrwx  1 root root 21 Jan 12 04:03 pip -> /root/Py37/bin/pip3.7

    9.安装virtualenv ,建议大家都安装一个virtualenv,方便不同版本项目管理

    [root@localhost /]# pip3 install virtualenv

    10.建立软链接

    [root@localhost /]# ln -s /root/Py37/bin/virtualenv /usr/bin/virtualenv

     11.安装成功在根目录下建立两个文件夹,主要用于存放env和网站文件的。(个人习惯,其它人可根据自己的实际情况处理),建立文件夹是切换到根目录。

    1 [root@localhost /]# mkdir -p /www/env
    2 [root@localhost /]# mkdir -p /www/wwwroot

    12.切换到/www/env/下,创建指定版本的虚拟环境,为python3指定虚拟环境,因为虚拟环境也可以有多个。

    virtualenv --python=/usr/bin/python3 mysite
    #mysite是我项目名称

    例如:

    13.然后进入/www/env/mysite/bin ,启动虚拟环境:

    (mysite) [root@localhost myblog]# source mysite/bin/activate

    注意:有个括号里面并且是之前设置的名称,证明你已经成功进入虚拟环境

    以上环境是基本上搭建完成了,如有遗漏请留言,后续补充。

    接下来就是项目部署与配置

      项目部署

    敲黑板:django项目部署启动方式有很多种,这里我只讲三种最基本的,如有更快捷的方式请留言,感激不尽!

      原始启动

    1. 简单粗暴

    项目开发完毕,在部署之前需要再配置文件中将 ALLOWED_HOSTS配置设置为:当前服务器IP或*,如:

    ALLOWED_HOSTS = ["*",]

    然后将源码上传至服务器指定目录,如:/data/ ,然后执行命令来运行:

    注: 上传命令: scp /Users/wupeiqi/PycharmProjects/oldboy-1.zip root@192.168.10.33:/data/

    可以在windows安装git,然后使用scp,windows自带的命令不支持。

    解压,进入目录并执行以下命令:

    python3 mange.py runserver 0.0.0.0:8000

      Uwsgi启动Django项目

    1. Uwsgi

    先简单了解一下uwsgi,uWSGI:是一个web服务器,实现了WSGI协议、uwsgi协议、http协议等。它是线路协议,是实现服务器与其他网络服务器通信的协议,可以看作Tomcat。

    Django框架运行依赖wsgi(本质提供socket服务端),众多模块实现了wsgi规范,而django框架中默认使用wsigiref模块来实现,他由于性能比较低,所以用于本地开发和测试,而线上部署时需要使用uwsgi来代替。

    2.安装uwsgi

    pip3 install uwsgi

    3.在服务器上编写一个Python文件:

    def application(env, start_response):
        start_response('200 OK', [('Content-Type','text/html')])
        return [b"Hello World"]

    在服务器上执行命令启动Web服务器:

    uwsgi --http :9001 --wsgi-file app.py
    #
    uwsgi --http :9002 --wsgi-file foobar.py --master --processes 4

     

    敲黑板:这里使用http的,并且ip地址是服务器的ip,本机访问,需要加上端口号,如访问不了,请确保命令中的端口是否被占用!

    4.Django项目使用uswgi启动

    在项目的根目录下,也就是manage.py同级目录下,新建一个" uwsgi.ini "文件。文件名可以随便,但扩展名必须是".ini"

     1 [uwsgi]
     2 socket = 192.168.1.2:8000                  #应用服务IP端口
     3 chdir = /pyvenv/src/eduonline              #项目根目录
     4 module = eduonline.wsgi                #指定wsgi模块,与Nginx连接时用
     5 #http = IP:Port                            #web服务IP端口,uWSGI做web服务器时用
     6 master = true                              #进程
     7 processes = 4                              #进程数
     8 
     9 #vhost = true                              #多站模式
    10 #no-site = true                            #多站模式时不设置入口模块和文件
    11 #workers = 2                               #子进程数
    12 #reload-mercy = 10
    13 #vacuum = true                             #退出、重启时清理文件
    14 #max-requests = 1000
    15 #limit-as = 512
    16 #buffer-size = 30000
    17 
    18 #进程文件,新建空文件即可,用于服务重启、停止。如:
    19 #重启指令:uwsgi --restart [pidfile路径]
    20 #停止指令:uwsgi --stop [pidfile路径]
    21 pidfile = /pyvenv/src/eduonline/uwsgi.pid      
    22 daemonize = /pyvenv/src/eduonline/uwsgi.log     #日志文件,一般会自动创建
    23 #disable-logging = true                         #不记录正常信息,只记录错误信息

    类似版本:

     1 [uwsgi]
     2 #项目的根目录
     3 chdir = /home/my_project/django_demo
     4  
     5 #项目的对接wsgi.pi文件
     6 module = django_demo.wsgi:application
     7  
     8 #项目执行的变口号,和nginx配置的要一致
     9 socket = 127.0.0.1:8000
    10  
    11 #是否以主进程模式允许
    12 master = true
    13  
    14 #开启的工作进程数量
    15 processes=4   
    16  
    17 #日志文件路径,前提是该文件要存在,且可写
    18 daemonize = /home/my_project/django_demo/run.log
    19  
    20 #表示不记录正常信息,只记录错误信息,否则你的日志可能很快就爆满
    21 disable-logging = true
    22  
    23 #当服务器退出的时候自动清理环境
    24 vacuum = true
    25  
    26 #进程信息文件路径(这里指项目的根目录)
    27 pidfile=%(chdir)/uwsgi.pid
    View Code

    敲黑板:这里有个坑,如果单纯把uwsgi作为web服务器的话,不搞nginx的话,要配置成http = ip:port,而不是socket = 192.168.1.2:8000,不然你哭死都无法访问,即使一切看起来正常,也没报错!

     配置好了就可以启动

    uwsgi --ini uwsgi.ini

    进入项目根目录(uwsgi.ini存放的目录),和manag.py同级目录,输入

    uwsgi --ini ./uwsgi.ini

     这样代表启动正常了。

    不放心,可以使用命令进行查看:

    netstat -anp|grep 9527
    #杀进程 
    kill -9 pid

     输入ip+端口,通过浏览器可以访问

     敲黑板:这里也有个坑,只用uwsgi作为web访问,在之前uwsgi.ini文件里,配置的服务器地址一定要是服务器真实IP地址,不能是localhost或127.0.0.1,不然你本机无法从浏览器访问了。

    例如:

     总结一下常用操作命令:

    # 启动uwsgi
    uwsgi --ini uwsgi.ini
    # 关闭uwsgi uwsgi --stop ./uwsgi.pid
    # 重启 uwsgi --reload ./uwsgi.pid
    #查看确认是否uwsgi启动 ps -ef|grep uwsgi
    #查看端口是否起来 netstat -anp|grep 9527

      静态文件处理

     启动之后你会页面静态文件没有加载,在生产上部署和开发模式加载静态文件方式是不一样的。

    1.首先,我们配置静态文件,要在setting.py里面加入如下几行代码:

    STATIC_ROOT = os.path.join(BASE_DIR, 'collect_static')

    2.进入到项目根目录,创建文件夹collect_static

    mkdir collect_static

    3.静态文件迁移

    python manage.py collectstatic

    django会把所有的static文件都复制到STATIC_ROOT文件夹下

    STATIC_ROOT 是在部署静态文件时(pyhtonmanage.pycollectstatic)所有的静态文静聚合的目录,STATIC_ROOT要写成绝对地址,在这里,比如我的项目mysite是/home/mysite/
    那么STATIC_ROOT 为 /home/mysite/collect_static/

    说明:

    STATIC_ROOT 是在部署的时候才发挥作用, 而实际情况下,静态文件的一般安放位置有两种:

    1.一种就是在每个app里面新建一个static文件夹,将静态文件放到里面,在加载静态文件时,比如要在模板中用到静态文件,django会自动在每个app里面搜索static文件夹(所以,不要把文件夹的名字写错哦, 否则django就找不到你的文件夹了)

    2.另一种,就是在所有的app文件外面,建立一个公共的文件夹, 因为有些静态文件不是某个app独有的,那么就可以把它放到一个公共文件夹里面,方便管理(注意,建立一个公共的静态文件的文件夹只是一种易于管理的做法,但是不是必须的,app是可以跨app应用静态文件的,因为最后所有的静态文件都会在STATIC_ROOT里面存在)
    那现在的问题是如何让django知道你把一些静态文件放到app以外的公共文件夹中呢,那就需要配置STATICFILES_DIRS了

    进入文件夹collect_static后查看

     全部迁移过来了,再次刷新浏览器,页面静态文件加载成功。

    至此,uwsgi部署已完成

      

    可能遇到的问题:

    1、启动uwsgi报错信息:

    (autoforedata) [root@test-bss-181 autoforecastdata]# uwsgi --ini uwsgi.ini
    [uWSGI] getting INI configuration from uwsgi.ini
    *** WARNING: Can't find section "uwsgi" in INI configuration file uwsgi.ini ***
    *** Starting uWSGI 2.0.18 (64bit) on [Tue Jan 14 09:43:30 2020] ***
    compiled with version: 4.4.7 20120313 (Red Hat 4.4.7-23) on 13 January 2020 08:58:36
    os: Linux-2.6.32-696.el6.x86_64 #1 SMP Tue Mar 21 19:29:05 UTC 2017
    nodename: test-bss-181
    machine: x86_64
    clock source: unix
    pcre jit disabled
    detected number of CPU cores: 8
    current working directory: /data/wwwroot/autoforecastdata
    detected binary path: /data/env/autoforedata/bin/uwsgi
    uWSGI running as root, you can use --uid/--gid/--chroot options
    *** WARNING: you are running uWSGI as root !!! (use the --uid flag) *** 
    *** WARNING: you are running uWSGI without its master process manager ***
    your processes number limit is 63718
    your memory page size is 4096 bytes
    detected max file descriptor number: 1024
    lock engine: pthread robust mutexes
    thunder lock: disabled (you can enable it with --thunder-lock)
    uWSGI running as root, you can use --uid/--gid/--chroot options
    *** WARNING: you are running uWSGI as root !!! (use the --uid flag) *** 
    uWSGI running as root, you can use --uid/--gid/--chroot options
    *** WARNING: you are running uWSGI as root !!! (use the --uid flag) *** 
    The -s/--socket option is missing and stdin is not a socket.

    解决方案:

    • 1.增加用户和组,具体命令如下:
    /usr/sbin/groupadd www
    /usr/sbin/useradd -g www www
    • 2.增加了www的用户名和组,之后修改uWsgi配置文件:
     这是我之前的配置
    [uwsgi]
    uid = root gid = root
    现在改成这样
    [uwsgi]
    uid = www
    gid = www

    之后重启一下uWsgi,即可

    [uwsgi-static] added mapping for /static => /data/wwwroot/autoforecastdata/collect_static   #出现这个就是正常

    2.还有一种报错,没有在项目根目录下启动

    (autoforedata) [root@test-bss-181 sbin]# uwsgi --ini uwsgi.ini
    realpath() of uwsgi.ini failed: No such file or directory [core/utils.c line 3654]

    cd到项目所在根目录下启动。(命令不要有空格,如果不行,将ini文件的所有注释清除!)

    3.启动正常,当项目后台调用其他服务接口出现:访问提示openurl错误,或者是没有服务或服务名

    这种情况是由于访问的域名没有映射对应的服务器IP地址

    进入

    cd /etc/

    编辑hosts文件

    vi hosts

    加入映射关系即可

      Uwsgi + Nginx的部署

    上面是uwsgi的启动方式,一般不考虑安全、负载均衡和代理的话,就不需要结合nginx来部署。

    这里介绍uwsgi+nginx的部署:

    1.首先是按照nginx程序

    [root@localhost ~]# cd /home/
    [root@localhost home]# wget http://nginx.org/download/nginx-1.13.7.tar.gz
    [root@localhost home]# tar -zxvf nginx-1.13.7.tar.gz
    [root@localhost home]# cd nginx-1.13.7
    [root@localhost nginx-1.13.7]# ./configure
    [root@localhost nginx-1.13.7]# make
    [root@localhost nginx-1.13.7]# make install

    2.nginx一般默认安装好的路径为/usr/local/nginx,在/usr/local/nginx/conf/中先备份一下nginx.conf文件,以防意外。

    [root@localhost nginx]# cp nginx.conf nginx.conf.bak

     3.配置nginx,这里是关键,然后打开nginx.conf,把原来的内容删除,直接加入以下内容:

    events {
        worker_connections  1024;
    }
    http {
        include       mime.types;
        default_type  application/octet-stream;
        sendfile        on;
        server {
            listen 80;
            server_name  127.0.0.1:80; #改为自己的域名,没域名修改为127.0.0.1:80
            charset utf-8;
            location / {
               include uwsgi_params;
               uwsgi_pass 127.0.0.1:8997;  #端口要和uwsgi里配置的一样
               uwsgi_param UWSGI_SCRIPT mysite.wsgi;  #wsgi.py所在的目录名+.wsgi
               uwsgi_param UWSGI_CHDIR /www/wwwroot/myblog/; #项目路径
               
            }
            location /static/ {
            alias /www/wwwroot/myblog/static/; #静态资源路径
            }
        }
    }

    要留意备注的地方,要和UWSGI配置文件myblog.xml,还有项目路径对应上。
    进入/usr/local/nginx/sbin/目录
    执行./nginx -t命令先检查配置文件是否有错,没有错就执行以下命令:

    [root@localhost sbin]# ./nginx 

    有时候改了配置后会报这样的错误:

    (autoforedata) [root@test-bss-181 sbin]# ./nginx -s reload
    nginx: [emerg] unknown directive "events" in /usr/local/nginx/conf/nginx.conf:1

    这个时候将原来的配置文件conf删除,将之前备份的重新弄一份,cp进去,然后配置一下之前的内容,配置文件里面的内容不正确很容易报错,注意一些细节,比如空格。

    敲黑板:这套部署setting.py需要设置成:

    1、关闭DEBUG模式。
    
    DEBUG = False
    
    2、ALLOWED_HOSTS设置为* 表示任何IP都可以访问网站。
    
    ALLOWED_HOSTS = [’*’]

    常用命令集:

    启动服务:nginx
    退出服务:nginx -s quit
    强制关闭服务:nginx -s stop
    重启服务:nginx -s reload
    验证配置文件:nginx -t
    使用配置文件:nginx -c "配置文件路径"
    使用帮助:nginx -h
    
    
    netstat -nupl (UDP类型的端口)
    netstat -ntpl (TCP类型的端口)
    netstat -anp 显示系统端口使用情况
    
    (autoforedata) [root@test-bss-181 autoforecastdata]# netstat -anp|grep nginx
    (autoforedata) [root@test-bss-181 autoforecastdata]# netstat -anp|grep 8090
    tcp        0      0 0.0.0.0:8090                0.0.0.0:*                   LISTEN      20985/nginx
    
    ps -aux|grep 进程名

      内网映射

     这里还需要注意,如果你公司有域名服务器,请运维给你弄个域名,做内网映射。那么内网任何一台电脑都可以通过域名访问了,不需要每台电脑配置域名映射(在hosts文件里配置服务器IP与域名映射关系),当然如果没有域名,那就只能通过服务器IP来访问了。

     如图/etc/hosts文件

     如图:/usr/local/nginx/conf配置:

     浏览器域名访问:

    完结!

    PS:部署过程蹲过很多坑耗时太久,为了方便以后使用,所以用文字来记录一下。如果您看完该篇,能帮上您,麻烦点个赞,如有不明白地方,可以留言咨询! 谢谢!

    资料查询链接:

    1.无法导入sll和_ssl报错问题:https://www.jianshu.com/p/3ec24f563b81

    2.删除linux服务器上yum和python2后导致无法安装其他(重装python和yum):

    https://www.jianshu.com/p/dad58d810734

    https://blog.csdn.net/qq_34646546/article/details/90714946

    3.cento6部署django详细步骤

    https://blog.csdn.net/weixin_43883625/article/details/100715363

    https://www.cnblogs.com/chaoqi/p/11103188.html

    4.CentOS6.5 安装openssl(可能有坑)

    https://www.cnblogs.com/hunttown/p/9626448.html

    5.静态文件处理

    https://blog.csdn.net/jj546630576/article/details/78606531

     https://note.qidong.name/2017/07/uwsgi-serve-django-static/

    6.uwsgi启动django

    https://blog.csdn.net/weixin_43667990/article/details/99710786

    https://www.jianshu.com/p/0e85cf58e677

    https://www.cnblogs.com/wcwnina/p/9906081.html

    https://blog.csdn.net/smart_liu8/article/details/82388930

    https://blog.csdn.net/qq_34939371/article/details/102856541

    7.nginx配置

    https://www.cnblogs.com/wcwnina/p/9906081.html

    https://www.cnblogs.com/suguangti/p/11334692.html

    8.nginx概念与配置

    https://www.jianshu.com/p/956debe2891d

    如果觉得写的还可以,请给个赞,多谢支持!

  • 相关阅读:
    IOS开发中Xcode常用插件安装与管理(转)
    IOS开发中摇一摇是怎么实现的
    IOS中APP开发常用的一些接口
    数据结构——不相交集(并查集)
    数据结构——(最小)堆(完全二叉树)
    JDK1.7 中的HashMap源码分析
    Java中hashCode()方法以及HashMap()中hash()方法
    《Java多线程核心技术》读书摘要
    Java for LeetCode 237 Delete Node in a Linked List
    Java类变量、实例变量的初始化顺序
  • 原文地址:https://www.cnblogs.com/liudinglong/p/12185180.html
Copyright © 2011-2022 走看看