Trace of executed programs called by a Bash script

后端 未结 8 1858
难免孤独
难免孤独 2020-12-13 14:44

A script is misbehaving. I need to know who calls that script, and who calls the calling script, and so on, only by modifying the misbehaving script.

This is similar

相关标签:
8条回答
  • 2020-12-13 15:04

    You can use Bash Debugger http://bashdb.sourceforge.net/

    Or, as mentioned in the previous comments, the caller bash built-in. See: http://wiki.bash-hackers.org/commands/builtin/caller

    i=0; while caller $i ;do ((i++)) ;done
    

    Or as a bash function:

    dump_stack(){
        local i=0
        local line_no
        local function_name
        local file_name
        while caller $i ;do ((i++)) ;done | while read line_no function_name file_name;do echo -e "\t$file_name:$line_no\t$function_name" ;done >&2
    }
    

    Another way to do it is to change PS4 and enable xtrace:

    PS4='+$(date "+%F %T") ${FUNCNAME[0]}() $BASH_SOURCE:${BASH_LINENO[0]}+ '
    set -o xtrace    # Comment this line to disable tracing.
    
    0 讨论(0)
  • 2020-12-13 15:06

    UPDATE: The code below should work. Now I have a newer answer with a newer code version that allows a message inserted in the stacktrace.

    IIRC I just couldn't find this answer to update it as well at the time. But now decided code is better kept in git so latest version of the above should be in this gist.

    original code-corrected answer below:

    There was another answer about this somewhere but here is a function to use for getting stack trace in the sense used for example in the java programming language. You call the function and it puts the stack trace into the variable $STACK. It show the code points that led to get_stack being called. This is mostly useful for complicated execution where single shell sources multiple script snippets and nesting.

    function get_stack () {
       STACK=""
       # to avoid noise we start with 1 to skip get_stack caller
       local i
       local stack_size=${#FUNCNAME[@]}
       for (( i=1; i<$stack_size ; i++ )); do
          local func="${FUNCNAME[$i]}"
          [ x$func = x ] && func=MAIN
          local linen="${BASH_LINENO[(( i - 1 ))]}"
          local src="${BASH_SOURCE[$i]}"
          [ x"$src" = x ] && src=non_file_source
    
          STACK+=$'\n'"   "$func" "$src" "$linen
       done
    }
    
    0 讨论(0)
  • 2020-12-13 15:06

    The simplest script which returns a stack trace with all callers:

    i=0; while caller $i ;do ((i++)) ;done
    
    0 讨论(0)
  • 2020-12-13 15:08

    You could try something like

    strace -f -e execve script.sh
    
    0 讨论(0)
  • 2020-12-13 15:12
    ~$ help caller
    caller: caller [EXPR]
        Returns the context of the current subroutine call.
    
        Without EXPR, returns "$line $filename".  With EXPR,
        returns "$line $subroutine $filename"; this extra information
        can be used to provide a stack trace.
    
        The value of EXPR indicates how many call frames to go back before the
        current one; the top frame is frame 0.
    
    0 讨论(0)
  • 2020-12-13 15:21

    adding pstree -p -u `whoami` >>output in your script will probably get you the information you need.

    0 讨论(0)
提交回复
热议问题