uWSGI作为进程运行,但不作为守护进程运行

时间:2013-06-13 23:56:22

标签: flask ubuntu-12.04 uwsgi

对于我目前的烧瓶部署,我必须设置一个uwsgi服务器。 这就是我创建uwsgi守护进程的方法:

sudo vim /etc/init/uwsgi.conf

# file: /etc/init/uwsgi.conf
description "uWSGI server"

start on runlevel [2345]
stop on runlevel [!2345]
respawn

exec /myproject/myproject-env/bin/uwsgi --uid www-data --gid www-data --home /myproject/myproject-env/site/F11/Engineering/  --socket /tmp/uwsgi.sock --chmod-socket --module F11 --callable app --pythonpath /myproject/myproject-env/site/F11/Engineering/ -H /myproject/myproject-env

但成功运行后:sudo start uwsgi

uwsgi start/running, process 1286

尝试通过浏览器访问该应用程序:

我收到 502 Bad Gateway

和nginx中的错误条目error.log:

  

2013/06/13 23:47:28 [错误] 743#0:* 296上游过早关闭   从上游,客户端读取响应头时连接:   xx.161.xx.228,服务器:myproject.com,请求:“GET / show_records / 2013/6 HTTP / 1.1”,上游:   “uwsgi:// unix:///tmp/uwsgi.sock:”,主持人:“myproject.com”

但是sock文件具有所需的权限:

srw-rw-rw- 1 www-data www-data 0 Jun 13 23:46 /tmp/uwsgi.sock

如果我在命令行中从上面运行exec命令作为一个进程,它可以正常工作。为什么守护程序不能正常工作?

btw Nginx正在运行 vim /etc/nginx/nginx.conf

user www-data;

vim /etc/nginx/sites-available/default

location / {
                uwsgi_pass   unix:///tmp/uwsgi.sock;
                include        uwsgi_params;
        }

,它以sudo service nginx start

开头

我在Ubuntu 12.04 LTS上运行此功能。

我希望我提供了所有必要的数据,希望有人能引导我走向正确的方向。感谢。

3 个答案:

答案 0 :(得分:19)

最后我在工作了近2天后解决了这个问题。我希望这个解决方案能够帮助遇到类似问题的其他flask / uwsgi用户。

我遇到了两个主要问题。

1)查找守护进程问题的最佳方法显然是日志文件和更清晰的结构。

sudo vim /etc/init/uwsgi.conf

将守护程序脚本更改为以下内容:

# file: /etc/init/uwsgi.conf
description "uWSGI server"

start on runlevel [2345]
stop on runlevel [!2345]
respawn
exec /home/ubuntu/uwsgi-1.9.12/uwsgi -c /myproject/uwsgi.ini

vim /myproject/uwsgi.ini

[uwsgi]
socket = /tmp/uwsgi.sock
master = true
enable-threads = true
processes = 5
chdir= /myproject/F11/Engineering
module=F11:app
virtualenv = /myproject/myproject-env/
uid =  www-data
gid = www-data
logto = /myproject/error.log

这是设置守护程序的更简洁方法。另请注意最后一行如何设置日志文件。最初我将日志文件设置为/var/log/uwsgi/error.log。经过大量的汗水和泪水后,我意识到守护进程正在以www-data运行,因此无法访问/var/log/uwsgi/error.log,因为error.log归root:root所有。这使得uwsgi无声地失败。

我发现只需将日志文件指向我自己的/myproject就更有效了,守护进程保证了www-data的访问权限。并且不要忘记让www-data可以访问整个项目,否则守护程序将失败并显示Internal Server error message。 - >

sudo chown www-data:www-data -R /myproject/

重启uwsgi守护程序:

sudo service uwsgi restart

2)现在您有三个要查找的日志文件:

  • tail -f /var/log/upstart/uwsgi.log - >启动时显示守护程序的问题

  • tail -f /var/log/nginx/error.log - >拒绝wsgi访问时显示权限问题,通常是因为/tmp/uwsgi.sock文件归root而非www-data所有。在这种情况下,只需删除sock文件sudo rm /tmp/uwsgi.sock

  • tail -f /myproject/error.log - >显示uwsgi在您的应用程序中引发的错误

这个日志文件的组合帮助我弄清楚我在Flask应用程序中使用Flask-Babel导入错误。在这个意义上说,我使用库的方式是回到系统的语言环境以确定日期时间格式。

File "/myproject/F11/Engineering/f11_app/templates/show_records.html", line 25, in block "body"
    <td>{{ record.record_date|format_date }}</td>
  File "./f11_app/filters.py", line 7, in format_date
    day = babel_dates.format_date(value, "EE")
  File "/myproject/myproject-env/local/lib/python2.7/site-packages/babel/dates.py", line 459, in format_date
    return pattern.apply(date, locale)
  File "/myproject/myproject-env/local/lib/python2.7/site-packages/babel/dates.py", line 702, in apply
    return self % DateTimeFormat(datetime, locale)
  File "/myproject/myproject-env/local/lib/python2.7/site-packages/babel/dates.py", line 699, in __mod__
    return self.format % other
  File "/myproject/myproject-env/local/lib/python2.7/site-packages/babel/dates.py", line 734, in __getitem__
    return self.format_weekday(char, num)
  File "/myproject/myproject-env/local/lib/python2.7/site-packages/babel/dates.py", line 821, in format_weekday
    return get_day_names(width, context, self.locale)[weekday]
  File "/myproject/myproject-env/local/lib/python2.7/site-packages/babel/dates.py", line 69, in get_day_names
    return Locale.parse(locale).days[context][width]
AttributeError: 'NoneType' object has no attribute 'days'

这就是我使用Flask过滤器的方式:

import babel.dates as babel_dates

@app.template_filter('format_date')
def format_date(value):
    day = babel_dates.format_date(value, "EE")
    return '{0} {1}'.format(day.upper(), affix(value.day))

最奇怪的是,这段代码在开发环境中运行得非常好(!)。从命令行运行uwsgi作为根进程时,它甚至可以正常工作。但是当由www-data守护进程运行时它失败了。这必须与设置语言环境的方式有关,Flask-Babel正试图回归。

当我像这样更改导入时,它最终都与守护进程一起工作:

from flask.ext.babel import format_date  

@app.template_filter('format_date1')
def format_date1(value):
    day = format_date(value, "EE")
    return '{0} {1}'.format(day.upper(), affix(value.day))

因此在使用Eclipse / Aptana Studio时要小心,它试图在代码中为类选择正确的命名空间。它真的可以变得难看。

从2天开始,它现在在Amazon Ec2(Ubuntu 12.04)上作为uwsgi守护程序工作得非常好。我希望这种经验可以帮助python开发人员。

答案 1 :(得分:0)

我放弃了,没有生成uwsgi.log,nginx一直在抱怨:

2014/03/06 01:06:28 [error] 23175#0: *22 upstream prematurely closed connection while reading response header from upstream, client: client.IP, server: my.server.IP, request: "GET / HTTP/1.1", upstream: "uwsgi://unix:/var/web/the_gelatospot/uwsgi.sock:", host: "host.ip"

每个请求。只有在将uwsgi作为服务运行时才会发生这种情况,因为它在任何用户下都可以正常运行。所以这可以从命令行(页面响应):

$exec /var/web/the_gelatospot/mez_server.sh

这不是(/etc/init/site_service.conf):

description "mez sites virtualenv and uwsgi_django" start on runlevel
[2345] stop on runlevel [06] respawn respawn limit 10 5 exec
/var/web/the_gelatospot/mez_server.sh

该过程将开始,但在每个请求中,nginx会抱怨已关闭的连接。奇怪的是,我有这个相同的配置工作正常2其他应用程序使用相同的nginx版本和相同的uwsgi版本以及这两个应用程序是夹层CMS应用程序。我尝试了我能想到的一切以及建议的内容。最后我转向了gunicorn工作正常:

#!/bin/bash

NAME="the_gelatospot"                                          # Name of the application
DJANGODIR=/var/web/the_gelatospot              # Django project directory
SOCKFILE=/var/web/the_gelatospot/gunicorn.sock     # we will communicte using this unix socket
USER=ec2-user
GROUP=ec2-user                                             # the user to run as, the group to run as
NUM_WORKERS=3                                     # how many worker processes should Gunicorn spawn
DJANGO_SETTINGS_MODULE=settings
#DJANGO_SETTINGS_MODULE=the_gelatospot.settings             # which settings file should Django use
#DJANGO_WSGI_MODULE=the_gelatospot.wsgi                   # WSGI module name
DJANGO_WSGI_MODULE=wsgi

echo "Starting $NAME as `the_gelatospot`"

# Activate the virtual environment
cd $DJANGODIR
source ../mez_env/bin/activate
export DJANGO_SETTINGS_MODULE=$DJANGO_SETTINGS_MODULE
export PYTHONPATH=$DJANGODIR:$PYTHONPATH

# Create the run directory if it doesn't exist
RUNDIR=$(dirname $SOCKFILE)
test -d $RUNDIR || mkdir -p $RUNDIR
cd ..
# Start your Django GUnicorn
# Programs meant to be run under supervisor should not daemonize themselves (do not use --daemon)
exec gunicorn -k eventlet ${DJANGO_WSGI_MODULE}:application \
  --name $NAME \
  --workers $NUM_WORKERS \
  --log-level=debug \
  --bind=unix:$SOCKFILE

这是一个不能作为服务工作的服务(nginx抱怨过早关闭的连接,没有应用程序日志数据通过)。

#!/bin/bash

DJANGODIR=/var/web/the_gelatospot/                # Django project directory
cd $DJANGODIR
source ../mez_env/bin/activate
uwsgi --ini uwsgi.ini

和uwsgi.ini:

[uwsgi]
uid = 222
gid = 500
socket = /var/web/the_gelatospot/uwsgi.sock
virtualenv = /var/web/mez_env
chdir = /var/web/the_gelatospot/
wsgi-file = /var/web/the_gelatospot/wsgi.py
pythonpath = ..
env = DJANGO_SETTINGS_MODULE=the_gelatospot.settings
die-on-term = true
master = true
chmod-socket = 666
;experiment using uwsgitop
worker = 1
;gevent = 100
processes = 1
daemonize = /var/log/nginx/uwsgi.log
logto = /var/log/nginx/uwsgi.logi
log-maxsize = 10000000
enable-threads = true

我去年从枪炮到uWSGI,直到现在我都没有问题,它似乎比枪炮快一点。现在我正在考虑坚持使用gunicorn。它越来越好,在安装了eventlet的情况下提供了更好的数字,并且更容易配置。

希望这种解决方法有所帮助。我仍然想知道uWSGI和nginx的问题,但我很难过。

<强>更新 因此,使用gunicorn允许我将服务器作为服务运行,同时在夹层中玩弄我遇到了这个错误:FileSystemEncodingChanged

为了解决这个问题,我在这里找到了解决方案: https://groups.google.com/forum/#!msg/mezzanine-users/bdln_Y99zQw/9HrhNSKFyZsJ

我不得不修改它,因为我不使用supervisord,我只使用upstart和shell脚本。我在mez_server.sh文件中执行gunicorn之前将其添加到了正确的位置:

export LANG=en_US.UTF-8, LC_ALL=en_US.UTF-8, LC_LANG=en_US.UTF-8
exec gunicorn -k eventlet ${DJANGO_WSGI_MODULE}:application \
  --name $NAME \
  --workers $NUM_WORKERS \
  --log-level=debug \
  --bind=unix:$SOCKFILE

我也尝试使用uWSGI这样修复(因为使用uwsgi.ini后要短得多):

export LANG=en_US.UTF-8, LC_ALL=en_US.UTF-8, LC_LANG=en_US.UTF-8
exec uwsgi --ini uwsgi.ini

我仍然坚持使用gunicorn,因为它仍然处理问题,并引导我朝着正确的方向解决它。我很失望uWSGI在日志文件中没有提供输出,即使有这些参数,我只看到服务器启动过程就是这样:

daemonize = /var/log/nginx/uwsgi.log
logto = /var/log/nginx/uwsgi.logi

虽然nginx继续抛出断开连接错误,但uWSGI坐在那里就像没有发生任何事情一样。

答案 2 :(得分:-1)

使用daemon true命令运行的单行是

var updateTime = function() {

    for (var i = 0; i < $scope.model.painel.length; i++) {
    if ($scope.model.painel[i].status.id === 'E' && $scope.model.painel[i].restante.segundos > 0) {
        var segundos = $scope.model.painel[i].restante.segundos - 1;
        $scope.model.painel[i].restante.horaMinutoSegundo = getHoraMinutoSegundo(segundos);
    }    
    }

$scope.apply();
};

将您的应用绑定到127.0.0.1:8000并且--deamon强制它以守护进程的形式运行

但是定义一个gunicorn_config.cfg文件并使用-c标志运行是一种很好的做法

了解更多信息:

https://gunicorn-docs.readthedocs.org/en/develop/configure.html