跟踪由Bash脚本调用的已执行程序

时间:2009-03-26 11:52:14

标签: linux bash scripting

脚本行为不端。我需要知道是谁调用了那个脚本,谁调用了调用脚本,等等,只能修改行为不端的脚本。

这类似于堆栈跟踪,但我对单个bash脚本中的函数调用的调用堆栈感兴趣。 相反,我需要由我的脚本启动的已执行程序/脚本链。

8 个答案:

答案 0 :(得分:15)

我几天前写的一个简单的脚本......

# FILE       : sctrace.sh
# LICENSE    : GPL v2.0 (only)
# PURPOSE    : print the recursive callers' list for a script
#              (sort of a process backtrace)
# USAGE      : [in a script] source sctrace.sh
#
# TESTED ON  :
# - Linux, x86 32-bit, Bash 3.2.39(1)-release

# REFERENCES:
# [1]: http://tldp.org/LDP/abs/html/internalvariables.html#PROCCID
# [2]: http://linux.die.net/man/5/proc
# [3]: http://linux.about.com/library/cmd/blcmdl1_tac.htm

#! /bin/bash

TRACE=""
CP=$$ # PID of the script itself [1]

while true # safe because "all starts with init..."
do
        CMDLINE=$(cat /proc/$CP/cmdline)
        PP=$(grep PPid /proc/$CP/status | awk '{ print $2; }') # [2]
        TRACE="$TRACE [$CP]:$CMDLINE\n"
        if [ "$CP" == "1" ]; then # we reach 'init' [PID 1] => backtrace end
                break
        fi
        CP=$PP
done
echo "Backtrace of '$0'"
echo -en "$TRACE" | tac | grep -n ":" # using tac to "print in reverse" [3]

......还有一个简单的测试。

test

我希望你喜欢它。

答案 1 :(得分:7)

~$ 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.

答案 2 :(得分:7)

您可以使用Bash Debugger http://bashdb.sourceforge.net/

或者,如前面的评论所述,内置了caller bash。请参阅:http://wiki.bash-hackers.org/commands/builtin/caller

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

另一种方法是更改​​PS4并启用xtrace:

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

答案 3 :(得分:6)

由于您说您可以编辑脚本本身,只需输入:

即可
ps -ef >/tmp/bash_stack_trace.$$

其中,问题正在发生。

这会在tmp目录中创建一些文件,这些文件在发生时显示整个进程列表。

然后,您可以通过检查此输出来确定哪个进程调用了哪个进程。这可以手动完成,也可以使用awk之类的功能自动完成,因为输出是常规的 -​​ 您只需使用PIDPPID列来计算所有进程之间的关系对此感兴趣。

您需要密切关注这些文件,因为每个进程都会有一个文件,因此可能需要对其进行管理。由于这是应该只在调试期间完成的事情,因此大多数时候该行将被注释掉(前面有#),因此不会创建文件。

要清理它们,您只需执行以下操作:

rm /tmp/bash_stack_trace.*

答案 4 :(得分:2)

<强>更新 下面的代码应该有效。现在我有一个newer answer,它有一个更新的代码版本,允许在堆栈跟踪中插入一条消息。

IIRC我当时也找不到这个答案来更新它。但现在决定代码更好地保存在git中,因此上面的最新版本应该在gist中。

以下原始代码更正的答案:

在某个地方还有另一个答案,但这里有一个函数用于获取堆栈跟踪,例如在java编程语言中使用。您调用该函数并将堆栈跟踪放入变量$ STACK中。它显示了导致get_stack被调用的代码点。这对于复杂的执行非常有用,其中单个shell会提供多个脚本片段和嵌套。

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
}

答案 5 :(得分:0)

在脚本中添加pstree -p -u`whoami`&gt;&gt;输出可能会为您提供所需的信息。

答案 6 :(得分:0)

最简单的脚本,它返回所有调用者的堆栈跟踪:

{
      headerName: "Rattachement",
      field: "rattachement",
      editable: true,
      headerTooltip:
        "Choisissez l'entité de rattachement parmi les choix présents dans la liste déroulante",
      cellEditor: "agSelectCellEditor",
      cellEditorParams: {
        values: [
          "",
          "Audit",
          "RA",
          "Consulting",
          "FA",
          "Tax&Legal",
          "ICS",
          "Taj"
        ]
      }
    }

答案 7 :(得分:-1)

您可以尝试类似

的内容
strace -f -e execve script.sh
相关问题