0

我在我的 bash 环境中内置了一个复杂的机制,它需要在生成提示时执行几个脚本,而且当用户按 Enter 开始处理命令时也需要执行。我将给出一个过于简单的描述:

调试陷阱以相当有限的方式执行此操作:每次执行语句时都会触发。

trap 'echo $BASH_COMMAND' DEBUG  # example

不幸的是,这意味着当我输入以下内容时:

sleep 1; sleep 2; sleep 3

我没有处理$BASH_COMMAND包含整行的 a ,而是在三个不同的陷阱中获得了三个睡眠。更糟糕的是:

sleep 1 | sleep 2 | sleep 3

在设置管道时触发所有三个 - 在sleep 1开始执行之前,输出可能会让您相信 sleep 3 正在运行。

我需要一种从一开始就执行脚本的方法,处理整个命令,并且我希望它在运行提示命令时不触发,但如果必须,我可以处理。

4

1 回答 1

0

这个解决方案存在一个主要问题。带有管道 (|) 的命令将完成陷阱的执行,但在陷阱期间后台处理进程将导致命令的处理冻结 - 如果不点击 ^C,您将永远不会收到提示。陷阱完成,但 $PROMPT_COMMAND 从未运行。即使您在后台处理后立即放弃该过程,此问题仍然存在。

这最终比我预期的更有趣:

LOGFILE=~/logfiles/$BASHPID

start_timer() {
  if [ ! -e $LOGFILE ]; then
    #You may have to adjust this to fit with your history output format:
    CMD=`history | tail -1 | tr -s " " | cut -f2-1000 -d" "`
    #timer2 keeps updating the status line with how long the cmd has been running
    timer2 -p "$PROMPT_BNW $CMD" -u -q & echo $! > $LOGFILE
  fi
}

stop_timer() {
  #Unfortunately, killing a process always prints that nasty confirmation line,
  #and you can't silence it by redirecting stdout and stderr to /dev/null, so you
  #have to disown the process before killing it. 
  disown `cat $LOGFILE`
  kill -9 `cat $LOGFILE`
  rm -f $LOGFILE
}

trap 'start_timer' DEBUG
于 2014-12-03T21:57:55.010 回答