bash 在不退出的情况下保存历史记录

Col*_*acX 24 bash linux-terminal ubuntu command-history

在 linux ubuntu bash 终端中。有没有办法在不写退出的情况下保存 bash 历史记录?我已将配置设置为“HISTCONTROL=erasedups”

在我看来,这比忽略的向上效果更好。

无论如何,它不会将最后几个命令保存在 bash 终端中,除非我输入“exit”。我习惯于点击终端窗口上的叉号,所以我总是很恼火,当我重新登录时,最后的命令没有保存。

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

小智 46

Bash 历史

在活动终端中发出的任何新命令都可以.bash_history使用以下命令附加到文件中:

history -a
Run Code Online (Sandbox Code Playgroud)

唯一需要理解的棘手概念是每个终端都有自己的 bash 历史列表.bash_history打开终端时从文件中加载)

如果要提取在此活动终端的生命周期内其他终端写入的任何新历史记录,可以将.bash_history 文件内容附加到活动 bash 历史记录列表中

history -c;history -r
Run Code Online (Sandbox Code Playgroud)

这将清除当前的历史列表,这样我们就不会得到重复的列表,并将历史文件附加到(现在是空的)列表中。

解决方案

您可以使用 bash 变量PROMPT_COMMAND在每个新提示下发出命令(每次在终端中按 Enter 键)

export PROMPT_COMMAND='history -a'
Run Code Online (Sandbox Code Playgroud)

这会将每个命令在发出时记录到历史文件中。

结果

现在,您打开的任何新终端都将拥有其他终端的历史记录,而无需使用exit其他终端。这是我首选的工作流程。

更精确

假设(出于某种原因)您有两个同时使用的终端,并且您希望每个新命令的历史记录都反映在两者之间。

export PROMPT_COMMAND='history -a;history -c;history -r'
Run Code Online (Sandbox Code Playgroud)

这里的主要缺点是您可能需要按 Enter 键重新运行 PROMPT_COMMAND,以便从对端终端获取最新历史记录。

您可以看到为什么这个更精确的选项可能有点矫枉过正,但它适用于该用例。


all*_*tic 1

一种方法可以将所有 bash 历史记录保存到单独的文件中,但是如果您尝试使用历史记录机制,并且由于某种原因它没有保存所有历史记录,那就是另一个问题了。

无论终端发生什么情况,始终将所有历史记录保存到单独的文件中

这里提供的脚本可以解决这个问题。

# 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"
Run Code Online (Sandbox Code Playgroud)

告诉历史命令“立即保存!” 单击虚拟终端窗口上的 X 时

首先你必须了解的是,你的虚拟终端模拟器使用什么机制在进程退出时杀死进程?bash-- 这将取决于您使用的具体终端模拟器。

有几个选项,它们都涉及UNIX 信号

  • SIGTERM、SIGINT、SIGQUIT:当 Bash 在交互模式下收到这些信号之一时,默认行为是忽略它,所以可能不是这样。

  • SIGHUP:此信号通常会导致 Bash 正常终止并进行清理,但我不确定该“清理”是否涉及保存历史文件。可能不会。

  • SIGKILL、SIGSTOP:Bash 作为用户空间进程不可能忽略这些信号。内核可以使用这些信号随时强制终止或停止进程。如果您的 VT 模拟器正在发送其中之一,我们无法捕获它并在退出之前执行某些操作,所以您不走运。

一些参考: ServerFault Question 337123

Unix 问题 6332

GNU Bash 手册中的交互式使用历史记录