Bash History

BASH - Bourne Again SHell BASH - Bourne Again SHell

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:

[email protected]:~ #
(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:

[email protected]:~ $ grep HIST .bash_profile

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):

[email protected]:~ $ 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:

[email protected]:~ $ 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

Keep Learning with Me

Follow me on Facebook and Twitter or jump into Telegram chat!:
I'm using Brave browser
Give it a try, it's awesome: Brave Browser
IT Consultancy
I'm a principal consultant with Tech Stack Solutions. I help with cloud architectrure, AWS deployments and automated management of Unix/Linux infrastructure. Get in touch!

Recent Tweets