Beim Kopieren von Bildern auf einen USB-Stick werden diese sporadisch korrupt

  • Hallo Zusammen,


    ich habe eine Fotobox gebaut, bei der sporadisch Probleme auftreten. Auf dem Raspi läuft ein entsprechendes Pythonskript.

    Workflow:

    - Tastendruck -> Bilder wird mit RaspiCam aufgenommen, temporär auf der SD Karte gespeichert und eine Vorschau angezeigt

    - Das Bild gefällt? dann wird mit einem weiteren Tastendruck das Bild von der SD Karte mittels python und "shutil.move(..)" auf einen USB-Stick verschoben


    Das ganze funktioniert grundsätzlich recht gut (...dachte ich bisher..).


    Wenn an einem Abend aber so um die 100 Fotos gemacht werden, dann sind ca. 3 - 5 Fotos korrupt auf dem USB-Stick.

    Ich konnte kein wirkliches Muster erkennen (mal kurz nachdem ein anderes Foto verschoben wurde, mal als die Fotobox länger nicht benutzt worden ist... )


    Möchte ich mit dem Fotoeditor von Raspbian das Foto öffnen kommen unterschiedliche Fehlermeldungen, z.B. "Fehler beim Lesen einer JPEG-Bilddatei (unsupported marker type 0x9c)", "Fehler beim Lesen einer JPEG-Bilddatei (Not a JPEG file: start with 0xff 0xff)", "Fehler beim Lesen einer JPEG-Bilddatei (invalid JPEG file structure: two SOI markers)".



    Hat jemand eine Idee was hier schief laufen könnte? Hatte schon mal jemand Probleme mit "shutil.move()"?

    Oder wäre es von Haus aus empfehlenswert, das Bild direkt auf dem USB-Stick zu speichern, sodass man auf das verschieben verzichten kann?



    Vielen Dank schon mal!

  • Ich könnte mir vorstellen, dass der Stick entweder noch nicht voll da oder / und noch beschäftigt ist und shutil davon nichts weiß.


    Mach vor dem Verschieben mal eine Abfrage auf dem Stick oder einen vergleichbaren Zugriff und dann erst den shutil.move(source, destination). In diese Richtung würde ich jedenfalls erstmal gehen. Bzw. bei diesem Test copyfile statt move verwenden, dann bleiben IMHO die Fotos wenigstens noch auf der SD. (Vor dem Ernstfall erstmal Testen! ;) )


    //Edit:


    Vergessen... Dann siehst Du auch ob nicht ggf. schon das originale Foto auf der SD korrupt war.

  • Quote

    - Das Bild gefällt? dann wird mit einem weiteren Tastendruck das Bild von der SD Karte mittels python und "shutil.move(..)" auf einen USB-Stick verschoben

    Die Funktion ist dem Befehl mv nachempfunden. Wenn man eine Datei von einem Dateisystem auf ein anderes verschieben will, wird zuerst die Datei kopiert und dann die Metadaten vom Original auf die Kopie übertragen. Das Programm kann schon lange fertig sein, was aber nicht zwangsweise bedeutet, dass die Kopieroperation erfolgreich beendet worden ist


    Unter Linux gibt es den Befehl und Syscall sync, der so lange blockiert, bis alle ausstehenden Änderungen auf die Datenträger geschrieben worden sind. Bei Python gibt es die Funktion os.sync() und falls man mal einen offenen Dateideskriptor hat, kann man os.fsync(fd) nutzen.


    1. USB-Stick erkannt und gemountet
    2. Prüfen, ob genug freier Speicherplatz vorhanden ist
    3. Foto machen
      1. Foto verschieben oder kopieren
      2. os.sync
      3. Dateisystem aushängen
    4. Signalisierung, dass der USB-Stick jetzt entfernt werden darf. Wer ihn vorher entfernt, riskiert Datenverlust
  • Das Programm kann schon lange fertig sein, was aber nicht zwangsweise bedeutet, dass die Kopieroperation erfolgreich beendet worden ist

    Vielleicht muss ich noch dazu sagen, dass es mehr ein "Dauerbetrieb" ist. Der USB-Stick ist ab Bootvorgang eingesteckt, das Programm läuft einige Stunden und immer wieder wird mal auf den USB-Stick ein Foto gespeichert. Nach einigen Stunden wird ausgeschaltet und auf dem USB-Stick sind z.B. 100 Fotos gespeichert worden, wobei Foto Nummer 3, Foto Nummer 51 und Foto Nummer 78 korrupt sind, alle anderen wurden "erfolgreich" abgespeichert. Der USB-Stick wird erst entfernt, wenn das System heruntergefahren ist.


    Deshalb kann ich mir irgendwie nicht vorstellen, dass der Grund für den Fehler ist, dass der Kopiervorgang noch nicht beendet wurde.

  • Mir fallen folgende Ansätze ein:

    • für Testbetrieb die Dateien auf SD- und USB-Stick lassen (cp statt mv) und bei korrupten Dateien vergleichen, ob sie auf der SD-Karte auch defekt sind
    • statt cp/mv mal rsync probieren
    • USB-Stick testweise tauschen um den USB-Stick als Fehlerquelle auszuschließen
    • direkt auf dem USB-Stick speichern (kein Umweg über SD-Karte)

    Viele Grüße,

    Peter

  • Nimm rsync und kopiere ohne Umweg. Das kann copy/verify

    "Really, I'm not out to destroy Microsoft. That will just be a completely unintentional side effect."

    Linus Benedict Torvalds, 28.9.2003


    Hast Du die Woche schon Deine Raspberry gesichert :fies: Bei mir tut das raspiBackup automatisch :shy:

  • Deshalb kann ich mir irgendwie nicht vorstellen, dass der Grund für den Fehler ist, dass der Kopiervorgang noch nicht beendet wurde.

    Ich mir auch nicht :D


    Ok, andere Möglichkeit wäre noch, dass der USB-Stick fehlerhafte Speicherzellen hat und kurz davor ist kaputtzugehen.

    Einfache Lösung: Anderen USB-Stick verwenden.


    Das Tool rsync halte ich für diese Aufgabe ungünstig. Soweit mir bekannt ist, prüft das Tool nach dem Schreiben nichts.


    Wenn Dateien beim Ziel bereits existieren, wird die Größe und der Zeitstempel verglichen.

    Wenn es dort einen Unterschied gibt, dann muss die Datei neu übertragen werden.

    Um Traffic zu sparen (rsync ist fürs Netzwerk konzipiert worden) wendet rsync einen Delta-Algorithmus an, um dann nur die Teile zu übertragen, die sich unterscheiden. Aber die Fotos existieren ja noch gar nicht auf dem USB-Stick, ergo kann dort vorher nichts vergleichen werden.


    Man könnte es mit Python auch vergleichen, muss dann aber schon über die Basics hinaus sein. Mit Pfaden zu arbeiten, ist nicht immer einfach.

    Einfacher wäre es wahrscheinlich mit externen Tools. Code zum Überprüfen könnte so aussehen:

    Aber das bringt dich nicht groß weiter, falls du den Code nicht verstehst.

  • Soweit mir bekannt ist, prüft das Tool nach dem Schreiben nichts.

    man rsync  und dort die Option -c;)

    "Really, I'm not out to destroy Microsoft. That will just be a completely unintentional side effect."

    Linus Benedict Torvalds, 28.9.2003


    Hast Du die Woche schon Deine Raspberry gesichert :fies: Bei mir tut das raspiBackup automatisch :shy:

  • Vielleicht ist es besser, den Fehler zu lokalisieren und zu beheben.

    Wenn das JPEG auf der SD noch angezeigt wird, kann es noch nicht korrupt sein.


    Ab dem Absenden ins Zielverzeichnis kommen als Fehler für mich in Betracht:

    Korruptes Dateisystem am Kopierziel

    (Re-)Mount-Fehler/Unpassendes Filesystem - Anzahl der gleichzeitig rw-geäffneten Dateien zu groß

    Mysterium


    Servus !

    RTFM = Read The Factory Manual, oder so

  • man rsync  und dort die Option -c;)

    Zugegeben, die Beschreibung ist sehr schlecht zu verstehen. Ich habss mir 2 Mal durchgelesen und einmal übersetzen lassen.


    Once the file data are received, rsync writes the data to the file and trusts that if the kernel indicates a successful write, the data were written without corruption to disk. rsync does not reread the data and compare against the known checksum as an additional check

    Das denken sehr viele, dass rsync das tun würde, aber letzendlich wird die Prüfsumme beim Übertragen gebildet, um sicherzustellen, dass die Datei auf der Empfängerseite richtig rekonstriuert worden ist. Die Datei wird nach dem Schreiben nicht noch einmal Byte-für-Byte neu eingelesen. Testen kann man das auch, indem man eine große Datei kopiert und die Zeit misst. Dann nochmal das Gleiche mit rsync (Zieldatei vorher löschen).



    Den USB-Stick kann man auch mit badblocks prüfen (Daten werden gelöscht).

    Das Programm überschreibt den gesammten USB-Stick mit einem Muster, dass dann geprüft wird.

  • Hallo helloBavaria,


    ich würde vor dem Kopieren noch eine Kontrolle durchführen: Dein Programm startet das Anzeigeprogramm für die Bilddatei. Dort kannst Du ermitteln, ob das Anzeigen des Bildes erfolgreich war.

    Auf diese Weise bekommst Du einen Eindruck, ob die Fehlerursache in der Quelldatei oder in der Zieldatei bzw. deren Dateisystemen zu suchen ist. Erst dann hast Du die Erkenntnis, an welchem Ort es sich lohnt, nach weiteren Ursachen zu suchen.


    Eine wichtige Erkenntnis hat dead_eye genannt. Das Ende der Durchführung einer Programmzeile ist nicht immer bis fast nie identisch mit der tatsächlichen Abarbeitung dessen, was die Programmzeile eigentlich machen sollte. Dies gilt insbesondere für die langsamsten Aktionen wie I/O (Input/Output). Das ist mir bei der Programmierung graphischer Programme aufgefallen. Testweise habe ich einzelne Pixel in schneller Folge zufällig gesetzt (Position, Farbe). Mir kam es zuerst merkwürdig vor, dass ich den Eindruck hatte, dass immer ca. 50 bis 100 Pixel "gleichzeitig" gesetzt wurden.

    Dann habe ich die Verzögerung des Pixelsetzens erhöht. Auch da bleib der Eindruck des gleichzeitigen Setzens - nur dass es bei Verzögerungen weniger Pixel "gleichzeitig" betraf.

    Als ich dann einen Flush()-Befehl (erzwingt das Schreiben evtl. gepufferter Daten, auch wenn weder der Puffer voll ist noch der letzte Rest vor dem Schließen ansteht) eingefügt hatte, erschien immer exakt 1 geändertes Pixel - auch bei Weglassen der Verzögerung.


    Das gleiche gilt auch für das Speichern von Daten, Kopieren/Verschieben von Dateien. Hier kommt nämlich das sog. Puffern von Daten ins Spiel. Die Datei ist nämlich nicht genau dann im Zielverzeichnis funktionsfähig vorhanden, wenn der letzte Befehl dazu durchlaufen ist, sondern wenn der letzte Puffer tatsächlich geschrieben und die Datei geschlossen ist.


    Bei Nutzung von Kommandos auf Betriebssystemebene passieren solche Fehler nicht. Bei selbstprogrammiertem Code musst Du selber an all das denken und programmtechnisch Maßnahmen treffen - wenn es Probleme gibt oder generell.


    Dann ist mein Lieblingsthema "Mysterium" von RTFM kurz angeschnitten worden.

    Je nach aktueller und kurzfristig extrem schwankender Auslastung des Prozessors schwankt auch der Strombedarf, der vom Netzteil bei Aufrechterhaltung der Spannung geliefert werden muss. Wenn es da Probleme gibt, schaltet das Betriebssysteme irgendwelche Dienste aus. Und wenn die Lage wieder gut ist auch wieder ein. Ich kann mir vorstellen, dass eine Datei korrumpiert wird, wenn beim Speichern genau der "USB-Dienst" deaktiviert und kurz danach wieder aktiviert wird.

    Das wirft dann auch die Frage nach Deinem Netzteil auf...


    Um das Ausmaß dieser Idee abzuschätzen, solltest Du nach Abschluss des Speichervorgangs einen Verify von Original und Kopie laufen lassen - bevor das Original gelöscht wird.


    Ich hoffe, dass wir der Ursache mit entsprechender Rückmeldung von dir auf die Spur kommen.


    Möglicherweise gibt es auch mehrere Ursachen. Das kann bedeuten, dass Du


    • korrupte Quelldateien gleich löschen solltest
    • korrupte Zieldateien nochmals (aber nicht beliebig oft) kopieren solltest

    Vielleicht sind aber auch nur Speicherstellen des Zielmediums defekt (können nicht mehr beschrieben werden).



    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

    • Icon-Tutorials (IDE: Geany) - GPIO-Library - µController-Programmierung in Icon! - ser. Devices - kein Support per PM / Konversation

    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.

    Edited once, last by Andreas ().

  • Es ist auch ziemlich blauäugig, ein Systemkommando in einem Pythonscript durchzujagen, ohne den Rückgabewert (Shellvariable $?=0) abzufragen und zu berücksichtigen.


    Ausserdem hängt es vom Dateisystem der Zielpartition (journalisierend, oder nicht) ab, und wann das letzte Check & Repair ausgeführt wurde.


    Servus !

    RTFM = Read The Factory Manual, oder so

  • Vielen Dank für eure Hinweise und Tipps.

    Da dieses Problem so sporadisch auftritt ist es etwas mühsam alles zu testen.

    Was ich mittlerweile ausschließen kann, ist dass es am USB Stick liegt. Dasselbe Problem ist auch mit einem anderen USB Stick aufgetreten.



    Netzteil verwende ich folgendes:


    [Official Standard 5.1V 3.5A 17.9W] Raspberry Pi 4 Power Supply, iUniker USB C Power Supply with On/Off Switch Raspberry Pi 4 Power Supply with On/Off Switch for Raspberry Pi 4 8GB/4GB/2GB/1GB https://amzn.eu/d/87pFq70


    Gibts hier andere Empfehlungen?




    Ich werde als nächstes mal versuchen die Bilder zu kopieren anstatt sie zu verschieben.

  • [Official Standard 5.1V 3.5A 17.9W] Raspberry Pi 4 Power Supply, iUniker USB C Power Supply with On/Off Switch Raspberry Pi 4 Power Supply with On/Off Switch for Raspberry Pi 4 8GB/4GB/2GB/1GB https://amzn.eu/d/87pFq70

    Jedes Mal wenn ich das lese bei diesen Wandwarzen könnte ich... :dau1:


    Gibts hier andere Empfehlungen?

    Ja, versuchs mit dem echten offiziellen Netzteil für den RPi4! https://www.raspberrypi.com/products/type-c-power-supply/ ;)

    Achte bei dem Kauf auf EU, damit das auch hier in die Steckdose passt!

  • with On/Off Switch

    So sexy so ein Schalter auch ist, er hat da nichts zu suchen. Der Widerstand erhöht sich und es kommt weniger Spannung am Pi an.

    Ein Pi benötigt eine konstante Spannung (bestensfalls zwischen 5,1 bis 5,2V), das aber auch bei wechselnder Last. Und genau da liegt das Problem für viele Netzteile, die für einen Pi genutzt werden. Bei wechselnder Last schießt die Spannung hoch und runter.

    Gibts hier andere Empfehlungen?

    Wie der User hyle schon sagte, das Original-NT von Raspberry ist absolut zu empfehlen. Und dazu noch relativ günstig.


    Erfahrungswerte aus erster Hand kann ich auch bieten.

    Ich überwache mit einem A/D-Wandler bei einem Pi4 (8GB) mit einem Original-NT die Spannung. Sie liegt immer zwischen 5,14 bis 5,22 Volt, bisher nie darüber und nicht darunter, egal ob der Pi4 mal auf Last läuft, im Leerlauf ist oder Sprünge bei der Last macht.


    Das ist die Spannung (höchste Werte) der letzten 24 Stunden:


    Das ist die Spannung (niedrigste Werte) der letzten 24 Stunden:

  • Interessant, hatte ich ehrlich nicht auf dem Schirm, dass dieses Netzteil problematisch sein könnte. Hab es empfohlen bekommen und Bewertungen sind auch gut...

    Erfahrungswerte aus erster Hand kann ich auch bieten.

    hast du auch Vergleichswerte von einem anderen Netzteil? Wäre spannend zu sehen ob es tatsächlich zu Spannungseinbrüchen kommt

  • Such mal im Forum nach dem Stichwort "Mysterium", dann wirst Du erstaunt sein was ein unzureichendes Netzteil alles so anrichten kann. Andreas hat in seiner Linksammlung viele Beispiele zusammengetragen.


    //Edit

    Der Hinweis kam ja in #12 schon, hatte ich nicht mehr auf dem Schirm.

  • dieses Netzteil problematisch sein könnte

    Neben dem NT ist es auch der Schalter, der je nach Bauart durch den Übergang die Spannung zusätzlich reduziert.


    Hier hat das mal jemand nachgemessen: https://www.raspberry-pi-geek.…ersorgung-fuer-den-raspi/


    Das Fazit dort:

    Quote

    Die Angabe zur Leistung auf einem Steckernetzteil für den RasPi stellt nur die halbe Wahrheit dar. Wichtiger sind ein kurzes Kabel, ein hochwertiger Micro-USB-Stecker und eine Spannung möglichst nahe am oberen Ende der Spezifikation von 5,25 Volt.

    Genau das erfüllt das Original-NT. Es läuft an der oberen Grenze bei 5,22V und hat damit auch Luft nach unten, z.B. bei Last bzw. Lastwechsel.

    Bewertungen sind auch gut

    Wie viele von denen, die bewertet haben, haben Ahnung und haben mal nachgemessen?

    Solange es funktioniert, sprich NT in die Steckdose und das Gerät leuchtet, sind doch 99,74% zufrieden. Spätere Probleme werden in allererster Linie gar nicht mit dem NT in Verbindung gebracht.

    hast du auch Vergleichswerte von einem anderen Netzteil? Wäre spannend zu sehen ob es tatsächlich zu Spannungseinbrüchen kommt

    Ja, habe ich. Es ist zwar kein Netzteil im klassischen Sinne, sondern der USB einer Fritzbox. Der soll 5V bringen und bis 500mAh belastbar sein. An ihm hängt ein Raspberry Zero2 (kurzes Kabel), der auf 3 Kerne und 900MHz begrenzt ist. So schluckt er unter Volllast maximal 300mAh, sprich er ist noch weit unterhalb was der USB dort bringen kann. Probleme sollte es also eigentlich nicht geben.


    Hier die höchsten Werte von 5V:

    Wie man sieht, kommen da maximal 4,93V an, nie mehr.


    Und hier die niedrigsten Werte von 5V:

    Einbrüche unter Last bis auf 4,6V. An manchen Tagen geht es sogar knapp darunter. Wie man sieht, bleibt die Spannung konstant bei ca. 4,9V, wenn er kaum was tut (0 bis 5 Uhr) und am Tage gibt es Einbrüche, wenn er mehr zu tun hat. In diesem Fall läuft der Zero2 zwar stabil, es hängt aber auch sonst nichts dran.


    Meine persönliche Erkenntnis der letzten Jahre:

    Spare nie am Zubehör für einen Raspberry, wenn er durchweg sicher laufen soll und man glücklich werden möchte.

    • Original Raspberry Netzteil (nichts anderes)
    • gutes Gehäuse (kein Plastikgelumpe), sondern ein lüfterloses selbstkühlendes Metallgehäuse (z.B. Flirc Case oder iUniker Vollmetallgehäuse)
    • gute SD-Karte (z.B. Sandisk Extreme, Samsung Evo plus)
    • (alternativ statt SD-Karte eine SSD am USB-Adapter)

    Viele Grüße,

    Peter

    Edited 2 times, last by Peter0311 ().

  • Wie viele von denen, die bewertet haben, haben Ahnung und haben mal nachgemessen?

    Solange es funktioniert, sprich NT in die Steckdose und das Gerät leuchtet, sind doch 99,74% zufrieden. Spätere Probleme werden in allererster Linie gar nicht mit dem NT in Verbindung gebracht.

    Da hast Du natürlich recht. So gehts ja auch mir :wallbash: Hier ist man halt auch bisschen verwöhnt, z.B. als Smartphone Netzteil wird es hier nie Probleme geben denke ich


    Spare nie am Zubehör für einen Raspberry, wenn er durchweg sicher laufen soll und man glücklich werden möchte.

    Ich werde es mir zu Herzen nehmen und mal schauen, ob das Problem mit einem Original Netzteil vielleicht schon behoben ist. Gehäuse verwende ich eins von Geekworm (Aluminium, Passivkühlung). Hier habe ich mehr Acht gegeben welches ich nehme, andere User haben bei diesem Gehäuse mal die Temperatur gemessen und waren sehr zufrieden.