Customize bash history in Linux
Overview
If you are a fan of the bash prompt and you have used Linux for some time it is quite likely that you have used the history command in your daily work. This command is used to recall previously entered commands at the bash prompt. This is an important feature of bash which could save you a lot of time for example if you type really long commands. By default the history option in bash is enabled. If somehow the option is not active you could turn it on by running the following command:
# set -o history
Changing bash history behaviour
The built-in bash history command offers a few environment variables which helps us customizing it’s output and behaviour. For example me might need to override the default number of commands kept in the history list during a session. For this we must change the value of the HISTSIZE variable according to our needs. The HISTSIZE variable sets the number of lines permitted in the history stack in memory and the default value is 500.
export HISTSIZE=1000
The above example will keep the 1000 last commands in the history of current session. If we to control how many lines are kept in the history file we must set the $HISTFILESIZE variable.
export HISTFILESIZE=1000
The above command tells bash to save the 1000 most recent commands between login sessions. For example, if we set the value of the HISTSIZE to 100 and the the value of the HISTFILESIZE is set to 1000 only those 100 commands will be stored in the history file.
The location and the name of the bash history file can be controlled by using the HISTFILE variable. For instance we could change the name and the location of the bash history file similar to the below:
export HISTFILE=/home/testuser/.my_history
By default all history is saved in a hidden file named .bash_history located in the home directory of each user. Normally, the history command will display only the typed list of commands each one being preceded by the order number in the list.
# history
1 ls -l
2 tail -f /var/log/messages
3 iptables -nL
…
For auditing purposes, the history command can be customized to display a timestamp with each command. For this we must set the HISTTIMEFORMAT variable like below:
export HISTTIMEFORMAT=’%F %T ‘
where:
%F – displays the date in %Y-%m-%d (year-month-date) format
%T – displays the time in 24-hour notation (%H:%M:%S)
The values used in the HISTTIMEFORMAT display are format strings used by strftime function. To get more details about these format strings check the man page of the strftime.
The shell allows us to control which commands are saved on the history list. The HISTCONTROL and HISTIGNORE variables may be set to cause the shell to save only a subset of the commands entered. Sometimes we type several repeated commands. In order to prevent duplicate commands from being stored in history, we can use the HISTCONTROL variable.
export HISTCONTROL=ignoredups
The values supported by the HISTCONTROL variable are explained below:
- ignoredups – lines which match continuous repetead history entries are not saved in the history list.
- ignorespace – lines which begin with a space character are not saved in the history list.
- ignoreboth – both duplicate lines and lines which begin with spaces are ignored.
- erasedups – all duplicate lines no matter their position in the list are removed
The HISTIGNORE environment variable controls which commands are ignored from the history. It receives a colon-separated list of patterns used to decide which command lines should be saved. So for example we can create a list of very basic commands which we use very often like ls, pwd or cd and exclude them from the history list.
export HISTIGNORE=”ls:pwd:cd ..”
The pattern used must be matched exactly, so if we would run “ls -l” this command will be stored in the history list. The pattern HISTIGNORE=”&” is identical to setting HISTCONTROL=ignoredups and a pattern of ‘[ ]*’ is identical to assign the ignorespace value to the HISTCONTROL variable.
In order for these settings to be available after session logout or system reboot we must export the enviroment variables either locally in the .bashrc file located in each user’s home directory or globally in /etc/bashrc file.
Using event designators
Event designators are used for referencing previous commands existent in the history list. They begin with an exclamation point (!). For example, to refer to the previous executed command we can use the !! event designator. Let’s assume that our last command typed at the bash prompt was pwd. In this case if we type !! the pwd command will be ran once again.
If we want to run a specific command from the history list we can use the !n event designator, where n is the order number corresponding to the command in the history list. Similarly the !-n event designator can be used to reference n lines back in the history list from the current command. For example, if the last command has the line number 330 and we type !-7 then the command correspoding to the line number 323 will be executed.
Another useful event designator is !string, which runs the most recent command beginning with the string you specify. For example if the type !ss and or last entered command was ssh then this line will be executed again. There is also a similar event designator !?string? which allows us to reference commands which contain the string beetwen the question marks.
Using word designators and modifiers
Word designators are used along with event designators and are separated by a colon “:” sign. They are used to select desired words from the event. For instance, the !ss:2 word designator refers to the second argument of the most recent command starting with letters ss. There are a few others useful word designators like:
- ^ – refers to the first argument of a command
- $ – refers to the last argument of a command
- % – refers to the word matched by the most recent ‘?string?’ search.
- * – refers to all arguments except the word 0 which mostly represents the command itself
Modifiers are used to change the behaviour of word designators. They are preceded by a colon “:” after the word designators. For example to remove all leading pathnames components and leaving the tail we use the “t” modifier like this:
echo /home/testuser
/home/testuser
$ echo !!:$:t
testuser
Other useful modifiers are “h” for remove the trailing pathname component, leaving only the head, “e” to remove all but the trailing suffix. To see a list of complete event designators, word designators and modifiers please check the bash documentation http://www.gnu.org/software/bash/manual/bashref.html#Using-History-Interactively
Searching bash history
A very useful key combination to search in bash history is Ctrl+R. This will perform a reverse search on the history file. After typing this key combination start typing the first letters of the command you are searching until you get the closest match. For example, if we have in our history list a specific ssh command and we want to run it once again wihout having to type the whole line again, hit Ctrl+R and the type ss and see what it returns. If it doesn’t return what you need hit Ctrl+R several times until you get the exact line and then hit Enter to run the command.
(reverse-i-search)`’:
(reverse-i-search)`ss’: ssh cioby@10.2.0.1
Another simple way to browse the history list is to press the up arrow key which will go back one position at a time in the list.
Conclusion
Bash history can ease the life of a Linux system administrator by offering some nice features for searching and filtering commands.