bash 是否有在执行命令之前运行的钩子?

Gil*_*il' 129 bash command-line hook

在 bash 中,我可以安排一个函数在运行命令之前执行吗?

$PROMPT_COMMAND,它在显示提示之前执行,即在运行命令之后执行。

Bash 的$PROMPT_COMMAND功能类似于 zsh 的precmd功能;所以我要找的是一个相当于 zsh 的 bash preexec

示例应用程序:将您的终端标题设置为正在执行的命令;time在每个命令之前自动添加。

Gil*_*il' 106

不是本地的,但可以使用DEBUG陷阱破解它。此代码的设置preexecprecmd功能类似于 zsh。命令行作为单个参数传递给preexec.

这是设置precmd在运行每个命令之前执行的函数的代码的简化版本。

preexec () { :; }
preexec_invoke_exec () {
    [ -n "$COMP_LINE" ] && return  # do nothing if completing
    [ "$BASH_COMMAND" = "$PROMPT_COMMAND" ] && return # don't cause a preexec for $PROMPT_COMMAND
    local this_command=`HISTTIMEFORMAT= history 1 | sed -e "s/^[ ]*[0-9]*[ ]*//"`;
    preexec "$this_command"
}
trap 'preexec_invoke_exec' DEBUG
Run Code Online (Sandbox Code Playgroud)

这个技巧是由于Glyph Lefkowitz;感谢bcat找到原作者。

编辑。可以在此处找到 Glyph hack 的更新版本:https : //github.com/rcaloras/bash-preexec

  • 我尝试在 cygwin 上使用此代码。可悲的是,它在那里有相当强烈的性能影响——运行一个简单的基准命令`time for i in {1..10}; 做真实的;done` 通常需要 0.040 秒,激活 DEBUG 陷阱后需要 1.400 到 1.600 秒。它会导致每个循环执行两次 trap 命令 - 在 Cygwin 上,执行 sed 所需的分叉速度非常慢,单独进行分叉大约需要 0.030 秒(`echo` 内置和 `/bin/echo` 之间的速度差异)。也许要记住一些事情。 (2认同)
  • @kdb Cygwin fork 的性能很糟糕。我的理解是,这在 Windows 上是不可避免的。如果您需要在 Windows 上运行 bash 代码,请尝试减少分叉。 (2认同)

cYr*_*rus 25

您可以使用trap命令(来自help trap):

如果 SIGNAL_SPEC 是 DEBUG,则在每个简单命令之前执行 ARG。

例如,要动态更改终端标题,您可以使用:

trap 'echo -ne "\e]0;$BASH_COMMAND\007"' DEBUG
Run Code Online (Sandbox Code Playgroud)

这个来源。


dst*_*erg 15

它不是执行的 shell 函数,但我提供了一个$PS0提示字符串,该字符串在每个命令运行之前显示。详情请见:http : //stromberg.dnsalias.org/~strombrg/PS0-prompt/

$PS0包含在bash4.4 中,尽管大多数 Linux 需要一段时间才能包含 4.4 - 如果需要,您可以自己构建 4.4;在这种情况下,您可能应该将其放在 下/usr/local,将其添加到其中/etc/shells并添加chsh到其中。然后注销并重新登录,可能是ssh对自己@localhost 或su首先对自己进行测试。


小智 11

我最近不得不为我的一个副项目解决这个确切的问题。我制作了一个相当健壮和有弹性的解决方案,它模拟了 zsh 的 preexec 和 precmd 功能。

https://github.com/rcaloras/bash-preexec

它最初基于 Glyph Lefkowitz 的解决方案,但我已经对其进行了改进并将其更新。如果需要,很乐意提供帮助或添加功能。