Shell-Skripte – Kleine Helfer selbst gemacht
Mit Shell-Skripten sind kleine Helfer schnell selbst geschrieben. Sie haben den Vorteil, dass man sich keine langen Befehlszeilen auswendig merken muss. Es reicht dann, einfach das eigene Shell-Skript aufzurufen.
Redaktioneller Hinweis: Dieser Artikel von mir ist erstmals in der Februarausgabe 02/2014 von freiesMagazin erschienen.
Spielend lernen
Eine erste Einführung in die Shell findet man im Artikel „Nur keine Angst: Effektives Arbeiten mit der Shell“ in freiesMagazin 04/2013 [1]. Für die Shell gibt es noch viele andere Bezeichnungen, wie beispielsweise Kommandozeile, Konsole oder Terminal.
Wer die Einführung schon gelesen hat und sein Wissen über Shell-Befehle noch weiter vertiefen will, sollte sich das Spiel Terminus [2] einmal ansehen. Es ist ein textbasiertes Computer-Rollenspiel, das einem dabei helfen soll, die Befehle der Kommandozeile zu lernen und zu verinnerlichen. In dem Spiel bewegt man sich mit Hilfe von Shell-Befehlen weiter. Mit pwd sieht man, wo man sich gerade befindet, mit ls schaut man sich um und mit less kann man Gegenstände betrachten.
Terminus erinnert ein bisschen an das Spiel NetHack [3], ein Computer-Rollenspiel mit ASCII-Grafik, bei dem man durch die Spielsteuerung schon erste Befehle für den Editor Vi/Vim gelernt hat.
Kurz-URLs expandieren
Als Beispiel für den kleinen Helfer wird ein Skript erstellt, das Kurz-URLs expandiert. Kurz-URLs [4] verkürzen die meist für Suchmaschinen optimierten Links von Internetseiten auf wenige Zeichen. Der Dienst tinyurl.com [5] war einer der ersten, die kurze URLs als simple HTTP-Weiterleitung auf die lange URL anbot. Mittlerweile gibt es schon viele mehr.
Mit Twitter und seiner Beschränkung auf 140 Zeichen pro Nachricht traten diese Dienste ihren Siegeszug an, da eine URL, die man gerne teilen möchte, ansonsten schnell mal die Zeichengrenze eines Tweets sprengen kann. Solche Kurz-URLs haben allerdings auch einen Haken: Man sieht ihnen am Domain-Namen nicht an, wo sie hinführen. Wenn man Pech hat, führt einen der Link geradewegs auf eine präparierte Seite mit Malware.
Informationen mit Wget holen
Zur Überprüfung der Kurz-URLs kann man Wget [6] benutzen, was meist schon mit der Linux-Distribution der eigenen Wahl installiert ist oder schnell installiert werden kann. Mit Wget kann man über das Terminal Dateien aus dem Internet herunterladen, wobei es auch noch ein hervorragender Downloadmanager ist. Möchte man zum Beispiel alle Bild-Dateien mit der Endung PNG von einer Homepage herunterladen, reicht der Befehl:
$ wget -r -A png http://www.example.de/ |
Bricht man den Download ab, kann man später die Option -c an den Befehl anhängen, um den Download dort fortzusetzen, wo er ausgesetzt hat. Darüber hinaus kann man mit Wget auch den Status des Webservers abfragen, der die Seite ausliefert, zu der die Kurz-URL führt:
$ wget --server-response -qO- 0cn.de/y6ck |
Die Option –server-response holt nur eine Antwort vom Webserver, ohne ihn dabei zu besuchen. Die Option -q sorgt dafür, dass unnötige Informationen nicht auf der Kommandozeile ausgegeben werden. Mit O- wird die Startseite, z. B. index.html, direkt auf die Standardausgabe des Terminals (STDOUT) geschrieben. Andernfalls würde Wget sie herunterladen. Zum Schluss folgt noch die Kurz-URL, die in diesem Fall mit dem Dienst 0cn.de erstellt wurde. Da die Ausgabe des Befehls durch den Quelltext der Startseite, die ins Terminal geschrieben wird, sehr lang ist, wird er noch um die Option –max-redirect=0 erweitert. Damit dringt Wget auf der Webseite nicht tiefer als bis zur Auflösung der URL vor.
$ wget --max-redirect=0 --server-response -qO- 0cn.de/y6ck HTTP/1.1 302 Moved Temporarily Date: Thu, 09 Jan 2014 21:03:30 GMT Server: Apache/2.2.3 (CentOS) Location: http://www.freiesmagazin.de/freiesMagazin-2014-01 Content-Length: 0 Connection: close Content-Type: text/html; charset=utf-8 |
Filtern mit Grep
Da letztendlich nur das Ziel interessiert, zu dem der gekürzte Link führt, benötigt man die Zeile mit der Location. Das Ausschneiden der Zeile erledigt Grep [7] (siehe auch „grep – Eine kleine Einführung“, freiesMagazin 10/2009 [8]).
Allerdings wird es jetzt ein bisschen verzwickt, da Wget noch eine kleine Besonderheit hat. Alle Befehle und Programme, die in der Shell gestartet werden, bekommen drei Kanäle zugewiesen. Zum einen den Standardeingabekanal STDIN, der auch die Nummer 0 hat und normalerweise die Eingaben von der Tastatur liest. Zum anderen den Standardausgabekanal STDOUT mit der Nummer 1, der die Ausgabe des Befehls auf den Bildschirm schreibt. Zum Schluss den Standardfehlerkanal STDERR mit der Nummer 2, der auch seine Ausgaben auf den Bildschirm bringt.
Die Besonderheit von Wget ist nun, dass es den HTTP-Header an die Standardfehlerausgabe (STDERR) übergibt. Der Datenstrom von Wget muss vorher mit 2>&1 in die Standardausgabe (STDOUT) umgeleitet werden, wovon Grep das Ergebnis dann übernehmen kann. Ansonsten würde Grep keine Daten erhalten. Wie beschrieben, ist STDERR in der Shell auch der Kanal 2 und STDOUT der Kanal 1, sodass 2>&1 nur „Leite die Ausgabe von Kanal 2 nach Kanal 1 um“ bedeutet.
$ wget --max-redirect=0 --server-response -qO- 0cn.de/y6ck 2>&1 | grep Location Location: http://www.freiesmagazin.de/freiesMagazin-2014-01 |
Ausschneiden mit Awk
Die Ausgabe sieht schon gut aus, allerdings stört noch das Location: vorne. Zur Bearbeitung strukturierter Texte und Strings in der Shell eignet sich awk [9] sehr gut (siehe auch „Keine Angst vor awk – ein Schnelleinstieg“, freiesMagazin 06/2009 [10]).
In diesem Fall besteht die Struktur aus einer zweispaltigen Ausgabe. Die erste Spalte ist Location:, die zweite die URL. Mit einer Weiterleitung zum Befehl awk ‚{print $2}‘, wird nur die zweite Spalte angezeigt:
$ wget --max-redirect=0 --server-response -qO- 0cn.de/y6ck 2>&1 | grep Location | awk '{print $2}' http://www.freiesmagazin.de/freiesMagazin-2014-01 |
Auslagerung in ein Skript
Mittlerweile ist schon eine ganz schön lange Befehlszeile zusammengekommen. Würde man sie immer wieder abtippen, um das Ziel einer Kurz-URL zu betrachten, hat man gut zu tun. Zur Vereinfachung wandert der komplette Befehl in ein Skript, das man mit einem Editor erstellen kann.
Auf den meisten Systemen ist heute der Vim (Vi IMproved [11]) installiert, eine Weiterentwicklung des Vi. Der Befehl vi funktioniert trotzdem, da er mit Vim verknüpft ist, was einem ein ls -l /usr/bin/vi zeigt. Wenn Vim vollständig installiert ist, sollte man unbedingt einmal den Befehl vimtutor in der Shell ausführen. Vimtutor hilft dabei, den Editor soweit zu beherrschen, dass man ihn als Allzweck-Editor nutzen kann.
Da nicht jeder Vim mögen muss, kann man auch einen anderen Editor verwenden, z. B. nano im Terminal. Sowohl zu Vim als auch nano gibt es Artikel in freiesMagazin 08/2008 [12]. Wer einen grafischen Editor bevorzugt, kann Gedit, KWrite, Geany oder einen der Hundert anderen benutzen.
Wenn man einen grafischen Editor aus dem Terminal heraus starten will, sollte man noch ein & ans Ende der Befehlszeile setzen, damit sie nicht blockiert wird. Wobei man GUI-Programme eher vom Desktop aus aufrufen sollte.
Ist der Editor der eigenen Wahl gestartet, tippt man folgende Zeilen ein bzw. kopiert sie in das Textfenster:
#! /bin/sh wget --max-redirect=0 --server-response -qO- "$@" 2>&1 | grep Location | awk '{print $2}' exit 0 |
Anschließend speichert man das Skript und wechselt wieder in die Kommandozeile, in der man das Skript noch ausführbar macht:
$ chmod +x linkextender.sh |
Das Skript beginnt in der ersten Zeile mit der Zeichenkombination #!, dem Shebang, auch Magic Line genannt (siehe „Shebang – All der Kram“, freiesMagazin 11/2009 [13]). Sie weist das Betriebssystem an, die Datei mit der Standard-Shell auszuführen. Die Zeile funktioniert übrigens mit und ohne Leerzeichen nach dem Ausrufezeichen.
Möchte man sich nicht darauf verlassen, welches die Standard-Shell auf einem System ist, kann man auch die Shell direkt eintragen. Das ist zum Beispiel sinnvoll, wenn das Skript besondere Befehle verwendet, die nicht jede Shell kennt. Dann gibt man zum Beispiel #! /bin/bash ein, wenn man die Bash verwenden will.
In der Zeile mit Wget steht nun anstelle der Kurz-URL die Zeichenfolge $@. Sie sorgt dafür, dass alle Parameter dem Skript als Argumente übergeben werden, wobei die Anführungszeichen sicherstellen sollen, dass jeder Parameter für sich ein separater String bleibt. Mit exit 0 liefert das Skript den Exitstatus 0 zurück und beendet sich normal.
Das Skript ruft man nun zusammen mit einem Argument in der Kommandozeile auf:
$ ./linkextender.sh 0cn.de/y6ck |
Alternativ kann man es auch mit einer vorangestellten Shell aufrufen:
$ sh linkextender.sh 0cn.de/y6ck |
Fazit
Auf jedem Linux- oder Unix-basiertem Betriebssystem gibt es eine Menge Shell-Skripte, die wichtige Aufgaben übernehmen. Einige sind ähnlich simpel wie das Skript weiter oben, andere sind wesentlich komplexer.
Wenn man diese Skripte versteht, ist man nicht mehr hilflos der Technik ausgeliefert, sondern kann selber Lösungen entwickeln. Dabei kann man vorhandene Skripte auf seinem System anpassen oder, wenn die das Problem nicht beheben, ein eigenes Skript schreiben. Dieses Wissen kann eine große Hilfe sein, um Probleme zu lösen.
Links
[1] http://www.freiesmagazin.de/freiesMagazin-2013-04
[2] http://web.mit.edu/mprat/Public/web/Terminus/Web/main.html
[3] http://nethack.org/
[4] https://de.wikipedia.org/wiki/Kurz-URL-Dienst
[5] http://tinyurl.com/
[6] http://www.gnu.org/software/wget/
[7] http://www.gnu.org/software/grep/
[8] http://www.freiesmagazin.de/freiesMagazin-2009-10
[9] http://www.gnu.org/software/gawk/
[10] http://www.freiesmagazin.de/freiesMagazin-2009-06
[11] http://www.vim.org/
[12] http://www.freiesmagazin.de/freiesMagazin-2008-08
[13] http://www.freiesmagazin.de/freiesMagazin-2009-11
Geschrieben in freiesMagazin, Gnu/Linux