Bash remembers the commands you type. Used well, history saves endless retyping. You can find that long rsync command from last week in two seconds, or rerun the last command with sudo. It also tells you what someone did on a server, as long as it’s configured properly.
View history
history # all saved commands, numbered
history 20 # the last 20
history | grep rsync
History is kept in memory during a session and written to ~/.bash_history when the shell exits.
Search: Ctrl+R
Press Ctrl+R and start typing. Bash shows the most recent matching command.
- Press Ctrl+R again for older matches.
- Enter runs the match. → or Esc puts it on the line for editing.
- Ctrl+G cancels.
This is the single most useful history feature. Tools like fzf give Ctrl+R a fuzzy, full-list search.
Rerun commands with ! (history expansion)
| Syntax | Meaning |
|---|---|
!! |
The previous command |
sudo !! |
Rerun the previous command with sudo |
!123 |
Command number 123 from history |
!-2 |
Two commands ago |
!rsync |
Most recent command starting with rsync |
!?backup? |
Most recent command containing backup |
!$ |
Last argument of the previous command |
!* |
All arguments of the previous command |
^old^new |
Rerun the previous command, replacing old with new |
Examples:
apt install nginx
sudo !! # sudo apt install nginx
mkdir -p /srv/app/releases
cd !$ # cd /srv/app/releases
systemctl status nginx
^status^restart # systemctl restart nginx
To see what a ! expression expands to before running it, add :p, as in !rsync:p. Or enable shopt -s histverify so expansions are shown for editing first.
Alt+. (or Esc then .) inserts the previous command’s last argument at the cursor. It’s often more convenient than !$.
Configure history
Add these to ~/.bashrc (or /etc/profile.d/history.sh for all users):
HISTSIZE=50000 # commands kept in memory
HISTFILESIZE=100000 # lines kept in ~/.bash_history
HISTTIMEFORMAT='%F %T ' # timestamps in `history` output
HISTCONTROL=ignoreboth # skip duplicates and commands starting with a space
HISTIGNORE='ls:ll:pwd:clear:history'
shopt -s histappend # append to the file instead of overwriting it
PROMPT_COMMAND="history -a${PROMPT_COMMAND:+; $PROMPT_COMMAND}" # save after every command
Why each matters on servers:
- Timestamps let you answer “when did someone run that?”
- histappend + history -a stops several SSH sessions from overwriting each other’s history, and saves commands even if the session is killed.
- ignoreboth keeps the history clean, and gives you a way to keep a command out of it (see below).
Run source ~/.bashrc to apply.
Keep secrets out of history
Commands with passwords or tokens end up in ~/.bash_history in plain text:
mysql -u root -pSuperSecret # bad: saved in history and visible in `ps`
Better options:
- Let the tool prompt you:
mysql -u root -p. - Use config files with restricted permissions (
~/.my.cnfwith mode 600), or environment files. - With
HISTCONTROL=ignorespaceorignoreboth, start the command with a space to keep it out of history.
Remove an entry that’s already there:
history | grep -n Secret
history -d 1234 # delete entry 1234 from memory
history -w # write the cleaned history to the file
history -c clears the whole in-memory history. Also check the file itself (~/.bash_history), and rotate the password. Treat a leaked credential as compromised.
History is not an audit log
Users can edit or clear their own history, and it only records interactive Bash. For real auditing on servers that need it, use auditd, sudo logging (/var/log/auth.log records every sudo command) or session recording tools. See sudo.
Root’s history and sudo -i
sudo -i and sudo su - give you root’s shell, so commands go to /root/.bash_history, not yours. Commands run as sudo cmd from your own shell go into your history, and into the auth log.
Quick reference
| Task | How |
|---|---|
| Search | Ctrl+R |
| Previous command | !! (or ↑) |
| With sudo | sudo !! |
| Last argument | !$ or Alt+. |
| By number | !123 |
| Replace and rerun | ^old^new |
| Timestamps | HISTTIMEFORMAT='%F %T ' |
| Don’t record | start with a space (ignorespace) |
| Delete entry | history -d N; history -w |