9 bash command-history text-processing date
我使用一个简单的别名在一个或多个终端窗口中启用“跟踪”命令:
alias trackmi='export PROMPT_COMMAND="history -a; $PROMPT_COMMAND"'
Run Code Online (Sandbox Code Playgroud)
然后我只是在工作区的另一个终端中使用tail -f我的.bash_history文件来获得即时反馈。我刚刚启用了无限历史记录 并export HISTTIMEFORMAT="[%F %T] "在.bashrc 中更新了我的历史记录格式 ( ) 。当然,该history命令会显示时间戳。但是历史文件本身的格式是:
#1401234303
alias
#1401234486
cat ../.bashrc
Run Code Online (Sandbox Code Playgroud)
如何转换 Unix 时间并将整个命令显示在一行中,就像history命令一样,包括编号:
578 [2014-05-27 19:45:03] alias
579 [2014-05-27 19:48:06] cat ../.bashrc
Run Code Online (Sandbox Code Playgroud)
......并遵循这一点。还是想办法把history命令的输出连续输出到终端?
使用 GNU awk:
tail -fn+1 ~/.bash_history | awk '
/^#/{printf "%-4d [%s] ", ++n, strftime("%F %T", substr($0, 2)); next}; 1'
Run Code Online (Sandbox Code Playgroud)
这是在分屏 xterm 上运行的最终产品,从基本上 shell 默认到仅使用几个命令:

比屏幕截图中展示的更粗略的方法可能如下所示:
PS1='$( { date ; fc -l -0 ; } >${TGT_PTY} )'$PS1
Run Code Online (Sandbox Code Playgroud)
在您想要输出的屏幕上实际运行交互式 shell 时,${TGT_PTY}您从tty命令中得到的任何内容。或者,实际上,您可以使用任何可写文件,因为它本质上只是文件重定向的目标。
我对伪终端使用pty语法,因为我假设它是某种类型的 xterm,但您可以轻松地将 vt 用于 - 而且您的流式历史记录始终只是一个关键组合。如果是我,我可能会将这两个概念结合起来,并在专用 vt 上创建一个或会话......但我离题了。CTRL-ALT-Fnscreentmux
在新启动的机器上,我会在/bin/login典型的 Linuxgetty控制台上看到典型的提示。我按下CTRL-ALT-F2访问一个不太典型的kmscon控制台,它的行为更像一个而xterm不是一个tty。我输入命令tty并收到响应/dev/pts/0。
通常,xterms 使用伪终端将单个终端设备多路复用为多个——因此,如果您在 X11 中通过在终端选项卡或窗口之间切换来做类似的事情,您可能也会收到类似的输出/dev/pts/[0-9]*。但是通过CTRL-ALT-Fn组合键访问的虚拟终端控制台是真正的(er)终端设备,因此会收到自己的/dev/tty[0-9]*指定。
这就是为什么当我tty在提示下输入时登录控制台 2 后,响应是,/dev/pts/0但是当我在控制台 1 上执行相同操作时,输出是/dev/tty1. 无论如何,回到控制台 2 我然后做:
bash
PS1='$( { date ; fc -l -0 ; } >/dev/tty1 )'$PS1
Run Code Online (Sandbox Code Playgroud)
没有明显的效果。我继续输入更多命令,然后CTRL-ALT-F1再次按下切换到控制台 1 。在那里,我发现重复的条目看起来像<date_time>\n<hist#>\t<hist_cmd_string>我在控制台 2 上键入的每个命令。
但是,除非直接写入终端设备,否则另一种选择可能类似于:
TGT_PTY=
mkfifo ${TGT_PTY:=/tmp/shell.history.pipe}
{ echo 'OPENED ON:'
date
} >${TGT_PTY}
Run Code Online (Sandbox Code Playgroud)
然后也许...
less +F ${TGT_PTY}
Run Code Online (Sandbox Code Playgroud)
粗略的提示命令不符合您的规范 - 没有格式字符串,date也没有格式选项fc- 但它的机制不需要太多:每次您的提示呈现最后一个历史命令时,当前日期和时间都被写出到${TGT_PTY}您指定的文件。就这么简单。
fc查看和打印 shell 历史记录是其主要目的。它是一个内置的外壳,即使date不是。Inzsh fc可以提供各种花哨的格式选项,其中一些适用于时间戳。当然,正如你上面提到的,bash'shistory可以做同样的事情。
为了更清晰的输出,您可以使用我在此处更好地解释的技术在当前 shell 中设置持久跟踪变量,尽管必须跟踪它并在提示序列中的子 shell 中处理它。
这是一种根据您的规格进行格式化的便携式方法:
_HIST() { [ -z ${_LH#$1} ] ||
{ date "+${1}%t[%F %T]"
fc -nl -0
} >${TGT_PTY}
printf "(_LH=$1)-$1"
}
: "${_LH=0}"
PS1='${_LH##*[$(($(_HIST \!)))-9]}'$PS1
Run Code Online (Sandbox Code Playgroud)
我实现了只跟踪最新更新的last_history计数器$_LH,这样你就不会两次写出相同的历史命令——例如只是按回车键。要在当前 shell 中使变量递增,因此需要进行一些争论,以便即使在子 shell 中调用该函数时它仍保留其值 - 再次在链接中更好地解释了这一点。
它的输出看起来像 <hist#>\t[%F %T]\t<hist_cmd>\n
但这只是完全便携的版本。有了bash它,只需实现 shell 内置函数就可以做到这一点——当您考虑到这是一个每次按下时都会运行的命令时,这可能是可取的[ENTER]。这里有两种方法:
_HIST() { [ -z ${_LH#$1} ] || {
printf "${1}\t[%(%F %T)T]"
fc -nl -0
} >${TGT_PTY}
printf "(_LH=$1)-$1"
}
PROMPT_COMMAND=': ${_LH=0};'$PROMPT_COMMAND
PS1='${_LH##*[$(($(_HIST \!)))-9]}'$PS1
Run Code Online (Sandbox Code Playgroud)
或者,使用bash'shistory命令,您可以通过_HIST以下方式定义函数:
_HIST() { [ -z ${_LH#$1} ] ||
HISTTIMEFORMAT="[%F %T]<tab>" \
history 1 >${TGT_PTY}
printf "(_LH=$1)-$1"
}
Run Code Online (Sandbox Code Playgroud)
任一方法的输出也如下所示:<hist#>\t[%F %T]\t<hist_cmd>\n尽管该history方法包含一些前导空格。尽管如此,我相信该history方法的时间戳会更准确,因为我认为他们不需要等待引用的命令完成才能获取他们的戳记。
在这两种情况下,您都可以避免跟踪任何状态,只要您以某种方式过滤流uniq-mkfifo正如我之前提到的那样。
但是在这样的提示中这样做意味着它总是只在需要时才更新,仅通过更新提示的操作即可。这很简单。
你也可以做一些类似于你正在做的事情,tail而是设置
HISTFILE=${TGT_PTY}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3118 次 |
| 最近记录: |