如何设置 zsh 将历史记录附加到按日期动态命名的文件中

如何设置 zsh 将历史记录附加到按日期动态命名的文件中

我从 bash 转到 zsh 最大的难点是历史配置。使用 oh-my-zsh 时,我发现 #ZSH/lib 中有一个 history.zsh 文件(我认为)可以通过unsetopt share_history.zshrc 禁用它。

我只想模仿我的 bash 历史记录设置,该设置使用 PROMPT_COMMAND bash 环境,该环境在每次交互操作(输入命令)后运行。我发现这里zsh 有一个名为的钩子precmd,有点类似。

下面是我自定义的 bash 历史记录设置,它将历史记录写入 ~/.logs 目录中当前日期的文件,即bash-history-2020-10-27.log


    # Saving history to file
    export PROMPT_COMMAND='if [ "$(id -u)" -ne 0 ]; then echo "$(date "+%Y-%m-%d.%H:%M:%S") $(pwd) $(history 1)" >> ~/.logs/bash-history-$(date "+%Y-%m-%d").log; fi'
    
    export HISTSIZE=100000
    export HISTTIMEFORMAT="%d/%m/%y %T  "
    # Avoid duplicates
    export HISTCONTROL=ignoredups:erasedups  
    # When the shell exits, append to the history file instead of overwriting it
    #shopt -s histappend
    
    # After each command, append to the history file and reread it
    export PROMPT_COMMAND="${PROMPT_COMMAND:+$PROMPT_COMMAND$'\n'}history -a; history -c; history -r"

修改后的 zsh 版本如下所示。此配置位于 $ZSH_CUSTOM 目录中。


    # Saving history to file
    setopt INC_APPEND_HISTORY
    setopt EXTENDED_HISTORY
    setopt HIST_FIND_NO_DUPS
    setopt HIST_IGNORE_ALL_DUPS
    unsetopt share_history
    
    export HISTSIZE=1000000000
    export HISTFILESIZE=1000000000
    export HISTTIMEFORMAT="%d/%m/%y %T  "
    
    # Functions
    precmd() { eval 'if [ "$(id -u)" -ne 0 ]; then echo "$(date "+%Y-%m-%d.%H:%M:%S") $(pwd) $(history 1)" >> ~/.logs/zsh-history-$(date "+%Y-%m-%d").log; fi' }

它确实会将内容写入 .logs 目录中名为日期的文件中,但是zsh-history-2020-10-27.log我的时间戳和当前目录格式并未在文件中利用,即:

    9  ls -a
   10  vi .zshrc
   11  cd Dev
   12  ls

当 bash 设置如下方式写入文件时:

2018-10-30.10:27:56 /Users/raysmets/dev/nexkey/nk-backend   201  30/10/18 10:27:56  git st
2018-10-30.10:27:59 /Users/raysmets/dev/nexkey/nk-backend   209  30/10/18 10:27:58  git log
2018-10-30.10:28:59 /Users/raysmets/dev/nexkey/nk-backend   202  30/10/18 10:28:59  git st

此外,在创建日期文件时,只会写入整个 .zsh_history 文件,而不会增量写入 shell 中输入的最后一个命令。我的意思是,10/28 的 shell 日志包含 10/27 的所有日志,而 10/27 又包含 10/26 的所有 shell 日志……这并不理想。

想知道是否有人更熟悉 zsh 和 oh-my-zsh 配置可以帮助我?我将不胜感激!我喜欢将时间戳 shell 日志写入日历日期文件,然后使用别名函数进行搜索的流程。如果有人感兴趣,以下是我在 bash 设置中使用的一个:


    alias s='search'
    search() {
       ls -rt ~/.logs/*.log | xargs grep -rnw "$1"
    }

也很想知道您推荐的替代 zsh 历史记录设置,以及它们如何更好地按日期进行分段。谢谢!

我目前的工作还算顺利,但仍然不够理想。我使用的是原生的 oh-my-zsh 历史功能,它有时间,但它只是将所有内容转储到一个平面文件中,没有当前目录信息。

alias s='search'
search() {
   omz_history -i | grep "$1"
}

输出的结果类似如下:

 2992  2020-11-13 15:56  terraform init
 3000  2020-11-13 16:03  cd .terraform.d
 3016  2020-11-13 16:24  mkdir terraform-modules

答案1

我不确定您看到的问题是什么。

在 bash 中,有一个方便的结构,可以使通用命令按提示运行(也可以看看

function prompt_command {
  export PS1=$(~/bin/bash_prompt)
}
export PROMPT_COMMAND=prompt_command

然后编写一个脚本(用 bash、perl、ruby 等语言),并将其放置在~/bin/bash_prompt.

在 zsh 中,你可以使用任何选项这里。也许你的问题在于引号和双引号的使用。

有关的:

  1. https://unix.stackexchange.com/questions/479592/zsh-consistent-history-between-machines
  2. https://unix.stackexchange.com/questions/432379/in-zsh-where-are-precmd-functions-defined

答案2

尝试使用 history -1 而不是 history 1

像这样:

precmd() { eval '如果 [ "$(id -u)" -ne 0 ]; 然后 echo "$(date "+%Y-%m-%d.%H:%M:%S") $(pwd) $(history -1)" >> ~/.logs/zsh-history-$(date "+%Y-%m-%d").log; fi' }

答案3

这似乎适用于 zsh。它会检查重复项,因此当您多次按下 Enter 键时,它不会记录重复项。

# 将历史记录保存到文件
设置选项 INC_APPEND_HISTORY
设置选项 EXTENDED_HISTORY
设置 HIST_FIND_NO_DUPS
setopt HIST_IGNORE_ALL_DUPS
unsetopt share_history

导出 HISTSIZE=1000
导出 HISTFILESIZE=1000
导出 HISTTIMEFORMAT="%d/%m/%y %T "

__last_history=$(历史-1)

前置命令() {
  如果 [ "$(id -u)" -ne 0 ] && [ "$__last_history" != "$(history -1)" ]; 然后
    __last_history=$(历史-1)
    回显“$(date“+%Y-%m-%d.%H:%M:%S”)$(pwd)$__last_history”>>\
      ~/.logs/zsh-history-$(date "+%Y-%m-%d").log;
}

相关内容