Tôi có một bộ tập lệnh khá lớn, đây là phần ban đầu để tạo một số logic gỡ lỗi/ghi nhật ký cho tập lệnh bash. Có một lượng mã đáng kể trong hệ thống. May mắn thay, tôi có thể chứng minh các kết quả khác nhau mà tôi không thể giải thích khi chạy tập lệnh +u và -u. Đặt các biến như đã kiểm tra bằng cách sử dụng +u trở thành các biến không được đặt khi chạy với -u. Tên biến.e trong trường hợp này là $FUNCNAME
Kịch bản thử nghiệm ngắn như sau:
#!/bin/bash
### đặt -e
### đặt -f
### đặt -u
### đặt -C
### đặt -P
### đặt -o lỗi đường ống
xuất PS4='+:${BASH_SOURCE[0]}:${FUNCNAME[0]}:${LINENO[0]}::x:: '
đặt -o dài dòng
# Bộ tách trường vXtrap u0081 (cộng/trừ)
### xuất vXtrapLFS='\v'
# thay thế BASH_SUBSHELL
xuất vXtrapSub=()
# thay thế BASH_SOURCE
xuất vXtrapSrc=()
# tập lệnh thay thế
# tên cơ sở "${vXtrapSub[$lIdx]}}" '.sh'
xuất vXtrapScr=()
# thay thế FUNCNAME
xuất vXtrapFNm=()
# thay thế LINENO
# trong đó BASH_LINENO[lIdx] phải bằng vXtrapLNo[lIdx+1]
xuất vXtrapLNo=()
# LINENO bắt đầu
# số dòng báo cáo ban đầu của chức năng trong Bẫy gỡ lỗi
xuất vXtrapLNI=()
# thay thế BASH_COMMAND
# đây là lệnh nguồn chưa được thay thế ban đầu
# sau đây là phiên bản thay thế được nén của lệnh nguồn
# "${vXtrcTrapArg0[$lIdx]} ${vXtrcTrapArgV[$lIdx]}"
xuất vXtrapCmd=()
# thay thế BASH_ARGV0
xuất vXtrapArg0=()
# thay thế BASH_ARGVC
xuất vXtrapArgC=()
# thay thế BASH_ARGV
# phân cách bằng dấu cách
xuất vXtrapArgV=()
# thay thế $?
xuất vXtrapRc=()
# thông báo syserr thay thế
xuất vXtrapRcMsg=()
đặt +o dài dòng
đọc -rp '090'
#####
# Chuyển Khởi tạo lệnh ban đầu sang bảng theo dõi đã sửa đổi
#####
tôi=0
iMax=${#BASH_LINENO[@]}
j=0
k=0
v=''
printf '\ n'
v="$BASH_SUBSHELL"
if [[ -z "$v" && -n "${v-_}" ]]; sau đó
tiếng vang '$BASH_SUBSHELL bỏ đặt '"$BASH_SUBSHELL"
khác
tiếng vang '$BASH_SUBSHELL đã đặt '"$BASH_SUBSHELL"
fi
v="$LINENO"
if [[ -z "$v" && -n "${v-_}" ]]; sau đó
echo '$LINENO unset '"$LINENO"
khác
tiếng vang '$LINENO set '"$LINENO"
fi
v="$BASH_COMMAND"
if [[ -z "$v" && -n "${v-_}" ]]; sau đó
tiếng vang '$BASH_COMMAND bỏ đặt '"$BASH_COMMAND"
khác
tiếng vang '$BASH_COMMAND đã đặt'"$BASH_COMMAND"
fi
cho (( i=0; i<=iMax; i++ ))
làm
printf '\ n'
v="${BASH_SOURCE["$i"]}"
if [[ -z "$v" && -n "${v-_}" ]]; sau đó
echo '${BASH_SOURCE['"$i"']} bỏ đặt '"${BASH_SOURCE[$i]}"
khác
echo '${BASH_SOURCE['"$i"']} set '"${BASH_SOURCE[$i]}"
fi
v="${FUNCNAME[$i]}"
if [[ -z "$v" && -n "${v-_}" ]]; sau đó
echo '${FUNCNAME['"$i"']} bỏ đặt '"${FUNCNAME[$i]}"
khác
echo '${FUNCNAME['"$i"']} set '"${FUNCNAME[$i]}"
fi
v="${BASH_LINENO["$i"]}"
if [[ -z "$v" && -n "${v-_}" ]]; sau đó
echo '${BASH_LINENO['"$i"']} bỏ đặt '"${BASH_LINENO[$i]}"
khác
echo '${BASH_LINENO['"$i"']} set '"${BASH_LINENO[$i]}"
fi
v="${BASH_ARGV0[i]}"
if [[ -z "$v" && -n "${v-_}" ]]; sau đó
echo '${BASH_ARGV0['"$i"']} bỏ đặt '"${BASH_ARGV0[$i]}"
khác
echo '${BASH_ARGV0['"$i"']} set '"${BASH_ARGV0[$i]}"
fi
v="${BASH_ARGC[i]}"
if [[ -z "$v" && -n "${v-_}" ]]; sau đó
echo '${BASH_ARGC['"$i"']} bỏ đặt '"${BASH_ARGC[$i]}"
khác
echo '${BASH_ARGC['"$i"']} set '"${BASH_ARGC[$i]}"
fi
j=0
trong khi [ "$j" -lt "${BASH_ARGC[i]}" ]
làm
v="${BASH_ARGV["$k"]}"
if [[ -z "$v" && -n "${v-_}" ]]; sau đó
echo '${BASH_ARGV['"$i $j"']} unset ref=${BASH_ARGV['"$k"']} '"${BASH_ARGV["$k"]}"
khác
echo '${BASH_ARGV['"$i $j"']} set ref=${BASH_ARGV['"$k"']} '"${BASH_ARGV["$k"]}"
fi
(( k ++ ))
(( j ++ ))
xong
xong
vPtrapScr="$(tên cơ sở "${BASH_SOURCE[0]}" '.sh' )"
vPtrapArgC='1'
vPtrapArgV=''
trong khi [ $vPtrapArgC -lt ${BASH_ARGC[0]} ]
làm
trường hợp "$vPtrapArgC" trong
(0)
vPtrapArgV=" \"${BASH_ARGV["vPtrapArgC"]}\""
;;
(*)
vPtrapArgV=" \"${BASH_ARGV["$vPtrapArgC"]}\"$vPtrapArgV"
;;
thoát hiểm
(( vPtrapArgC++ ))
xong
# Không biết tại sao FUNCNAME[0] sau khi thiết bị đầu cuối mới là
# '' thay vì 'nguồn'
### vPtrapArg0="${FUNCNAME[0]}"
vPtrapArg0='nguồn'
vPtrapCmd="source \"${BASH_SOURCE[0]}\" ${vPtrapArgV}"
vPtrapArgV="\"${BASH_SOURCE[0]}\" ${vPtrapArgV}"
đặt -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' )
# giá trị bên dưới dòng này hiện dành cho lệnh gọi
# khi bẫy GỠ LỖI kích hoạt, đây sẽ là hướng dẫn tập lệnh hiện tại
vXtrapCmd=( "$vPtrapCmd" "$vPtrapCmd" '' )
vXtrapArg0=( "$vPtrapArg0" "$vPtrapArg0" '' )
vXtrapArgC=( "$vPtrapArgC" "$vPtrapArgC" '0' )
vXtrapArgV=( "$vPtrapArgV" "$vPtrapArgV" '' )
vXtrapRc=( '0' '0' '0' )
vXtrapRcMsg=( '' '' '' )
đặt +o xtrace
đọc -rp '100'
bỏ đặt tôi
bỏ đặt iMax
bỏ đặt j
bỏ đặt k
bỏ đặt v
bỏ đặt vPtrapScr
bỏ đặt vPtrapCmd
bỏ đặt vPtrapArg0
hủy đặt vPtrapArgC
bỏ đặt vPtrapArgV
đọc -rp '110'
trả về "${vXtrapRc[0]}"
Lần chạy đầu tiên +u đã đặt các biến mà chính các biến đó sẽ không được đặt (cụ thể là $FUNCNAME ngăn không cho nhiều biến khác được kiểm tra) trong lần chạy -u.
Đầu ra thử nghiệm:
ubuntu@ubuntu:/$ set +u
ubuntu@ubuntu:/$ cd /pool/src/trap/scr
ubuntu@ubuntu:/pool/src/trap/scr$ nguồn SHtest.sh
# Bộ tách trường vXtrap u0081 (cộng/trừ)
### xuất vXtrapLFS='\v'
# thay thế BASH_SUBSHELL
xuất vXtrapSub=()
# thay thế BASH_SOURCE
xuất vXtrapSrc=()
# tập lệnh thay thế
# tên cơ sở "${vXtrapSub[$lIdx]}}" '.sh'
xuất vXtrapScr=()
# thay thế FUNCNAME
xuất vXtrapFNm=()
# thay thế LINENO
# trong đó BASH_LINENO[lIdx] phải bằng vXtrapLNo[lIdx+1]
xuất vXtrapLNo=()
# LINENO bắt đầu
# số dòng báo cáo ban đầu của chức năng trong Bẫy gỡ lỗi
xuất vXtrapLNI=()
# thay thế BASH_COMMAND
# đây là lệnh nguồn chưa được thay thế ban đầu
# sau đây là phiên bản thay thế được nén của lệnh nguồn
# "${vXtrcTrapArg0[$lIdx]} ${vXtrcTrapArgV[$lIdx]}"
xuất vXtrapCmd=()
# thay thế BASH_ARGV0
xuất vXtrapArg0=()
# thay thế BASH_ARGVC
xuất vXtrapArgC=()
# thay thế BASH_ARGV
# phân cách bằng dấu cách
xuất vXtrapArgV=()
# thay thế $?
xuất vXtrapRc=()
# thông báo syserr thay thế
xuất vXtrapRcMsg=()
đặt +o dài dòng
090
$BASH_SUBSHELL đặt 0
$LINENO đặt 89
$BASH_COMMAND đặt tiếng vang '$BASH_COMMAND đặt '"$BASH_COMMAND"
${BASH_SOURCE[0]} đặt SHtest.sh
đã đặt ${FUNCNAME[0]}
${BASH_LINENO[0]} bộ 3
${BASH_ARGV0[0]} được đặt /usr/bin/bash
${BASH_ARGC[0]} bộ 1
${BASH_ARGV[0 0]} đặt ref=${BASH_ARGV[0]} SHtest.sh
bộ ${BASH_SOURCE[1]}
bộ ${FUNCNAME[1]}
đã đặt ${BASH_LINENO[1]}
bộ ${BASH_ARGV0[1]}
${BASH_ARGC[1]} đặt 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$ nguồn SHtest.sh
# Bộ tách trường vXtrap u0081 (cộng/trừ)
### xuất vXtrapLFS='\v'
# thay thế BASH_SUBSHELL
xuất vXtrapSub=()
# thay thế BASH_SOURCE
xuất vXtrapSrc=()
# tập lệnh thay thế
# tên cơ sở "${vXtrapSub[$lIdx]}}" '.sh'
xuất vXtrapScr=()
# thay thế FUNCNAME
xuất vXtrapFNm=()
# thay thế LINENO
# trong đó BASH_LINENO[lIdx] phải bằng vXtrapLNo[lIdx+1]
xuất vXtrapLNo=()
# LINENO bắt đầu
# số dòng báo cáo ban đầu của chức năng trong Bẫy gỡ lỗi
xuất vXtrapLNI=()
# thay thế BASH_COMMAND
# đây là lệnh nguồn chưa được thay thế ban đầu
# sau đây là phiên bản thay thế được nén của lệnh nguồn
# "${vXtrcTrapArg0[$lIdx]} ${vXtrcTrapArgV[$lIdx]}"
xuất vXtrapCmd=()
# thay thế BASH_ARGV0
xuất vXtrapArg0=()
# thay thế BASH_ARGVC
xuất vXtrapArgC=()
# thay thế BASH_ARGV
# phân cách bằng dấu cách
xuất vXtrapArgV=()
# thay thế $?
xuất vXtrapRc=()
# thông báo syserr thay thế
xuất vXtrapRcMsg=()
đặt +o dài dòng
090
$BASH_SUBSHELL đặt 0
$LINENO đặt 89
$BASH_COMMAND đặt tiếng vang '$BASH_COMMAND đặt '"$BASH_COMMAND"
${BASH_SOURCE[0]} đặt SHtest.sh
bash: FUNCNAME[$i]: biến không liên kết
bash: FUNCNAME[0]: biến không liên kết
++:${BASH_SOURCE[0]}:${FUNCNAME[0]}:${LINENO[0]}::x:: vXtrapSub=("$BASH_SUBSHELL" "$BASH_SUBSHELL" "$BASH_SUBSHELL")
bash: FUNCNAME[0]: biến không liên kết
++:${BASH_SOURCE[0]}:${FUNCNAME[0]}:${LINENO[0]}::x:: vXtrapSrc=("${BASH_SOURCE[0]}" '' '')
bash: FUNCNAME[0]: biến không liên kết
++:${BASH_SOURCE[0]}:${FUNCNAME[0]}:${LINENO[0]}::x:: vXtrapScr=("$vPtrapScr" '' '')
bash: FUNCNAME[0]: biến không liên kết
++:${BASH_SOURCE[0]}:${FUNCNAME[0]}:${LINENO[0]}::x:: vXtrapFNm=('' '' '')
bash: FUNCNAME[0]: biến không liên kết
++:${BASH_SOURCE[0]}:${FUNCNAME[0]}:${LINENO[0]}::x:: vXtrapLNo=('0' "${BASH_LINENO[0]}" '0')
bash: FUNCNAME[0]: biến không liên kết
++:${BASH_SOURCE[0]}:${FUNCNAME[0]}:${LINENO[0]}::x:: vXtrapLNI=('0' '0' '0')
bash: FUNCNAME[0]: biến không liên kết
++:${BASH_SOURCE[0]}:${FUNCNAME[0]}:${LINENO[0]}::x:: vXtrapCmd=("$vPtrapCmd" "$vPtrapCmd" '')
bash: FUNCNAME[0]: biến không liên kết
++:${BASH_SOURCE[0]}:${FUNCNAME[0]}:${LINENO[0]}::x:: vXtrapArg0=("$vPtrapArg0" "$vPtrapArg0" '')
bash: FUNCNAME[0]: biến không liên kết
++:${BASH_SOURCE[0]}:${FUNCNAME[0]}:${LINENO[0]}::x:: vXtrapArgC=("$vPtrapArgC" "$vPtrapArgC" '0')
bash: FUNCNAME[0]: biến không liên kết
++:${BASH_SOURCE[0]}:${FUNCNAME[0]}:${LINENO[0]}::x:: vXtrapArgV=("$vPtrapArgV" "$vPtrapArgV" '')
bash: FUNCNAME[0]: biến không liên kết
++:${BASH_SOURCE[0]}:${FUNCNAME[0]}:${LINENO[0]}::x:: vXtrapRc=('0' '0' '0')
bash: FUNCNAME[0]: biến không liên kết
++:${BASH_SOURCE[0]}:${FUNCNAME[0]}:${LINENO[0]}::x:: vXtrapRcMsg=('' '' '')
bash: FUNCNAME[0]: biến không liên kết
++:${BASH_SOURCE[0]}:${FUNCNAME[0]}:${LINENO[0]}::x:: set +o xtrace
100
110
ubuntu@ubuntu:/pool/src/trap/scr$
Tôi hy vọng mã này và đầu ra có ý nghĩa với những người đọc nó.