2013-06-13 11 views
15

Für meine aktuelle Kolben-Bereitstellung musste ich einen uwsgi-Server einrichten. Dies ist, wie ich die uwsgi Daemon erstellt haben:uWSGI funktioniert als Prozess, aber nicht als Daemon

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 

jedoch nach diesem erfolgreich ausgeführt wird: sudo start uwsgi

uwsgi start/running, process 1286 

Und versuchen, die Anwendung über einen Browser zugreifen:

Ich bekomme eine 502 Bad Gateway

und ein Fehlereintrag in nginx error.log:

2013/06/13 23:47:28 [error] 743#0: *296 upstream prematurely closed connection while reading response header from upstream, client: xx.161.xx.228, server: myproject.com, request: "GET /show_records/2013/6 HTTP/1.1", upstream: "uwsgi://unix:///tmp/uwsgi.sock:", host: "myproject.com"

Aber die Socke Datei hat die Erlaubnis, es braucht:

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

Wenn ich den exec Befehl von oben in der Befehlszeile ausführen als ein Prozess, es funktioniert vollkommen in Ordnung. Warum funktioniert der Daemon nicht richtig?

btw Nginx läuft als vim /etc/nginx/nginx.conf

user www-data; 

und vim /etc/nginx/sites-available/default

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

und es begann als sudo service nginx start

ich dies auf Ubuntu 12.04 LTS leite.

Ich hoffe, ich habe alle notwendigen Daten zur Verfügung gestellt, hoffe, dass jemand mich in die richtige Richtung führen kann. Vielen Dank.

+0

Verwenden Sie Debian oder Ubuntu? – Joe

+0

@joe, Ubuntu 12.04 LTS das ist. Ich habe es gerade auf meinem Laptop mit 13.04 getestet und es ist genau das gleiche Problem. Was gut ist, also reproduzierbar. – Houman

+0

klingt wie der Daemon läuft unter einem anderen Benutzer oder hat Zugriff auf verschiedene Konfigurationen ... ist das nicht ein Hinweis: http://StackOverflow.com/questions/394984/best-practice-to-run-linux-service- as-a-different-user – Paul

Antwort

19

Endlich habe ich dieses Problem gelöst, nachdem ich fast 2 Tage daran gearbeitet habe. Ich hoffe, dass diese Lösung anderen Benutzern von flask/uwsgi hilft, die ein ähnliches Problem haben.

Ich hatte zwei große Probleme, die dies verursacht haben.

1) Der beste Weg, um die Probleme mit einem Daemon zu finden, ist offensichtlich eine Protokolldatei und eine sauberere Struktur.

sudo vim /etc/init/uwsgi.conf

Ändern der Daemon-Skript auf die folgenden:

# 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 

Das ist viel sauberer Weg, um den Dämon der Einrichtung. Beachten Sie auch die letzte Zeile zum Einrichten der Protokolldatei. Anfangs hatte ich die Protokolldatei auf /var/log/uwsgi/error.log festgelegt. Nach viel Schweiß und Tränen stellte ich fest, dass der Daemon als www-data ausgeführt wird und daher nicht auf die /var/log/uwsgi/error.log zugreifen kann, da die error.log von root:root gehört. Dies ließ die uwsgi schweigend versagen.

Ich fand es viel effizienter, die Protokolldatei nur auf meine eigene /myproject zu verweisen, wo der Daemon garantierten Zugriff als www-data hat. Vergessen Sie auch nicht, das gesamte Projekt für www-data zugänglich zu machen oder der Daemon wird mit einem Internal Server error message fehlschlagen. ->

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

Restart uwsgi Daemon:

sudo service uwsgi restart 

2) Jetzt haben Sie drei Protokolldateien Suche nach:

  • tail -f /var/log/upstart/uwsgi.log -> Zeigt Probleme mit Ihrem Daemon auf start

  • tail -f /var/log/nginx/error.log -> Zeigt Erlaubnis Probleme, wenn wsgi Zugriff verweigert wird, oft weil /tmp/uwsgi.sock Datei von root statt www-data gehört. In diesem Fall löschen Sie einfach die Datei Socke sudo rm /tmp/uwsgi.sock

  • tail -f /myproject/error.log -> Fehler von uwsgi in der Anwendung geworfen Zeigt

Diese Kombination von Protokolldateien hat mich geholfen, um herauszufinden, dass ich auch einen schlechten Import mit Flask-Babel in meiner Flask-Anwendung. Schlecht in diesem Sinne, dass die Art, wie ich die Bibliothek verwendet habe, auf das Gebietsschema des Systems zurückgefallen ist, um das Datetime-Format zu bestimmen.

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' 

Dies ist die Art, wie ich die Kolben-Filter wurde:

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)) 

Das Merkwürdigste ist, dass dieser Code völlig in Ordnung, in der Dev-Umgebung arbeitet (!). Es funktioniert sogar gut, wenn Sie den uwsgi als Root-Prozess über die Befehlszeile ausführen. Aber es schlägt fehl, wenn es vom www-data-Daemon ausgeführt wird. Das muss etwas damit zu tun haben, wie das Gebietsschema eingestellt ist, auf das Flask-Babel zurückzugreifen versucht.

Wenn ich den Import wie folgt geändert, alle es endlich geklappt mit dem Dämon:

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)) 

daher vorsichtig sein, wenn Eclipse/Aptana Studio verwenden, die den richtigen Namensraum für Ihre Klassen in Code zu holen versucht. Es kann wirklich hässlich werden.

Es funktioniert jetzt perfekt als uwsgi-Daemon auf einem Amazon Ec2 (Ubuntu 12.04) seit 2 Tagen. Ich hoffe, diese Erfahrung hilft anderen Python-Entwicklern.

+0

Gut zu wissen, dass Sie das Problem gelöst haben, aber ich würde empfehlen, den folgenden Weg zu verwenden: https://library.linode.com/web-servers/nginx/python-uwsgi/ubuntu -12.04-präzise-pangolin. Ich habe es in vielen Servern verwendet. – Joe

0

gab ich auf, keine uwsgi.log dort erzeugt wurde, und nginx hielt gerade über beschweren: für jede einzelne Anfrage

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" 

. Dies geschah nur, wenn uwsgi als Dienst ausgeführt wurde, als ein Prozess, der unter jedem Benutzer gestartet wurde. So würde dies von der Befehlszeile funktionieren (Seite reagiert):

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

Dies tat nicht (/ 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 

Der Prozess beginnen würde, aber bei jeder Anfrage nginx würde über die geschlossene Verbindung beschweren. Seltsamerweise habe ich die gleiche Konfiguration für zwei andere Apps, die die gleiche nginx-Version und die gleiche uwsgi-Version verwenden, sowie beide Mezzanine-CMS-Apps. Ich habe alles versucht, was mir einfiel und was vorgeschlagen wurde. Am Ende wechselte ich gunicorn was funktioniert:

#!/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 

Und hier ist derjenige, der als Dienst (nginx Beschweren von vorzeitig geschlossener Verbindung und keine App Logdaten kommen durch) nicht funktionieren würde.

#!/bin/bash 

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

Und die 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 

ich von gunicorn bis uwsgi letztes Jahr ging, und ich hatte keine Probleme mit ihm bis jetzt, es schien auch ein bisschen schneller als gunicorn. Im Moment denke ich daran, bei Gunicorn zu bleiben. Es wird besser, bringt mit dem Eventlet viel bessere Zahlen und es ist einfacher zu konfigurieren.

Hoffe, diese Abhilfe hilft. Ich würde immer noch gerne das Problem mit uWSGI und nginx wissen, aber ich bin ratlos.

Update: Also mit gunicorn mir erlaubt, den Server als Dienst ausgeführt werden und während in Mezzanine liebäugelt Ich lief in diesem Fehler: FileSystemEncodingChanged

dies zu beheben ich die Lösung hier: https://groups.google.com/forum/#!msg/mezzanine-users/bdln_Y99zQw/9HrhNSKFyZsJ

Und ich musste es ein bisschen ändern, da ich Supervisord nicht verwende, ich benutze nur Emporkömmling und ein Shell-Skript. Ich habe diese nach rechts, bevor ich gunicorn in meiner mez_server.sh Datei ausführen:

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 

Ich habe auch versucht, dieses Update mit uwsgi wie so (viel kürzer, da mit 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 

Ich bleibe immer noch bei Gunicorn, da es immer noch mit dem Problem funktioniert und mich in die richtige Richtung führt, um es zu lösen. Ich war sehr enttäuscht, dass uwsgi keine Ausgabe in der Protokolldatei zur Verfügung gestellt, auch mit diesem params, ich habe nur den Server Startprozess gesehen und das ist es:

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

Während nginx den disconnect Fehler gehalten zu werfen, uwsgi saß da ​​wie nichts Ereignis.

+0

Es tut mir leid, dass meine obige Lösung Ihnen nicht geholfen hat. Ich kämpfte damit auch über eine Woche. Es kann sehr frustrierend sein. Es muss für einige Verzeichnisse keine Privilegien geben, die nicht leicht zu finden sind. Gunicorn ist viel einfacher einzurichten, benötigt aber auch 150 MB Speicher. uWSGI hat einen winzigen Speicherbedarf, ist aber schwer einzurichten. – Houman

+0

Ich habe es jetzt behoben, aber ich werde immer noch Gunicorn benutzen, es schien mir den richtigen Weg zu zeigen, um das Problem zu lösen. Das Problem für mich war ein Locale-Problem, ich musste diese Variablen in meiner Aufgabe (mez_server.sh) setzen, die den Prozessstart steuert: Export LANG = en_US.UTF-8, LC_ALL = en_US.UTF-8, LC_LANG = en_US.UTF -8 – radtek

+0

Sie haben Recht, uWSGI nahm 0,7% Speicher (13-17MB), das ist weniger als 1%, für die gleiche Aufgabe, aber ich erhöhte die Arbeiter von 1 bis 3, jeder Arbeiter auf Gunicorn ist etwa 3- 7% (20-40MB), plus die Hauptaufgabe ist 2%. Ich mag es wirklich beide zu benutzen und fand nicht eine schwerer zu konfigurieren als die andere. Ich bleibe bei Gunicorn, wenn ich nicht wirklich brauche, dass der Speicherbedarf reduziert wird. PS. vacuum parm für uwsgi funktionierte nicht für mich, der Zombie-Prozess läuft weiter, was behebt es ist dieser parm: die-on-term = true – radtek

0

als eine einzige Zeile mit Daemon wahr Befehl ausgeführt ist

gunicorn app.wsgi:application -b 127.0.0.1:8000 --daemon 

binden Sie Ihre App mit 127.0.0.1:8000 und --deamon es als Daemon laufen zwingen

aber eine gunicorn_config definieren Datei .cfg und laufen mit -c ist eine gute Praxis

für mehr:

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

+2

gunicorn =/= uWsgi obwohl – Houman

Verwandte Themen