Debian环境 Python + Django + Nginx + uWSGI + MySQL 配置备忘

!本文可能 超过1年没有更新,今后内容也许不会被维护或者支持,部分内容可能具有时效性,涉及技术细节或者软件使用方面,本人不保证相应的兼容和可操作性。

最近尝试把项目迁移到Python环境下,特别新装了一台干净的Debian系统,准备重新配置环境,上网找了一些运行Python Web的环境方案,最后敲定Nginx+uWSGI组合,Nginx用得比较多,熟练些;uWSGI据说性能不错,想尝试一下。

网上大部分教程都是要求到uWSGI官方网站下载源码包,然后通过编译的方式安装,比如对于一台新Debian系统,可以通过下面的命令安装:

apt-get update
apt-get upgrade
apt-get install build-essential psmisc
apt-get install python-dev libxml2 libxml2-dev
apt-get install python-setuptools
cd /opt/
wget http://projects.unbit.it/downloads/uwsgi-latest.tar.gz
tar -zxvf uwsgi-latest.tar.gz
mv uwsgi-latest/ uwsgi/
cd uwsgi/
python setup.py install

还有一些配置我就不介绍了,大家可以参考Linode Library的《Deploy Python Code with WSGI using uWSGI and nginx on Debian 6 (Squeeze)》介绍。

今天要介绍的是利用APT源直接apt-get install安装配置我们所需要的环境,首先按惯例先安装MySQL和Nginx:

apt-get install mysql-server
apt-get install nginx

然后通过Debian Packages网站找到我们所需要的uWSGI在sid里,sid版里的东西表示仍在开发测试中,不是最终稳定版,不过对于我们测试来说是够用了,为了用sid里面的软件包,我们还需要修改我们的/etc/apt/sources.list源,添加deb http://ftp.tw.debian.org/debian sid main non-free contrib这一行,或者直接输入命令:

echo "deb http://ftp.tw.debian.org/debian sid main non-free contrib" >> /etc/apt/sources.list

配置过源列表后,我们就可以通过下面的命令安装了:

apt-get update
apt-get install uwsgi uwsgi-core uwsgi-plugin-python

安装完成后,配置文件按惯例放在了/etc/uwsgi里面,服务控制可以通过invoke-rc.d uwsgi后面跟命令参数来实现,不过这里有个小插曲我不得不提一下,安装时可能会报这样的错误:

The following packages have unmet dependencies: 
libc6-dev : Breaks: gcc-4.4 (< 4.4.6-4) but 4.4.5-8 is to be installed. 
E: Broken packages

看样子是依赖包gcc版本不匹配,我后来通过下面的方式解决了:

apt-get update
apt-get upgrade # 先尝试升级系统软件包
 
apt-get install libc6-dev

接下来就是安装django以及Python的MySQL支持,继续APT命令:

apt-get install python-django python-mysqldb

通过上面的步骤,Python环境应该安装到你的系统里了,切换到/usr/lib

cd /usr/lib
ls -l | grep python

你可能会发现系统内被默认安装了几个版本的Python,比如我这里就安装有3个版本:

/usr/lib/python2.6
/usr/lib/python2.7
/usr/lib/python3

如何确定当前的Python默认版本呢?很容易,直接通过下面的命令就可以了:

python --version

大家知道django是安装到python目录下的site-packages下的,但是这几个python目录下都没有site-packages这个文件夹,其实我们可以先通过下面的命令定位一下:

python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()"

上面的命令会在控制台上打印Python包路径,比如这里我们可能获得dist-packages这个目录,切换到这个目录你就会发现django在那儿啦。给django-admin.py加上权限,再做个符号连接,便于我们以后操作(我这里Django在Python2.7下):

chmod 777 /usr/lib/python2.7/dist-packages/django/bin/django-admin.py
ln -s /usr/lib/python2.7/dist-packages/django/bin/django-admin.py /usr/local/bin

记下Django所在的Python版本,然后通过下面的命令切换uwsgi的默认Python版本(一般不需要切换):

update-alternatives --config uwsgi-plugin-python

好啦,到这里基本上安装部分就介绍完了,下面讲解配置部分,首先建立我们项目的文件夹,比如说放在/home/user/www下,然后通过下面的命令创建名为mysite的Django项目:

cd /home/user/www
django-admin.py startproject mysite

好了,这下/home/user/www目录下应该有个子文件夹名字叫mysite,我们需要丢个wsgi的配置文件到/home/user/www/mysite/里面去,配置文件命名为wsgi.py,内容如下:

# wsgi.py
# /home/user/www/mysite/wsgi.py
import sys
import os
 
sys.path.append(os.path.abspath(os.path.dirname(__file__)))
# 下面这行是mysite的父目录
sys.path.append('/home/user/www')
# 下面这行的值请改成相应项目名称.settings
# 我们这里是mysite.settings
os.environ['DJANGO_SETTINGS_MODULE'] = 'mysite.settings'
 
import django.core.handlers.wsgi
 
application = django.core.handlers.wsgi.WSGIHandler()

接下来是修改uwsgi配置文件,先通过如下命令按照刚才的设置建立个配置文件:

cat > /etc/uwsgi/apps-enabled/www.ini << EOF
[uwsgi]
socket = /var/run/uwsgi/app/www/socket
chmod-socket = 666
limit-as = 256
processes = 6
max-request = 2000
memory-report = true
enable-threads = true
pythonpath = /home/user/www
chdir = /home/user/www/mysite
wsgi-file = /home/user/www/mysite/wsgi.py
EOF
 
# 重启uwsgi
invoke-rc.d uwsgi restart

注意上面的socket配置,这个在我机子上是这个路径,大家可以cd /var/run里面找下,然后配置正确,接下来建立Nginx配置文件:

cat > /etc/nginx/sites-enabled/www << EOF
server {
        listen   80;
        server_name localhost;
        location / {
                include uwsgi_params;
                uwsgi_pass unix:///var/run/uwsgi/app/www/socket;
        }
}
EOF

这里的uwsgi_pass依旧是上面我们找到的socket,注意一下server_name,这个是我们绑定的域名,通过nginx -s reload重新加载nginx。

好了,现在可以访问看看是不是成功了?如果出现502 Bad Gateway,可以检查一下uwsgi是否正常启动,通过ps aux | grep uwsgi看下进程列表,最后在检查下socket路径是否正确。

假如出现uWSGI Error:Python application not found这个问题,主要是路径配置问题,这点你可以查阅/var/log/uwsgi下面的日志文件,比如我就遇到过ImportError: No module named django.core.handlers.wsgi这个问题,实际上是wsgi.py里面路径配置不正确。

参考文档

  1. ImportError: No module named django.core.handlers.wsgi in install django mod_wsgi config on apache
  2. Django admin directory on Debian
  3. Running Django with Nginx and uWSGI
若无特别说明,本网站文章均为原创,原则上这些文章不允许转载,但是如果阁下是出于研究学习目的可以转载到阁下的个人博客或者主页,转载遵循创作共同性“署名-非商业性使用-相同方式共享”原则,请转载时注明作者出处谢绝商业性、非署名、采集站、垃圾站或者纯粹为了流量的转载。谢谢合作!

  1. 请教博主UWSGI日志出现:
    — unavailable modifier requested: 0 —
    NGINX日志出现:
    upstream prematurely closed connection while reading response header from upstream
    有什么解决办法?

  2. 是502-bad-gateway
    uwsgi有启动的,
    uwsgi-plugin-python也装了,
    uwsgi和NGINX日志里的错误信息是同一时刻出现的,证明NGINX和UWSGI之间是有通信的,我觉得应该是UWSGI的配置问题,也有可能是NGINX没有权限读写socket文件,socket的权限是www-data,在/usr/share/uwsgi/conf/default.ini里我把它改成www(因为NGINX是以www的权限运行的),可还是不行,

    • 抱歉暂时没能帮你找到有价值的信息,不过可以尝试依次移除nginx和uwsgi(记得备份部分需要的配置文件),然后apt-get purge nginx和apt-get purge uwsgi uwsgi-core uwsgi-plugin-python(移除这两个软件),然后再依次使用apt-get方式安装nginx和uwsgi,然后再按照本文所叙述方式进行配置。
      通过apt-get安装的nginx和uwsgi默认是www-data账户的,这样权限应该也没有什么问题了。

  3. Hello 问下,安装uwsgi时,没有错误报出,我以为正常了,可是执行invoke-rc.d uwsgi restart就failed啊…
    invoke-rc.d uwsgi status也是一样的,我怀疑是uwsgi没正常安装,可是又找不到问题所在……

    • 你可以尝试下面的命令看能不能定位到错误:
      cd /var/log
      grep uwsgi *.log

      由于uwsgi仍然处于Debian的sid包中,所以可能会存在不稳定现象,特别是Python网页出现错误时,假如invoke-rc.d uwsgi restart失败的话,尝试换用invoke-rc.d uwsgi start命令,最后用ps aux|grep uwsgi|grep -v检查一下uwsgi进程是否存在。

  4. 呃,log里看不到任何错误,最后一条是
    status installed uwsgi-plugin-python 1.1.1+dfsg-1
    用invoke-rc.d uwsgi start也是
    Starting app server(s): uwsgi -> ! failed!
    然后看不到uwsgi进程……
    郁闷 我uninstall重新install也不行…

    • 检查/etc/uwsgi/apps-enabled路径下的app配置文件,找到socket路径,看是否配置正确,然后到/var/run/uwsgi/app路径及其子目录下查找pid和socket文件是否和配置文件对应(如果未正常启动,应该不会有pid和socket这两个文件,只需检查下路径是否正确和可写),检查运行uwsgi的用户权限与/var/run/uwsgi的权限是否一致。
      日志文件貌似uwsgi是存放在/var/log/uwsgi/app路径下,看下有没有错误记录。

      如果需要重新安装的话,建议尝试
      apt-get purge uwsgi uwsgi-core uwsgi-plugin-python
      命令。

  5. lz,我按照你步骤进行,可是当我sudo nginx -s reload的时候,出现了
    nginx: [emerg] unknown directive “listen:” in /etc/nginx/sites-enabled/www:2。
    lz能够解释一下吗?

    另外lz你的django是哪个版本的,1.4还是之前的。

    • nginx: [emerg] 错误的原因大多是因为配置文件语法不正确,你打开/etc/nginx/sites-enabled/www文件,检查是不是由于cat > /etc/nginx/sites-enabled/www < < EOF...命令数据导入导致配置文件语法错误。

      抱歉,Django版本有些记不清了,当时是直接通过apt-get install安装的,后来系统被重置了,所以版本也无从考证了。

请稍后...

发表评论

电子邮件地址不会被公开。 必填项已用*标注