Подтвердить что ты не робот

Трассировка исполняемых программ, вызываемых скриптом Bash

A script является неправильным. Мне нужно знать, кто называет этот script, и который вызывает вызывающий script и т.д., Только путем изменения недопустимого script.

Это похоже на трассировку стека, но меня не интересует стек вызовов вызовов функций в пределах одного bash script. Вместо этого мне нужна цепочка исполняемых программ/скриптов, инициированная моим script.

4b9b3361

Ответ 1

Поскольку вы говорите, что можете редактировать сам script, просто поместите a:

ps -ef >/tmp/bash_stack_trace.$$

в нем, где возникает проблема.

Это создаст несколько файлов в вашем каталоге tmp, которые покажут весь список процессов в момент его возникновения.

Затем вы можете определить, какой процесс называется другим процессом, изучив этот вывод. Это можно сделать вручную или автоматизировать с помощью чего-то вроде awk, так как выход является регулярным - вы просто используете те столбцы PID и PPID, чтобы выработать отношения между всеми интересующими вас процессами.

Вам нужно следить за файлами, так как вы получите один на каждый процесс, поэтому им, возможно, придется управлять. Поскольку это то, что нужно делать только во время отладки, большую часть времени, когда эта строка будет прокомментирована (ей предшествует #), поэтому файлы не будут созданы.

Чтобы очистить их, вы можете просто сделать:

rm /tmp/bash_stack_trace.*

Ответ 2

Простой script, который я написал несколько дней назад...

# 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

Надеюсь, вам понравится.

Ответ 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.

Ответ 4

Вы можете использовать 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 и включить xxt:

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

Ответ 5

ОБНОВЛЕНИЕ: приведенный ниже код должен работать. Теперь у меня есть более новый ответ с более новой версией кода, которая позволяет вводить сообщение в стеке.

IIRC Я просто не мог найти этот ответ, чтобы обновить его в то время. Но теперь принятый код лучше держать в git, поэтому последняя версия выше должна быть в этом контексте.

исходный код, скорректированный ниже:

Был еще один ответ об этом, но вот функция, используемая для получения трассировки стека в том смысле, который используется, например, на языке 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
}

Ответ 6

добавление вывода pstree -p -u `whoami` → в ваш script, вероятно, даст вам необходимую вам информацию.

Ответ 7

Самый простой скрипт, который возвращает трассировку стека со всеми вызывающими:

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

Ответ 8

Вы можете попробовать что-то вроде

strace -f -e execve script.sh