У меня есть довольно большой набор сценариев, которые являются начальной частью создания некоторой логики отладки/регистрации для сценариев bash. В системе имеется значительное количество кода. К счастью, я могу продемонстрировать различные результаты, которые я не могу объяснить, когда скрипт запускает +u и -u. Установить переменные как проверенные с помощью +u, которые становятся неустановленными переменными при запуске с -u. Имя переменной в этом случае $FUNCNAME.
Краткий тестовый сценарий выглядит следующим образом:
#!/бин/баш
### установить -e
### установить -f
### установить -у
### установить -C
### установить -P
### set -o pipefail
экспорт PS4='+:${BASH_SOURCE[0]}:${FUNCNAME[0]}:${LINENO[0]}::x:: '
установить -o подробный
# Разделитель полей vXtrap u0081 (плюс/минус)
### экспорт vXtrapLFS='\v'
# замена BASH_SUBSHELL
экспортировать vXtrapSub=()
# замена BASH_SOURCE
экспортировать vXtrapSrc=()
# скрипт замены
# базовое имя "${vXtrapSub[$lIdx]}}" '.sh'
экспортировать vXtrapScr=()
# замена FUNCNAME
экспортировать vXtrapFNm=()
# замена ЛИНЕНО
# где BASH_LINENO[lIdx] должен равняться vXtrapLNo[lIdx+1]
экспортировать vXtrapLNo=()
# LINENO инициация
# номер строки начального отчета функции в ловушке отладки
экспортировать vXtrapLNI=()
# замена BASH_COMMAND
# это исходная незамещенная исходная команда
# ниже приведена сжатая версия исходной команды с заменой
# "${vXtrcTrapArg0[$lIdx]} ${vXtrcTrapArgV[$lIdx]}"
экспортировать vXtrapCmd=()
# замена BASH_ARGV0
экспортировать vXtrapArg0=()
# замена BASH_ARGVC
экспортировать vXtrapArgC=()
# замена BASH_ARGV
# разделен пробелом
экспортировать vXtrapArgV=()
# замена $?
экспортировать vXtrapRc=()
# замена сообщения syserr
экспортировать vXtrapRcMsg=()
установить +o подробный
читать -рп '090'
#####
# Передача инициализации начальной команды в исправленную таблицу трассировки
#####
я=0
iMax=${#BASH_LINENO[@]}
j=0
к=0
v=''
напечатать '\n'
v="$BASH_SUBSHELL"
если [[ -z "$v" && -n "${v-_}" ]]; тогда
echo '$BASH_SUBSHELL не установлен '"$BASH_SUBSHELL"
еще
echo '$BASH_SUBSHELL установить '"$BASH_SUBSHELL"
фи
v="$LINENO"
если [[ -z "$v" && -n "${v-_}" ]]; тогда
echo '$LINENO отключено'"$LINENO"
еще
echo '$LINENO установить '"$LINENO"
фи
v="$BASH_КОМАНДА"
если [[ -z "$v" && -n "${v-_}" ]]; тогда
эхо '$ BASH_COMMAND отключено '"$ BASH_COMMAND"
еще
echo '$BASH_COMMAND установить '"$BASH_COMMAND"
фи
для (( я = 0; я <= iMax; я ++ ))
делать
напечатать '\n'
v="${BASH_SOURCE["$i"]}"
если [[ -z "$v" && -n "${v-_}" ]]; тогда
echo '${BASH_SOURCE['"$i"']} отключено '"${BASH_SOURCE[$i]}"
еще
echo '${BASH_SOURCE['"$i"']} установить '"${BASH_SOURCE[$i]}"
фи
v="${ИМЯ_ФУНКЦИИ[$i]}"
если [[ -z "$v" && -n "${v-_}" ]]; тогда
echo '${FUNCNAME['"$i"']} снято '"${FUNCNAME[$i]}"
еще
echo '${FUNCNAME['"$i"']} установить '"${FUNCNAME[$i]}"
фи
v="${BASH_LINENO["$i"]}"
если [[ -z "$v" && -n "${v-_}" ]]; тогда
echo '${BASH_LINENO['"$i"']} отключено '"${BASH_LINENO[$i]}"
еще
echo '${BASH_LINENO['"$i"']} установить '"${BASH_LINENO[$i]}"
фи
v="${BASH_ARGV0[i]}"
если [[ -z "$v" && -n "${v-_}" ]]; тогда
echo '${BASH_ARGV0['"$i"']} снято '"${BASH_ARGV0[$i]}"
еще
echo '${BASH_ARGV0['"$i"']} установить '"${BASH_ARGV0[$i]}"
фи
v="${BASH_ARGC[i]}"
если [[ -z "$v" && -n "${v-_}" ]]; тогда
echo '${BASH_ARGC['"$i"']} снято '"${BASH_ARGC[$i]}"
еще
echo '${BASH_ARGC['"$i"']} установить '"${BASH_ARGC[$i]}"
фи
j=0
в то время как ["$j" -lt "${BASH_ARGC[i]}"]
делать
v="${BASH_ARGV["$k"]}"
если [[ -z "$v" && -n "${v-_}" ]]; тогда
echo '${BASH_ARGV['"$i $j"']} unset ref=${BASH_ARGV['"$k"']} '"${BASH_ARGV["$k"]}"
еще
echo '${BASH_ARGV['"$i $j"']} set ref=${BASH_ARGV['"$k"']} '"${BASH_ARGV["$k"]}"
фи
((к++))
(( j++ ))
сделано
сделано
vPtrapScr="$(базовое имя "${BASH_SOURCE[0]}" '.sh' )"
vPtrapArgC='1'
vPtrapArgV=''
в то время как [$vPtrapArgC -lt ${BASH_ARGC[0]}]
делать
case "$vPtrapArgC" в
(0)
vPtrapArgV=" \"${BASH_ARGV["vPtrapArgC"]}\""
;;
(*)
vPtrapArgV=" \"${BASH_ARGV["$vPtrapArgC"]}\"$vPtrapArgV"
;;
эсак
(( vPtrapArgC++ ))
сделано
# Не знаю, почему FUNCNAME[0] после нового терминала
# '' вместо 'источник'
### vPtrapArg0="${FUNCNAME[0]}"
vPtrapArg0='источник'
vPtrapCmd="источник \"${BASH_SOURCE[0]}\" ${vPtrapArgV}"
vPtrapArgV="\"${BASH_SOURCE[0]}\" ${vPtrapArgV}"
установить -o xtrace
vXtrapSub=( "$BASH_SUBSHELL" "$BASH_SUBSHELL" "$BASH_SUBSHELL" )
vXtrapSrc=( "${BASH_SOURCE[0]}" '' '' )
vXtrapScr=( "$vPtrapScr" '' '' )
vXtrapFNm=( '' '' '' )
vXtrapLNo=('0' "${BASH_LINENO[0]}" '0' )
vXtrapLNI=( '0' '0' '0' )
# значения ниже этой строки в настоящее время относятся к вызывающей инструкции
# когда активируется ловушка DEBUG, это будет текущая инструкция скрипта
vXtrapCmd=( "$vPtrapCmd" "$vPtrapCmd" '' )
vXtrapArg0=( "$vPtrapArg0" "$vPtrapArg0" '' )
vXtrapArgC=( "$vPtrapArgC" "$vPtrapArgC" '0' )
vXtrapArgV=( "$vPtrapArgV" "$vPtrapArgV" '' )
vXtrapRc=( '0' '0' '0' )
vXtrapRcMsg=( '' '' '' )
установить +o xtrace
читать -рп '100'
отключить я
отключить iMax
сбросить j
сбросить k
снято v
сбросить vPtrapScr
отключить vPtrapCmd
сбросить vPtrapArg0
сбросить vPtrapArgC
сбросить vPtrapArgV
читать -рп '110'
вернуть "${vXtrapRc[0]}"
Первый запуск +u установил переменные, те же самые переменные становятся неустановленными (в частности, $FUNCNAME, которая предотвращает тестирование многих других) при запуске -u.
Вывод теста:
ubuntu@ubuntu:/$ установить +u
ubuntu@ubuntu:/$ cd /pool/src/trap/scr
ubuntu@ubuntu:/pool/src/trap/scr$ источник SHtest.sh
# Разделитель полей vXtrap u0081 (плюс/минус)
### экспорт vXtrapLFS='\v'
# замена BASH_SUBSHELL
экспортировать vXtrapSub=()
# замена BASH_SOURCE
экспортировать vXtrapSrc=()
# скрипт замены
# базовое имя "${vXtrapSub[$lIdx]}}" '.sh'
экспортировать vXtrapScr=()
# замена FUNCNAME
экспортировать vXtrapFNm=()
# замена ЛИНЕНО
# где BASH_LINENO[lIdx] должен равняться vXtrapLNo[lIdx+1]
экспортировать vXtrapLNo=()
# LINENO инициация
# номер строки начального отчета функции в ловушке отладки
экспортировать vXtrapLNI=()
# замена BASH_COMMAND
# это исходная незамещенная исходная команда
# ниже приведена сжатая версия исходной команды с заменой
# "${vXtrcTrapArg0[$lIdx]} ${vXtrcTrapArgV[$lIdx]}"
экспортировать vXtrapCmd=()
# замена BASH_ARGV0
экспортировать vXtrapArg0=()
# замена BASH_ARGVC
экспортировать vXtrapArgC=()
# замена BASH_ARGV
# разделен пробелом
экспортировать vXtrapArgV=()
# замена $?
экспортировать vXtrapRc=()
# замена сообщения syserr
экспортировать vXtrapRcMsg=()
установить +o подробный
090
$BASH_SUBSHELL установить 0
$LINENO набор 89
$BASH_COMMAND установить эхо '$BASH_COMMAND установить '"$BASH_COMMAND"
${BASH_SOURCE[0]} задал SHtest.sh
Набор ${FUNCNAME[0]}
${BASH_LINENO[0]} набор 3
${BASH_ARGV0[0]} установить /usr/bin/bash
${BASH_ARGC[0]} установить 1
${BASH_ARGV[0 0]} установить ссылку=${BASH_ARGV[0]} SHtest.sh
Набор ${BASH_SOURCE[1]}
Набор ${FUNCNAME[1]}
Набор ${BASH_LINENO[1]}
Набор ${BASH_ARGV0[1]}
${BASH_ARGC[1]} установить 0
++:SHtest.sh::184::x:: vXtrapSub=("$BASH_SUBSHELL" "$BASH_SUBSHELL" "$BASH_SUBSHELL")
++:SHtest.sh::185::x:: vXtrapSrc=("${BASH_SOURCE[0]}" '' '')
++:SHtest.sh::186::x:: vXtrapScr=("$vPtrapScr" '' '')
++:SHtest.sh::187::x:: vXtrapFNm=('' '' '')
++:SHtest.sh::188::x:: vXtrapLNo=('0' "${BASH_LINENO[0]}" '0')
++:SHtest.sh::189::x:: vXtrapLNI=('0' '0' '0')
++:SHtest.sh::192::x:: vXtrapCmd=("$vPtrapCmd" "$vPtrapCmd" '')
++:SHtest.sh::193::x:: vXtrapArg0=("$vPtrapArg0" "$vPtrapArg0" '')
++:SHtest.sh::194::x:: vXtrapArgC=("$vPtrapArgC" "$vPtrapArgC" '0')
++:SHtest.sh::195::x:: vXtrapArgV=("$vPtrapArgV" "$vPtrapArgV" '')
++:SHtest.sh::196::x:: vXtrapRc=('0' '0' '0')
++:SHtest.sh::197::x:: vXtrapRcMsg=('' '' '')
++:SHtest.sh::199::x:: set +o xtrace
100
110
ubuntu@ubuntu:/pool/src/trap/scr$ установить -u
ubuntu@ubuntu:/pool/src/trap/scr$ источник SHtest.sh
# Разделитель полей vXtrap u0081 (плюс/минус)
### экспорт vXtrapLFS='\v'
# замена BASH_SUBSHELL
экспортировать vXtrapSub=()
# замена BASH_SOURCE
экспортировать vXtrapSrc=()
# скрипт замены
# базовое имя "${vXtrapSub[$lIdx]}}" '.sh'
экспортировать vXtrapScr=()
# замена FUNCNAME
экспортировать vXtrapFNm=()
# замена ЛИНЕНО
# где BASH_LINENO[lIdx] должен равняться vXtrapLNo[lIdx+1]
экспортировать vXtrapLNo=()
# LINENO инициация
# номер строки начального отчета функции в ловушке отладки
экспортировать vXtrapLNI=()
# замена BASH_COMMAND
# это исходная незамещенная исходная команда
# ниже приведена сжатая версия исходной команды с заменой
# "${vXtrcTrapArg0[$lIdx]} ${vXtrcTrapArgV[$lIdx]}"
экспортировать vXtrapCmd=()
# замена BASH_ARGV0
экспортировать vXtrapArg0=()
# замена BASH_ARGVC
экспортировать vXtrapArgC=()
# замена BASH_ARGV
# разделен пробелом
экспортировать vXtrapArgV=()
# замена $?
экспортировать vXtrapRc=()
# замена сообщения syserr
экспортировать vXtrapRcMsg=()
установить +o подробный
090
$BASH_SUBSHELL установить 0
$LINENO набор 89
$BASH_COMMAND установить эхо '$BASH_COMMAND установить '"$BASH_COMMAND"
${BASH_SOURCE[0]} задал SHtest.sh
bash: FUNCNAME[$i]: несвязанная переменная
bash: FUNCNAME[0]: несвязанная переменная
++:${BASH_SOURCE[0]}:${FUNCNAME[0]}:${LINENO[0]}::x:: vXtrapSub=("$BASH_SUBSHELL" "$BASH_SUBSHELL" "$BASH_SUBSHELL")
bash: FUNCNAME[0]: несвязанная переменная
++:${BASH_SOURCE[0]}:${FUNCNAME[0]}:${LINENO[0]}::x:: vXtrapSrc=("${BASH_SOURCE[0]}" '' '')
bash: FUNCNAME[0]: несвязанная переменная
++:${BASH_SOURCE[0]}:${FUNCNAME[0]}:${LINENO[0]}::x:: vXtrapScr=("$vPtrapScr" '' '')
bash: FUNCNAME[0]: несвязанная переменная
++:${BASH_SOURCE[0]}:${FUNCNAME[0]}:${LINENO[0]}::x:: vXtrapFNm=('' '' '')
bash: FUNCNAME[0]: несвязанная переменная
++:${BASH_SOURCE[0]}:${FUNCNAME[0]}:${LINENO[0]}::x:: vXtrapLNo=('0' "${BASH_LINENO[0]}" '0')
bash: FUNCNAME[0]: несвязанная переменная
++:${BASH_SOURCE[0]}:${FUNCNAME[0]}:${LINENO[0]}::x:: vXtrapLNI=('0' '0' '0')
bash: FUNCNAME[0]: несвязанная переменная
++:${BASH_SOURCE[0]}:${FUNCNAME[0]}:${LINENO[0]}::x:: vXtrapCmd=("$vPtrapCmd" "$vPtrapCmd" '')
bash: FUNCNAME[0]: несвязанная переменная
++:${BASH_SOURCE[0]}:${FUNCNAME[0]}:${LINENO[0]}::x:: vXtrapArg0=("$vPtrapArg0" "$vPtrapArg0" '')
bash: FUNCNAME[0]: несвязанная переменная
++:${BASH_SOURCE[0]}:${FUNCNAME[0]}:${LINENO[0]}::x:: vXtrapArgC=("$vPtrapArgC" "$vPtrapArgC" '0')
bash: FUNCNAME[0]: несвязанная переменная
++:${BASH_SOURCE[0]}:${FUNCNAME[0]}:${LINENO[0]}::x:: vXtrapArgV=("$vPtrapArgV" "$vPtrapArgV" '')
bash: FUNCNAME[0]: несвязанная переменная
++:${BASH_SOURCE[0]}:${FUNCNAME[0]}:${LINENO[0]}::x:: vXtrapRc=('0' '0' '0')
bash: FUNCNAME[0]: несвязанная переменная
++:${BASH_SOURCE[0]}:${FUNCNAME[0]}:${LINENO[0]}::x:: vXtrapRcMsg=('' '' '')
bash: FUNCNAME[0]: несвязанная переменная
++:${BASH_SOURCE[0]}:${FUNCNAME[0]}:${LINENO[0]}::x:: set +o xtrace
100
110
ubuntu@ubuntu:/pool/src/trap/scr$
Я надеюсь, что этот код и вывод имеют смысл для тех, кто его читает.