220 lines
7.1 KiB
Markdown
220 lines
7.1 KiB
Markdown
# Basics of the Linux Bash Command History with Examples
|
|
|
|
The bash command history shows the previously used commands. By default, the history is saved in memory per session and can be saved to a file for later sessions. We will explore ways to show, search and modify the history in this blog post.
|
|
|
|
I use RHEL and Debian-based Linux distributions and bash in this blog post as a reference.
|
|
|
|
# Configuration <a href="#configuration" id="configuration">#</a>
|
|
|
|
I want to start with ways to configure the behavior of the bash history.
|
|
|
|
The configuration of the history can be changed in the bash startup file. Those can typically be found in the home directory of the user.
|
|
|
|
System-wide `/etc/profile` or in the home directory `~/.bashrc` or `~/.profile`. There are more, but just to list some examples.
|
|
|
|
If you want to use an option for one session only, you can just type it in like this:
|
|
|
|
`HISTFILE=/dev/null` or `unset HISTFILE`
|
|
|
|
In both ways, you would disable the history for the current bash session.
|
|
|
|
|
|
# The basics <a href="#basics" id="basics">#</a>
|
|
|
|
The bash history should be enabled by default, but you might want to change some settings.
|
|
|
|
The history file that is stored on disk can be found with the following command:
|
|
: `echo $HISTFILE`
|
|
|
|
The default location for the history on disk is `~/.bash_history`.
|
|
|
|
Add the following option to change the name and storage location of the history file on disk:
|
|
: `HISTFILE=/path/to/the/history.txt`
|
|
|
|
Show the complete history from memory:
|
|
: `history`
|
|
|
|
Just show the last number of commands:
|
|
: `history 20`
|
|
|
|
Read history from disk to memory:
|
|
: `history -r`
|
|
|
|
Append history entries from memory to disk:
|
|
: `history -a`
|
|
|
|
Overwrite the disk history with the memory history:
|
|
: `history -w`
|
|
|
|
Since I am used to working with multiple sessions and I want to share the history of them, I've added the following line to my startup file to append every entry to the history on disk.
|
|
|
|
`export PROMPT_COMMAND='history -a'`
|
|
|
|
Delete a specific history entry or range:
|
|
: `history -d 20` *# one specific entry*
|
|
: `history -d 15-20` *# range*
|
|
: `history -d -5` *# last 'n' of entries*
|
|
|
|
#### Disabling bash command history <a href="#disable" id="disable">#</a>
|
|
|
|
As mentioned above, there are multiple options to disable the bash command history.
|
|
|
|
`HISTFILE=/dev/null` or `unset HISTFILE`
|
|
|
|
#### Number of history entries
|
|
|
|
The following option sets the number of entries that are displayed if you enter `history`:
|
|
: `HISTSIZE=20`
|
|
|
|
The following option sets the maximum number of entries in the history on disk:
|
|
: `HISTFILESIZE=2000`
|
|
|
|
|
|
# Search function <a href="#search" id="search">#</a>
|
|
|
|
You can start a **reversed search** through the history by pressing `CTRL` + `r` and entering the search term. You can jump to the next result by pressing `CTRL` + `r` again. After finding the desired command, you can press `TAB` to get filled to the current command line or press `ENTER` to run the command immediately.
|
|
|
|
If you skipped through your desired command, you can cancel the current search request with `CTRL` + `g` and start from the top again.
|
|
|
|
There is no native way to jump forward again - but you could add a forward search by adding `stty -ixon` to your startup file. The keyboard shortcut for the forward search is `CTRL` + `s`.
|
|
|
|
#### Using 'grep'
|
|
|
|
I prefer to use grep to find commands. Simply use one of these examples to do so.
|
|
|
|
```bash
|
|
history | grep SEARCHTERM
|
|
or
|
|
grep SEARCHTERM $HISTFILE
|
|
```
|
|
|
|
**Side note**: use the `-i` flag if you want search case-insentitive.
|
|
|
|
|
|
#### Add comments to commands
|
|
|
|
You can add comments to commands with `#`. This makes it easy to find commands again or document the thoughts behind the command in troubleshooting sessions and later reviews.
|
|
|
|
```bash
|
|
kuser@pleasejustwork:$ echo nightmare # dolphins chasing me in a mall
|
|
nightmare
|
|
```
|
|
|
|
# Exclusions <a href="#exclusion" id="exclusion">#</a>
|
|
|
|
We can add exclusion with the `HISTIGNORE` option in your startup file. This can be useful for privacy and security reasons.
|
|
|
|
There are some predefined options we can choose from:
|
|
: `ignorespaces` - if the command starts with a `SPACE`, it will be excluded
|
|
: `ignoredups` - duplicate commands will be excluded
|
|
: `ignoreboth` - both above-mentioned options together
|
|
|
|
If those options are not enough, you can create your own rules. For example, the `ignoreboth` rule could be written like this:
|
|
|
|
`HISTIGNORE="&:[ ]*"` *# the ampersand `&` means no duplicates, `:` is the separator, `[ ]*` checks if the command begins with a `SPACE`*
|
|
|
|
You can add commands too.
|
|
|
|
`HISTIGNORE="ls:pwd:cd"`
|
|
|
|
# Timestamps <a href="#timestamps" id="timestamps">#</a>
|
|
|
|
Timestamps are often important for reviews of troubleshooting sessions. With the `HISTTIMEFORMAT` option, you can add timestamps in various formats to your history.
|
|
|
|
The default history looks like this:
|
|
|
|
```bash
|
|
kuser@pleasejustwork:$ history 6
|
|
1150 history
|
|
1151 vim .bash_history
|
|
1152 vim .bashrc
|
|
1153 source .bashrc
|
|
1154 ls
|
|
1155 history
|
|
```
|
|
|
|
And the same lines look like this after adding `HISTTIMEFORMAT="%F %T "` to the configuration:
|
|
|
|
```bash
|
|
kuser@pleasejustwork:$ history 6
|
|
1150 02/02/23 18:03:32 history
|
|
1151 02/02/23 18:03:45 vim .bash_history
|
|
1152 02/02/23 18:05:03 vim .bashrc
|
|
1153 02/02/23 18:05:22 source .bashrc
|
|
1154 02/02/23 18:05:26 ls
|
|
1155 02/02/23 18:05:30 history
|
|
```
|
|
|
|
You can adjust the format with the following placeholders:
|
|
|
|
```bash
|
|
%d: day
|
|
%m: month
|
|
%y: year
|
|
%H: hour
|
|
%M: minutes
|
|
%S: seconds
|
|
%F: full date (Y-M-D format)
|
|
%T: time (H:M:S format)
|
|
%c: complete date and timestamp (day-D-M-Y H:M:S format)
|
|
```
|
|
|
|
# Re-run commands <a href="#rerun" id="rerun">#</a>
|
|
|
|
`!!` is a variable for the previous command and, for example, can be used to run the last command as 'sudo' .
|
|
|
|
```bash
|
|
kuser@pleasejustwork:$ whoami
|
|
kuser
|
|
kuser@pleasejustwork:$ sudo !!
|
|
[sudo] password for kuser:
|
|
root
|
|
```
|
|
|
|
---
|
|
|
|
`!` can be used to re-run the last command starting with a chosen term.
|
|
|
|
```bash
|
|
kuser@pleasejustwork:$ history 5
|
|
41 ping ittavern.com # !ping
|
|
42 whoami # !whoami
|
|
43 nmap -sP 10.10.10.0/24 # !nmap
|
|
44 vim .bashrc # !vim
|
|
45 history
|
|
kuser@pleasejustwork:$ !who # runs immediately and auto-completes
|
|
kuser
|
|
```
|
|
|
|
---
|
|
|
|
`!n` would run the 'n' command in the history, and `!-n` refers to the current command minus 'n'
|
|
|
|
```bash
|
|
kuser@pleasejustwork:$ history 5
|
|
41 ping ittavern.com # !41 / !-5
|
|
42 whoami # !42 / !-4
|
|
43 nmap -sP 10.10.10.0/24 # !43 / !-3
|
|
44 vim .bashrc # !44 / !-2
|
|
45 history # !45 / !-1 / !!
|
|
kuser@pleasejustwork:$ !-4 # runs immediately
|
|
kuser
|
|
```
|
|
|
|
#### modify and re-run previous command
|
|
|
|
With the following syntax, you can replace keywords from the previous command and run it again.
|
|
|
|
`^OLD KEY WORD^NEW KEY WORD OR PHRASE^`
|
|
|
|
**Example:**
|
|
|
|
```bash
|
|
kuser@pleasejustwork:$ sudo nmap -T3 10.10.22.0/24 -p 80,443
|
|
kuser@pleasejustwork:$ ^22^50^ # the command will be executed immediately
|
|
kuser@pleasejustwork:$ sudo nmap -T3 10.10.50.0/24 -p 80,443`
|
|
```
|
|
|
|
Use a backslash `\` as an escape character if you need to find or replace a `^`.
|
|
|
|
---
|