Die meisten Daten haben überlebt

Noch ein kleines Update zum letzten Beitrag: Nach vielen On-Off-Zyklen der Festplatte war ddrescue bei 100 % aber doch nicht fertig.

ddrescueview zeigte folgendes:

416,24 GB wiederhergestellt, aber knapp 84 fehlen noch. Hm, das ist ungewöhnlich schlechte Ausbeute, vor allem weil so große Blöcke fehlen. Da muss ich etwas falsch gemacht haben.

Ich höre schon meine alte Ausbildungskollegin schreien „manpage, MANPAGE!!!“

ddrescue läuft mit den Parametern (Reihenfolge zu Dramaturgiezwecken geändert)

-f -r10 -v -n

-f: force overwrite of outfile, braucht man, wenn auf eine Partition geschrieben wird
-r10: Exit after the given number of retry passes
-v: Verbose mode
-n: Skip the scraping phase

Vielleicht sollte ich das letzte weglassen 😉

Gesagt, getan – und ddrescue läuft weiter. Im Schleichmodus werden die restlichen Daten zusammengekratzt. Um diese Schleichfahrt nicht zu blockieren, habe ich den Knockout meines Scripts auf 2 Stunden gesetzt. Nach ein paar weiteren Tagen sieht es wie folgt aus:

Das würde ich als Erfolg bezeichnen. Mit dem Hintergrund, dass die erste Partition der Platte eine versteckte EFI-Partition mit 200 MB ist, sollten die Userdaten vollständig lesbar sein.

Das Volume ließ sich dann auch wieder mounten. Um auf Nummer sicher zu gehen, habe ich aber trotzdem noch ein Image der Partition gezogen.

dd if=/dev/sdxy of=/media/foo/bar/image.bin bs=64K

macht den Job. Wichtig ist, die Blocksize anzugeben, da sonst gefühlt Byteweise kopiert wird und so der Durchsatz unterirdisch ist – ohne Parameter dümpelte der Kopiervorgang von USB 2.0 nach USB 2.0 mit 4 MB/s herum, mit 64K bei 38 MB/s. Mehr geht über die Schnittstelle fast nicht.

ddrescue. aggressiv.

„Nein“ wäre die richtige Antwort gewesen. „Nein“ zur Frage, ob ich eine Festplatte wiederherstellen kann, die vor meinen Augen nochmal fallen gelassen wurde.

„Macht der das was?“

JA, verdammt nochmal – Festplatten (also „klassische“ mit Magnetscheiben) sind mechanisch empfindliche Komponenten.

Naja. Eine zweite Platte für die Wiederherstellung hat er immerhin schon besorgt, also versuche ich mein Glück. Also ein Live-Linux in das olle Thinkpad geworfen und ddrescue gestartet.

Quelle: 500 GB 2,5 Zoll Western Digital Blue, Ziel: 1 TB 2,5 Zoll Seagate.

Zunächst ging es auch ordentlich schnell und ich dachte, der begrenzende Faktor wäre das USB 2.0 am Rechner. Doch auch mit der extra georderten USB 3.0 Expresscard ging es nach ein paar Klimmzügen (zusätzliche Versorgung der Festplatten) nicht wirklich schneller.

Nach den ersten paar Gigabyte sackte die Leserate aber auf mehrere 100 kByte/s ab. Nicht so schlimm, wäre da nicht folgendes Geräusch:

(das nach 10 Sekunden)

Wäre da nur das Geräusch, könnte man vielleicht noch damit leben, aber ddrescue macht nur noch eines: Fehler für Runde zwei melden. Das bringt einen nicht weiter. Also Platte weg und wieder ran. Die ersten paar Stunden mache ich das noch manuell, dementsprechend haben sich knapp 100 GByte Lesefehler und ein wenig Frustration angesammelt. Grmpf. Dabei fiel auf, dass die ersten 30 Sekunden die Übertragungsrate mit 15-30 MByte/s noch relativ hoch war, danach sank sie schlagartig ab und schwankte zwischen 65 und 300 kByte/s.

In einer Woche (Abends, musste in der Nähe sein) kamen so etwa 90 GByte von Platte A auf Platte B. 150 GByte wurden als nicht lesbar markiert.

Um nicht dauernd den USB-Stecker ein- und ausstecken zu müssen, habe kam eines meiner Schubladen-Projekte zum Einsatz, der (verbuggte) USB-Switch. Mit einem Mit einem TS3USB221 (sehr klein und bescheiden zu löten) und einem IRLML2244 lässt sich das angeschlossene Device mit dem PC verbinden und trennen. Die Verbindungsfolgen werden erwartungsgemäß nicht eingehalten und durch einen Denkfehler und zu wenig Koffein schaltete die aktuelle Version entweder die Versorgung oder USB durch. Fädeldraht hat es zumindest vorübergehend gerichtet. Mit einem Schalter ausgestattet bleiben nun die Stecker heile.

Aber zurück zur Datenrettung. Zwei Gedanken: Die Platte alle 30 Sekunden pauschal zu trennen erhöht zwar die Datenrate, aber auch die elektromechanischen Zyklen, was der Lebensdauer nicht wirklich zuträglich ist. Gleichzeitig kommt die Platte nach einem Aussetzer nicht mehr hoch. Sie muss neu gestartet werden. Das kann man überwachen, indem man die Größe der Logfile von ddrescue prüft. Wächst diese stark an, ist etwas im faul. Ferner beendet sich ddrescue automatisch, wenn die Platte sich komplett abwirft.

So viel zum Wissen, aber wie kommt diese Information zum USB-Switch? Am einfachsten wäre es ja, den USB-Port selbst aus- und wieder einzuschalten. Geht in manchen Systemen, aber eine mittelkurze Recherche zeigte: die Erfolgschancen sind eher gering.

Also doch irgendwie anders. Hm. Der Laptop ist zu jung für den Parallelport, einen Microcontroller dafür zu programmieren ist mir ehrlich gesagt auch zu blöd. Hm, DTR und RTS lassen sich doch üblicherweise durch Software schalten und einen USB<>UART-Wandler, bei dem zumindest RTS herausgeführt ist, liegt auch herum.

Unter Linux ist doch alles eine Datei, also sollte es doch ein Leichtes sein, das Flag zu setzen. Leider nicht ganz. ioctl macht zwar genau das, aber es ist nicht persistent. Sobald das Programm sich beendet, wird der Port geschlossen und RTS/DTR ist wieder low. über stty schafft man es zwar auch irgendwie, aber mein Shell-Script begann eh anfangen, ziemlich übel zu stinken.

Nachdem desinfec’t mit Python kommt – warum nicht damit? Mit pyserial kann ich zumindest unter Windows schon einmal alles machen, unter Linux klappt es auch auf Anhieb.

Mittlerweile sieht das Setup so aus:

Die Platte liegt (ich weiß, nicht ganz ideal) auf einer Schütte, der Lüfter hält sie kühl. Am Notebook hängt der USB-Stick mit Scripts und Log (wichtig, da im Notebook kein persistenter Speicher ist), daneben der USB-Switch, der mit dem RTS des USB<>UART-Wandler verbunden ist.

Das Python-Script macht aktuell folgendes:

Verbinden der Platte und warten, bis /dev/sdx (also die Platte) existiert. ddrescue mit den entsprechenden Parametern als subprocess starten. Während es läuft, also .poll() des Prozesses keinen Exitcode ausweist. Weiter wird geprüft ob die Logdatei anschwillt. Dank Caching ist das leider nicht ganz so zielführend, aber immerhin. Das dritte Kriterium ist die Laufzeit. Ist die Datenrettung länger als 10 Minuten aktiv, naja – ich bin nicht stolz drauf. Tritt eine der drei Bedingungen ein, wird die Platte getrennt und gewartet (falls nicht schon passiert), bis ddrescue fertig mit dem Schreiben der Logdatei ist. Nach einer weiteren Wartezeit geht das Spiel von vorne los:

rescue.zip (weil WordPress mir Python-Scripts verbietet)

Für Schäden, die das Script verursachen kann, übernehme ich keine Haftung.

In nicht ganz 24 Stunden sind so nun weitere 130 GByte in Richtung Ersatzplatte gewandert. „Nur“ 35 weitere Gbyte wurden als defekt markiert.

Ob die Aktion erfolgreich gewesen sein wird, kann ich erst in knapp 280 GByte sagen und hoffe, dass auch so viel davon gelesen werden kann.

Abschließend kann ich nur mal wieder sagen: Kein Backup? Kein Mitleid!

Flashen für faule

Und gleich noch einer hinterher:

Hintergrund für das gerade eben gebloggte visacon ist meine akute Faulheit. Weil am aktuellen Mikrocontroller-Projekt die Pins vom ISP anderweitig verwendet werden sollen, musste ein Bootloader auf den AVR. Die Wahl fiel auf Peter Danneggers FastBoot, den ich mit einem anderen Initstring kompiliert habe. Zunächst wollte die 64-Bit-Version von fboot.exe nicht damit sprechen. Für AVRDUDE gibt es zwar einen Patch, der hat es in fast 5 Jahren aber nicht in in die offizielle Version geschafft. Ich habe es versucht, mit Cygwin und MinGW, aber ich bin offenbar zu blöd, diese Software zu kompilieren.

Also habe ich UpdateLoader von Luani verwendet. Das hat eine ansprechende GUI und funktioniert auch prächtig mit meinem abweichenden Passwort, nur hat das Teil einen Nachteil: Es nimmt als Argument nur eine HEX- oder INI-Datei an. Keine wirkliche Scriptingfähigkeit. Ok, Sourcen sind vorhanden, aber ehrlich gesagt wenig Zeit und Lust, mich in Pascal und dessen Entwicklungswerkzeuge einzuarbeiten.

Bleibt die Frage: was macht UpdateLoader anders als fboot? Der Logic Analyzer liefert Erkenntnisse: Leo-Andres war so clever und stellt dem Passwort das Steuerzeichen \r voran. In der Protokoll-Beschreibung vom Bootloader steht auch, dass für die Bestimmung der Baudrate ein high-bit und vier low-bits erwartet werden. im Standardpasswort „Peda“ macht das das „a“ (binär 01100001). Was passiert nun, wenn ich meinem Passwort ein „a“ voranstelle – also nur bei der Verwendung von fboot.exe?

>fboot /C7 /B115200 /IaXYZ /P"program.hex"
COM7 at 115200 Baud: Connected
Bootloader V2.1
Target: 1E9403 fbDEF
Buffer: 512 Byte
Size available: 15872 Byte
Program program.hex: 00000 - 00533 successful
CRC: o.k.
Elapsed time: 0.64 seconds

läuft.

Nur muss ich jedes Mal PuTTy beenden, das Netzteil ausschalten, fboot anwerfen, Netzteil einschalten, PuTTy wieder starten. Muss ich? Nein.

PuTTy kann Profile – und man kann ihm sagen, einen bestimmten Fenstertitel zu verwenden:

putty_fenstertitel

Das ganze als Profil abgespeichert, schon kann man das Programm nach seinen Wünschen per Kommandozeile lostreten:

start putty.exe -load "meinprofil"

Warum das alles? Natürlich um PuTTy ganz einfach beenden zu können:

taskkill /fi "IMAGENAME eq putty.exe" /fi "WindowTitle eq meintitel" /f

Okay, dass man fürs Starten und Beenden ggf. unterschiedliche Bezeichnungen braucht, ist nicht so edel, genauso könnte die Gegenstelle den Fenstertitel verändern. Aber es funktioniert. Debug-Anzeige geht auf und das Flashen kann gestartet werden. Nur muss für das Flashen ein Reset vom Mikrocontroller ausgeführt werden. UpdateLoader kann dazu die DTR-Leitung toggeln, fboot nicht. Aber wofür habe ich mein neuestes Tool geschrieben, wenn nicht für das?

Das Rigol-Netzteil kann außer laut sein auch über den PC gesteuert werden:

visacon.exe USB0::0x1AB1::0x0E11::<snr>::INSTR W "INST CH1; OUTP OFF"

Der Befehl wählt Kanal 1 aus und schaltet ihn sogleich ab. Mit ON statt OFF passiert (oh Wunder) genau das Gegenteil.

es gibt nun also eine kleine BAT-Datei auf meinem Rechner:

taskkill /fi "IMAGENAME eq putty.exe" /fi "WindowTitle eq meintitel" /f
visacon.exe USB0::0x1AB1::0x0E11::<snr>::INSTR W "INST CH1; OUTP OFF"
timeout 1
visacon.exe USB0::0x1AB1::0x0E11::<snr>::INSTR W "INST CH1" W "OUTP ON"
fboot /C7 /B115200 /IaXYZ /P"program.hex"
start putty.exe -load "meinprofil"

Der Timeout-Befehl gibt dem Elko auf der Leiterkarte Zeit sich zu entladen. Bis jetzt funktioniert das Ganze wie ’ne Eins.

Jetzt sollte nur noch Atmel Studio nach dem erfolgreichen Build… Moment:

AS7_Buildevents
Warum es dafür keinen Wiki-Artikel gibt? Steht doch oben, weil ich faul bin.

visacon

Messautomatisierung ist etwas tolles und – wenn man sich damit einmal grundlegend beschäftigt hat – vor allem sehr einfach. Nur leider braucht man in den meisten Fällen irgendeine Entwicklungsumgebung, um mit über VISA mit den Instrumenten zu sprechen. Es gibt zwar noch NI MAX oder Hewlentsight IO Libraries Suite, mit letzterem kann man zwar auch automatisieren aber für manche Anwendungen ist es einfach etwas unpraktisch.

Für manche Anwendungen würde eine einfache Batchfile absolut ausreichen, nur daraus VISA sprechen? Ich habe zumindest kein Programm gefunden. Mit VBS/JScript bzw. dem, was der Windows Scripting Host hergibt, geht es wohl auch nicht so einfach.

Man darf sich nicht über Dinge beschweren, die man selbst machen könnte. Also habe ich ein kleines Kommandozeilen-Programm geschrieben: visacon.

Es verwendet das, was National Instruments mit dem Bollwerk an Treibern mitbringt – die beiden Assemblies NationalInstruments.Common und NationalInstruments.VisaNS. An dieser Stelle sei noch darauf hingewiesen, dass ich nicht der Urheber dieser DLLs bin und auch keinerlei Rechte daran besitze. Der Compiler hat sie einfach gelinkt und im Release-Verzeichnis abgelegt.

Das Programm ist einfach gestrickt – es versucht die angegebene Ressource zu öffnen und führt dann Write- und Query-Befehle aus – die Syntax ist wie folgt:

visacon.exe <resourcename> ((W|R) „<cmd>“)+

Wer der Regulären Ausdrücke nicht mächtig ist: als ersten Parameter muss man den Resourcennamen (natürlich ohne spitze Klammern) angeben, danach W für einen Write-Befehl oder Q für einen Query-Befehl. Im Anschluss daran den jeweilig auszuführenden SCPI-Befehl. Die letzten beiden Argumente kann man beliebig oft wiederholen. Alle Ergebnisse der Queries werden in der Konsole ausgegeben. Tritt ein Fehler auf, wird die zugehörige Exception ausgespuckt.

Benötigt werden funktionierende VISA-Treiber, .NET 4.0 und die Kommandozeile.

Viel Spaß damit!