38

in linux ubuntu bash terminal. is there any way to save bash history without writing exit? i've set the config to "HISTCONTROL=erasedups"

which in my opinion works better than ignoredups.

anyways for some reason it wont save the last few commands in the bash terminal unless i type in "exit". I'm used to just click the cross on the terminal window, so i'm always annoyed that the last commands were not saved when i relogin.

reminder: http://www.thegeekstuff.com/2008/08/15-examples-to-master-linux-command-line-history/#more-130

1
  • when remote accessing the terminal from putty there is the option to choose close window on exit: always. which saves the history for me.
    – ColacX
    Feb 26, 2014 at 2:58

4 Answers 4

68

Bash History

Any new commands that have been issued in the active terminal can be appended to the .bash_history file with the following command:

history -a

The only tricky concept to understand is that each terminal has its own bash history list (loaded from the .bash_history file when you open the terminal)

If you want to pull any new history that's been written by other terminals during the lifetime of this active terminal, you can append the contents of the .bash_history file to the active bash history list

history -c;history -r

This will clear the current history list so we don't get a repeated list, and append the history file to the (now empty) list.

Solution

You can use the bash variable PROMPT_COMMAND to issue a command with each new prompt (every time you press enter in the terminal)

export PROMPT_COMMAND='history -a'

This will record each command to the history file as it is issued.

Result

Now any new terminal you open will have the history of other terminals without having to exit those other terminals. This is my preferred workflow.

More Precision

Let's say (for some reason) you have two terminals that you're using simultaneously and you want the history to reflect between both for each new command.

export PROMPT_COMMAND='history -a;history -c;history -r'

The main drawback here is that you may need to press enter to re-run the PROMPT_COMMAND in order to get the latest history from the opposite terminal.

You can see why this more precise option is probably overkill, but it works for that use case.

7
  • 1
    this is so awesome for proper workflows ....
    – matanox
    Aug 7, 2019 at 11:45
  • Carefull!!! I lost a script using history -c... it clears your current history and does not save it anywhere!
    – Ray Foss
    Apr 10, 2020 at 17:03
  • If you want to share the whole history between shells, I'd recommend using export PROMPT_COMMAND="history -a;history -n;$PROMPT_COMMAND" instead because it has better performance than -c followed by -r. For me just history -a is clearly the best option because it keeps separate history per shell but stores all commands in shared history file. Sep 22, 2021 at 8:35
  • history -a doesn't work for me on Mac OS Big Sur. It doesn't give any error, but ~/.bash_history file is not changed after this command. Can someone please help? Jan 19, 2022 at 23:07
  • you saved my thousands of rewriting same commands again in an unstable ssh connections.
    – edib
    May 5, 2023 at 14:36
3

To save bash history to file:

history -w ~/history.txt
vim ~/history.txt

It exports the history to a file called history.txt. You can then view it using your favorite editor.

Answer copied from http://tech.karbassi.com/2007/01/14/view-and-change-bash-history/

1

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

0

I have tmux sessions that run for days and I would like their histories saved, but a simple history -a will jumble up different histories together when using multiple terminals simultaneously.

An alternative to using different files is to save them periodically, so at least their histories are somewhat organized in continuous N+ minute blocks. The function below will append to the history every 15 minutes of use, so the history is a bit more consistent when frequently switching terminals.

# Append to bash history every few minutes - called from PROMPT_COMMAND
function append_history_periodically() {

    # update history every 15 minutes
    _BASH_UPDATE_PERIOD_SEC=$((15 * 60))

    if [ -z "${_BASH_HIST_LAST_UPDATE}" ]; then
        # time tracking not set - save current timestamp and return
        _BASH_HIST_LAST_UPDATE="$(date +%s)"
        return
    fi

    _BASH_NOW="$(date +%s)"
    _BASH_TIME_DIFF="$((_BASH_NOW - _BASH_HIST_LAST_UPDATE))"

    # append history and reset _BASH_HIST_LAST_UPDATE
    if [ "${_BASH_TIME_DIFF}" -gt "${_BASH_UPDATE_PERIOD_SEC}" ]; then
        history -a
        _BASH_HIST_LAST_UPDATE="${_BASH_NOW}"
    fi

    unset _BASH_TIME_DIFF
    unset _BASH_NOW

}
PROMPT_COMMAND='append_history_periodically'

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .