1

My aim is to do something before every user-defined function executed. The most straightforward method coming to my head is to use trap to debug signal.

The pilot script run quite well:

#! /bin/env bash

function welcome { echo "Welcome :)"; }

trap 'declare -F ${BASH_COMMAND%% *} >/dev/null && \
      echo "[Running] ${BASH_COMMAND%% *}"' DEBUG

welcome
## will output:
# [Running] welcome
# Welcome :)

Since I want trap every user-defined function, 'functrace' option should be turned on. However, once 'functrace' is on, it seems that trap will be evoked twice. For example:

#! /bin/env bash
set -o functrace

function welcome { echo "Welcome :)"; }

trap 'declare -F ${BASH_COMMAND%% *} >/dev/null && \
      echo "[Running] ${BASH_COMMAND%% *}"' DEBUG

welcome
## will output:
# [Running] welcome
# [Running] welcome
# Welcome :)

So, what is the problem with my script or bash? How to distinguish these two evocation?

  • DEBUG trap is also run before $PROMPT_COMMAND if set. – Tom Hale Apr 23 '17 at 6:24
2

I've just hit this issue as well. It's hard to say exactly what is going on, but it seems the second invocation triggers within the context of the function being called, so you could do:

! /bin/env bash
set -o functrace

function welcome { echo "Welcome :)"; }


function __debug_trap {
  declare -F ${BASH_COMMAND%% *} >/dev/null
  # funcname[0] is __debug_trap; funcname[1] is the next function on stack
  if ! [[ "${BASH_COMMAND%% *}" == "${FUNCNAME[1]}" ]]; then
    echo "[Running] ${BASH_COMMAND%% *}"
  fi
}

trap __debug_trap DEBUG

welcome
echo not in function

#bash test.sh
#[Running] welcome
#[Running] echo
#Welcome :)
#[Running] echo
#not in function

The main remaining issue is that this will incorrectly suppress directly recursive calls; but those are not common in bash.

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.