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 이상에서 테스트되었으므로 4 이전 버전에 필요한 것이 있으면 의견을 남기거나 최소 버전이 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'
작동합니다.