I have a fairly large set of scripts that is the initial part of creating some debug/logging logic for bash scripts. There is a considerable amount of code in the system. Fortunately I can demonstrate the different results that I cannot explain when the script is run +u and -u. Set variables as tested using +u become unset variables when run with -u. The variabl.e name in this case is $FUNCNAME
The short test script are as follows:
#!/bin/bash
### set -e
### set -f
### set -u
### set -C
### set -P
### set -o pipefail
export PS4='+:${BASH_SOURCE[0]}:${FUNCNAME[0]}:${LINENO[0]}::x:: '
set -o verbose
# vXtrap Field Separator u0081 (plus/minus)
### export vXtrapLFS='\v'
# replacement BASH_SUBSHELL
export vXtrapSub=()
# replacement BASH_SOURCE
export vXtrapSrc=()
# replacement Script
# basename "${vXtrapSub[$lIdx]}}" '.sh'
export vXtrapScr=()
# replacement FUNCNAME
export vXtrapFNm=()
# replacement LINENO
# where BASH_LINENO[lIdx] should equal vXtrapLNo[lIdx+1]
export vXtrapLNo=()
# LINENO initiation
# line number initial report of function in Debug Trap
export vXtrapLNI=()
# replacement BASH_COMMAND
# this is the original unsubstituted source command
# the following is a compressed substituted version of the source command
# "${vXtrcTrapArg0[$lIdx]} ${vXtrcTrapArgV[$lIdx]}"
export vXtrapCmd=()
# replacement BASH_ARGV0
export vXtrapArg0=()
# replacement BASH_ARGVC
export vXtrapArgC=()
# replacement BASH_ARGV
# space delimited
export vXtrapArgV=()
# replacement $?
export vXtrapRc=()
# replacement syserr message
export vXtrapRcMsg=()
set +o verbose
read -rp '090'
#####
# Transfer Initial command initiation to the revised trace table
#####
i=0
iMax=${#BASH_LINENO[@]}
j=0
k=0
v=''
printf '\n'
v="$BASH_SUBSHELL"
if [[ -z "$v" && -n "${v-_}" ]]; then
echo '$BASH_SUBSHELL unset '"$BASH_SUBSHELL"
else
echo '$BASH_SUBSHELL set '"$BASH_SUBSHELL"
fi
v="$LINENO"
if [[ -z "$v" && -n "${v-_}" ]]; then
echo '$LINENO unset '"$LINENO"
else
echo '$LINENO set '"$LINENO"
fi
v="$BASH_COMMAND"
if [[ -z "$v" && -n "${v-_}" ]]; then
echo '$BASH_COMMAND unset '"$BASH_COMMAND"
else
echo '$BASH_COMMAND set '"$BASH_COMMAND"
fi
for (( i=0; i<=iMax; i++ ))
do
printf '\n'
v="${BASH_SOURCE["$i"]}"
if [[ -z "$v" && -n "${v-_}" ]]; then
echo '${BASH_SOURCE['"$i"']} unset '"${BASH_SOURCE[$i]}"
else
echo '${BASH_SOURCE['"$i"']} set '"${BASH_SOURCE[$i]}"
fi
v="${FUNCNAME[$i]}"
if [[ -z "$v" && -n "${v-_}" ]]; then
echo '${FUNCNAME['"$i"']} unset '"${FUNCNAME[$i]}"
else
echo '${FUNCNAME['"$i"']} set '"${FUNCNAME[$i]}"
fi
v="${BASH_LINENO["$i"]}"
if [[ -z "$v" && -n "${v-_}" ]]; then
echo '${BASH_LINENO['"$i"']} unset '"${BASH_LINENO[$i]}"
else
echo '${BASH_LINENO['"$i"']} set '"${BASH_LINENO[$i]}"
fi
v="${BASH_ARGV0[i]}"
if [[ -z "$v" && -n "${v-_}" ]]; then
echo '${BASH_ARGV0['"$i"']} unset '"${BASH_ARGV0[$i]}"
else
echo '${BASH_ARGV0['"$i"']} set '"${BASH_ARGV0[$i]}"
fi
v="${BASH_ARGC[i]}"
if [[ -z "$v" && -n "${v-_}" ]]; then
echo '${BASH_ARGC['"$i"']} unset '"${BASH_ARGC[$i]}"
else
echo '${BASH_ARGC['"$i"']} set '"${BASH_ARGC[$i]}"
fi
j=0
while [ "$j" -lt "${BASH_ARGC[i]}" ]
do
v="${BASH_ARGV["$k"]}"
if [[ -z "$v" && -n "${v-_}" ]]; then
echo '${BASH_ARGV['"$i $j"']} unset ref=${BASH_ARGV['"$k"']} '"${BASH_ARGV["$k"]}"
else
echo '${BASH_ARGV['"$i $j"']} set ref=${BASH_ARGV['"$k"']} '"${BASH_ARGV["$k"]}"
fi
(( k++ ))
(( j++ ))
done
done
vPtrapScr="$(basename "${BASH_SOURCE[0]}" '.sh' )"
vPtrapArgC='1'
vPtrapArgV=''
while [ $vPtrapArgC -lt ${BASH_ARGC[0]} ]
do
case "$vPtrapArgC" in
(0)
vPtrapArgV=" \"${BASH_ARGV["vPtrapArgC"]}\""
;;
(*)
vPtrapArgV=" \"${BASH_ARGV["$vPtrapArgC"]}\"$vPtrapArgV"
;;
esac
(( vPtrapArgC++ ))
done
# Don't know why FUNCNAME[0] after new terminal is
# '' instead of 'source'
### vPtrapArg0="${FUNCNAME[0]}"
vPtrapArg0='source'
vPtrapCmd="source \"${BASH_SOURCE[0]}\" ${vPtrapArgV}"
vPtrapArgV="\"${BASH_SOURCE[0]}\" ${vPtrapArgV}"
set -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' )
# values below this line are currently for the calling instruction
# when the DEBUG trap activates these will be current script instruction
vXtrapCmd=( "$vPtrapCmd" "$vPtrapCmd" '' )
vXtrapArg0=( "$vPtrapArg0" "$vPtrapArg0" '' )
vXtrapArgC=( "$vPtrapArgC" "$vPtrapArgC" '0' )
vXtrapArgV=( "$vPtrapArgV" "$vPtrapArgV" '' )
vXtrapRc=( '0' '0' '0' )
vXtrapRcMsg=( '' '' '' )
set +o xtrace
read -rp '100'
unset i
unset iMax
unset j
unset k
unset v
unset vPtrapScr
unset vPtrapCmd
unset vPtrapArg0
unset vPtrapArgC
unset vPtrapArgV
read -rp '110'
return "${vXtrapRc[0]}"
The first run +u has set variables those same variables become unset (specifically $FUNCNAME that prevents the many of the others from being tested) in the -u run.
The test output:
ubuntu@ubuntu:/$ set +u
ubuntu@ubuntu:/$ cd /pool/src/trap/scr
ubuntu@ubuntu:/pool/src/trap/scr$ source SHtest.sh
# vXtrap Field Separator u0081 (plus/minus)
### export vXtrapLFS='\v'
# replacement BASH_SUBSHELL
export vXtrapSub=()
# replacement BASH_SOURCE
export vXtrapSrc=()
# replacement Script
# basename "${vXtrapSub[$lIdx]}}" '.sh'
export vXtrapScr=()
# replacement FUNCNAME
export vXtrapFNm=()
# replacement LINENO
# where BASH_LINENO[lIdx] should equal vXtrapLNo[lIdx+1]
export vXtrapLNo=()
# LINENO initiation
# line number initial report of function in Debug Trap
export vXtrapLNI=()
# replacement BASH_COMMAND
# this is the original unsubstituted source command
# the following is a compressed substituted version of the source command
# "${vXtrcTrapArg0[$lIdx]} ${vXtrcTrapArgV[$lIdx]}"
export vXtrapCmd=()
# replacement BASH_ARGV0
export vXtrapArg0=()
# replacement BASH_ARGVC
export vXtrapArgC=()
# replacement BASH_ARGV
# space delimited
export vXtrapArgV=()
# replacement $?
export vXtrapRc=()
# replacement syserr message
export vXtrapRcMsg=()
set +o verbose
090
$BASH_SUBSHELL set 0
$LINENO set 89
$BASH_COMMAND set echo '$BASH_COMMAND set '"$BASH_COMMAND"
${BASH_SOURCE[0]} set SHtest.sh
${FUNCNAME[0]} set
${BASH_LINENO[0]} set 3
${BASH_ARGV0[0]} set /usr/bin/bash
${BASH_ARGC[0]} set 1
${BASH_ARGV[0 0]} set ref=${BASH_ARGV[0]} SHtest.sh
${BASH_SOURCE[1]} set
${FUNCNAME[1]} set
${BASH_LINENO[1]} set
${BASH_ARGV0[1]} set
${BASH_ARGC[1]} set 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$ set -u
ubuntu@ubuntu:/pool/src/trap/scr$ source SHtest.sh
# vXtrap Field Separator u0081 (plus/minus)
### export vXtrapLFS='\v'
# replacement BASH_SUBSHELL
export vXtrapSub=()
# replacement BASH_SOURCE
export vXtrapSrc=()
# replacement Script
# basename "${vXtrapSub[$lIdx]}}" '.sh'
export vXtrapScr=()
# replacement FUNCNAME
export vXtrapFNm=()
# replacement LINENO
# where BASH_LINENO[lIdx] should equal vXtrapLNo[lIdx+1]
export vXtrapLNo=()
# LINENO initiation
# line number initial report of function in Debug Trap
export vXtrapLNI=()
# replacement BASH_COMMAND
# this is the original unsubstituted source command
# the following is a compressed substituted version of the source command
# "${vXtrcTrapArg0[$lIdx]} ${vXtrcTrapArgV[$lIdx]}"
export vXtrapCmd=()
# replacement BASH_ARGV0
export vXtrapArg0=()
# replacement BASH_ARGVC
export vXtrapArgC=()
# replacement BASH_ARGV
# space delimited
export vXtrapArgV=()
# replacement $?
export vXtrapRc=()
# replacement syserr message
export vXtrapRcMsg=()
set +o verbose
090
$BASH_SUBSHELL set 0
$LINENO set 89
$BASH_COMMAND set echo '$BASH_COMMAND set '"$BASH_COMMAND"
${BASH_SOURCE[0]} set SHtest.sh
bash: FUNCNAME[$i]: unbound variable
bash: FUNCNAME[0]: unbound variable
++:${BASH_SOURCE[0]}:${FUNCNAME[0]}:${LINENO[0]}::x:: vXtrapSub=("$BASH_SUBSHELL" "$BASH_SUBSHELL" "$BASH_SUBSHELL")
bash: FUNCNAME[0]: unbound variable
++:${BASH_SOURCE[0]}:${FUNCNAME[0]}:${LINENO[0]}::x:: vXtrapSrc=("${BASH_SOURCE[0]}" '' '')
bash: FUNCNAME[0]: unbound variable
++:${BASH_SOURCE[0]}:${FUNCNAME[0]}:${LINENO[0]}::x:: vXtrapScr=("$vPtrapScr" '' '')
bash: FUNCNAME[0]: unbound variable
++:${BASH_SOURCE[0]}:${FUNCNAME[0]}:${LINENO[0]}::x:: vXtrapFNm=('' '' '')
bash: FUNCNAME[0]: unbound variable
++:${BASH_SOURCE[0]}:${FUNCNAME[0]}:${LINENO[0]}::x:: vXtrapLNo=('0' "${BASH_LINENO[0]}" '0')
bash: FUNCNAME[0]: unbound variable
++:${BASH_SOURCE[0]}:${FUNCNAME[0]}:${LINENO[0]}::x:: vXtrapLNI=('0' '0' '0')
bash: FUNCNAME[0]: unbound variable
++:${BASH_SOURCE[0]}:${FUNCNAME[0]}:${LINENO[0]}::x:: vXtrapCmd=("$vPtrapCmd" "$vPtrapCmd" '')
bash: FUNCNAME[0]: unbound variable
++:${BASH_SOURCE[0]}:${FUNCNAME[0]}:${LINENO[0]}::x:: vXtrapArg0=("$vPtrapArg0" "$vPtrapArg0" '')
bash: FUNCNAME[0]: unbound variable
++:${BASH_SOURCE[0]}:${FUNCNAME[0]}:${LINENO[0]}::x:: vXtrapArgC=("$vPtrapArgC" "$vPtrapArgC" '0')
bash: FUNCNAME[0]: unbound variable
++:${BASH_SOURCE[0]}:${FUNCNAME[0]}:${LINENO[0]}::x:: vXtrapArgV=("$vPtrapArgV" "$vPtrapArgV" '')
bash: FUNCNAME[0]: unbound variable
++:${BASH_SOURCE[0]}:${FUNCNAME[0]}:${LINENO[0]}::x:: vXtrapRc=('0' '0' '0')
bash: FUNCNAME[0]: unbound variable
++:${BASH_SOURCE[0]}:${FUNCNAME[0]}:${LINENO[0]}::x:: vXtrapRcMsg=('' '' '')
bash: FUNCNAME[0]: unbound variable
++:${BASH_SOURCE[0]}:${FUNCNAME[0]}:${LINENO[0]}::x:: set +o xtrace
100
110
ubuntu@ubuntu:/pool/src/trap/scr$
I hope this code and output makes sense to those that read it.