bash 스크립트를 디버깅하는 방법이 있습니까? 예를 들어 "calling line 1", "calling line 2"등과 같은 일종의 실행 로그를 인쇄하는 것.
bash 스크립트를 디버깅하는 방법이 있습니까? 예를 들어 "calling line 1", "calling line 2"등과 같은 일종의 실행 로그를 인쇄하는 것.
답변:
sh -x script [arg1 ...]
bash -x script [arg1 ...]
이것들은 실행중인 것을 추적합니다. (답변 하단의 '설명'도 참조하십시오.)
때로는 스크립트 내에서 디버깅을 제어해야합니다. 이 경우 Cheeto가 상기 한 것처럼 다음을 사용할 수 있습니다.
set -x
디버깅이 켜집니다. 그런 다음 다음을 사용하여 다시 끌 수 있습니다.
set +x
$-
에 대한 현재 플래그 를 분석하여 현재 추적 상태를 찾을 수 있습니다 x
.
또한 쉘은 일반적으로 ' -n
'실행 없음 ' 의 경우' '및 -v
'세부 정보 '모드의 경우 ' ' 옵션을 제공 합니다. 이것들을 조합하여 사용하면 쉘이 스크립트를 실행할 수 있다고 생각하는지 알 수 있습니다. 어딘가에 불균형 한 인용 부호가있는 경우 유용합니다.
-x
Bash 의 ' '옵션이 다른 쉘과 다르다는 주장이 있습니다 (주석 참조). 배쉬 설명서는 말한다 :
-엑스
간단한 명령, for
명령, case
명령, select
명령 및 산술 for
명령 및 인수 또는 관련 단어 목록을 확장 한 후 실행하기 전에 추적하십시오 . PS4
변수 값 이 확장되고 결과 값이 명령 및 확장 인수 앞에 인쇄됩니다.
그다지 다른 행동을 나타내는 것은 아닙니다. -x
매뉴얼 에 ' '에 대한 다른 관련 참조가 없습니다 . 시작 순서의 차이점에 대해서는 설명하지 않습니다.
설명 : 일반적인 Linux 상자와 같은 시스템에서 ' /bin/sh
'는 ' '에 대한 심볼릭 링크 /bin/bash
(또는 Bash 실행 파일이있는 곳)이면 두 명령 줄은 실행 추적이 설정된 상태에서 스크립트를 실행하는 것과 동일한 효과를 얻습니다. 다른 시스템 (예 : Solaris 및 일부 최신 Linux 변형)에서는 /bin/sh
Bash가 아니며 두 명령 행은 (약간) 다른 결과를 제공합니다. 특히 ' /bin/sh
'는 Bash의 구문에 의해 전혀 인식되지 않는 혼란 스러울 것입니다. (Solaris에서 /bin/sh
Bourne 쉘이며, 현대 Linux에서는 때때로 더 작고 더 엄격하게 POSIX 전용 쉘인 Dash입니다.) 이와 같은 이름으로 'shebang'행 ( ' #!/bin/bash
'vs '#!/bin/sh
'
bash는 설명서에 대한 섹션이 배쉬 POSIX 모드 의 차이 '배쉬로 호출 광범위한 자세히 설명 않습니다 (아래도 의견을 참조)이 답변의 오랜하지만 잘못된 버전과 달리 sh
'와 '배쉬로 호출 bash
'.
(Bash) 쉘 스크립트를 디버깅 할 때 shebang 행에 이름이 지정된 쉘을 -x
옵션 과 함께 사용하는 것이 합리적이고 제정신 입니다. 그렇지 않으면 스크립트를 실행할 때와 디버깅 할 때 다른 동작이 나타날 수 있습니다.
bash
스크립트를 지정했습니다 . 그리고 bash 스크립트를 실행하면 sh -x
완전히 다르게 동작합니다! 답변을 업데이트하십시오.
export PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
스크립트를 디버깅하기 위해 다음 방법을 사용했습니다.
set -e
외부 프로그램이 0이 아닌 종료 상태를 리턴하면 스크립트가 즉시 중지됩니다. 이것은 스크립트가 모든 오류 사례를 처리하려고 시도하고 실패한 경우를 포착해야하는 경우에 유용합니다.
set -x
위에서 언급했으며 모든 디버깅 방법 중 가장 유용합니다.
set -n
스크립트에서 구문 오류를 확인하려는 경우에도 유용 할 수 있습니다.
strace
무슨 일이 일어나고 있는지 볼 때도 유용합니다. 스크립트를 직접 작성하지 않은 경우 특히 유용합니다.
strace -f
당신은 또한 스크립트에 의해 시작 프로세스에서 오류를 발견 할 경우 필요합니다. (여러 번 더 장황하게 만들지 만 관심있는 syscalls로 제한하면 여전히 유용합니다).
set -e
... 논쟁의 여지가 있습니다.
이 답변은 유효하고 유용합니다 : https://stackoverflow.com/a/951352
그러나 "표준"스크립트 디버깅 방법은 비효율적이며 직관적이지 않으며 사용하기 어렵다는 것을 알게되었습니다. 복잡한 GUI 디버거에 익숙한 사용자라면 모든 문제를 쉽게 해결할 수 있고 작업이 쉬워 쉽게 문제를 해결할 수 있습니다 (어려운 문제는 가능).
내가하는 일은 DDD와 bashdb의 조합을 사용하는 것입니다. 전자는 후자를 실행하고 후자는 스크립트를 실행합니다. 이를 통해 다중 창 UI에 컨텍스트를 유지하거나 소스를 계속 나열하려는 지속적인 정신적 노력없이 컨텍스트에서 코드를 단계별로 실행하고 변수, 스택 등을 볼 수 있습니다.
여기에 설정에 대한 지침이 있습니다 : http://ubuntuforums.org/showthread.php?t=660223
나는 shellcheck 유틸리티를 발견했고 어떤 사람들은 그것을 재미 있다고 생각할지도 모른다 https://github.com/koalaman/shellcheck
작은 예 :
$ cat test.sh
ARRAY=("hello there" world)
for x in $ARRAY; do
echo $x
done
$ shellcheck test.sh
In test.sh line 3:
for x in $ARRAY; do
^-- SC2128: Expanding an array without an index only gives the first element.
버그 수정, 먼저 시도해보십시오 ...
$ cat test.sh
ARRAY=("hello there" world)
for x in ${ARRAY[@]}; do
echo $x
done
$ shellcheck test.sh
In test.sh line 3:
for x in ${ARRAY[@]}; do
^-- SC2068: Double quote array expansions, otherwise they're like $* and break on spaces.
다시 해보자...
$ cat test.sh
ARRAY=("hello there" world)
for x in "${ARRAY[@]}"; do
echo $x
done
$ shellcheck test.sh
지금 찾으십시오!
작은 예일뿐입니다.
플러그인 쉘 및 basheclipse와 함께 이클립스를 사용하십시오.
https://sourceforge.net/projects/shelled/?source=directory https://sourceforge.net/projects/basheclipse/?source=directory
껍질이있는 경우 : zip을 다운로드하고 도움말을 통해 일식으로 가져 오기-> 새 소프트웨어 설치 : 로컬 아카이브 basheclipse의 경우 : 항아리를 일식의 dropins 디렉토리에 복사하십시오.
https://sourceforge.net/projects/basheclipse/files/?source=navbar 제공 단계를 따르십시오
http://dietrichschroff.blogspot.de/2017/07/bash-enabling-eclipse-for-bash.html 에서 많은 스크린 샷이있는 자습서를 작성했습니다.
+ x = @ECHO OFF로 설정하고 -x = @ECHO ON으로 설정하십시오.
-xv
다음과 같이 표준 Shebang 에 옵션을 추가 할 수 있습니다 .
#!/bin/bash -xv
-x
: 명령과 인수가 실행될 때 표시합니다.
-v
: 쉘 입력 라인을 읽을 때 표시합니다.
ltrace
와 비슷한 다른 Linux 유틸리티 strace
입니다. 그러나 ltrace
실행 파일 또는 실행중인 프로세스에서 호출되는 모든 라이브러리 호출을 나열합니다. 이름 자체는 라이브러리 호출 추적에서 비롯됩니다. 예를 들면 다음과 같습니다.
ltrace ./executable <parameters>
ltrace -p <PID>
이 Bash 디버거를 사용할 수 있다고 생각합니다 : http://bashdb.sourceforge.net/ .
set -[nvx]
이외에
set -x
과
set +x
덤프를 중지합니다.
set -v
덜 개발 된 출력만큼 작은 덤프 에 대해 이야기하고 싶습니다 .
bash <<<$'set -x\nfor i in {0..9};do\n\techo $i\n\tdone\nset +x' 2>&1 >/dev/null|wc -l
21
for arg in x v n nx nv nvx;do echo "- opts: $arg"
bash 2> >(wc -l|sed s/^/stderr:/) > >(wc -l|sed s/^/stdout:/) <<eof
set -$arg
for i in {0..9};do
echo $i
done
set +$arg
echo Done.
eof
sleep .02
done
- opts: x
stdout:11
stderr:21
- opts: v
stdout:11
stderr:4
- opts: n
stdout:0
stderr:0
- opts: nx
stdout:0
stderr:0
- opts: nv
stdout:0
stderr:5
- opts: nvx
stdout:0
stderr:5
일부 변수를 테스트하기 위해 언젠가 이것을 사용합니다.
bash <(sed '18ideclare >&2 -p var1 var2' myscript.sh) args
추가를 위해 :
declare >&2 -p var1 var2
18 번째 줄에서 스크립트 를 편집하지 않고도 결과 스크립트 ( args 사용 )를 실행 합니다.
물론 이것은 다음을 추가하는 데 사용될 수 있습니다 set [+-][nvx]
.
bash <(sed '18s/$/\ndeclare -p v1 v2 >\&2/;22s/^/set -x\n/;26s/^/set +x\n/' myscript) args
declare -p v1 v2 >&2
줄 18 뒤에, set -x
줄 22와 set +x
줄 26 앞에 추가됩니다 .
bash <(sed '2,3s/$/\ndeclare -p LINENO i v2 >\&2/;5s/^/set -x\n/;7s/^/set +x\n/' <(
seq -f 'echo $@, $((i=%g))' 1 8)) arg1 arg2
arg1 arg2, 1
arg1 arg2, 2
declare -i LINENO="3"
declare -- i="2"
/dev/fd/63: line 3: declare: v2: not found
arg1 arg2, 3
declare -i LINENO="5"
declare -- i="3"
/dev/fd/63: line 5: declare: v2: not found
arg1 arg2, 4
+ echo arg1 arg2, 5
arg1 arg2, 5
+ echo arg1 arg2, 6
arg1 arg2, 6
+ set +x
arg1 arg2, 7
arg1 arg2, 8
참고 : 주의 사항 $LINENO
은 즉석 수정 으로 인해 영향을받습니다 !
(실행하는 동안 결과 스크립트를 보려면 간단히 삭제 bash <(
하고 ) arg1 arg2
)
bash 스크립트를 프로파일 링하는 방법에 대한 내 대답을 살펴보십시오.
셸의 전역 변수를 통한 셸 스크립트 로깅에 대한 자세한 내용이 있습니다. 쉘 스크립트에서 비슷한 종류의 로깅을 에뮬레이트 할 수 있습니다 : http://www.cubicrace.com/2016/03/log-tracing-mechnism-for-shell-scripts.html
이 게시물에는 INFO, DEBUG, ERROR와 같은 로그 수준 소개에 대한 세부 정보가 있습니다. 스크립트 입력, 스크립트 종료, 기능 입력, 기능 종료와 같은 세부 사항 추적
샘플 로그 :