Seite 1 von 2

django: fastCGI Probleme...

Verfasst: Mittwoch 19. September 2007, 13:36
von jens
Hm. Stehe irgendwie auf dem Schlauch... Ich bekomme django nicht mit fastCGI zum laufen :(

Leider habe ich keinen Zugriff auf die Apache Log-Dateien :(

Das kleine Test-Skript aus dem Wiki läuft einwandfrei: [wiki]Web-Skripte zum Laufen bringen#EinKleinerFastcgiTest[/wiki]

Wenn man es selber macht, sieht es ja so aus (der dispatcher):

Code: Alles auswählen

from flup.server.fcgi import WSGIServer

from fastCGI_test_app import app

WSGIServer(app).run()
Es es möglich django als "app" zu bekommen? Dann könnte ich das damit mal probieren. Auf jeden Fall geht's wie auf http://www.djangoproject.com/documentat ... ith-apache beschrieben nicht.
Auch lokal funktioniert das ganze nicht. In der Log sehe ich allerdings auch nur sowas:
[Wed Sep 19 14:31:48 2007] [notice] mod_fcgid: server /home/jens/workspace/PyLucid0.8(django)/index.fcgi(9358) started
[Wed Sep 19 14:31:49 2007] [notice] mod_fcgid: server /home/jens/workspace/PyLucid0.8(django)/index.fcgi(9359) started
[Wed Sep 19 14:31:49 2007] [notice] mod_fcgid: process /home/jens/workspace/PyLucid0.8(django)/index.fcgi(9358) exit(server exited), terminated by calling exit(), return code: 255
[Wed Sep 19 14:31:49 2007] [notice] mod_fcgid: process /home/jens/workspace/PyLucid0.8(django)/index.fcgi(9356) exit(server exited), terminated by calling exit(), return code: 255
[Wed Sep 19 14:31:55 2007] [notice] mod_fcgid: process /home/jens/workspace/PyLucid0.8(django)/index.fcgi(9359) exit(server exited), terminated by calling exit(), return code: 255

Verfasst: Mittwoch 19. September 2007, 16:42
von Leonidas
Also bei mir funktioniert der Django-Code mit Lightys FastCGI. Welches FastCGI Modul nutzt du denn?

Eine WSGI-App bekommst du eigentlich ganz einfach mit ``django.core.handlers.wsgi.WSGIHandler()``.

Verfasst: Mittwoch 19. September 2007, 17:33
von jens
Anscheinend ist es der neuere "fcgid"...

Also du meinst das so:

Code: Alles auswählen

import os
os.environ['DJANGO_SETTINGS_MODULE'] = "PyLucid.settings"

from flup.server.fcgi import WSGIServer
from django.core.handlers.wsgi import WSGIHandler

app = WSGIHandler() # Evtl. ohne die Klammern?

WSGIServer(app).run()

Verfasst: Mittwoch 19. September 2007, 20:36
von mitsuhiko
Das stimmt so, also mit den Klammern.

Verfasst: Donnerstag 20. September 2007, 10:00
von jens
Aha! Das bringt mich ein Stückchen weiter! Denn so geht's...

Nun funktioniert es auch... Ich hab mir mal was gebastelt:

Code: Alles auswählen

#!/usr/bin/python

import os

from django.core.handlers.wsgi import WSGIHandler
from django.core.servers.fastcgi import runfastcgi

os.environ['DJANGO_SETTINGS_MODULE'] = "PyLucid.settings"

def tb_catch_app(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/html')])
    yield '<h1>FastCGI Traceback catch:</h1>'

    global msg
    yield "<pre>"
    yield msg
    yield "</pre>"

try:
    runfastcgi(method="threaded", daemonize="false")
except Exception, err1:
    import traceback
    msg = traceback.format_exc()
    
    from flup.server.fcgi import WSGIServer
    WSGIServer(tb_catch_app).run()
else:
    msg = "Error: Nothings happends?!?!"
    from flup.server.fcgi import WSGIServer
    WSGIServer(tb_catch_app).run()
Ich denke das sollte irgendwie auch eleganter gehen, oder???

Zum eigentlichen Problem: Anscheinend waren meine benutzten Parameter für runfastcgi() falsch. Das verhinderte wohl eine Ausführung.
Ich hatte wohl statt den Parameter method="threaded" das angegeben: socket="fcgi.sock"

Verfasst: Freitag 21. September 2007, 14:11
von jens
OK, also beim GPcom geht's nun mit fastCGI...

Nun probiere ich es bei unserm PyHosting... Dort sehe ich in den log's das:
[Fri Sep 21 13:06:32 2007] [error] [client 88.76.139.87] FastCGI: comm with (dynamic) server "./index.fcgi" aborted: (first read) idle timeout (50 sec)
[Fri Sep 21 13:06:32 2007] [error] [client 88.76.139.87] FastCGI: incomplete headers (0 bytes) received from server "./index.fcgi"
Komisch. Ist eigentlich das selbe Skript...

Verfasst: Freitag 21. September 2007, 19:40
von Leonidas
jens hat geschrieben:Nun probiere ich es bei unserm PyHosting... [...] Komisch. Ist eigentlich das selbe Skript...
xorAxAx gefragt?

Verfasst: Samstag 22. September 2007, 21:22
von ahouben
Das ist dann meistens ein Problem mit der Umformatierung beim Hochladen auf den Server. Set transfer mode to binary, then upload again.

Verfasst: Dienstag 9. Oktober 2007, 07:23
von jens
Ne, also es lag wohl an den Dateirechten. suexec ist da wohl etwas penibel. In meinem Fall hatte die Gruppe Schreibrechte und das mag suexec nicht.

Aber jetzt siehts dennoch komisch aus! Also bei dem Skript von oben: http://www.python-forum.de/post-77936.html#77936
tritt doch tatsächlich der Fall ein das "Error: Nothings happends?!?!" ausgegeben wird! Das sollte ja IMHO nie auftreten...

Jetzt wo ich mir mal http://code.djangoproject.com/browser/d ... fastcgi.py angesehen habe, könnte es ja sein, das etwas auf stderr geschrieben wurde... Das könnte ich ja mal versuchen abzufangen...

Verfasst: Freitag 15. Februar 2008, 16:29
von jens
Hab mich heute nochmal dem Thema django + fastCGI angenommen...

Ich hab was dolles gefunden und zwar in /django/core/servers/fastcgi.py :

Code: Alles auswählen

wsgi_opts['debug'] = False # Turn off flup tracebacks
http://code.djangoproject.com/browser/d ... =6075#L121

Warum nur ist das Hardcoded? Ich suche schon seid einiger Zeit eine Möglichkeit für einen solchen "Low-Level"-Debug Modus. Dabei exstiert der schon so einfach, ist aber immer abgeschaltet :(

Verfasst: Freitag 15. Februar 2008, 16:34
von Leonidas
jens hat geschrieben:Warum nur ist das Hardcoded?
Weil Django eine eigene Traceback-Middleware hat die etwas gegen das Leaken von Informationen abgesichert ist. Wie zum Beispiel Datenbankpasswörter.

Verfasst: Freitag 15. Februar 2008, 16:40
von jens
Ja, das stimmt. Allerdings ist es so: Wenn du einen Fehler in einer Middleware hast, dann funktioniert der django traceback überhaupt nicht!

Geh mal hin und setzte eine FastCGI App mit SQLite auf. Dann entziehst du der SQLite Datei die Schreibrechte. Wenn nun die Session Middleware versucht die Session zu schreiben, dann Peng.
Vom normalen Traceback sieht man nix. Nur in der Apache Log schneien Fehlermeldungen über stderr rein.

Im Browser sieht man nur was von "FastCGI Unhandled Exception"...

Wenn man aber den flup tracebacks aktiviert, dann sieht man auch einen Traceback im Browser...

Wenn man also keinen Zugriff auf die Apache Log hat, schaut man normalerweise in die Röhre...

Verfasst: Freitag 15. Februar 2008, 16:46
von Leonidas
jens hat geschrieben:Ja, das stimmt. Allerdings ist es so: Wenn du einen Fehler in einer Middleware hast, dann funktioniert der django traceback überhaupt nicht!
Ja, mag ja sein.
jens hat geschrieben:Vom normalen Traceback sieht man nix. Nur in der Apache Log schneien Fehlermeldungen über stderr rein.

Im Browser sieht man nur was von "FastCGI Unhandled Exception"...
Naja, findest du es besser die Datenbankpasswörter zu leaken, damit der User sich selbst einloggen kann und sich die Daten selbst aus der Datenbank holt?
jens hat geschrieben:Wenn man also keinen Zugriff auf die Apache Log hat, schaut man normalerweise in die Röhre...
Das ist an sich auch nicht verkehrt, denn error.log ist genau der Ort wo so etwas hin soll. Wenn man keinen Zugriff darauf hat, dann hat man ein generelles Problem und nicht angezeigte Tracebacks sind noch das geringste.

Verfasst: Freitag 15. Februar 2008, 16:48
von jens
Ich sagt ja nicht, das der flup traceback generell an geschaltet werden sollte. Aber es sollte so sein, das man in einschalten kann, ohne an django rumfummeln zu müssen.

Verfasst: Freitag 15. Februar 2008, 17:02
von Leonidas
Kannst ja einen Patch schreiben. Viel Glück.

Verfasst: Freitag 15. Februar 2008, 17:15
von jens

Verfasst: Dienstag 19. Februar 2008, 11:36
von jens
Also irgendwie ist das alles nix mit fastCGI... Ich hab lokal einen Apache laufen und kann dort in die LOG Dateien schauen... Aber auch daraus wird man oft nicht schlau, wenn dort nur sowas auftaucht wie:
[Tue Feb 19 10:26:03 2008] [error] [client 127.0.0.1] (104)Connection reset by peer: FastCGI: comm with server "/home/jens/workspace/PyLucid_trunk/pylucid/index.fcgi" aborted: read failed, referer: http://localhost/
[Tue Feb 19 10:26:03 2008] [error] [client 127.0.0.1] Handler for fastcgi-script returned invalid result code 1, referer: http://localhost/
Hin und wieder tauchen dort ausgaben von stderr auf, das hilft dann schon mal weiter...

z.Z. hänge ich wein wenig fest. Ich möchte das eine Traceback-App nur einmal läuft, damit jede Änderung sofort aktiv ist, ohne das ich die Prozesse killen muss oder Apache einen Neustart braucht.

Ich hab mal eine kleine Test App gemacht:

Code: Alles auswählen

#!/usr/bin/env python2.4
# -*- coding: utf-8 -*-

import os, time
from flup.server.fcgi_fork import WSGIServer


start_overall = time.time()

def app(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/html')])
    yield '<p>overall time: %.2fsec</p>\n' % (time.time() - start_overall)

    pid = os.getpid()
    yield '<p>pid: %s</p>\n' % pid


WSGIServer(
    app, maxRequests=1, maxSpare=1, maxChildren=1
).run()
Man kann sehen, das die pid pro Request eine andern Nummer ist. Denoch werden Änderungen im Sourcecode nicht direkt sichtbar. Das kann man auch an der Zeit sehen, die immer schön weiter läuft und nicht bei jedem Request von Null anfängt.

Ich bin wohl auf der Suche nach einer "auto-reload" Funktion für fastCGI, gibt es sowas?

Verfasst: Dienstag 19. Februar 2008, 13:25
von jens
Ich hab's, die Holzhammer Methode:

Code: Alles auswählen

#!/usr/bin/env python2.4
# -*- coding: utf-8 -*-

from flup.server.fcgi_fork import WSGIServer

import os, time

pid = os.getpid()
start_overall = time.time()

def app(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/html')])
    yield '<p>overall time: %.2fsec</p>\n' % (time.time() - start_overall)

    global pid
    yield '<p>pid1: %s</p>\n' % pid

    yield '<p>pid2: %s</p>\n' % os.getpid()

    import signal
    os.kill(pid, signal.SIGHUP)

WSGIServer(
    app, maxRequests=1, maxSpare=1, maxChildren=1
).run()
Wenn man os.kill() auskommentiert kann man sehen, das der Hauptprozess immer der selbe ist, aber die App immer in einem neuen Prozess gestartet wird.
Würgt man den Hauptprozess ab, dann startet die App quasi nach jedem Request von neuem...

Kann man das so machen? Solle ich ein anderes Signal senden?

Verfasst: Dienstag 19. Februar 2008, 13:25
von Leonidas
Unter Lighty werden bei mir FastCGI-Prozesse beim Server-Reload neu gestartet - sehr nützlich bisher.

Verfasst: Dienstag 19. Februar 2008, 13:28
von jens
Apache mus man restarten. Das dauert lange und man kann es nur mit root machen :(

Edit: Hm, mit os.kill() scheint Apache zusammen zu brechen...