Bash-Tricks: Die History

Nach einer laaaangen Sommerpause, in der es für mich viel zu tun gab und in der ich unter anderem meine Abschlussarbeit fertiggestellt habe, melde ich mich wieder zu Wort, mit einer kurzen Einführung in die „Bash-History“.

Zunächst einmal: Was ist überhaupt eine „Bash-History“? „History“ kommt, wie wir alle wissen, aus dem Englischen und bedeutet „Geschichte“. Was die Bash ist, das dürfte den meisten Linux-Nutzern vermutlich klar sein: Die Shell bzw. die Eingabeaufforderung, über die man Programme starten und das System steuern kann. Die „Bash-History“ ist also eine Art Protokoll über die von uns im Laufe der Zeit eingegebenen Befehle.

Der Sinn der History ist, bei Bedarf zurückverfolgen zu können, welche Schritte man bei der letzten Arbeit in der Shell durchgeführt hat. Dies kann sehr sinnvoll sein, wenn man zum Beispiel unbeabsichtigt etwas verstellt hat und aufgrund dessen nun etwas nicht so will wie es sollte. Es kann aber auch sehr sinnvoll sein sich eine benötigte Befehlszeile wieder ins Gedächtnis zu rufen, die einem entfallen ist.


Durch die History navigieren

Wer sich einmal seine eigene Bash-History anschauen möchte, gibt in der Bash einfach folgenden Befehl ein:

history

Nun werden alle gespeicherten Einträge untereinander ausgegeben und durch eine Zeilennummer am Anfang ergänzt. Bei mir fängt die erste Zeile mit der Zeilennummer 14 an und endet mit der Zeilennummer 513 – warum auch immer.

Wer nicht die komplette History sehen möchte, kann durch diese auch mit den Cursortasten [↑] und [↓] navigieren. Dabei muss man sich die History wie einen Stack – also zum Beispiel einen Stapel Papier vorstellen. Das was ich nun als letztes auf den Stapel lege, das kann ich auch als erstes wieder greifen. Mit der Cursortaste [↑] kann ich immer weiter in die Vergangenheit der History eindringen. Mit der Cursortaste [↓] gehe ich den umgekehrten Weg.

Wer eine Zeile gefunden hat, die wieder ausgeführt werden soll, muss diese einfach nur mit der Enter-Taste bestätigen. Soll diese Zeile etwas angepasst werden, so kann man sich mit den Cursortasten [←] und [→] innerhalb der Zeile bewegen. Wem das bei langen Zeilen zu langsam geht, kann zusätzlich die [Strg]- bzw. [Ctrl]-Taste gedrückt halten.


Die History durchsuchen

Bei einer langen History ist es manchmal mühselig sich mit den Cursortasten durch die Liste zu bewegen, deshalb ist es hier praktisch, dass man die History auch durchsuchen kann.

Eine sehr einfache Methode ist in der Bash [Strg] + [R] zu drücken. Wenn man nun zu tippen anfängt, dann sucht die Bash die letzte zutreffende Zeile raus. Nun ist es aber oft so, dass nicht unbedingt die zuletzt eingegebene Zeile, die mit dem eingegebenen String anfängt, auch gleich die richtige ist. Wenn man nun erneut [Strg]+[R] eingibt, so gelangt man zur vorletzten, dem eingegebenen String entsprechenden Befehlszeile. Mit dem erneuten Drücken von [Strg]+[R] gelangt man dann zur vorvorletzten Befehlszeile und immer so weiter.

Wurde die gewünschte Zeile gefunden, so kann man sie mit der Enter-Taste ausführen. Wer den Suchvorgang abbrechen möchte, drückt auf [Esc]. Und wer die gefundene Zeile anpasse möchte, drückt eine der beiden Cursortasten [←] oder [→].

Diese Suchmethode erfordert allerdings, dass man weiß, womit die gesuchte Befehlszeile anfängt. Ist das nicht der Fall, so kann man auf eine so genannte „Pipe“ zurückgreifen. Das bedeutet, dass die Ausgabe des Befehls vor der Ausgabe auf dem Bildschirm zunächst abgefangen, verarbeitet und erst dann ausgegeben wird. Hier leiten wir die Ausgabe des Befehls history durch eine grep-Pipe, mit der wir nach einem String suchen können:

history | grep apt-get

Diese Zeile lieferte in meinem Falle beispielsweise folgende Ausgabe, in der der gesuchte String „apt-get“ vorkommt:

35  sudo apt-get install gtk2-engines-equinox equinox-theme equinox-ubuntu-theme faenza-icon-theme
  156  sudo apt-get install darktable
  404  sudo apt-get cache search pidgin
  405  sudo apt-get —purge autoremove
  407  sudo apt-get update
  408  sudo apt-get upgrade
  523  history | grep apt-get

Für kompliziertere Suchvorgänge, beispielsweise wenn ihr mehrere Begriffe in einer Befehlszeile finden möchtet, müsst ihr erst mal auf Google zurückgreifen. Ein kleines Tutorial zu grep ist hier schon geplant, aber würde in diesem Beitrag etwas den Rahmen sprengen.

Die History lässt sich übrigens auch als Datei öffnen, einsehen, durchsuchen und modifizieren:

gedit ~/.bash_history


Größe der History ändern

Wer die aktuelle Größe seiner History erfahren möchte, kann dies mit folgender Zeile tun:

echo $HISTSIZE

Die Zahl gibt die Länge der History an (Anzahl der Einträge). Um diese Größe anzupassen, genügt es in der .bashrc zwei Werte zu setzen. Am besten ist, man sucht zunächst nach folgender Zeile:

# for setting history length see HISTSIZE and HISTFILESIZE in bash(1)

Findet man sie nicht, so kann man sie am Ende der Datei einfügen. Darunter fügt man dann die folgenden beiden Zeilen ein:

export HISTFILESIZE=10000
export HISTSIZE=10000

Natürlich können die Werte nach belieben angepasst werden.


History löschen

Wer Spuren verwischen möchte (Ihr Bösnickel, ihr! ;), hat natürlich die Möglichkeit die History zu löschen. Der folgende Befehl macht die History wieder „clean“:

history -c

Wer nicht die komplette History, sondern nur Teile daraus löschen oder gar modifizieren möchte, kann dies – wie bereits erwähnt – in der .bash_history machen:

gedit ~/.bash_history


History-Einträge mit Zeit- und Datumsangaben

Manchmal wäre es beim Durchsuchen der History ganz sinnvoll zu erfahren wann eine Befehlszeile ausgeführt wurde – also mit Datum und Uhrzeit. Durch eine kleine Modifikation an der .bashrc ist dies möglich:

gedit ~/.bashrc

Am Ende der Datei fügt man die folgenden beiden Zeilen ein, bevor man die Datei speichert und den Editor wieder schließt:

# HISTTIMEFORMAT
export HISTTIMEFORMAT=’%Y-%m-%d, %T – ‘

Jetzt nur noch die Bash geschlossen und wieder geöffnet und durch Eingabe von history kann man nun in Erfahrung bringen, wann welche Zeile ausgeführt wurde.


History-
Shortcuts

Es gibt noch ein nettes Feature der Bash, dass ich hier mal als „Shortcuts“ bezeichnen möchte.

Nehmen wir zum Beispiel an, wir haben eine Befehlszeile, die wir immer wieder nacheinander in gewissen Zeitabständen ausführen müssen/wollen. Einmal eingegeben, holen wir die Zeile mit der Cursortaste [↑] wieder aus der History und bestätigen sie mit der Enter-Taste. Statt dessen kann man den letzten Befehl aber auch mit folgender Zeile erneut ausführen:

!!

Der Vorteil des ganzen ist jetzt sicherlich nicht so ganz ersichtlich. In Scripten kann dies aber durchaus sinnvoll sein. Oder man führt die zuvor eingegebene Zeile mit Root-Rechten aus:

sudo !!

Was auch noch möglich ist, ist das Hervorholen der Befehlszeile, die mit einem bestimmten String anfängt, der das letzte Mal in der History aufgetaucht ist. Oder kurz und verständlich: Wenn ich fünf Zeilen vorher ps -fe | grep pino ausgeführt habe und danach kein weiterer ps-Aufruf erfolgt ist, dann kann ich eben diese Zeile mit folgendem Befehl erneut ausführen:

!ps

Der String nach dem Ausrufezeichen ist variabel. Die Bash holt einfach die Befehlszeile aus der History raus, die als erstes dem nach dem Ausrufezeichen eingegebenen String entspricht und führt diese aus.


Mehr über die History

Dies ist natürlich nur ein kurzer Einblick in die History-Funktion der Bash. Kombinationsmöglichkeiten mit anderen Befehlen gibt es natürlich nahezu unendlich viele, man muss sich nur ein wenig Zeit nehmen und das Netz danach mit Google durchsuchen.

Wer sehen möchte, wie mächtig der history-Befehl ist und was damit noch alles möglich ist, der sollte sich die Manpage dazu durchlesen:

man history

Ansonsten wünsche ich noch viel Spaß mit der History!

Bash: Aliase permanent setzen

Für viele ist sie das Schreckgespenst, für manche aber ein Segen. Es geht um den unter Linux wohl bekanntesten Kommandozeilen-Interpreter, die “Bourne-again shell” oder kurz “Bash”. Hat man sich erst an die Arbeit mit der Shell gewöhnt und die Grundlagen drauf, so möchte man sie nicht mehr missen, weil sie Vieles doch schneller realisierbar macht als eine GUI. Zudem lassen sich mit Shell-Scripts Vorgänge ganz wunderbar automatisieren. So weit die schöne Seite der Shell.

Wäre da nur nicht immer dieses Getippe der Befehle und der Parameter! Oft hat man nicht alle Parameter eines Befehls im Kopf und muss noch vorher umständlich die Hilfe zum Befehl aufrufen. Doch zum Glück gibt es die “Aliase”. Hier nur zwei Beispiele, wie sich viel Tipp-Arbeit ersparen und zusätzliche Sicherheit bzw. zusätzlicher Komfort erreichen lässt.

Beispiel für APT

Wer es leid ist bei der Überprüfung nach Updates aus der Shell heraus immer wieder folgendes zu tippen:

sudo apt-get update
sudo apt-get upgrade
sudo apt-get dist-upgrade


der kann mit folgenden zwei Zeilen:

alias apt-upd=’sudo apt-get update’
alias apt-ugd=’sudo apt-get upgrade’
alias apt-dugd=’sudo apt-get dist-upgrade’


folgendes daraus machen:

apt-upd
apt-ugd
apt-dugd


Denkbar, aber nicht unbedingt empfehlenswert, ist auch eine extreme Kürzung, die für alle drei Zeilen nur noch einen Alias vorsieht:

alias apt-allupd=’sudo apt-get update && sudo apt-get dist-upgrade’


Somit würde eine Eingabe von:

apt-allupd


genügen, um alle Quellen des lokalen Repository zu aktualisieren und sämtliche verfügbaren Upgrades zu installieren.

Beispiel für Datei-Operationen (cp + rm)

Ein anderer Fall ist das Löschen von Dateien. Der Löschbefehl rm unter Linux macht, was ein jeder Löschbefehl unter einem UNIX-kompatiblen Betriebssystem tut: Er löscht, was man ihm zum Löschen vorgibt, und zwar ohne Rückfrage. Wer sich schon mal darüber geärgert hat, weil er/sie zu voreilig etwas gelöscht hat oder womöglich mit Root-Rechten in einem System-Verzeichnis gewütet hat, der kann das Löschen in Zukunft etwas sicherer und zugleich komfortabler machen.
Der folgende Alias:

alias rm=’rm -r —interactive=always’


verändert den ursprünglichen Löschbefehl nicht, sondern überdeckt ihn lediglich mit einem Alias, der dafür sorgt, dass auch Verzeichnisse gelöscht werden und vor jedem Löschen einer Datei eine Abfrage erfolgt. Wem das zu penetrant ist, der kann rm auch anweisen nur einmal vor dem Löschen aller Dateien nachzufragen:

alias rm=’rm -r —interactive=once’


Wer mag, kann aus dem Löschbefehl rm auch einen anderen Befehlsnamen mit gleicher Wirkung “kreieren” und in Zukunft delete statt rm eingeben, wenn dies denn leichter merkbar sein sollte:

alias delete=’rm’


Ähnlich kann auch die Arbeit mit dem Kopierbefehl cp sicherer und komfortabler gestaltet werden. Wer Angst hat versehentlich eine bereits existierende Datei zu überschreiben und es leid ist, ständig den Parameter -r für das Kopieren von Verzeichnissen anzugeben, kann folgenden Alias für cp setzen:

alias cp=’cp -ri’


Damit werden nun standardmäßig auch Verzeichnisse kopiert und vor dem Überschreiben einer Datei wird nachgefragt. Wer nochmals auf Nummer sicher gehen möchte, kann noch zusätzlich Backups von existierenden Dateien anlegen lassen:

alias cp=’cp -ri —backup’


Somit wird vor dem Überschreiben der existierenden Datei eine Kopie der Datei mit dem Dateinamen DATEINAME~ angefertigt.

Die Benutzung beider Befehle geschieht wie gewohnt weiter.

Aliase permanent setzen

Das Setzen der Aliase erfolgt bisher jedoch nur temporär. Soll heißen: Sobald das Terminal-Fenster geschlossen wird, sind auch die Aliase aus dem Speicher und somit wieder vergessen. Wer sie dauerhaft setzen möchte, hat zwei Möglichkeiten.

Wechseln wir zunächst in das Heimatverzeichnis, falls nicht schon geschehen und öffnen die Konfigurations-Datei für die Bash:

cd ~
gedit .bashrc


Irgendwo ziemlich weit unten, sofern die Datei nicht bereits verändert oder erweitert wurde, sollte sich folgender Textblock finden:

# Alias definitions.
# You may want to put all your additions into a separate file like
# ~/.bash_aliases, instead of adding them here directly.
# See /usr/share/doc/bash-doc/examples in the bash-doc package.


Unter diesem Block können nun alle Aliase eingetragen werden. Dies geschieht genauso, wie wir die Aliase bereits in der Shell gesetzt haben, zum Beispiel:

alias delete=’rm -r —interactive=always’
alias cp=’cp -ri’
alias apt-upd=’sudo apt-get update’
alias apt-ugd=’sudo apt-get upgrade’
alias apt-dugd=’sudo apt-get dist-upgrade’


Ich persönlich bevorzuge und empfehle jedoch eine andere Variante, bei der sich die Aliase einfacher auf andere Benutzer und Systeme übertragen lassen und bei der die .bashrc vor Änderungen unberührt bleibt. Dazu öffnet man ebenfalls, wie oben beschrieben, die Konfigurations-Datei der Bash – die .bashrc – und sucht unter dem vorhin genannten Textblock nach folgenden drei Zeilen:

#if [ -f ~/.bash_aliases ]; then
#    . ~/.bash_aliases
#fi


Diese sind am Zeilenanfang mit einem Nummerzeichen, einem #, auskommentiert. Nach dem entfernen der drei Nummerzeichen speichert man die Datei und legt in der Shell eine neue Datei an:

gedit .bash_aliases


Hier kann man nun wie auch eben all seine bevorzugten Aliase eintragen und die Datei abspeichern.

In jedem Falle gelten die hier gesetzten Aliase für die jeweiligen Benutzer, bei denen die Datei(en) geändert wurde(n). Alle übrigen Benutzer bleiben davon unberührt. Zum Übernehmen der Aliase muss in beiden Fällen das Terminal neu gestartet werden.

Aliase entfernen

Aliase lassen sich natürlich auch entfernen – sowohl temporär angefertigte Aliase, wie auch permanente. Das geschieht mit folgendem Befehl:

unalias [ALIASNAME]


Also zum Beispiel:

unalias apt-allupd
unalias apt-upd
unalias apt-ugd
unalias apt-dugd
unalias cp
unalias rm


Bei permanenten Aliases sollte man allerdings beachten, dass diese sich auf diese Weise nur vorübergehend entfernen lassen. Wer sie dauerhaft löschen möchte, muss sie aus der .bashrc bzw. der .bash_aliases löschen.

Ein gut gemeinter Rat

Aliase haben jedoch einen Nachteil. Durch die ständige Benutzung der Aliase läuft man Gefahr den Umgang mit den Befehlen zu verlernen. Zudem gibt es noch das Problem, dass nicht auf allen Rechnern die selbst gesetzten Aliase existieren – dies gilt besonders für fremde Rechner. Außerdem sollte man darauf achten, nicht bereits “reservierte” Befehls- oder Programm-Namen zu benutzen. In der Regel wird ein Alias nämlich einem vorhandenem Programm-Namen vorgezogen. Dazu ein Beispiel:

alias echo=’la -la’


Führt man nun den Befehl echo aus, so stellt man fest, dass nicht der erwartete echo-Befehl dahinter steckt, sondern eben der Befehl für die Auflistung aller im aktuellen Verzeichnis sich befindenden Dateien, mit Angabe der detaillierten Datei-Informationen.

Auch wenn man selbst bestimmte Befehle nicht nutzt, so sollte man es vermeiden diese mit einem permanenten Alias zu überdecken, da andere Scripte diese Befehle eventuell nutzen möchten. Manchmal werden aber auch erst Aliase gesetzt und irgendwann später Programme installiert, die über den selben Namen aufgerufen werden. In diesem Falle gilt es zunächst seine gesetzten Aliase zu überprüfen.