“If something isn't easy to understand,
it just has to be explained in a different way ...”

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 ~/.bash_history directly.

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 ~/.bash_history:

~$ tail -n 4 ~/.bash_history
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.

~$ history -w
~$ tail -n 4 ~/.bash_history
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 HISTCONTROL and HISTIGNORE.

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.

  You've got questions? Challenge me! Ask Robert!