2

I have a complicated mechanism built into my bash environment that requires the execution of a couple scripts when the prompt is generated, but also when the user hits enter to begin processing a command. I'll give an oversimplified description:

The debug trap does this in a fairly limited way: it fires every time a statement is executed.

trap 'echo $BASH_COMMAND' DEBUG  # example only

Unfortunately, this means that when I type this:

sleep 1; sleep 2; sleep 3

rather than processing a $BASH_COMMAND that contains the entire line, I get the three sleeps in three different traps. Worse yet:

sleep 1 | sleep 2 | sleep 3

fires all three as the pipe is set up - before sleep 1 even starts executing, the output might lead you to believe that sleep 3 is running.

I need a way to execute a script right at the beginning, processing the entire command, and I'd rather it not fire when the prompt command is run, but I can deal with that if I must.

  • Good question. But more programming oriented so it should go to StackOverflow. – JakeGould Dec 3 '14 at 2:14
3

Not very pretty, but if you really need this you could use PROMPT_COMMAND in addition to the debug trap to get rid of the extra calls:

trap 'debug_hook' DEBUG

debug_hook()
{ 
  [ -n "$debug_hook_on" ] || return 
  debug_hook_on="" 
  echo hook             # cmds to run ...
}

PROMPT_COMMAND='debug_hook_on=1'

Now:

$ echo 1 ; echo 2 | cat
hook
1
2

We still don't have access to the whole input line however: $BASH_COMMAND is just echo 1.


Another idea inspired by this article is to use readline bindings to get access to the whole line:

$ bind -x '"\C-o":hook'
$ hook(){ echo "hook: $READLINE_LINE";  }
$ bind 'RETURN: "\C-o\n"'

Now it works:

hook: echo 1; echo 2
$ echo 1; echo 2
1
2

One thing to keep in mind though: for multi-line input it'll get invoked once for each line which may not be what you want (could use a combination of both approaches then).

  • I eventually wound up calling history from the trap handler and grabbing the most recent command line. Along the way, I learned to NEVER background a process in a trap handler. Even if you disown the process, the trap will not return until the subprocess has terminated. – Sniggerfardimungus Dec 10 '14 at 0:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.