一个脚本是行为不端。 我需要知道是谁调用了这个脚本,谁调用了这个调用脚本,等等,只能通过修改这个不正确的脚本。
这类似于堆栈跟踪,但是我对一个bash脚本中的函数调用堆栈不感兴趣。 相反,我需要由脚本启动的已执行程序/脚本链。
既然你说你可以编辑脚本本身,简单地把一个:
ps -ef >/tmp/bash_stack_trace.$$
在这个问题发生的地方。
这将在您的tmp
目录中创建许多文件,以便在发生时显示整个进程列表。
然后,您可以通过检查此输出来确定哪个进程调用了哪个其他进程。 这可以手动完成,也可以使用类似awk
自动化方式完成,因为输出是常规的 - 您只需使用这些PID
和PPID
列来计算您感兴趣的所有进程之间的关系。
您需要密切关注这些文件,因为每个进程都会得到一个文件,因此可能需要进行管理。 由于这是只能在调试过程中完成的,大多数时候该行会被注释掉(以#
),所以文件将不会被创建。
清理它们,你可以简单地做:
rm /tmp/bash_stack_trace.*
我前几天写的一个简单的脚本
# 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]
…和一个简单的测试。
我希望你喜欢它。
~$ 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.
你可以使用Bash调试器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.
更新:下面的代码应该工作。 现在我发现我有一个更新的代码版本的新答案 ,允许在堆栈跟踪中插入一条消息。
IIRC我只是无法找到这个答案来更新它,当时。 但现在决定的代码更好地保存在git中,所以最新版本的应该在这个要点 。
原码纠正的答案如下:
关于这个地方还有另外一个答案,但是这里有一个函数用于获取堆栈跟踪,例如用于java编程语言。 你调用这个函数,它把堆栈跟踪放入变量$ STACK。 它显示了导致get_stack
被调用的代码点。 这对于复杂的执行非常有用,其中单个外壳程序源多个脚本片段和嵌套。
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 }
在脚本中添加pstree -p -u`whoami` >>输出可能会为您提供所需的信息。
你可以尝试类似的东西
strace -f -e execve script.sh