There is a way to save all your bash history to a separate file, but if you are trying to use the history mechanism and for some reason it is not saving all of your history, that is a different issue.
To save all your history to a separate file, always, no matter what happens to the terminal
A script provided here does the trick.
# don't put duplicate lines in the history. See bash(1) for more options
# ... and ignore same sucessive entries.
export HISTCONTROL=ignoreboth
# set the time format for the history file.
export HISTTIMEFORMAT="%Y.%m.%d %H:%M:%S "
# If this is an xterm set the title to user@host:dir
case "$TERM" in
xterm*|rxvt*)
# Show the currently running command in the terminal title:
# http://www.davidpashley.com/articles/xterm-titles-with-bash.html
show_command_in_title_bar()
{
case "$BASH_COMMAND" in
*\033]0*)
# The command is trying to set the title bar as well;
# this is most likely the execution of $PROMPT_COMMAND.
# In any case nested escapes confuse the terminal, so don't
# output them.
;;
*)
if test ! "$BASH_COMMAND" = "log_bash_eternal_history"
then
echo -ne "\033]0;$(history 1 | sed 's/^ *[0-9]* *//') :: ${PWD} :: ${USER}@${HOSTNAME}\007"
fi
;;
esac
}
trap show_command_in_title_bar DEBUG
;;
*)
;;
esac
log_bash_eternal_history()
{
local rc=$?
[[ $(history 1) =~ ^\ *[0-9]+\ +([^\ ]+\ [^\ ]+)\ +(.*)$ ]]
local date_part="${BASH_REMATCH[1]}"
local command_part="${BASH_REMATCH[2]}"
if [ "$command_part" != "$ETERNAL_HISTORY_LAST" -a "$command_part" != "ls" -a "$command_part" != "ll" ]
then
echo $date_part $HOSTNAME $rc "$command_part" >> ~/.bash_eternal_history
export ETERNAL_HISTORY_LAST="$command_part"
fi
}
PROMPT_COMMAND="log_bash_eternal_history"
To tell the history command "Save now!" when clicking the X on a virtual terminal window
First what you have to understand is, what mechanism does your virtual terminal emulator use to kill the bash process when it exits? -- This will depend on what exact terminal emulator you are using.
There are a few options, and all of them involve UNIX signals.
SIGTERM, SIGINT, SIGQUIT: The default behavior when Bash receives one of these signals in interactive mode is to ignore it, so it's probably not that.
SIGHUP: This signal ordinarily causes Bash to terminate gracefully and do cleanup, but I'm not sure if that "cleanup" involves saving the history file. It probably doesn't.
SIGKILL, SIGSTOP: It is impossible for Bash as a userspace process to ignore these signals. The kernel can forcibly kill or stop the process at any time using these signals. If your VT emulator is sending one of these, we can't trap it and do something before exiting, so you're out of luck.
A few references:
ServerFault question 337123
Unix question 6332
Using History Interactively in the GNU Bash manual