ERR sinyalinin hangi hatta gönderildiğini bulmak mümkün müdür?
Evet LINENO
ve BASH_LINENO
değişkenler akşam yemeğinde başarısızlık hattını ve buna yol açan satırları almak için kullanışlıdır.
Ya da belki de tamamen yanlış yapıyorum?
Hayır, sadece -q
grep seçeneğiyle eksik seçenek ...
echo hello | grep -q "asdf"
... ile -q
seçeneği grep
dönecektir 0
için true
ve 1
için false
. Ve Bash'de trap
değil Trap
...
trap "_func" ERR
... doğal bir çözüme ihtiyacım var ...
İşte size biraz daha döngüsel karmaşıklığı olan şeyleri hata ayıklamak için yararlı bulabileceğiniz bir tuzak ...
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}
}
... ve yukarıdaki fonksiyon tuzağının nasıl ayarlanacağına dair ince farkları ortaya çıkarmak için örnek bir komut dosyası ...
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'in sürüm 4+ üzerinde test edildiği yukarıdakiler, dört yaşından önceki sürümler için bir şeye ihtiyaç duyulursa bir yorum bırakın ya da en az dört sürümü olan sistemlerdeki arızaları yakalayamazsa bir Sorun Açın .
Ana paket servis yerleri ...
set -E -o functrace
trap 'failure "LINENO" "BASH_LINENO" "${BASH_COMMAND}" "${?}"' ERR
Tek tırnak, işlev çağrısı etrafında kullanılır ve çift tırnak, bağımsız değişkenlerin etrafındadır.
Mevcut değerlerin yerine referanslar verilir LINENO
ve BASH_LINENO
bu, tuzağa bağlı olan sonraki sürümlerinde kısaltılabilir, ancak son başarısızlık çizgisi bunu çıktı haline getirir.
Değerleri BASH_COMMAND
ve çıkış durumu ( $?
) ilk hata döndürdü komutu almak için geçti ve ikinci tuzak olmayan hata durumları ile ilgili tetiklemez sağlamaktan
Ve diğerleri aynı fikirde olmayabilirken, bir çıktı dizisi oluşturmanın ve her dizi öğesini kendi satırına yazdırmak için printf kullanmanın daha kolay olduğunu düşünüyorum ...
printf '%s\n' "${_output_array[@]}" >&2
... ayrıca >&2
sondaki bit, hataların olması gerektiği yere gitmesine neden olur (standart hata) ve sadece hataların yakalanmasına izin verir ...
## ... to a file...
some_trapped_script.sh 2>some_trapped_errros.log
## ... or by ignoring standard out...
some_trapped_script.sh 1>/dev/null
Bunlar ve Yığın Taşması ile ilgili diğer örnekler tarafından gösterildiği gibi , yerleşik yardımcı programları kullanarak bir hata ayıklama yardımı oluşturmanın birçok yolu vardır.
bashdb
.trap
İstenen bağlamda değerlendirilen değişkenleri içerebilecek ilk argümanın olduğu anlaşılmaktadır . Öyleysetrap 'echo $LINENO' ERR'
çalışmalı.