How you delete commandlines from the bash history
And suddenly it happened again: I’ve typed sensitive information - at this time it was a password - into the commandline.
And the shell kindly saved the typed commandline into it’s history. This way it want’s to help me, if I need the same commandline again.
But what happens, if the system I’ve worked on isn’t under my full control (a customer system)? Or what if someone later looks over my shoulder, while I’m searching my history for an other command?
The sensitive line needs to be removed.
- what’s the best way to do this?
- How do we save us from doing this again at some time in the future?
Generally you have two ways to remove commanlines from the bash-history: by using the
history command or by editing
Use “history -d” to remove a single entry from the history
If you want to remove a single entry from the bash history, you can use the “-e” commandline switch of the history command: Every command in the bash-history has a unique id by witch it can be referenced.
~$ Secr3t.P4ssword! <-- Oops -bash: Secr3t.P4ssword!: command not found ~$ history | tail -n 4 1004 ps ax | grep httpd 1005 clear 1006 Secr3t.P4ssword! <-- =:-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 - this looks quite good. But unfortunately the history-command only modifies the online-history of the running shell. But potentially my password was already written to the offline Storage in the file
~$ tail -n 4 ~/.bash_history clear Secr3t.P4ssword! <-- =:-O history | tail -n 4 history | tail -n 4
To make sure the entry is wiped completely, just overwrite the ~/.bash_history with the already cleaned online-history of your current shell. Do this, by using
~$ history -w ~$ tail -n 4 ~/.bash_history clear history | tail -n 4 history | tail -n 4 tail -n 4 ~/.bash_history
Hint: Make sure, your running shell ist the last running for the current account. If there is an other shell runnig in parallel, this one could have the password in it’s history an write it to disk, once it is closed.
Second option: edit the ~/.bash_history directly
As a second option, you can of cource directly edit the file .bash_history in your home-directory. But you have to bear in mind, that every running shell potentially has the password in its online-history and therefor could overwrite your changes later on.
To avoid this, clean the online-history of the running shell(s) (
history -c) and read it back in from your modified .bash_history.
~$ tail -n 2 ~/.bash_history ps ax | grep httpd Secr3t.P4ssword! <-- =:-O ~$ vi ~/.bash_history <-- make changes ~$ tail -n 2 ~/.bash_history ps ax | grep httpd here I removed my Secr3t.P4ssword! <-- :-) ~$ history -c ~$ history -r <-- read history from cleaned .bash_history ~$ history | tail -n 2 ps ax | grep httpd here I removed my Secr3t.P4ssword! <-- :-)
Prevention is better …
If you know beforhand that you don’t want the shell to save certain commandlines to history, yout can tell the bash to do so by using the variables
1. HISTCONTROL: Let the shell ignore commandlines with leading spaces and or duplicates
With the shell-variable
HISTCONTROL you are able to prevent the bash from recording commandlines with leading spaces (
ignorespace) or duplicated commandlines (
ignoredups) into the history.
For our use-case
ignorespace is appropriate:
~$ history | tail -n 3 1004 ps ax | grep httpd 1005 clear 1006 history | tail -n 3 $~ HISTCONTROL=ignorespace $~ this commandline starts with a space -bash: this: command not found ~$ history | tail -n 3 1005 clear 1006 history | tail -n 3 1007 HISTCONTROL=ignorespace
perfect: the commandline with the leading space doesn’t show up in the history.
From now on - if we know beforehand that certain commands must not enter the history, we will start the commandline with a single leading space.
If HISTCONTROL isn’t already set in your environment (test with
echo $HISTCONTROL), set it by adding the line
HISTCONTROL=ignorespace to your ~/.bashrc file. If you do so - better choose the value
ignoreboth for additionally ignoring commandline duplicates.
Tip: Changes in ~/.bashrc only take effect after restarting the bash.
2. HISTIGNORE: Let the Bash ignore commandlines by searchpatterns
For some use-cases the variable
HISTIGNORE may be interesting for you: The variable lets you define by searchpatterns, witch commanddlines the bash should ignore for history-recording. Every commandline that starts with one of the given searchpatterns would be ignored.
The searchpatterns you can use are the same as for searching for files: filename globbing (man 7 glob).
~$ HOSTIGNORE="ls*" <-- ignore all commands starting with 'ls' ~$ 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
You will find further information regarding this topic within the help-output of the history command (
help history) and within the bash manual-page.