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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/685435/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-17 20:47:07  来源:igfitidea点击:

Trace of executed programs called by a Bash script

linuxbashscripting

提问by flybywire

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 to a stack-trace, but I am notinterested in a call stack of function calls within a single bash script. Instead, I need the chain of executed programs/scripts that is initiated by my script.

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

采纳答案by paxdiablo

Since you say you can edit the script itself, simply put a:

既然你说你可以编辑脚本本身,只需输入:

ps -ef >/tmp/bash_stack_trace.$$

in it, where the problem is occurring.

在其中,出现问题的地方。

This will create a number of files in your tmpdirectory that show the entire process list at the time it happened.

这将在您的tmp目录中创建许多文件,显示发生时的整个进程列表。

You can then work out which process called which other process by examining this output. This can either be done manually, or automated with something like awk, since the output is regular - you just use those PIDand PPIDcolumns to work out the relationships between all the processes you're interested in.

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

You'll need to keep an eye on the files, since you'll get one per process so they may have to be managed. Since this is something that should only be done during debugging, most of the time that line will be commented out (preceded by #), so the files won't be created.

您需要密切关注文件,因为每个进程都会得到一个文件,因此可能需要对其进行管理。由于这应该只在调试期间完成,因此大多数情况下该行将被注释掉(以 开头#),因此不会创建文件。

To clean them up, you can simply do:

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

rm /tmp/bash_stack_trace.*

回答by Gian Paolo Ghilardi

A simple script I wrote some days ago...

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

# 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]
        TRACE="$TRACE [$CP]:$CMDLINE\n"
        if [ "$CP" == "1" ]; then # we reach 'init' [PID 1] => backtrace end
                break
        fi
        CP=$PP
done
echo "Backtrace of '
i=0; while caller $i ;do ((i++)) ;done
'" echo -en "$TRACE" | tac | grep -n ":" # using tac to "print in reverse" [3]

... and a simple test.

...和一个简单的测试。

test

测试

I hope you like it.

我希望你喜欢它。

回答by Mircea Vutcovici

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

您可以使用 Bash 调试器http://bashdb.sourceforge.net/

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

或者,正如前面的评论中提到的,caller内置的bash。请参阅:http: //wiki.bash-hackers.org/commands/builtin/caller

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
}

Or as a bash function:

或者作为 bash 函数:

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

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

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

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

回答by Juliano

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
}

回答by akostadinov

UPDATE:The code below should work. Now I have a newer answerwith 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.

IIRC 我当时也找不到这个答案来更新它。但是现在决定的代码最好保存在 git 中,所以上面的最新版本应该在这个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_stackbeing called. This is mostly useful for complicated execution where single shell sources multiple script snippets and nesting.

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

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

回答by Dominik

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

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

strace -f -e execve script.sh

回答by Brian Mitchell

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

在脚本中添加 pstree -p -u `whoami` >>output 可能会为您提供所需的信息。

回答by sigjuice

You could try something like

你可以尝试类似的东西

##代码##