- Where is bash’s history stored?
- 6 Answers 6
- Bash History Commands and Expansions
- Bash History
- Working with Bash History
- Basic Usage
- Deleting Commands from History
- Bash History Settings
- Buffer Size
- Command Exclusion
- Timestamping
- History Persistence
- History Expansion and Designators
- History Keyboard Shortcuts
- Conclusion
- About the author
- Sidratul Muntaha
Where is bash’s history stored?
If I run history , I can see my latest executed commands. But if I do tail -f $HISTFILE or tail -f ~/.bash_history , they do not get listed. Does the file get locked, is there a temporary location or something similar?
6 Answers 6
Bash maintains the list of commands internally in memory while it’s running. They are written into .bash_history on exit:
When an interactive shell exits, the last $HISTSIZE lines are copied from the history list to the file named by $HISTFILE
If you want to force the command history to be written out, you can use the history -a command, which will:
Append the new history lines (history lines entered since the beginning of the current Bash session) to the history file.
Write out the current history to the history file.
which may suit you more depending on exactly how you use your history.
If you want to make sure that they’re always written immediately, you can put that command into your PROMPT_COMMAND variable:
export PROMPT_COMMAND='history -a'
Side note: if your .bash_history file accidentally becomes owned by root, things stop working. In that case, check the ownership and use sudo to fix the ownership if needed.
@young_souvlaki I expect your man history is for a library; at least, that’s what the only such man page I have available says at the top. It would be unusual for a library to document command-line options of other software, but help history (in Bash) will show applicable Bash documentation.
Thank you! You are correct! Oddly man history defaults to «history(n)» under «Tcl Built-In Commands». man 3 history gives the «Library Functions Manual». help history gives the options described.
(Not an answer but I cannot add comments)
If you are checking .bash_history because you just want delete a specific command (e.g. containing a password in clear), you can directly delete the entry in memory by history -d .
For example, supposing an output like:
$ history 926 ll 927 cd .. 928 export --password=super_secret 929 ll
and you want purge the export line, you can simply achieve it by:
bash keeps it in working memory, bash can be configured to save it when bash closes or after each command, and to be loaded when bash starts or on request.
If you configure to save after each command, then consider the implications of having multiple bash running at same time. (command lines will be interleaved)
The start of you answer makes it sound as if the history is stored in a file called bash, or even in the bash exetable. I would write «It is stored by bash in memory, . «
While running, the history is kept only in memory (by default) if:
- set -o history (an H in echo «$-» ) is set.
- HISTSIZE is not 0 and
- HISTIGNORE is not * (or some other very restrictive pattern).
If any of the above fail, no history is stored in memory and consequently no history could or will be written to disk.
History in memory is written to disk if:
But only when the shell exits or if the commands history -a (append) or history -w (write) are executed.
To trigger an immediate write to disk you can use the variable:
which will append the new history lines to the history file. These are history lines entered since the beginning of the current bash session, but not already appended to the history file.
To overwrite the history in the HISTFILE with the list from memory.
So, you can remove a command from the history in memory:
$ history 5 6359 ls 6360 cd .. 6361 comand --private-password='^%^&$@#)!@*' 6362 top 6363 set +o | less $ history -d 6361 $ history 5 6359 ls 6360 cd .. 6361 top 6362 set +o | less $ history -w
And write it to disk with the last command:
history -w # with `shopt -u histappend` unset
Bash History Commands and Expansions
To perform the steps that are demonstrated in this tutorial, you need the following components:
- A properly-configured Linux system. Check out how to setup an Ubuntu VM in VirtualBox.
- Basic familiarity with the command-line interface.
Bash History
Bash is the default shell in most modern Linux systems. As a successor of “sh”, the original UNIX shell, it comes with numerous features and improvements like the directory manipulation, job control, aliases, command history, and more.
Bash keeps track of all the commands that were previously executed from the terminal. This can be incredibly useful in numerous situations like debugging. It can also reduce the need of typing the same/similar commands over and over.
For history management, Bash comes with two built-in commands:
To store the history, Bash uses two different techniques:
- Whenever working with a shell session, its history is stored in the memory.
- When closed, the history that is stored in the memory is dumped into a history file.
The default history file that Bash uses is located at:
There are also a handful of environment variables and keyboard shortcuts that change how Bash handles history.
Working with Bash History
Basic Usage
To get the list of commands that are recently run, use the following command:
Here, all the commands that are stored in the buffer are listed. Each command has assigned numerical value. The oldest command is assigned with 1.
We can limit the number of commands to print using the following command:
Here, N is an integer where N >= 0. The output contains the last N commands from the history.
We can also use the output in tandem with grep for filtering:
To browse through a long history, we can use the “less” command:
Deleting Commands from History
If you need to remove a specific command from the history, use the following commands:
Similarly, to remove the commands from M to N from the history, we can use the following commands:
To clear the history from the RAM buffer for the current terminal session, use the following commands instead:
To clear the history from the history file that is stored on the disk, we can overwrite it completely with NULL:
Bash History Settings
There are multiple ways of tweaking how Bash handles history. Many of these options are managed by environment variables.
To change their value, we edit the “bashrc” file:
After editing, save the file and reload it in Bash.
To make the system-wide changes, edit the “bashrc” which is located at the following locations:
Buffer Size
As mentioned earlier, Bash uses two buffers to store the command history in RAM (for the current session) and in a disk file (for all the previous sessions).
The sizes of these buffers are controlled by two environment variables:
- HISTSIZE: It defines the number of entries to store in the RAM buffer.
- HISTFILESIZE: It defines the number of entries to store in the disk file.
We can change their value in the “bashrc” to fit our needs:
For example, to store 5000 entries in both buffers, update “bashrc” with the following code:
Command Exclusion
By default, Bash stores every single command run in the history buffers. However, we can configure it so that Bash ignores certain commands. It can be useful in situations where you have to run the same commands numerous times, filling the buffer with spam.
Let’s start with the following command example:
As the output of the history command demonstrates, only the first echo command is registered but not the second one.
This is the working of the HISTIGNORE environment variable. It tells Bash not to log the commands in the history buffer based on certain patterns. The following values are available:
- ignoredups: It’s not logged if a command matches the previous history entry.
- ignorespace: It won’t be logged if a command starts with a space at the beginning.
- ignoreboth: It applies the rule of both ignoredups and ignorespace.
- erasedups: All the previous lines that match the current command will be erased from the history.
In the first example, we demonstrated the usage of ignorespace. However, not all distros may ship Bash with this configuration. As always, we can add them to “bashrc”:
It’s also possible to enable multiple options using the following command:
Here, ignoredups:ignorespace is the equivalent of ignoreboth.
This environment variable can contain one or more patterns. Any command that matches any pattern that is described by the HISTIGNORE will not be registered to either history buffer. The patterns are defined using the regular expressions.
The structure is as follows:
For example, to exclude the history and echo commands from the Bash history, update HISTIGNORE as follows:
We can use the following chain of commands to test it out:
$ ls -l / var / lob &> / dev / null
Timestamping
Bash can also be configured to log the time that a command was run. It can be useful in various situations like debugging.
To enable the timestamps in Bash history, update the value of HISTTIMEFORMAT:
All the available time format control characters are available in the man page of the date command.
The following list includes some simple ones:
History Persistence
When working with the CLI, in many cases, you will find yourself working with multiple terminals. This is where Bash’s history management can become a source of pain.
By default, the history file is updated once the session closes. While it’s fine for a single session, it’s not adequate for multiple simultaneous sessions. We can solve this issue by forcing Bash to update the history file every time a command is run.
To do so, update the value of PROMPT_COMMAND:
Here, the PROMPT_COMMAND variable can contain valid commands. The contents of PROMPT_COMMAND are run before Bash starts taking the user input. The “history –a” command forces the history to append the contents to the history file.
History Expansion and Designators
Bash comes with a couple of built-in shortcuts to take advantage of its history feature. Here’s the list of the designators:
- !!: Runs the last command from the history.
- !N: Runs the Nth command from the history.
- !-N: Runs the Nth command before the most recent command from the history.
- ! : Runs the most recent command.
The following chain of commands demonstrate their usage:
Some designators also work with the command arguments from the history:
- !:*: Use all the arguments of the most recent command.
- !:^: Use the first argument of the most recent command.
- !:N: Use the Nth argument of the most recent command.
- !:M-N: Use the arguments from M to N of the most recent command.
- !:$: Use the last argument of the most recent command.
The following chain of commands demonstrate their usage:
If you need to work with the parameters of a different command, the designators look like this:
The following command chain demonstrates their usages:
$ ls -lh / var / log &> / dev / null
$ touch 1 .txt 2 .txt 3 .txt 4 .txt 5 .txt
History Keyboard Shortcuts
Besides all the commands and environment variables, Bash also supports a handful of keyboard shortcuts for easier history navigation:
- Up arrow key: Scroll backward
- Down arrow key: Scroll forward
There are also keyboard shortcuts that are available for an interactive history search:
- Ctrl + R: Search for commands in history.
- Ctrl + O: Run the selected command.
- Ctrl + G: Exit the interactive search.
Conclusion
We discussed about Bash history in details. We learned how Bash stores the command history and how to take advantage of it in different ways. We demonstrated how to work with Bash history using various examples.
Interested in learning more about Bash? The Bash programming sub-category contains hundreds of guides on different features of Bash.
About the author
Sidratul Muntaha
Student of CSE. I love Linux and playing with tech and gadgets. I use both Ubuntu and Linux Mint.