So löschst Du Zeilen aus der History der Bash

Und plötzlich ist es doch wieder passiert: Ich habe sensible Informationen - diesmal ein Passwort - auf der Kommandozeile der Bash eingetippt.

In ihrer unendlichen Hilfsbereitschaft hat die Shell die so abgesetzte Kommandozeile in ihrer History vermerkt. So kann ich sie später problemlos noch einmal verwenden.

Dumm nur, wenn sich das betroffene System nicht unter meiner vollständigen Kontrolle befindet (Kundensystem?), oder wenn mir beim nächsten Mal jemand über die Schulter schaut, während ich die History nach einem anderen Befehl durchsuche.

Die betreffende Zeile muss also aus der History entfernt werden.

  • Wie stellt man das am besten an, und
  • Wie verhindert man das Problem in Zukunft?

Generell hast Du zwei Möglichkeiten, Befehle aus der Bash-History zu entfernen. Entweder, verwendest direkt das history-Kommando, oder Du bearbeitest die ~./bash_history.

Mit “history -d” einzelne Einträge aus der History entfernen

Wenn du einen einzelnen Eintrag aus der History der aktuellen Shell entfernen möchtest, hilft der Kommandozeilenschalter “-d” des History-Kommandos: Jede Kommandozeile hat in der History eine ID, anhand derer der entsprechende Eintrag gelöscht werden kann:

~$ MeinPasswort                         <-- Oops
-bash: MeinPasswort: command not found
~$ history | tail -n 4
 1004  ps ax | grep httpd
 1005  clear
 1006  MeinPasswort                     <-- =:-O
 1007  history | tail -n 4
~$ history -d 1006
~$ history | tail -n 4
 1005  clear
 1006  history | tail -n 4
 1007  history -d 1006
 1008  history | tail -n 4

Puh - das sieht ja schon ganz gut aus. Allerdings bearbeitet das history-Kommando ausschließlich die History der aktuell laufenden Bash. Möglicherweise ist der ungewollte Eintrag aber bereits im Offline-Speicher der History gelandet - in der Datei ~/.bash_history:

~$ tail -n 4 ~/.bash_history
clear
MeinPasswort	                         <-- =:-O
history | tail -n 4
history | tail -n 4

Um sicherzugehen, dass der Eintrag wirklich vollständig entfernt wird, überschreibst Du die ~/.bash_history mit der History der aktuell laufenden Shell (dort hast Du den Eintrag ja gerade entfernt) mit dem Kommando history -w.

~$ history -w
~$ tail -n 4 ~/.bash_history
clear
history | tail -n 4
history | tail -n 4
tail -n 4 ~/.bash_history

Alternative: Bearbeite die ~/.bash_history direkt

Alternativ kannst Du natürlich auch die Datei .bash_history in Deinem Heimatverzeichnis direkt bearbeiten. Dabei musst Du lediglich bedenken, dass alle aktuell laufenden Shells die History aus dieser Datei möglicherweise bereits eingelesen haben und beim Beenden auch wieder dorthin zurückschreiben.

Um Deine Änderungen von einer laufenden Shell nicht überschreiben zu lassen, leerst Du am besten zuerst die History der laufenden Shell (history -c') und lässt dann die History aus deiner geänderten .bash_history wieder einlesen.

~$ tail -n 2 ~/.bash_history
ps ax | grep httpd
MeinPasswort	                         <-- =:-O
~$ vi ~/.bash_history                    <-- Änderungen vornehmen
~$ tail -n 2 ~/.bash_history
ps ax | grep httpd
hier stand mal mein MeinPasswort         <-- :-)
~$ history -c
~$ history -r                            <-- History aus .bash_history einlesen
~$ history | tail -n 2
ps ax | grep httpd
hier stand mal mein MeinPasswort         <-- :-)

Vorbeugen ist besser

Wenn man vorher weiß, dass bestimmte Kommandozeilen nicht in der History der Bash verewigt werden sollen, kann man das der Shell im Voraus mit Hilfe von zwei Variablen sagen: HISTCONTROL und HISTIGNORE

1. HISTCONTROL: Die Shell ignoriert Kommandozeilen mit führenden Leerzeichen oder/und Duplikate

Mit der Variablen HISTCONTROL kannst Du steuern, dass die Shell Kommandozeilen mit führenden Leerzeichen nicht in die History aufnimmt (ignorespace), und/oder dass Kommandozeilen-Duplikate für die History ignoriert werden (ignoredups).

Für unseren Anwendungsfall ist ignorespace interessant:

~$ history | tail -n 3
1004  ps ax | grep httpd
1005  clear
1006 history | tail -n 3
$~ HISTCONTROL=ignorespace
$~  diese Kommandozeile beginnt mit einem Leerzeichen
~$ history | tail -n 3
1005  clear
1006 history | tail -n 3
1007 HISTCONTROL=ignorespace

Perfekt: Die eingerückte Kommandozeile taucht nicht in der History auf.

Wenn wir also vorher wissen, dass auf der Kommandozeile sensible Informationen stehen werden, beginnen wir ab jetzt die Kommandozeile einfach mit einem Leerzeichen.

Falls die Variable HISTCONTROL in Deiner Umgebung nicht automatisch gesetzt ist, trage die entsprechende Zeile (HISTCONTROL=ignorespace) am einfachsten in Deine ~/.bashrc ein. Dabei verwendest Du dann vielleicht sogar den Wert ignoreboth statt ignorespace, um zusätzlich auch alle Kommando-Duplikate von der History fernzuhalten.

Hinweis: Änderungen in der .bashrc werden erst dann wirksam, wenn Du Deine Shell neu öffnest.

2. HISTIGNORE: Die Shell ignoriert Kommandozeilen, die Suchmustern entsprechen

Für einige Anwendungsfälle ist dagegen die Variable HISTIGNORE interessant: Mit dieser Variablen wird die Shell angewiesen, Kommandozeilen, die mit einem bestimmten Suchmuster (beginnend) übereinstimmen, zu ignorieren. Dabei genau können die Suchmuster verwendet werden, die man sonst zum Suchen nach Dateinamen verwendet (man 7 glob).

~$ HOSTIGNORE="ls*"    <-- alle Kommandos, die mit 'ls' beginnen, ignorieren
~$ echo "Test 1"
Test 1
~$ ls > /dev/null
~$ echo "Test2"
Test 2
~$ history | tail -n 3
1012 echo "Test 1"
1013 echo "Test 2"
1014 history | tail -n 3

Weitere Informationen zum Thema findest Du in der Hilfe von history (help history) und in der Manual-Page der Bash

Du hast Fragen zum Thema? Fordere mich heraus! Frag Robert!