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
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
Let’s verify this:
~$ 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 simply calling
~$ 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
~$ 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
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
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.
Wanna take an unfair advantage?
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 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).