Flask Server findet plötzlich statische Dateien nicht mehr

  • Hallo, ich habe momentan einen Flask Server mit Apache2 auf meinem RasPi am Laufen. Bis gestern abend funktionierte alles wunderbar. Aber ganz plötzlich findet Flask die statischen Dateien wie die css und js Dateien nicht mehr. Ich habe seit mehreren Tagen an der Konfiguration nichts verändert und auch nichts neues installiert. Die Dateien liegen in ihren eigenen Ordnern im static Ordner im root Verzeichnisses des Servers.

    Ich frage die Dateien mit

    Code
    <link href="{{ url_for('static', filename="css/custom.css") }}" rel="stylesheet">

    ab. Alle anderen Funktionen des Servers (Skripte ausführen, in eine Datenbank schreiben) funktionieren weiterhin problemlos. Das Problem ist Browser und Clientunabhängig und auch ein Neustart vom RasPi hat nichts geholfen.


    Danke im Vorraus

  • Hallo,


    welchen Fehler bekommst du vom Server? 404? Wirft Flask einen Fehler? Kannst du, wenn du die volle URL eines statischen Inhalts angibst, diesen sehen bzw. liefert der Server was aus?

    Wie liefert Apache deine Flask Applikation aus? Sitzt noch ein WSGI Applikationsserver dazwischen?


    BTW: wenn du keine Webseite mit hunderten oder tausenden von Request pro Sekunde hast, dann wirf mal einen Blick auf WhiteNoise. Damit können Flask, Django & Co statische Inhalte selber & performant ausliefern, ohne nginx oder Apache oder ... Praktisch und einfach(er) zu konfigurieren.


    Gruß, noisefloor

  • Ja Flask gibt nur 404 aus. Im Debug Log ist auch nur 404 zu finden und keine weitere Angaben. Sowohl der relative als auch absolute Pfad haben keine Besserung gebracht.

    Ja ich benutze WSGI um den Flask Server auszuliefern. Aber selbst ohne Apache oder WhiteNoise sollte Flask doch in der Lage zu sein die Dateien zu finden,wenn ich Flask lokal laufen lasse.

  • Hallo,


    Quote

    Aber selbst ohne Apache oder WhiteNoise sollte Flask doch in der Lage zu sein die Dateien zu finden,wenn ich Flask lokal laufen lasse.

    Ja, ABER: das macht einen ziemlichen Unterschied in der Konfiguration! Wenn der Entwicklungsserver von Flask läuft, sendet dieser statischen Dateien mit. Wenn du dein App über WSGI anbindest, was produktiv ja sinnvoll ist, dann musst du dich selber drum kümmern. Das ist bei anderen Frameworks wie z.B. Django genau so.

    Hast du Apache so konfiguriert, dass er die statischen Dateien ausliefert?


    Und genau das ist der Vorteil von White Noise: du brauchst keine separate Konfiguration im Webserver, weil der statischen Content via WSGI mit kommt.


    BTW: Apache also WSGI Applikationsserver ist jetzt IMHO auch nicht soooo der Hit, weil vergleichsweise kompliziert. Deutlich einfacher ist Gunicorn als WSGI-Applikationsserver. Bei Bedarf kannst du da ja noch Apache oder (besser) nginx als Reverse Proxy davor setzen. Wobei Gunicorn auch als direkter Server dienen kann, Apache oder nginx sind optional.


    Gruß, noisefloor

  • Das ist klar, dass ich für die Produktion mich selbst drum kümmern muss. Mein Problem ist aber, dass selbst der Entwicklungsserver von Flask die Dateien nicht findet.

    Bis gestern abend lief alles noch problemlos mit Apache und WSGI. Die statischen Dateien wurden problemlos gefunden und ausgeliefert.

  • Eigentlich von beidem, aber erstmal nur vom Entwicklungsserver der lokal läuft. Ich gehe davon aus dass das Problem nicht an Apache liegt, da selbst der Entwicklungsserver der die statischen Dateien selbst ausliefert, die Dateien nicht findet.

  • Verzeichnisstruktur:

    Code
    webroot
    - static
    -- css
    --- custom.css
    --- bootstrap.min.css
    -- js
    --- custom.js
    - templates

    Ich bin mir nicht sicher was du mit Konfiguration meinst. Den Code von Flask?

    Falls ja sollten das die relevanten Stellen sein:

    Code
    app = Flask(__name__, static_folder="/var/www/html/static")
    
    @app.route('/static/<path>/<file>',methods=['GET'])
    def serve_file(path,file):
            return send_from_directory('/static/' + path,file)
    
    app.run(host="0.0.0.0",port=80,debug=True)

    Die serve_file Funktion habe ich zum testen eingebaut, welche Dateien gefunden werden und welche nicht. Ergebnis war gar keine werden gefunden.

    Ich habe die App sowohl mit static_folder Parameter als auch ohne, und sowohl mit relativem als auch mit absolutem Pfad getestet.

  • Wie ich bereits geschrieben habe, hatte ich die Option nur drin um zu testen ob es evtl. daran liegen könnte. Mein Problem besteht aber sowohl mit der Option als auch ohne.

  • Den mMn. relevanten Code habe ich oben gepostet. Alles andere enthält nur die verschiedenen Seiten und Unterfunktionen die mit den statischen Dateien nichts zu tun haben. Ich habe mal noch die ganze layout.html Datei hochgeladen. layout.html

    layout.html ist bei mir für das grundlegende Layout verantwortlich und wird in jeder anderen HTML Datei benutzt.


    Ich bin mir nicht sicher was ich geändert haben sollte, dass einfache Dateien nicht mehr gefunden werden obwohl sie ganz offensichtlich da sind.

  • Hallo,


    xMaschx: der Punkt ist, wie ich oben schon schrieb, dass es einen Unterschied macht, auch von der Konfig, ob der Entwicklungsserver oder der Apache läuft.

    Wenn der Entwicklungsserver läuft, gibt es ja 0,0 Gründe, die statischen Daten in /var/www/html zu legen. Da macht es sehr viel Sinn, `/static`als Unterverzeichnis der Verzeichnisses zu nehmen, wo deine Python-Datei liegt. Apropos: wo liegt die eigentlich?


    Gruß, noisefloor

  • Code
    app = Flask(__name__)
    app.run(host="0.0.0.0",port=80,debug=True)

    Das ist der relevante der Teil der python Datei. Alle anderen Funktionen haben nichts mit den statischen Dateien zu tun.

    Die python run.py Datei liegt in /var/www/html und die statischen Dateien in z.B. /var/www/html/static/css/ oder /var/www/html/static/js.

    Ich müsste noch erwähnen dass der Entwicklungsserver und der Apache Server im Grunde das gleiche sind. Bei dem Entwicklungsserver starte ich nur die Pythondatei und bei dem normalen Server starte ich Apache.

    "/static" ist ein Unterverzeichnis von /var/www/html also ein Unterverzeichnis von dem Ordner wo die Pythondatei des Servers liegt.


    Ich habe einen 2. Flask Server aufgesetzt, der nur die minimalsten Anforderungen zum Starten abdeckt. Rufe ich dann meine Website wieder auf, werden die Dateien ohne Probleme gefunden. Der 2. Server liegt im selben Verzeichnis wie der erste.

  • Hallo,


    Quote

    Ich müsste noch erwähnen dass der Entwicklungsserver und der Apache Server im Grunde das gleiche sind.

    Nee, ist es nicht. Wenn du den Entwicklungsserver startest, dann musst du das in der gegebenen Konfiguration mit Root-Rechten machen (was generell schlecht ist), weil du sonst nicht an 0.0.0.0 binden kannst (macht zum Entwickeln auch wenig Sinn).
    Wenn du deine App via mod_wsgi auslieferst, ist die Zeile`app.run(...)` überflüssig. Ob das Kontraproduktiv ist kann ich dir nicht sagen, weil ich Flask nicht produktiv nutze.


    Gruß, noisefloor

  • Ja okay, daran habe ich nicht gedacht. Aber das sind ja im Grunde auch nur Kleinigkeiten. Es lief bis vor Kurzem ja sowohl mit dem Entwicklungsserver mit root Rechten als auch mit dem Apache Server als www-data Benutzer.


    Ich habe hier fast die ganze run.py hochgeladen (ohne die sensiblen Daten und Funktionen) und hier die 2. run.py mit der alles funktioniert.

    Die 2. Datei ist absolut minimalistisch hat nur das Nötigste zum Starten.

  • Hallo,


    Linus hat es ja schon mal gesagt :"es lief bis vor kurzem" in Kombination mit "ich habe nichts geändert" kann einfach nicht sein. Computer sind nicht launisch und verweigern nicht aufgrund eines schlechten Tags die ausliefern von statischem Content "nur mal so".


    Aus dem Code geht jedenfalls nicht hervor, was das Problem ist. Zeig' bitte auch mal deine Apache Config für den statischen Content.


    Allgemeines zum Code:

    • Ich würde das auch mehrere Dateien aufteilen, damit es übersichtlicher ist, nicht eine monolithische Datei.
    • Python 2 ist Ende 2019 EOL -> schreib' das ganze auf Python 3 um.
    • `os.system` ist veraltet, schon länger. Das steht auch wörtlich in der Python Doku. Der korrekte Weg ist das `subprocess` Modul.
    • Eingerückt wird _immer_ mit 4 Leerzeichen.
    • Wenn das Skript unter Apache als `www-data` läuft, kann das `os.system("sudo irgendwas")` eigentlich nicht funktionieren - wo soll das Skript die Root-Rechte her bekommen?

    Grundsätzlich halte ich es auch für überhaupt nicht sinnvoll, bei der lokalen Entwicklung a) mit Root-Rechten b) auf Port 80 d) auf 0.0.0.0 und d) aus /var/www/html laufen zu lassen. Außer umständlich und ein potentielle risikobehaftet ist das nämlich nichts. Das schöne an WSGI ist ja, dass das auch nicht notwendig ist.


    Schaltet du eigentlich den Apache ab, wenn das Skript auf Port 80 läuft? Es können ja keine 2 Dienste auf dem gleichen Port lauschen. Wenn ja: ist das garantiert, dass Apache nicht, wenn das Skript läuft?


    Gruß, noisefloor