Lebensdauer Raspberry PI/Fehlermeldung

Heute ist Stammtischzeit:
Jeden Donnerstag 20:30 Uhr hier im Chat.
Wer Lust hat, kann sich gerne beteiligen. ;)
  • Guten Morgen zusammen,
    ich nutze meinen Raspberry zur Messung des Wasserstandes in der Zisterne mit Levelsensoren (Schwimmschalter). Funktioniert auch gut. Allerdings habe ich eine Frage und ein Problem. Belastet dieses Script, welches alle 5 Sekunden per PI FACE DIGITAL 2 eine Messung durchführt die Lebensdauer des Raspberry?

    Nach mehr als zwei Tagen Dauerbetrieb erscheint folgende Meldung: (<class 'OSError'>, OSError(24, 'Too many open files'), <traceback object at 0x763e6a80>)
    Kann jemand damit was an fangen?

    Vielen Dank und einen sonnigen Tag für alle.

    whitechristmas

  • Hallo whitechrismas,

    Du öffnest in einer Endlos-Schleife eine Datei (hier einen Socket). Mit jedem Öffnen wird ein Zähler der offenen Dateien hochgezählt. Irgendwann ist die Grenze, die das Betriebssystem erlaubt, erreicht. Dies führt zu der Fehlermeldung.

    Ändere die Zeit mal von 5 Minuten auf 5 Sekunden. Dann wird's vorher knallen.

    Die Best-Practice in Deinem Fall besteht darin, jede geöffnete Datei zu schließen, wenn der Schreib-/Lesevorgang beendet ist. Im Fall der Sockets öffnet man den Socket VOR der Python-Endlosschleife und kommuniziert dann darüber. Hier sollte aber der der Teilnehgmer prüfen, ob die Verbindung noch besteht - und im Falle einer Störung die Verbindung ebenfalls zu schließen um sie dann wieder nbeu aufzubauen.


    Beste Grüße

    Andreas

    Ich bin wirklich nicht darauf aus, Microsoft zu zerstören. Das wird nur ein völlig unbeabsichtigter Nebeneffekt sein.
    Linus Torvalds - "Vater" von Linux

    Linux is like a wigwam, no windows, no gates, but with an apache inside dancing samba, very hungry eating a yacc, a gnu and a bison.

    Einmal editiert, zuletzt von Andreas (16. Januar 2017 um 09:23)

  • Ist es wirklich notwendig, alle fünf Sekunden zwei Messungen zu machen?
    Ändert sich der Wasserstand so schnell?

    Wenn der Wasserstand sich schnell und plötzlich ändern kann, könntest du auch messen und nur die Änderungen zum vorherigen Wert in einer Datei schreiben.
    Du hältst also den 'alten' Wert im Speicher und vergleichst den neuen Wert mit diesem.
    Entspricht der neue Wert dem alten, passiert nicht. Ändert¹ sich der neue Wert, wird er mit Zeitstempel geschrieben und für den nächsten Vergleich vorgehalten.

    ¹: außerhalb einer vorgegebenen Toleranz

    Computer ..... grrrrrr

  • Andreas: Vielen Dank für Deine Rückmeldung. Das Intervall ist keine 5 Minuten, sondern jetzt schon bei 5 Sekunden. Wenn ich mein Pythonprogramm in Windows öffne möchte ich den aktuellen Wasserstand haben. Damit ich nicht zu lange warten muss, habe ich 5 Sekunden eingestellt. Ich habe jetzt mal folgendes im Code geändert:

    Damit sollte dann das Problem mit der Anzahl der offnenen Dateien (hoffentlich) beendet sein.
    Hat dieses kurze Intervall einen Einfluss auf die Lebensdauer des Raspberry?

    Rasp-Berlin: Der Wasserstand ändert sich definitiv nicht so schnell. Es geht mir darum wie oben beschrieben, dass ich bei einer Abfrage von Windows aus nicht allzu lange warten muss, bis ich das Ergebnis der aktuellen Messung habe. Wenn die Lebensdauer des Raspberry darunter nicht leidet, soll mir das recht sein.

    Ich würde mich über Eure Rückmeldungen freuen. Euch einen schönen Tag noch.

    whitechristmas

  • Hallo Whitechrismas,

    dann wird es immer noch knallen, sobald die erlaubte Anzahl offener Dateien erreicht ist. In Beitrag #2 bat ich Dich, den Socket nur einmal und dann VOR der Endlossschleife zu öffnen. Dies hast Du weiterhin nicht beachtet. Und somit wird sich am Absturz Deines Programmes nichts ändern. Ich tippe mal auf eine Laufzeit von etwa 1 Stunde...

    Hmm ... und wenn sich der Wasserstand nicht soooo schnell ändert, dann braucht man ihn auch nicht so häufig abzufragen... :s


    Beste Grüße

    Andreas

    Ich bin wirklich nicht darauf aus, Microsoft zu zerstören. Das wird nur ein völlig unbeabsichtigter Nebeneffekt sein.
    Linus Torvalds - "Vater" von Linux

    Linux is like a wigwam, no windows, no gates, but with an apache inside dancing samba, very hungry eating a yacc, a gnu and a bison.

  • Hi Andreas,

    ich dachte, wenn ich den Socket jedes Mal schließe, ist das Problem behoben. Ich schlage folgendes vor. Ich lasse das Script jetzt mal laufen und schaue wie lange es läuft. Dann werde ich die Zeit hier im Forum zurück melden. Danach schreibe ich wie von Dir empfohlen die Anweisung vor die Endlosschleife.

    Zitat

    Hmm ... und wenn sich der Wasserstand nicht soooo schnell ändert, dann braucht man ihn auch nicht so häufig abzufragen...


    Wenn ich das Intervall zu groß mache, muss ich in Windows zu lange auf eine Rückmeldung warten.

    Wie denkst Du über die Lebensdauer?

    Vielen Dank für Deine Rückmeldung.

    whitechristmas

    Einmal editiert, zuletzt von whitechristmas (16. Januar 2017 um 09:58)

  • Hallo Rasp-Berlin,

    momentan schreibe ich in keine Datei. Wenn ich die Lösung nicht stabil über UDP hinbekomme, dann muss ich die Werte in eine Datei schreiben. Dann genügt es auch z.B. alle 15 Minuten eine Messung weg zuschreiben. Dann kann ich über crontab das Skript starten und habe mit dem Socket keine Probleme mehr. Die Lösung über UDP würde mir besser gefallen.

    Vielen Dank.

    whitechristmas


    Einmal editiert, zuletzt von whitechristmas (16. Januar 2017 um 10:31)

  • Hallo Whitechrismas,



    ich dachte, wenn ich den Socket jedes Mal schließe, ist das Problem behoben. Ich schlage folgendes vor. Ich lasse das Script jetzt mal laufen und schaue wie lange es läuft. Dann werde ich die Zeit hier im Forum zurück melden. Danach schreibe ich wie von Dir empfohlen die Anweisung vor die Endlosschleife.

    Ach, passt schon - ich war so auf die Öffnung des Sockets fixiert, dass ich auf das Schließen gar nicht geachtet habe. In der aktuellen Form sollte es bis zum Stromausfall laufen. Und vor allem wird zeitnah geschlossen, was nach dem Öffnen nicht mehr gebraucht wird.



    Wenn ich das Intervall zu groß mache, muss ich in Windows zu lange auf eine Rückmeldung warten.


    :s Verstehe ich nicht. Macht für mich keinen Sinn. Kommunikation anleiern, kommunizieren, Kommunikation beenden. Dauert immer ungefähr vergleichbar lange - egal wieviel Zeit zwischen Beenden und Anleiern vergangen ist.


    Wie denkst Du über die Lebensdauer?

    Wen meinst Du mit Lebensdauer? Sensor? Programm? RPi?

    • Der Abfragezyklus des Sensors braucht eine gewisse Zeit, die im Datenblatt definiert ist. Diese solltest Du nicht unterschreiten - und besser eine ausreichende Zeitspanne zwischen zwei Messungen verstreichen lassen. Bei einem 5 Minuten-Intervall bist Du da sehr auf der sicheren Seite.
    • Programme stürzen u.a. dann ab, wenn durch Speicherklau (Memory Leaks) der Speicher volläuft, also allozierter Speicher nicht sauber freigegeben wird, diverse bedtriebsbedingte Zähler überschritten werden (den der offenen Dateien hast Du kennen gelernt), irgendwas Undefiniertes aufgerufen oder verwendet wird, was bei der Syntax-Prüfung nicht entdeckt wurde, unzureichendes Fehlerereignisbehandlung (was passiert, wenn Öffnen nicht funkioniert?)..., ..., ... Da sehe ich in Deinem Programm wenig Angriffspunkte (außer, das nicht definiert ist, was passieren soll, wenn der Socket nicht geöffnet werden kann - und im Fall des Scheiterns ins "Leere" geschrieben wird, was auch zum Absturz führen wird).
    • Dem RPi ist das vollkommen schnurz. Beobachte mal die CPU-Auslastung, CPU-Temperatur und den freien Speicher. Im Panel kann man derartige Tools platzieren. Wenn das so bei 5 - 10 % herumdümpelt, die Temperatur im erträglichen Bereich bleibt, und der Arbeitsspeicher nicht kontinuierlich abnimmt, dann kann das Programm ewig auf dem RPi laufen. Tools wie top, htop, sudo vcgencmd measure_temp, watch free (oder von mir hier im Forum gepostete ressourcenschonendere Varianten) geben Dir die gleichen Informationen.

    Für eine Auftragsentwicklung habe ich mal einen RPi eine Woche bei zyklisch wechselnden CPU-Auslastungen von 85 bzw. 100 % laufen lassen. Die CPU-Temperatur lag immer bei 42 - 45 °C.

    Da brauchst Du Dir bei Deiner Anwendung keine Gedanken zu machen.


    Beste Grüße

    Andreas

    Ich bin wirklich nicht darauf aus, Microsoft zu zerstören. Das wird nur ein völlig unbeabsichtigter Nebeneffekt sein.
    Linus Torvalds - "Vater" von Linux

    Linux is like a wigwam, no windows, no gates, but with an apache inside dancing samba, very hungry eating a yacc, a gnu and a bison.

    Einmal editiert, zuletzt von Andreas (16. Januar 2017 um 10:42)

  • Servus whitechristmas,

    also ich denke, der korrekte Weg wäre ein anderer.
    Warum? Nun, Du schmeisst einfach Deine Daten ins Netz ... egal ob sie jemand empfängt bzw. benötigt oder nicht.
    Das erzeugt unnötigen Traffic und zudem Last auf dem Pi ...
    Mir wurde mal beigebracht bedacht und sinnvoll mit den Resourcen unzugehen.
    Deshalb würde ich mal folgenden Ansatz überdenken:
    1. Du liest Deinen Sensor wie geplant alle 15 Minuten aus und merkst Dir den Wert.
    2. Das Programm geht in der Zwischenzeit in eine Art "Lauschmodus" auf der Multicast-Adresse Deines Netzes.
    3. Dein Windows-Prozess meldet sich mit einer kurzen Multicast-Anfrage.
    4. Dein Programm registriert diese Anfrage, merkt sich, dass eine "Verbindung" besteht, und speichert die Adresse des anfragenden Rechners in einer Liste. Anschliessend werden an diese Adresse sofort die aktuellen Daten gesendet.
    5. Dein Programm weiss jetzt, dass mindestens ein "Interessent" vorhanden ist und sendet die Sensordaten wiederum entweder explizit an jeden oder aber per Multicast an alle auf einmal.
    6. Die Interessenten quittieren den Empfang der Daten. Fehlen mindestens ein/zwei/drei ... Quittungen, wird die Adresse aus der Liste genommmen.
    7. Wird Dein Windows-Programm beendet, sendet es eine goodbye-Message an Dein Programm. Dieses nimmt daraufhin die Adresse aus seiner Liste.
    8. Hat die Liste die Länge 0 gibt es keine potentiellen Empfänger und es wird auch nichts gesendet.

    Ich hoffe, ich hab jetzt nichts essentielles übersehen. Ich denke, damit reduzierst Du einiges an Last in einigen Bereichen.

    cu,
    -ds-

  • Die paar Bytes als Broadcast gehen völlig im Lärm der diversen Auto-Discovery und Netzwerkfreigaben Pakete unter.

    Aber noch besser als immer auf & zu machen ist der von Andreas schon erwähnte weg, den Socket VOR der Schleife einmal zu öffnen.

    Ob das aber etwas an dem Problem ändert bin ich mir nicht so sicher. Auch wenn man in Python angehalten ist, resource Management zu betreiben (etwa mit dem with-statement), ist es schon so programmiert, daß es den socket von selbst schließen sollte. Weil nämlich das letzte socket Objekt überschrieben wird, und dadurch automatisch schließt.

    Falls das Problem also nicht weg geht, poste bitte den gesamten stacktrace. Den bekommst du, indem du den try/except Unfug entfernst, der eine propere Ausgabe unterdrückt.
    Automatisch zusammengefügt:
    Nachtrag: mein Verdacht ist naemlich wesentlich eher das ebenfalls von dir permanent neu vorgenommene initialisieren des PIFACE. Auch *das* gehoert nur einmal gemacht.

  • Hallo!

    Zitat

    Verstehe ich nicht. Macht für mich keinen Sinn. Kommunikation anleiern, kommunizieren, Kommunikation beenden. Dauert immer ungefähr vergleichbar lange - egal wieviel Zeit zwischen Beenden und Anleiern vergangen ist.


    Wenn ich z.B. nur alle 100 Sekunden eine Messung versende, dann muss ich max. 100 Sekunden warten, bis ich auf meinem Windowsrechner eine Messwert empfangen kann. Die Übergabe des Messwertes erfolgt nur, wenn zeitgleich gesendet und empfangen wird.

    Die CPU-Temperatur liegt bei ca. 34 °Celsius und die Prozessorlast liegt zwischen 0% und 5%. Springt immer hin und her, im Durchschnitt vielleicht bei ein paar Prozent.

    Mit dem Socket vor die Schleife werde ich auch noch versuchen.

    @dreamshader: Der von Dir beschriebene Weg hört sich gut und professionell an. Ich habe allerdings keinen Schimmer, wie ich eine Multicast-Anfrage programmiere. Dafür fehlen mir dann doch die Kenntnisse. Die Netzwerklast ist kein Problem (Heimnetz).

    @__deets__: Bisher läuft das Skript ohne Probleme. Sobald sich was tut, poste ich das Ergebnis. Das mit der Initialisierung könnte das Problem sein. Ziehe ich dann auch vor die Schleife.

    Vielen Dank an alle.

    whitechristmas

  • Hallo Whitechrismas,


    Hallo!


    Wenn ich z.B. nur alle 100 Sekunden eine Messung versende, dann muss ich max. 100 Sekunden warten, bis ich auf meinem Windowsrechner eine Messwert empfangen kann. Die Übergabe des Messwertes erfolgt nur, wenn zeitgleich gesendet und empfangen wird.


    Verstehe ich immer noch nicht.

    Eine Socket-Kommunikation läuft doch so ab:
    - Eine Verbindung wird über IP-Adresse und Portnummer hergestellt.
    - Beide Teilnehmer lauschen auf dem Port, ob da was ankommt - ggf. wird ein Ereignis ausgelöst und dieses behandelt
    - Wenn einer was zu senden hat, dann sendet er - über die Ereignisbehandlung auf der anderen Seite ist sichergestellt, dass mit den gesendeten Daten auch irgendwas passiert.
    - Die Seite, die etwas empfangen hat, bestätigt den Empfang durch einen speziellen Code.
    - Empfängt der Sender diese Bestätigung innerhalb einer Zeit nicht, wiederholt er die Sendung einige wenige Male

    Erst jetzt ist der Sende-Empfangszyklus beendet. Und ich kann mir nicht vorstellen, dass das in einem Heimnetz (Rechner 1 - Router - Rechner 2) bei wenigen Daten länger als wenige hundert ms dauern sollte.

    Wenn der Empfang so lange dauert wie der Zeitraum zwischen zwei Messungen, dann liegt's an was anderem.


    Beste Grüße

    Andreas

    Ich bin wirklich nicht darauf aus, Microsoft zu zerstören. Das wird nur ein völlig unbeabsichtigter Nebeneffekt sein.
    Linus Torvalds - "Vater" von Linux

    Linux is like a wigwam, no windows, no gates, but with an apache inside dancing samba, very hungry eating a yacc, a gnu and a bison.

  • Servus Andreas,


    ...
    Verstehe ich immer noch nicht.

    er schickt alle 5 Sekunden ein UDP Datenppaket ins Netz, weil sich der Windows-Teil eben nicht per Anfrage bei ihm meldet, sondern darauf wartet ein Paket aus dem Äther zu fischen und die Daten dann anzuzeigen.
    Würde er nur alle 15 Minuten die Daten senden, dann würde der Windows-Client (oder wie mal ihn nennen mag) im ungünstigsten Fall eben knapp 15 Minuten auf die Daten warten ;)

    cu,
    -ds-


  • Die Best-Practice in Deinem Fall besteht darin, jede geöffnete Datei zu schließen, wenn der Schreib-/Lesevorgang beendet ist.

    das gilt unabhängig eigentlich IMMER, man lässt keine "Dateien" offen

    zumal bei Absturz, Netzunterbrechung dann das Dateisystem korrupt ist!

    Immer öffnen und Schliessen mit Speicheranforderung malloc() kann aber das OS überfordern u.U. den Speicher zerfleddern zumal es keine garbadge collection mehr zu geben scheint, war früher im OS serienmäig (CBM Basic).
    Im ersten Atari TOS 1.0 war die Speicheranforderung auf 128 begrenzt was Atari den "Ruf" einbrachte leicht abzustürzen, danach war ein boot fällig, mit TOS 1.4 wurde das auf 1024 erhöht, wer aber 1024 x Speicher anforderte sah das auch, nur andere halt weniger.

    Richtig ist zum Schreiben der Datei öffnen und schliessen wenn neu geschrieben werden muss.
    Speicher für das Programm nur einmal anfordern und nicht freigeben bis das Programm terminiert.
    Muss man öfter in eine Datei schreiben sollte man eine RAM Disk bemühen um nicht den flash über Gebühr zu belasten.
    Man kann auch nur neu schreiben wenn sic wirklich was ändert, also nicht alle 5s sondern bei echten wesentlichen Änderungen, dabei ist es die 3te Stelle hinterm Komma meist nicht die gesichert werden muss, hier Füllstand, ich sage ob 4,99m oder 5,01m dürfte genauso unerheblich sein, wenn überaupt die dH/dT, als0 sollte es um 2cm in 1µs sich verändern also steigen oder fallen ist das interessanter als 2cm in 5 Tagen

    lasst die PIs & ESPs am Leben !
    Energiesparen:
    Das Gehirn kann in Standby gehen. Abschalten spart aber noch mehr Energie, was immer mehr nutzen. Dieter Nuhr
    (ich kann leider nicht schneller fahren, vor mir fährt ein GTi)

    Einmal editiert, zuletzt von jar (16. Januar 2017 um 12:28)

  • Hallo Andreas,

    Dreamshader liegt das richtig mit Post #16. Ich versende per UDP und wenn die Gegenstelle empfangsbereit ist, werden die Daten empfangen. Wenn nicht, versucht er es wieder im eingestellten Intervall die Daten zu versenden. Das was Du meinst ist TCP, das ist verbindungsorientiert.

    Viele Grüße

    whitechristmas

  • Der Vorschlag von Zentrist ist definitiv der richtige Weg. Es sei denn du brauchst eine Art Auto Discovery.

  • Warum versendest du?
    Wie du selber geschrieben hast, musst du dann bis zum nächsten Sendeintervall warten, bis das Zielsystem die Daten bekommt.
    Außerdem musst du etwas an deinem Programm ändern, wenn das Zielsystem z.B. eine andere IP bekommt oder noch ein zweites Zielsystem hinzu kommt.
    Setzt doch einen kleinen Webserver auf, auf dem das/Die Zielsystem(e) sich die Daten bei bedarf abholen, wie in #13 vorgeschlagen wurde.

    Computer ..... grrrrrr

Jetzt mitmachen!

Du hast noch kein Benutzerkonto auf unserer Seite? Registriere dich kostenlos und nimm an unserer Community teil!