If you want to help people,
keep it simple!

How to delete command lines from the bash history

And suddenly it happened again: I’ve typed sensitive information (at this time it was a password) into the command line.

And the shell kindly saved the typed commandline into its history. This way it wants to help me if I need the same command line later again. Great!

But what happens, if the system I’m working on isn’t under my full control? Imagine I’ve worked on a customer system …

Or what if someone later looks over my shoulder while I’m searching through my history?

The sensitive line needs to be removed!

  • What’s the best way for doing this?
  • How do we protect ourselves from this happening again later?

Generally speaking: You have two options to remove command lines from the bash history: first, by using the history command and second, 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 command line switch of the history command:

Every command in the bash-history has a unique id, by which 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 current running shell. But potentially my password was already written to the offline storage in the file ~/.bash_history.

Let’s verify this:

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

hmm …

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 simply calling history -w.

~$ 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 one running for the current account. If there is another shell runnig in parallel, this one could have the password in its in-memory history already. Then it would write this to disk and overwrite your changes once it is closed.

Second option: edit the ~/.bash_history directly

As a second option, you can of course 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 therefore could overwrite your changes later on.

To avoid this, clean the online-history of every running shell with history -c and read it back in from your modified .bash_history by calling history -r

~$ 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 command lines into the history, you 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 command lines with leading spaces (ignorespace) or duplicated command lines (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 command line 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 command line with a single leading space.

If HISTCONTROL isn’t already set in your environment (verify this 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 command line duplicates.

Tip: Changes in ~/.bashrc only take effect after restarting the bash.

2. HISTIGNORE: Let the Bash ignore command lines by search-patterns

For some special use-cases, the variable HISTIGNORE may be interesting for you:

The variable lets you define by search-patterns, which command lines the bash shall ignore for history-recording.

Every command line that starts with one of the given search-patterns will be ignored.

The search-patterns you can use are the same as for searching for files at the command line: 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 can find further information regarding this topic within the help-output of the history command (help history) and within the bash manual-page.

Here is what to do next

LBFCoverSmall

If you followed me through this article, you certainly have realized that knowing some internals about how things are working at the Linux command line, can save you a lot of time and frustration.

And sometimes it’s just fun to leverage these powerful mechanics.

If you wanna know more about such “internal mechanisms” of the Linux command line - written especially for Linux beginners

have a look at “The Linux Beginners Framework”

In this framework I guide you through 5 simple steps to feel comfortable at the Linux command line.

This framework comes as a free pdf and you can get it here.

Wanna take an unfair advantage?

ToolboxCoverSmall

If it comes to working at the Linux command line - at the end of the day it is always about knowing the right tool for the right task.

And it is about knowing the tools that are most certainly available on the Linux system you are currently on.

To give you all the tools for your day-to-day work at the Linux command line, I have created “The ShellToolbox”.

This book gives you everything

  • from the very basic commands, through
  • everything you need for working with files and filesystems,
  • managing processes,
  • managing users and permissions, through
  • hardware analyses and
  • simple shell-scripting to the tools you need for
  • doing simple “networking stuff”.

Everything in one single, easy to read book.

With explanations and example calls for illustration.

If you are interested, go to shelltoolbox.com and have a look (as long as it is available).