ฉันมีชุดสคริปต์ที่ค่อนข้างใหญ่ซึ่งเป็นส่วนเริ่มต้นของการสร้างตรรกะการดีบัก/การบันทึกสำหรับสคริปต์ทุบตี มีรหัสจำนวนมากในระบบ โชคดีที่ฉันสามารถแสดงผลลัพธ์ต่างๆ ที่ฉันไม่สามารถอธิบายได้เมื่อเรียกใช้สคริปต์ +u และ -u ตั้งค่าตัวแปรตามที่ทดสอบโดยใช้ +u กลายเป็นตัวแปรที่ไม่ได้ตั้งค่าเมื่อรันด้วย -u ชื่อ varibl.e ในกรณีนี้คือ $FUNCNAME
สคริปต์การทดสอบสั้น ๆ มีดังนี้:
#!/bin/bash
### ชุด -e
### ตั้ง -f
### ชุด -u
### ชุด -C
### ชุด -P
### ตั้งค่า -o ไปป์ไลน์
ส่งออก 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=()
#เปลี่ยนLINENO
# โดยที่ BASH_LINENO[lIdx] ควรเท่ากับ vXtrapLNo[lIdx+1]
ส่งออก vXtrapLNo=()
#การเริ่มต้นLINENO
# บรรทัดรายงานเริ่มต้นของฟังก์ชันใน Debug Trap
ส่งออก vXtrapLNI=()
# แทนที่ BASH_COMMAND
# นี่คือคำสั่งซอร์สต้นฉบับที่ไม่ถูกแทนที่
# ต่อไปนี้คือคำสั่งซอร์สเวอร์ชันบีบอัดที่ถูกแทนที่
# "${vXtrcTrapArg0[$lIdx]} ${vXtrcTrapArgV[$lIdx]}"
ส่งออก vXtrapCmd=()
# แทนที่ BASH_ARGV0
ส่งออก vXtrapArg0=()
# การแทนที่ BASH_ARGVC
ส่งออก vXtrapArgC=()
# การแทนที่ BASH_ARGV
#คั่นด้วยช่องว่าง
ส่งออก vXtrapArgV=()
# เปลี่ยน $?
ส่งออก vXtrapRc=()
# ข้อความแทนที่ syserr
ส่งออก vXtrapRcMsg=()
ตั้ง +o อย่างละเอียด
อ่าน -rp '090'
#####
# ถ่ายโอนการเริ่มต้นคำสั่งเริ่มต้นไปยังตารางการติดตามที่แก้ไข
#####
ฉัน=0
iMax=${#BASH_LINENO[@]}
เจ=0
k=0
วี=''
พิมพ์f '\n'
v="$BASH_SUBSHELL"
ถ้า [[ -z "$v" && -n "${v-_}" ]]; แล้ว
echo '$BASH_SUBSHELL unset' "$BASH_SUBSHELL"
อื่น
เสียงสะท้อน '$BASH_SUBSHELL ชุด ' "$BASH_SUBSHELL"
ไฟ
v="$LINENO"
ถ้า [[ -z "$v" && -n "${v-_}" ]]; แล้ว
echo '$LINENO unset' "$LINENO"
อื่น
echo '$LINENO ชุด '"$LINENO"
ไฟ
v="$BASH_COMMAND"
ถ้า [[ -z "$v" && -n "${v-_}" ]]; แล้ว
echo '$BASH_COMMAND unset' "$BASH_COMMAND"
อื่น
echo '$BASH_COMMAND ตั้ง' "$BASH_COMMAND"
ไฟ
สำหรับ (( i=0; i<=iMax; i++ ))
ทำ
พิมพ์f '\n'
v="${BASH_SOURCE["$i"]}"
ถ้า [[ -z "$v" && -n "${v-_}" ]]; แล้ว
echo '${BASH_SOURCE['"$i"']} unset '"${BASH_SOURCE[$i]}"
อื่น
echo '${BASH_SOURCE['"$i"']} set '"${BASH_SOURCE[$i]}"
ไฟ
v="${FUNCNAME[$i]}"
ถ้า [[ -z "$v" && -n "${v-_}" ]]; แล้ว
echo '${FUNCNAME['"$i"']} unset '"${FUNCNAME[$i]}"
อื่น
echo '${FUNCNAME['"$i"']} set '"${FUNCNAME[$i]}"
ไฟ
v="${BASH_LINENO["$i"]}"
ถ้า [[ -z "$v" && -n "${v-_}" ]]; แล้ว
echo '${BASH_LINENO['"$i"']} unset '"${BASH_LINENO[$i]}"
อื่น
echo '${BASH_LINENO['"$i"']} set '"${BASH_LINENO[$i]}"
ไฟ
v="${BASH_ARGV0[i]}"
ถ้า [[ -z "$v" && -n "${v-_}" ]]; แล้ว
echo '${BASH_ARGV0['"$i"']} unset '"${BASH_ARGV0[$i]}"
อื่น
echo '${BASH_ARGV0['"$i"']} set '"${BASH_ARGV0[$i]}"
ไฟ
v="${BASH_ARGC[i]}"
ถ้า [[ -z "$v" && -n "${v-_}" ]]; แล้ว
echo '${BASH_ARGC['"$i"']} unset '"${BASH_ARGC[$i]}"
อื่น
echo '${BASH_ARGC['"$i"']} set '"${BASH_ARGC[$i]}"
ไฟ
เจ=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"]}"
ไฟ
(( k++ ))
(( j++ ))
เสร็จแล้ว
เสร็จแล้ว
vPtrapScr="$(ชื่อฐาน "${BASH_SOURCE[0]}" '.sh' )"
vPtrapArgC='1'
vPtrapArgV=''
ในขณะที่ [ $vPtrapArgC -lt ${BASH_ARGC[0]} ]
ทำ
กรณี "$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 Trap สิ่งเหล่านี้จะเป็นคำสั่งสคริปต์ปัจจุบัน
vXtrapCmd=( "$vPtrapCmd" "$vPtrapCmd" '' )
vXtrapArg0=( "$vPtrapArg0" "$vPtrapArg0" '' )
vXtrapArgC=( "$vPtrapArgC" "$vPtrapArgC" '0' )
vXtrapArgV=( "$vPtrapArgV" "$vPtrapArgV" '' )
vXtrapRc=( '0' '0' '0' )
vXtrapRcMsg=( '' '' '' )
ตั้ง +o xtrace
อ่าน -rp '100'
ยกเลิกการตั้งค่า
ยกเลิกการตั้งค่า iMax
ยกเลิกการตั้งค่า J
ยกเลิกการตั้งค่า k
ยกเลิกการตั้งค่า v
ยกเลิกการตั้งค่า vPtrapScr
ยกเลิกการตั้งค่า vPtrapCmd
ยกเลิกการตั้งค่า vPtrapArg0
ยกเลิกการตั้งค่า vPtrapArgC
ยกเลิกการตั้งค่า vPtrapArgV
อ่าน -rp '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=()
#เปลี่ยนLINENO
# โดยที่ BASH_LINENO[lIdx] ควรเท่ากับ vXtrapLNo[lIdx+1]
ส่งออก vXtrapLNo=()
#การเริ่มต้นLINENO
# บรรทัดรายงานเริ่มต้นของฟังก์ชันใน Debug Trap
ส่งออก 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 set echo '$BASH_COMMAND set ' "$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]} ตั้งค่า ref=${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:: ตั้งค่า +o xtrace
100
110
ubuntu@ubuntu:/pool/src/trap/scr$ set -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=()
#เปลี่ยนLINENO
# โดยที่ BASH_LINENO[lIdx] ควรเท่ากับ vXtrapLNo[lIdx+1]
ส่งออก vXtrapLNo=()
#การเริ่มต้นLINENO
# บรรทัดรายงานเริ่มต้นของฟังก์ชันใน Debug Trap
ส่งออก 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 set echo '$BASH_COMMAND set ' "$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$
ฉันหวังว่ารหัสและผลลัพธ์นี้จะสมเหตุสมผลสำหรับผู้ที่อ่าน