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!
Programm-Abstürze unter Ubuntu Linux handhaben
Jedes Betriebssystem hat hin und wieder Fehler, die früher oder später beseitigt werden und wenn es nicht das Betriebssystem ist, dann vielleicht eine Anwendung. In der Regel kann man eine abgestürzte Anwendung über die Systemüberwachung unter System → Systemverwaltung abschießen. Dazu klickt man mit der rechten Maustaste auf die gewünschte Anwendung und probiert es zunächst mit Prozess beenden. Klappt dies nicht, kann man noch immer den Prozess abwürgen. Doch was tun, wenn die Anwendung das System stark auslastet oder gar die GUI komplett blockiert? Die Maus lässt sich dann zwar noch bewegen, aber alles steht still und man kann noch so viel klicken und drücken, aber nix passiert.
Bevor man das System nun neu startet und womöglich noch nicht gespeicherte Daten flöten gehen, gibt es noch die Möglichkeit die jeweilige Anwendung über die Shell abzuschießen. Dazu kann man mit Strg + Alt + F1 bis F6 in eine der virtuellen Konsolen wechseln. Dort logt man sich wie gewohnt ein und schon kann man sich auf die Jagd nach dem Übeltäter begeben. Zurück zur GUI geht es übrigens mit F7, manchmal auch F9.
Bei stark ausgelasteten Systemen kann es allerdings etwas dauern, bis die Shell erscheint oder ausgeführte Befehlszeilen verarbeitet werden. Wem eventuell nicht gespeicherte Daten lieb sind, der sollte sich in Geduld üben.
X abschließen
Die einfachste Möglichkeit, vom Benutzer ausgeführte Prozesse (!) schnell abzuschießen ist oft einfach den Grafikserver – genannt X – abzuschießen. In der Regel lösen sich damit die meisten Schwierigkeiten in Luft auf, allerdings lösen sich damit in der Regel auch meistens alle nicht gespeicherten Daten in Luft auf. Dazu drückt man unter Ubuntu ab Version 9.10 Strg + Alt + Druck/Print und anschließend K, wobei man die zuvor gedrückten Tasten nicht loslassen darf. Bei älteren Versionen dürfte die Tastenkombination Strg + Alt + Entf/Del das gleiche bewirken.
Um diese Tastenkombination auszuführen, bedarf es übrigens nicht eines Wechsels in die Shell, beispielsweise mittels Strg + Alt + F1.
top
Ist man schon mal in der Shell, so kann man mit dem Befehl top, einem einfach zu bedienenden und informativen Tool, die laufenden Prozesse einsehen. Das Programm aktualisiert die Ansicht alle paar Sekunden, so dass je nach Prozessorauslastung die jeweiligen Prozesse über den Bildschirm „hüpfen”.
Durch drücken der Taste K und die eingabe der jeweiligen PID eines Prozesses, erlaubt es das Programm einen Prozess zu „killen”. Mit der Taste Q kann man das Programm wieder verlassen. Wer sein zu beobachtendes Programm in der Liste nicht findet, kann es auch explizit beobachten lassen:
top -p PID
Root-Prozesse lassen sich allerdings nur abschließen, wenn man top zuvor mit sudo ausgeführt hat!
Wer sich außerdem sicher ist, einen Prozess killen zu wollen, den man selbst oder den ein bestimmter Benutzer ausgeführt hat, der kann sich auch explizit nur die Prozesse eines Benutzers anzeigen lassen:
top -u BENUTZERNAME
Dies dürfte für etwas mehr Übersicht im Prozess-Gewusel sorgen.
PID herausfinden
Ok, schön. Jetzt haben wir das Programm eben in top nicht gesehen und wissen auch nicht die PID des gewünschten Prozesses. Was nun? Mittels pidof kann man ganz leicht die PID eines laufenden Prozesses herausfinden. Alles was man dazu wissen muss, ist der Prozessname. Also nehmen wir also zum Beispiel an, wir möchten Firefox abschießen, so können wir die PID des Firefox-Prozesses wie folgt abfragen:
pidof firefox
Als Rückgabe erhalten wir eine Nummer, welches die PID des Firefox-Prozesses ist.
Prozess und PID finden
Manchmal kommt es aber vor, dass der gewünschte Prozessname anders lautet, als man denkt. Dies ist zum Beispiel bei der Schriftenverwaltung „Specimen” der Fall. Wir wissen aber zumindest den ungefähren Namen. Also können wir mittels ps und einer grep-Pipe die PID der Schriftenverwaltung wie folgt abfragen:
ps -fe | grep specimen
Als Ausgabe erhalten wir dann etwas in der Art:
benutzer 24230 1 3 19:20 ? 00:00:02 /usr/bin/python /usr/bin/gnome-specimen
benutzer 24675 29046 0 19:21 pts/0 00:00:00 grep specimen
Die erste Zeile ist die gewünschte Anwendung, die wir abschießen möchten. Hier finden wir die PID in der zweiten Spalte und diese lautet 24230. Die zweite Zeile ist unsere grep-Abfrage.
Was hier geschieht, ist ganz einfach: Mittels ps -fe lassen wir uns eine detaillierte Liste aller Prozesse ausgeben. Diese Liste wird allerdings nicht auf dem Bildschirm ausgegeben, sondern über eine Pipe (eine Art virtuelles Rohr) an grep weiter gereicht, was nun jede Zeile ausgibt, in der der String specimen vorkommt.
Wer möchte, kann sich auch die ganze Prozessliste anzeigen lassen:
ps -fe
Scrollen kann man in der Shell übrigens auch. Dazu hält man die Shift-Taste gedrückt und bewegt sich auf und ab mit den Bild ↑ und Bild ↓ beziehungsweise Page ↑ und Page ↓ Tasten.
Der Killer-Instinkt
Ok, nun gehen wir davon aus, dass wir den Übeltäter haben. Jetzt geht es darum ihn los zu werden. Bitten wir den Prozess zunächst höflich sich sauber aus dem Staub zu machen:
kill -TERM [PID]
Also zum Beispiel:
kill -TERM 24230
Können wir ihn dazu nicht überreden, dann müssen wir direkter werden und ihn schlichtweg killen:
kill -KILL 24230
Bei Prozessen, die man nicht selbst ausgeführt hat, muss man natürlich noch ein sudo vorne anhängen. Statt der Option -TERM wird oft auch die Option -15 und statt der Option -KILL die Option -9 verwendet.
Wer dagegen der Prozessnamen weiß, kann diesen natürlich auch auf direktem Wege umlegen, dazu bedarf es nicht einer vorherigen Recherche bezüglich der PID:
killall -TERM firefox
Beziehungsweise auch wieder auf die harte Tour:
killall -KILL firefox
Und schließlich gibt es da noch die Methode für die ganz verzweifelten:
killall5
Dieser Befehl schießt alles ab, was kein Kernel-Thread ist und von dem Befehl selbst zur Ausführung nicht gebraucht wird und wofür es auch die Zugriffsrechte besitzt (in dem Falle nicht als sudo ausgeführt). Nicht gespeicherte Daten gehen mit großer Sicherheit damit allerdings verloren.
Wer hat in meinem Bettchen geschlafen?
In einigen vermutlich eher seltenen Fällen kann es durchaus mal sein, dass man einen Übeltäter ganz anderer Art abschießen möchte, nämlich den, der gerade auf eine bestimmte Datei, ein bestimmtes Verzeichnis, Dateisystem oder einen bestimmten Socket zugreift.
Nehmen wir beispielsweise an, wir möchte herausfinden, welche Prozesse auf das eigene Heimverzeichnis zugreifen. Um eine entsprechende Liste an Prozessen zu erhalten, führen wir folgendes aus:
fuser -uv ~
Die Liste besteht nun aus vier Spalten: USER, PID, ACCESS und COMMAND. Unter COMMAND findet sich der Prozessname wieder, PID bezeichnet die Prozess-ID und unter ACCESS sehen wir, wie auf die Datei zugegriffen wird (siehe auch: man fuser).
Alle Prozesse, die auf eine Datei zugreifen, lassen sich auch gleich mittels der nachfolgenden Zeile und einer interaktiven Abfrage killen:
fuser -uvki ~
Darüber hinaus lässt sich mit fuser auch herausfinden, welcher Prozess gerade an einem TCP- oder UDP-Port lauscht:
fuser -uv -n tcp mail
Oder auch durch Angabe der Portnummer:
fuser -uv -n tcp 80
Oder man kann rausfinden ob, und wenn ja, welcher Prozess gerade auf das CD- beziehungsweise DVD-Laufwerk zugreift:
fuser -uv /media/cdrom
In jedem Falle erhält man eine Liste mit Prozess-IDs und -Namen.
Und nun viel Spaß und Erfolg beim Suchen und Killen! ;)