เป็นไปได้ไหมที่จะรับสัญญาณ ERR ที่เป็นเส้นตรง?
ใช่LINENO
และBASH_LINENO
ตัวแปรต่าง ๆ เป็นอาหารมื้อเย็นที่มีประโยชน์สำหรับการทำให้เกิดความล้มเหลวและเส้นที่นำไปสู่มัน
หรือบางทีฉันอาจจะทำผิดทั้งหมดนี้?
ไม่เหลือ-q
ตัวเลือกที่มี grep ...
echo hello | grep -q "asdf"
... ด้วย-q
ตัวเลือกที่grep
จะกลับมา0
สำหรับtrue
และสำหรับ1
false
และใน Bash trap
ไม่ใช่Trap
...
trap "_func" ERR
... ฉันต้องการวิธีแก้ปัญหาแบบเนทีฟ ...
นี่เป็นกับดักสัตว์ที่คุณคิดว่ามีประโยชน์สำหรับการดีบั๊กสิ่งที่มีความซับซ้อนเพิ่มขึ้นอีกเล็กน้อย ...
failure.sh
## Outputs Front-Mater formatted failures for functions not returning 0
## Use the following line after sourcing this file to set failure trap
## trap 'failure "LINENO" "BASH_LINENO" "${BASH_COMMAND}" "${?}"' ERR
failure(){
local -n _lineno="${1:-LINENO}"
local -n _bash_lineno="${2:-BASH_LINENO}"
local _last_command="${3:-${BASH_COMMAND}}"
local _code="${4:-0}"
## Workaround for read EOF combo tripping traps
if ! ((_code)); then
return "${_code}"
fi
local _last_command_height="$(wc -l <<<"${_last_command}")"
local -a _output_array=()
_output_array+=(
'---'
"lines_history: [${_lineno} ${_bash_lineno[*]}]"
"function_trace: [${FUNCNAME[*]}]"
"exit_code: ${_code}"
)
if [[ "${#BASH_SOURCE[@]}" -gt '1' ]]; then
_output_array+=('source_trace:')
for _item in "${BASH_SOURCE[@]}"; do
_output_array+=(" - ${_item}")
done
else
_output_array+=("source_trace: [${BASH_SOURCE[*]}]")
fi
if [[ "${_last_command_height}" -gt '1' ]]; then
_output_array+=(
'last_command: ->'
"${_last_command}"
)
else
_output_array+=("last_command: ${_last_command}")
fi
_output_array+=('---')
printf '%s\n' "${_output_array[@]}" >&2
exit ${_code}
}
... และสคริปต์การใช้งานตัวอย่างสำหรับการเปิดเผยความแตกต่างเล็กน้อยในวิธีการตั้งค่ากับดักด้านบนสำหรับการติดตามการทำงานเช่นกัน ...
example_usage.sh
#!/usr/bin/env bash
set -E -o functrace
## Optional, but recommended to find true directory this script resides in
__SOURCE__="${BASH_SOURCE[0]}"
while [[ -h "${__SOURCE__}" ]]; do
__SOURCE__="$(find "${__SOURCE__}" -type l -ls | sed -n 's@^.* -> \(.*\)@\1@p')"
done
__DIR__="$(cd -P "$(dirname "${__SOURCE__}")" && pwd)"
## Source module code within this script
source "${__DIR__}/modules/trap-failure/failure.sh"
trap 'failure "LINENO" "BASH_LINENO" "${BASH_COMMAND}" "${?}"' ERR
something_functional() {
_req_arg_one="${1:?something_functional needs two arguments, missing the first already}"
_opt_arg_one="${2:-SPAM}"
_opt_arg_two="${3:0}"
printf 'something_functional: %s %s %s' "${_req_arg_one}" "${_opt_arg_one}" "${_opt_arg_two}"
## Generate an error by calling nothing
"${__DIR__}/nothing.sh"
}
## Ignoring errors prevents trap from being triggered
something_functional || echo "Ignored something_functional returning $?"
if [[ "$(something_functional 'Spam!?')" == '0' ]]; then
printf 'Nothing somehow was something?!\n' >&2 && exit 1
fi
## And generating an error state will cause the trap to _trace_ it
something_functional '' 'spam' 'Jam'
ด้านบนที่ทดสอบกับ Bash เวอร์ชัน 4+ ดังนั้นโปรดแสดงความคิดเห็นหากต้องการบางสิ่งสำหรับรุ่นก่อนหน้าสี่รายการหรือเปิดปัญหาถ้าไม่สามารถดักจับความล้มเหลวในระบบที่มีรุ่นต่ำสุดสี่รายการ
ประเด็นหลักคือ ...
set -E -o functrace
trap 'failure "LINENO" "BASH_LINENO" "${BASH_COMMAND}" "${?}"' ERR
อัญประกาศเดียวใช้รอบการเรียกใช้ฟังก์ชันและอัญประกาศคู่ล้อมรอบอาร์กิวเมนต์แต่ละตัว
การอ้างอิงถึงLINENO
และBASH_LINENO
ถูกส่งผ่านแทนค่าปัจจุบันแม้ว่าอาจจะสั้นลงในเวอร์ชันที่ใหม่กว่าของการเชื่อมโยงไปยังกับดักเช่นนั้นบรรทัดความล้มเหลวสุดท้ายทำให้มันกลายเป็นเอาท์พุท
ค่าของBASH_COMMAND
และสถานะการออก ( $?
) ถูกส่งก่อนอื่นเพื่อรับคำสั่งที่ส่งคืนข้อผิดพลาดและที่สองเพื่อให้แน่ใจว่ากับดักไม่ได้ทริกเกอร์สถานะที่ไม่ใช่ข้อผิดพลาด
และในขณะที่คนอื่นอาจไม่เห็นด้วยฉันพบว่ามันง่ายกว่าในการสร้างอาเรย์เอาท์พุทและใช้ printf สำหรับการพิมพ์แต่ละอิลิเมนต์อาร์เรย์ในบรรทัดของตัวเอง ...
printf '%s\n' "${_output_array[@]}" >&2
... อีก>&2
เล็กน้อยที่ส่วนท้ายทำให้เกิดข้อผิดพลาดไปยังที่ที่ควร (ข้อผิดพลาดมาตรฐาน) และช่วยให้จับข้อผิดพลาดเพียง ...
## ... to a file...
some_trapped_script.sh 2>some_trapped_errros.log
## ... or by ignoring standard out...
some_trapped_script.sh 1>/dev/null
ดังที่แสดงโดยตัวอย่างเหล่านี้และอื่น ๆใน Stack Overflow มีหลายวิธีในการสร้างตัวช่วยการดีบักโดยใช้ยูทิลิตี้ในตัว
bashdb
คุณสามารถดูสคริปต์ทุบตีดีบัก ดูเหมือนว่าอาร์กิวเมนต์แรกที่trap
สามารถมีตัวแปรที่ประเมินในบริบทที่ต้องการ ดังนั้นtrap 'echo $LINENO' ERR'
ควรทำงาน