In Bash, history shows the list of commands run by the current account. That sounds simple, but it is one of the biggest time savers when you work on servers, especially for long commands you do not want to retype.
Viewing the history
history # the whole history, with line numbers
history 10 # the 10 most recent commands
The output looks like this:
501 cd /var/www/html
502 tail -f storage/logs/laravel.log
503 systemctl reload nginx
504 history 10
The number on the left is the command’s position in the history, and you are about to use it.
Re-running an old command
!503 # run command number 503 again
!! # run the previous command again
!systemctl # run the most recent command starting with "systemctl"
!! is particularly useful when you forget sudo:
$ systemctl restart nginx
Failed to restart nginx.service: Access denied
$ sudo !!
# equivalent to: sudo systemctl restart nginx
Another handy one is !$, which pulls the last argument from the previous command:
$ mkdir /var/www/new-project
$ cd !$
# equivalent to: cd /var/www/new-project
Searching the history
The fastest way is not history at all, it is Ctrl + R. Press it, type a few characters, and Bash searches backwards through your history for the closest match:
(reverse-i-search)`nginx': systemctl reload nginx
Press Ctrl + R again to step to an older match. Press Enter to run it, or the right arrow to edit before running. Ctrl + G cancels.
This is the shortcut I use more than any other on the command line.
The alternative is filtering with grep:
history | grep mysql
Clearing the history
Sometimes you accidentally type a password or a token on the command line and it stays in your history.
history -d 503 # delete one specific line
history -c # clear the history for the current session
history -c && history -w # clear it and overwrite the file on disk
History is stored permanently in ~/.bash_history. history -c alone is not enough, because the file on disk is still there. You need history -w to overwrite it.
The better approach is keeping secrets out of your history in the first place. In Bash, if you type a leading space before a command and HISTCONTROL includes ignorespace, that command never gets recorded:
mysql -u root -pYourPassword # note the leading space
Customising how history is saved
Add this to ~/.bashrc:
# How many commands to keep in memory and in the file
HISTSIZE=10000
HISTFILESIZE=20000
# Skip duplicate commands and commands starting with a space
HISTCONTROL=ignoreboth
# Record a timestamp with each command
HISTTIMEFORMAT="%d/%m/%Y %H:%M:%S "
# Append to the file rather than overwriting on exit
shopt -s histappend
HISTTIMEFORMAT is well worth turning on. When you need to answer “what did I run on this server last Tuesday”, having timestamps changes everything.
After editing, reload the config:
source ~/.bashrc
A note on multiple SSH sessions
Bash only writes history to the file when you exit a session. If you have several SSH windows open at once, the last one to close can overwrite the history from the others. The shopt -s histappend line above fixes exactly that.
If you want every command recorded immediately and shared across sessions, add:
PROMPT_COMMAND="history -a; history -c; history -r"