lennxa

Bash History

Importance: 4 | # | bash, shell, mine

TLDR

Tired of losing your command history? Add this to your .bashrc:

# Ensure history is appended, not overwritten on exit
shopt -s histappend

# After every command, append new history lines from this session to the history file
export PROMPT_COMMAND="history -a"

# Manually sync in new history lines from the file (added by other sessions)
alias s='history -n'

Now you won't lose your history in case your system powers-off unexpectedly or your bash process crashes. And you can use s to sync histories from other shell sessions into the current shell.


I use tmux (oh-my-tmux) with bash along with fzf. ctrl-r is an indispensible feature - how are you going to get anything done if you cannot access your command history without friction.

More recently I've noticed that the utility of ctrl-r has gone down significantly for me. It never seems to work!? The commands from any session (not the tmux session - I mean a single instance of a shell) only seem to be available within the session and I magically lose the history sometimes. I put off looking into this for a while now, and I've finally found some time.

Bash History Storage

So what happens when you press up-arrow or use ctrl-r? Where's it stored? How's it synced between shell sessions (sometimes).

There's two levels of storage

  1. in-memory buffer
    • specific to each running shell process (bash)
    • accessible with history or ⬆️ or Ctrl-R
    • lost when shell crashes
  2. persistent file
    • shared at the user level (usually ~/.bash_history)
    • like a shared archive
    • written when a shell closes cleanly

The in-memory buffer per shell session is appended each time a command is run. This buffer can be accessed with history, and this is also how ⬆️ and ctrl-r are implemented.

But a new shell session's history does not start out empty. It's loaded from the persistent file - usually ~/.bash_history. By default, ~/.bash_history is read once at the initialization of shell session and written when the shell exits cleanly. It takes the new commands in history and appends to ~/.bash_history.

Since I use tmux, you can see how this would not be great for me. Roughly I think of my shell sessions in two categories -

  1. short term - quick stuff, execute a few commands, exit
  2. long term - kept running for weeks/months

Once created the long term sessions will not recieve any commands from other sessions and will also not write to ~/.bash_history until they are closed - so these commands are not available in my short-terms sessions. And although the short-term commands are written out, it's usually not read by long-term sessions as they are usally initialized before most short sessions.

Solving sync

history provides a couple of useful options -

Running these manually would be tedious, so add the following to ~/.bashrc:

So now I type away commands on different shells and only use the current session's history until I need commands from other sessions - in which case I sync with a s.

Additional Options

You can specify a few additional options:

The sourcecode for bash contains the implementation for history and everything discussed above and it's less complicated than one might expect. In case you're interested, most of the stuff related to history can be found in lib/readline/hist*.c/h and builtins/history.def

#bash #im-4 #mine #shell