Linux – BASH history truncated to 500 lines on each login

bashhistorylinuxshellterminal

For some reason, I cannot get my system to keep my BASH history after a reboot. Here are the relevant sections of my ~/.bashrc:

shopt -s histappend
PROMPT_COMMAND='history -a; updateWindowTitle'
export HISTCONTROL=ignoredups
export HISTSIZE=9999
export HISTFILESIZE=999999
export HISTFILE="$HOME/.bash_history"

As far as I can tell those are all the necessary options (I know I used to be able to keep history across multiple reboots without all of these in the past). However, despite having added these options several reboots ago, I still loose most of my history after a reboot. It is not empty, but it does not have the 9999 lines I had before rebooting.

Before anyone complains, yes I have read these questions. I have implemented some of their suggestions as listed above, the rest were either unhelpful or not relevant:

On the off chance that there may be other relevant commands in there, you can view my entire ~/.bashrc here.

So, what am I missing? Why is my history not saved? If anyone thinks another file may be relevant let me know and I'll post it. I checked by running grep -i hist \.* in my $HOME which showed that the only relevant . file containing the string hist or HIST was .bashrc.

I am running Linux Mint Debian Edition, GNU bash, version 4.2.36(1)-release (x86_64-pc-linux-gnu) and my favorite terminal emulator (in case that's relevant) is terminator.


UPDATE:

Following @mpy's suggestion in the comments, I changed my ~/.bashrc to set HISTFILE=~/bash_history as opposed to the default ~/.bash_history and that seems to solve the problem for interactive shells. Login shells still display the same behavior, with the history truncated at 500 lines. However, there are no HIST related variables set in the relevant files:

$ for f in /etc/profile ~/.profile ~/.bash_profile ~/.bash_login; do \
   echo -ne "$f :"; echo `grep HIST $f`; \
done
/etc/profile :
/home/terdon/.profile :grep: /home/terdon/.profile: No such file or directory
/home/terdon/.bash_profile :grep: /home/terdon/.bash_profile: No such file or directory
/home/terdon/.bash_login :grep: /home/terdon/.bash_login: No such file or directory
$ grep -r HIST /etc/profile.d/  <-- returns nothing

So, why is setting HISTSIZE and HISTFILESIZE in the ~/.bashrc not enough unless I explicitly set the $HISTFILE to something other than the default ~/.bash_history?

Best Answer

The problem actually boils down to the different behavior of login and non-login shells. I had set the variables that control history in my ~/.bahsrc. This file is not read when one starts a login shell, it's only read by interactive, non-login shells (from man bash):

When bash is invoked as an interactive login shell, or as a non-interactive shell with the --login option, it first reads and executes commands from the file /etc/profile, if that file exists. After reading that file, it looks for ~/.bash_profile, ~/.bash_login, and ~/.profile, in that order, and reads and executes commands from the first one that exists and is readable. The --noprofile option may be used when the shell is started to inhibit this behavior.

[. . . ]

When an interactive shell that is not a login shell is started, bash reads and executes commands from ~/.bashrc, if that file exists. This may be inhibited by using the --norc option. The --rcfile file option will force bash to read and execute commands from file instead of ~/.bashrc.

Therefore, each time I logged in, or dropped to a tty, or used ssh, the .history file was getting truncated because I had not set it to the right size in ~/.profile as well. I finally realized this and simply set the variables in ~/.profile where they belong, instead of ~/.bashrc

So, the reason my ~/.history was getting truncated was because I had only set the HISTORY variables in a file read by interactive, non-login shells and therefore every time I ran a different type of shell the variables would be ignored and the file would be cut accordingly.