history command in bash, Linux
Posted on January 17, 2016 • 4 minutes • 818 words • Suggest Changes
This is one of those commands every sysadmin should read up on the manpage. I use history on a daily basis and recently I bumped onto a article with a nice find. Although I never stopped to think this was supposed to be out there : removing/filtering stuff from history. If you don’t know the command history, this is how it looks (part)
# history 988 php -v 989 which php 990 ll /usr/bin/php 991 ls -l /usr/bin/php 992 cat /var/log/messages 993 iptables -L 994 exit 995 iptables -L -n 996 iptables-save
While generally I prefer to have close to infinite history in Linux, when you just entered :
mysql -u root -pMYFANCYDIFFICULTPASSWORD main_database
You start to think, jee I hope nobody checks my history here… or
rm -rf *
I hope nobody just copy’s this in the root… -I know its a bad habit, don’t judge-. On the other hand I type ls, ll, pwd, cd,
about 15 times/minute when logged in to a console (I’m that sort of crazy). That is not really useful information to store.
So I was very happy to learn these new tricks with history
command in mind. First thing to do, is increase the total amount of commands saved, cause it happened that the commands I am searching for are just out of reach. Since this is low IO and storage these days is cheap, I don’t see a point not to increase it hugely. I changed HISTSIZE and HISTFILESIZE to 1000 and 10000.
changed in ~/.bashrc
HISTFILESIZE=10000 HISTSIZE=1000
Why two variables ? In short HISTSIZE is the in memory storage per session, while HISTFILESIZE is the “long term” storage. (source)
Another handy bash variable is HISTCONTROL; In the current version of GNU Bash (history is a part of GNU Bash), 3 options are available;
- ignorespace : when you enter a line starting with a space, its not saved in history
- ignoredups : when a command is repeated, only the first instance is saved
- erasedups : when a command is entered, it is checked with previous commands and those are removed. For example when running regular backups of MySQL with mysqldump only the latest mysqldump line is saved. (this makes it more of a “library”)
The ignore[space|dups] also have an alias ignoreboth.
I also added this to ~/.bashrc
HISTCONTROL=ignorespace:ignoredups:erasedups
When using history, an indication of when this command was issued could be useful. In case you wanne look what your drunken collegae did at three in the morning under root. This can be achieved with HISTTIMEFORMAT, again bash builtin variable, it internally calls a strftime() so you can setup how to visualize the date. I don’t care for seconds or years (to specific, to unspecific) So I left those out, note that you best end with a space, as it gets concatenated with the command.
HISTTIMEFORMAT="%H:%M %m/%d "
The last GNU Bash variable is HISTIGNORE, this filters out commands. I removed some that I know by heart, although ignoredups and erasedups are probably more then enough to catch most redundant commands. Its separated by colon.
HISTIGNORE="ls":"ll":"pwd":"free *"
This would filter out ls, ll (alias of ls -l) and pwd. The command free with flags would also be fully ignored (free -m, among the most known ones)
The last setting to play with is shopt this is the shell option “manager”. You wanne change _histappend _this will append the history to the history file, I don’t exactly know why this is not on by default. It occurred that multiple commands where gone from history, while I was certain I entered them. This might be a issue with multiple sessions overwriting one another. This might be “solved” with this. You can check for this option :
shopt | grep histappend
its either on or off, enabling or disabling can be done from console with :
# enable shopt -s histappend # disable shopt -u histappend
Although I just appended it to ~/.bashrc
That all being said, I found it a very useful find. However if you hit on the cases I described at the start of this article, removing a single line can be accomplished with :
history -d LINE_NUMBER
or if you wanne hide your tracks :
history -c
Will remove all history. (not recommended)
note : I tested this with GNU bash, version 4.1.2(1) your mileage might be different!
All together :
HISTFILESIZE=10000 HISTSIZE=1000 HISTCONTROL=ignorespace:ignoredups:erasedups shopt -s histappend
Update : I removed HISTIGNORE, as it also ignores “ls *” if you use arrow-up key. So there is no way to find the dir you just typed. I commonly use :
ls /data/ ls /data/somedir ls /data/somedir/with ls /data/somedir/with/something/
Typelog : “ls /dat”, tab, arrow up, som, tab arrow up, wit tab arrow up, som tab
some nice sources / examples of history :