Bash 스크립트에서 실행된 마지막 줄을 쉽게 찾을 수 있는 방법이 있습니까?

Bash 스크립트에서 실행된 마지막 줄을 쉽게 찾을 수 있는 방법이 있습니까?

수천 번 실행되는 for 루프가 포함된 bash 스크립트를 실행하고 있습니다. 이 for 루프의 어딘가에서 코드가 자주 멈추는 경우가 있습니다. (내가 본 가장 낮은 반복은 32회이고 대부분은 4000회 정도에서 멈춥니다. 코드는 5000회 실행해야 하며 때로는 작업을 완료하기도 합니다.) 이 문제를 디버깅하고 싶습니다. 분명히 명령 창에 수십만 줄의 코드를 수동으로 입력하고 멈출 때까지 기다리고 싶지 않습니다.

마지막으로 실행했거나 실행하려고 시도한 줄이 무엇인지 알아내는 쉬운 방법이 있습니까? (무언가 잘못되면 터미널이 정지되는 것처럼 보입니다. 때로는 전체 시스템이 작동을 멈추고 다시 시작하려면 원격 재설정이 필요하다는 점을 명심하십시오.) 이것이 echo의 기능일지도 모른다고 생각했습니다. 내가 찾은이 질문과 답변그러나 "명령이 파서의 관점에서 스크립트의 특정 줄을 나타내는 경우"가 무엇을 의미하는지 잘 모르겠습니다. 따라서 적용되는 경우입니다. 또한 이 코드가 실제로 무엇을 하는지 매우 혼란스럽습니다. 이 코드가 도움이 된다면 감사하겠습니다.

이것이 내가 찾고 있는 답인가? 이 문제에 대한 다른 해결책이 있습니까?

답변1

먼저 문제가 발생하는 반복을 확인해야 합니다. 운이 좋으면 항상 똑같습니다. 어쨌든 그렇게 하지 않으면 반복 횟수를 세어 인쇄하거나 파일에 써야 합니다.

exec 3>/my/logfile
iter=0
while whatevercondition; do
  ((iter++))
  echo "$iter" >&3
done

동일한 반복에서 문제가 항상 발생하는 경우 디버그 출력을 활성화한 후 다음을 수행해야 합니다.

CRASH_ITER=12345
iter=0
while whatevercondition; do
  ((iter++))
  if [ "$iter" -eq "$CRASH_ITER" ]; then
    set -vx
  fi
done

재현 불가능한 오류

오류를 특정 반복으로 좁힐 수 없는 경우 bash가 전체 디버그 출력을 파일에 쓰도록 할 수 있습니다.

bash -vx ./script.sh 2>debug.txt

답변2

Bash 스크립트 상단에 이것을 추가하는 경우:

   함수 DEBUG_TRAP() {
      조판-p BASH_SOURCE; 조판-p BASH_LINENO;
   }
   트랩 DEBUG_TRAP INT

프로세스에 INT 신호를 보내면 프로그램 위치에 대한 정보를 얻을 수 있습니다.

kill -INT process-number

다음과 같이 bash 스크립트에서 프로세스 번호를 얻을 수 있습니다.

   에코$$

이 작업을 수행한 후에도 출력이 나오지 않으면 스크립트가 출력을 리디렉션했거나 스크립트가 진행 중인 것입니다. lsof는 출력 리디렉션에 대해 알려줍니다.메모진행상황에 대한 정보가 제공됩니다.

답변3

루프가 다음과 같은 경우:

i=0
while [ "$((i+=1))" -le 5000 ] &&
      set >iter.log
do    monte_carlo
done

각 반복은 매번 모든 쉘 변수의 현재 값을 나열하는 파일을 덮어씁니다. 따라서 488을 실행하는 동안 중단되면반복 로그파일은 $i반복 시작 시 488 값과 기타 모든 쉘 변수를 기록합니다.

실패한 줄 번호를 추적하려면 한 단계 더 나아갈 수 있습니다.

i=0 PS4='$LINENO : '; set -x
while [ ... ] &&
      set >iter.log
do    ...
done 2>>iter.log

이렇게 하면 반복할 때마다 파일을 덮어쓰지만 실행된 각 줄에 대한 디버그 출력도 추가하고 파일에 해당 줄 번호를 포함합니다.

관련 정보