捕获在我的 shell 中启动 运行 进程的命令

capture the command that launched the running process in my shell

我试着让 windows 在 GNU screen 中的标题自动等于工作目录的路径 PLUS 过程 运行ning 如果有的话(例如:npm startvim file.js

为此,我在我的 .zshrc 中添加了这些行:

precmd () {
  local action = action_to_define
  if [[ $TERM == screen* ]]; then
    printf -Pn '\ek%~ $action\e\'
  fi
}

这会(以某种方式)将路径作为标题发送到屏幕(参见 this post

和变量 action 将打印 运行ning 程序(如果存在)

我尝试了 local action= $(history | tail -1 | sed 's#[0-9 ]*##') 因为这个 select 历史上最后一个命令的提示(就像 history !! 会做如果选项 !! 被识别,这不是出于某种原因...)

local action= $(ps -lr | tail -1 | sed 's#^.*:...##')因为这个select运行ning进程的命令

但它不起作用,好像这个过程既没有被历史捕获也没有被ps...也许在动作启动之前precmd 运行,所以我尝试了其他功能,如 preexeczshaddhistory 没有任何运气......

precmd 挂钩仅在命令完成后 运行,就在显示下一个提示之前。因此它可用于更改显示提示时的终端标题。为了在命令为 运行 时更改终端标题,您需要 preexec 挂钩,即在命令被接受后 运行(在按下 Enter,就在命令之前 运行.

当在提示符下确认命令时,此命令将以三种形式作为参数传递给preexec

  1. 第一个参数是键入的字符串,包括任何 new-lines(只要历史记录机制处于活动状态,它通常是活动的)
  2. 第二个参数是单行,size-limited(如果太长,它会被截断)带有扩展别名的命令版本。
  3. 第三个参数是命令的全文,实际上是运行(带有扩展别名)

所以这应该可以解决问题:

preexec () {
  local action=""
  if [[ $TERM == screen* ]]; then
    printf -Pn '\ek%~ $action\e\'
  fi
}

由于precmd钩子只有运行,在提示下一个命令之前,可以简化为:

precmd () {
  if [[ $TERM == screen* ]]; then
    printf -Pn '\ek%~\e\'
  fi
}

虽然这不是它不起作用的主要原因,但重要的是要注意在 Zsh(和大多数其他 Unix shell)中 [=19= 之前或之后不能有 spaces ] 为参数赋值时。

确切的行为可能会有所不同,具体取决于您放置 space 的位置以及您使用的是 localset 之类的东西还是简单的赋值。

以问题中的代码为例:

  • = 前后放置 space 和 local 通常会导致 错误分配

    % local action = action_to_define
    zsh: bad assignment
    
  • 仅在 = 之后将 spaces 与 local 一起将分配一个空字符串给变量和 create/set 另一个空变量或导致上下文错误,取决于预期值是否是可行的参数名称:

     % local action= "echo" 
    

    这会清空 actionecho

     % local action= "echo foo"
     local: not valid in this context: echo foo
    

    此处 action 也被清空,但 local 之后失败,因为 echo foo 由于包含 space.[=30= 而不是一个可行的参数名称]