
Bash is still my Unix shell of choice in 2020, and history is its major functionality that I rely on. This post will be an experiment: I want to collect as much useful information as I can remember in a single post about a particular topic. It's a concept very similar to Unix Reference pages, but for smaller topics.
Shell History
Shell history is a functionality that allows you to use history command for quickly accessing the commands you typed in the past:
603 exit 604 docker ps 605 systemctl start docker 606 exit 607 docker ps 608 more /etc/redhat-release 609 systemctl start docker 610 virsh list 611 history
Where is the Bash History File?
Bash history is stored in the user's home directory, in the /home/$USER/.bash_history file – so if your username is greys (like mine!), the location for Bash history is /home/greys/.bash_history.
Search Bash History
There's a special command called history – you need to learn it. This isn't a separate binary but usually a built-in function in shells like Bash.
You very learn typing "history" – this returns all of the commands you've typed before, then start using history command with grep to find most relevant results, like this:
$ history | grep systemctl
582 systemctl restart ssh
583 systemctl restart sshd
586 systemctl restart sshd
605 systemctl start docker
609 systemctl start docker
612 history | grep systemctl
… and then progress to REALLY make the most of bash history by using its built-in history management features, like reverse search:
Press Ctrl+r right there in the prompt and bash will want you to start typing pattern for searching in its history. It shows you the best matched line from history and if you press Enter you'll execute that command from history again:
root@s1:~ #
(reverse-i-search)`systemctl start n': systemctl start nftables
In this example above, I pressed Ctlr+r and typed systemctl start n – and bash suggested the "systemctl start nftables".
Using Better Timestamps in Bash History
Next evolutionary step is to equip your shell history with proper timestamps – instead of just knowing the order in which your past commands ran, you'll know exactly when this happened:
$ export HISTTIMEFORMAT='%F %T '
This will give you history like this going forward:
$ history |grep systemctl | tail -10 582 2020-03-31 07:07:53 systemctl restart ssh 583 2020-03-31 07:07:53 systemctl restart sshd 586 2020-03-31 07:07:53 systemctl restart sshd 605 2020-03-31 07:07:53 systemctl start docker 609 2020-03-31 07:37:24 systemctl start docker 612 2020-03-31 08:01:15 history | grep systemctl 613 2020-03-31 08:04:26 systemctl start nftables 619 2020-03-31 08:08:08 history |grep systemctl 621 2020-03-31 08:08:16 history |grep systemctl | tail -10
IMPORTANT: this will only add meaningful timestamps to current and future commands. All the ones in the past will have no valid timestamp, so they'll just show you the date when you enabled history using HISTTIMEFORMAT.
Configure Permanent History Settings
You need to save history settings in your bash profile – this makes sure the same settings are applied next time you SSH login to the server or start another terminal window with Bash prompt on your desktop.
Step 1: check for existing history settings
Check for anything like HIST (not HISTORY because some parameters are shortened) in the /home/$USER/.bash_profile file of yours:
greys@xps:~ $ grep HIST .bash_profile export HISTTIMEFORMAT='%F %T '
See? If I want to update the HISTTIMEFORMAT, I don't need to add new option to .bash_profile – I'll just find and edit the existing one.
Step 2: update or add history settings to bash profile
Let's say I want to update HISTFILESIZE parameter to specify maximum size of the .bash_history file. Here's how I do it (assuming it's not found in Step 1):
greys@xps:~ $ echo "HISTFILESIZE 10000000" >> /home/greys/.bash_profile
Temporarily Disable Bash History
If you need to run a few sensitive commands like API keys or passwords that are passed as command line options, it's probably best NOT to commit them into bash history.
Just unset the HISTFILE right from command line before you type anything sensitive:
greys@xps:~ $ unset HISTFILE
After that your history won't be committed even when you finish your current Bash session.
IMPORTANT: best do this in brand new Bash session – otherwise you may lost relevant history that happened prior to you unsetting HISTFILE.
How To Centralize Bash History
Once timestamps are showing and history is tracking, you will discover a peculiar thing: some servers you'll be accessing via multiple remote sessions, and their history won't all necessarily be captured.
To help with this, we need to centralize bash history – that is, configure your bash profile to commit history more often (via PROMPT_COMMAND variable):
export HISTCONTROL=ignoredups:erasedups shopt -s histappend export PROMPT_COMAMND="${PROMPT_COMMAND:+$PROMPT_COMMAND$'\n'}history -a; history -c; history -r;" export HISTCONTROL=ignoreboth
What this will do is:
- enable history file append functionality (shopt -a histappend)
- make sure every bash prompt (new command line) updates history file and refreshes current history from it (in case other sessions updated history file)
Can you think of any other cool tricks with Bash History? Let me know and I'll update this page.
See Also
