Ich möchte hier mein Skript safeject vorstellen. Es hilft eingebundene Datenträger sicher zu entfernen bzw. einen Datenträger in einen Zustand zu bringen, in dem er ohne Datenverlust aus dem laufenden System entfernt werden kann.
Der Benutzer naubaddi hat vor kurzem hier im Forum im Thread „USB Speichermedien sicher entfernen mit einem Skript“ sein Skript veröffentlicht, welches auch diese Aufgabe erfüllt. Seine Veröffentlichung war für mich der Anlass, mein eigenes Skript für diese Aufgabe zu überarbeiten und vor allem, eine sehr wichtige Idee von ihm zu übernehmen und in mein Skript einzubauen:
Es geht um das Abschalten des Datenträgers mit udiskctl. Auf die Wichtigkeit dieses Abschaltens bin ich erst durch den Beitrag von naubaddi aufmerksam geworden. Dabei muss man zwar keine Angst haben, dass durch die Spannung von 5V, welche ein USB-Anschluss bereitstellt, man selbst zu Schaden kommen kann oder dass die Daten auf dem Stick beeinträchtigt werden könnten, aber der Versuch der Spannungsabschaltung verhindert bei Datenträgern mit mehreren Partitionen den Datenverlust, wenn man erst eine Partition in den sicheren Zustand gebracht hat. In solchen Situationen erhält man beim Abschalten einen Fehler, den man im Skript natürlich behandeln muss.
Obwohl beide Skripte eine gemeinsame Zielrichtung haben und auch im Groben derselben Programmlogik folgen, sind sie völlig unterschiedlich und zur Erreichung der einzelnen Teilziele werden unterschiedliche Hilfsmittel eingesetzt. Außerdem unterscheiden sie sich im individuellen Programmierstil.
Mein Skript macht im wesentlichen:
Für die Auffindung der verwendeten Datenträger wird das Programm findmnt verwendet. Dieses Programm findet alle eingebundenen Dateisysteme; das sind ziemlich viele, da hier neben den Blockgeräten auch /sys, /proc, cgroups und weitere auftauchen, bei mir ca. 40 Zeilen. Diese Liste wird dann per grep gefiltert, da für die Aufgabe dieses Skripts nur Blockgeräte relevant sind. Die Filterung kann man über Angaben in den Variablen
verlangt
undverboten
steuern. Suchbegriffe, die inverlangt
stehen müssen in den Eigenschaften des Dateisystems auftreten, solche inverboten
dürfen nicht auftreten. Beim Programmaufruf kann man durch Angabe eines Parameters bestimmte Dateisysteme verlangen, z.B.safeject sda ^/media/
listet nur Dateisysteme, die von sda stammen oder unter /media/ eingebunden sind oder deren Beschreibung diese Suchbegriffe an anderen Stellen enthält. Die letzte Möglichkeit wirkt sich aber in der Praxis nicht störend aus.
Die so gefilterte Liste wird dem Benutzer angezeigt; er kann ein Dateisystem auswählen oder eine der ebenfalls angebotenen Optionen „Programm beenden“ bzw. „Erneut suchen“ benutzen.
Wenn ein Medium zur Bearbeitung ausgewählt wurde, betritt das Programm den Rumpf der Hauptschleife. Hier werden die Inhalte der Puffer per sync weggeschrieben, das Dateisystem wird ausgebunden (hier bevorzuge ich das universeller verwendbare umount vor udiskctl) und eben das USB-Gerät abgeschaltet. Leider funktioniert das Abschalten nicht universell, sondern eben nur bei USB-Geräten. Fehler, die bei diesen drei Vorgängen auftreten können, werden gemeldet und es wird entsprechend konsequent fortgesetzt, nötigenfalls bis zum Tode (DIE).
Zum persönlichen Programmstil:
Wichtig ist mir ein klares visuelles Erscheinungsbild des Programms, weil dies das Verständnis des Programms erleichtert. Dafür werden Einrückungen und Leerzeilen verwendet. Leerzeilen dienen zur Gliederung des Programmablaufs in einzelne Teilaufgaben.
Sonderzeichen erschweren den Lesefluss und werden deshalb minimiert. Aus diesm Grunde wird auch auf übervorsichtige und unnötige Quotierung von Strings verzichtet.
Klammerpaare – dazu zählen auch zusammengehörende Schlüsselwortpaare wie beispielsweise if-fi, do-done, case-esac – stehen entweder in derselben Zeile oder in derselben Spalte.
Bei Befehlen bzw. Befehlsketten, die sich über mehrere Zeilen erstrecken, werden die Folgezeilen zusätzlich eingerückt.
Variablen und Programmteile (Funktionen) bekommen sprechende Namen. Überhaupt wird eine Selbstdokumentation des Programmtextes angestrebt. Kommentare werden sparsam, aber ausreichend verwendet: Es wird beschrieben, was erreicht werden soll, sowie ggf. warum ein Befehl wichtig ist, und nicht wie es erreicht wird. Andererseits werden nichtssagende kurze Namen wie z.B. X für lokale Laufvariablen verwendet, weil hier die Kürze die Lesbarkeit verbessert.
Ich mag keine if-then-elif-else-fi, weil ich sie als schwer lesbar und unübersichtlich empfinde und ersetze diese daher durch bedingte Befehle mit Alternative.
Ich mag auch kein GOTO, welches die bash zum Glück nicht kennt. Ich mag aber auch keine verkappten goto-Befehle wie
break
oderexit
. Diese vermeide ich, weil sie mein Verständnis der Programmlogik erschweren weitgehend bis auf die Fälle, in denen sie unvermeidbar sind (wie bei der Verwendung vonselect
) oder es keine kürzere Alternative gibt. Das führt dazu, dass die Kopfteile meinerwhile
-Schleifen ziemlich lang werden können und sogar selbst Schleifen enthalten können. Das ist, soweit ich sehe, eine ungebräuchliche oder vielleicht auch wenig bekannte Methode. Für mich ist sie sehr natürlich.Ich nutze die Möglichkeiten der jeweiligen Programmiersprache aus und verwende auch weniger Bekanntes bei der bash u.a.: Type-Deklarationen, Arrays, Steuerung des Verhaltens über Optionen, Pattern-Matching. Mein Programm ist auch ein nichttriviales Beispiel für den verpönten Befehl
eval
.Programmieren ist eine Kunst (Donald E. Knuth: The Art of Computer Programming). Ein Programm ist also ein Kunstwerk und muss schön sein. Aber Schönheit liegt im Auge des Betrachters. Meine Programme sind schön – jedenfalls für mich.
Warum dieses Skript?
Die Grundfunktion dieses Skripts hat jeder Desktop eingebaut. Aber nicht jeder arbeitet mit einem Desktop und auch wer grafische Programme mag, arbeitet vielleicht nicht immer mit einem Desktop. In solchen Situationen kann dieses Skript helfen.
Bei Datenträgern mit besonders wichtigen Datenbeständen will mancher sich nicht auf Funktionalitäten des Desktops verlassen.
Schließlich ist es auch ein Spass, ein Problem kunstvoll zu lösen und die eigenen Fähigkeit zu trainieren. Und jeder darf behalten, was er beim Genuß eines Kunstwerks lernt.