如何记录运行 zsh 命令的终端会话

如何记录运行 zsh 命令的终端会话

在 zsh 的历史文件中,所有命令都记录在所有的终端会话中。有没有办法记录命令是在哪个终端会话中运行的(即,这个 shell 实例的唯一标识符?)。

一个可能的用例是查看历史文件并确定在给定命令之前或之后运行的内容(仅限于此精确会话)。

答案1

如果你改变历史文件那么你就会给自己带来麻烦!

但是可以将命令记录到单独的文件中。您可以更改执行某行时执行的操作以包括记录当前行,然后您可以查阅该文件以获取所需的信息。

让我们首先定义一个可以记录当前行的函数然后执行它:

function log_and_accept {
    echo "$TTY $BUFFER" >> /tmp/log
    zle accept-line
}

现在 $TTY 是您当前 shell 的标识符,但它并不是您可能使用的唯一标识符。$TTY 是 /dev/pts/NUMBER 文件的路径。这里唯一的问题是,这个数字始终是下一个可用的数字,因此如果您关闭一个终端并打开另一个终端,那么您将重用相同的 tty 号码。

如果您不喜欢这样,那么也可以获取包含 shell 进程 ID 的路径(进程 ID 也可以重复使用,但这不太可能妨碍您 - 进程 ID 由所有进程使用,而 tty 只是终端)。这可以通过 /proc/self 符号链接轻松完成,它始终指向查看它的进程的进程文件夹。因此,要使用进程文件夹,上述函数将是:

function log_and_accept {
    process=/proc/self
    echo "${process:A} $BUFFER" >> /tmp/log
    zle accept-line
}

现在,一旦你决定了如何识别行,下一步就是用新函数替换默认行为。我们要替换的默认行为是 accept-line 函数,如果我们看一下zle 文档,你会看到 accept-line 与 ^J 和 ^M 绑定。

要将此功能绑定到这些字母,您首先需要将其变成一个小部件:

zle -N log_and_accept_widget log_and_accept

然后你可以绑定它,取代旧的行为:

bindkey '^J' log_and_accept_widget
bindkey '^M' log_and_accept_widget

现在 zsh 已支持多行,因此当您查阅此文件时,您可能会发现这些行最终不如您最初希望的那样清晰。以下是我在测试时生成的文件的一些输出:

/proc/19170 function log_and_accept {
shell=/proc/self
echo "${shell:A} $BUFFER" >> /tmp/log
zle accept-line
}
/proc/19170 echo woo
/proc/19170 cat /tmp/log

您可能希望在记录之前将 $BUFFER 传递给某种漂亮的打印机。

如果你在执行此操作时遇到问题,并且你确实希望恢复以前的行为,那么你可以使用以下命令恢复它:

bindkey '^J' accept-line
bindkey '^M' accept-line

尽管实际执行这些命令可能很……困难。

相关内容