在bash:处理每个命令行而不使用调试陷阱?

时间:2014-12-03 17:57:08

标签: bash debugging command-line shell-trap

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

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

trap 'echo $BASH_COMMAND' DEBUG  # example

不幸的是,这意味着当我输入时:

sleep 1; sleep 2; sleep 3

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

sleep 1 | sleep 2 | sleep 3
管道设置时

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

我需要一种方法来在开始时执行脚本,处理整个命令,而且在运行prompt命令时我不会触发,但如果必须,我可以处理它。

1 个答案:

答案 0 :(得分:0)

这个解决方案存在一个主要问题。带管道的命令(|)将完成执行陷阱,但是在陷阱过程中的背景将导致命令的处理冻结 - 你永远不会在没有点击的情况下获得提示。陷阱完成,但$ 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