bash가 신호 11, 분할 오류로 종료되는 이유를 찾는 방법

bash가 신호 11, 분할 오류로 종료되는 이유를 찾는 방법

Red Hat Linux(V6)를 실행하는 프로덕션 서버에서는 bash로부터 코어 덤프를 자주 받습니다. 이런 일이 하루에도 몇 번씩, 수십 번씩 일어납니다.

총 길이TR

해결하다: 코어에서 더 자세한 정보를 얻고 충돌을 일으킨 명령문을 찾으려면 bash-debuginfo를 설치하십시오.

이유: 이 경우에는 이전 버전의 bash에서 수정되지 않은 버그 때문이었습니다.lists.gnu.org/archive/html/bug-bash/2010-04/msg00038.html4.1에 대해 2010년 4월에 보고되었으며 4.2에서 수정되었습니다(2011년 초 출시).

세부 사항
이 서버는 단일 웹 애플리케이션(apache + cgi-bin)과 여러 배치를 실행합니다. webapp cgi(C 프로그램)는 종종 시스템 호출을 수행합니다.

셸 상호 작용이 많지 않으므로 일부 서비스나 웹 응용 프로그램으로 인해 코어 덤프가 발생할 수 있으며 이 오류의 원인을 알아야 합니다.

코어 덤프 역추적은 약간 지루합니다(아래 참조).

이 오류에 대한 자세한 내용을 보려면 어떻게 해야 합니까? 상위 프로세스 체인이 무엇인지(자세히), 현재 변수와 환경이 무엇인지, 어떤 스크립트 및/또는 명령이 실행되었는지 알고 싶습니다.

중재 시스템을 활성화했지만 이에 대한 중재 스레드도 약간 지루합니다. 예는 다음과 같습니다.

type=ANOM_ABEND msg=audit(1516626710.805:413350): auid=1313 uid=1313 gid=22107 ses=64579 pid=8655 comm="bash" sig=11

핵심 추적은 다음과 같습니다.

    Core was generated by `bash'.
Program terminated with signal 11, Segmentation fault.
#0  0x000000370487b8ec in free () from /lib64/libc.so.6
#0  0x000000370487b8ec in free () from /lib64/libc.so.6
#1  0x000000000044f0b0 in hash_flush ()
#2  0x0000000000458870 in assoc_dispose ()
#3  0x0000000000434f55 in dispose_variable ()
#4  0x000000000044f0a7 in hash_flush ()
#5  0x0000000000433ef3 in pop_var_context ()
#6  0x0000000000434375 in pop_context ()
#7  0x0000000000451fb1 in ?? ()
#8  0x0000000000451c84 in run_unwind_frame ()
#9  0x000000000043200f in ?? ()
#10 0x000000000042fa18 in ?? ()
#11 0x0000000000430463 in execute_command_internal ()
#12 0x000000000046b86b in parse_and_execute ()
#13 0x0000000000444a01 in command_substitute ()
#14 0x000000000044e38e in ?? ()
#15 0x0000000000448d4e in ?? ()
#16 0x000000000044a1b7 in ?? ()
#17 0x0000000000457ac8 in expand_compound_array_assignment ()
#18 0x0000000000445e79 in ?? ()
#19 0x000000000044a264 in ?? ()
#20 0x000000000042ee9f in ?? ()
#21 0x0000000000430463 in execute_command_internal ()
#22 0x000000000043110e in execute_command ()
#23 0x000000000043357e in ?? ()
#24 0x00000000004303bd in execute_command_internal ()
#25 0x0000000000430362 in execute_command_internal ()
#26 0x0000000000432169 in ?? ()
#27 0x000000000042fa18 in ?? ()
#28 0x0000000000430463 in execute_command_internal ()
#29 0x000000000043110e in execute_command ()
#30 0x000000000041d6d6 in reader_loop ()
#31 0x000000000041cebc in main ()
~

고쳐 쓰다: 시스템이 VMWare에서 처리되는 가상 머신에서 실행되고 있습니다.

  • 배쉬의 버전은 무엇입니까? GNU bash, 버전 4.1.2(1)-릴리스(x86_64-redhat-linux-gnu)

  • 어떤 버전의 libc 및 기타 라이브러리가 bash에 연결되어 있습니까?

ldd(GNU libc) 2.12

(Bash에는 어떤 다른 라이브러리가 연결되어 있습니까? 세부 정보를 지속적으로 가져오는 명령이 있습니까?

  • 스크립트나 대화형 셸, 또는 둘 다를 실행할 때 이런 일이 발생합니까? 스크립트인 경우 하나의 스크립트에서만 발생합니까, 아니면 여러 스크립트에서 발생합니까, 아니면 모든 스크립트에서 발생합니까? 일반적으로 bash 스크립트는 어떤 유형의 작업을 수행합니까? 다른 프로세스에서 세그먼트 오류가 발생합니까? 서버에서 메모리 테스트를 실행해 보셨나요? ECC RAM이 있나요?

내 질문에 명시된 바와 같이: 잘 모르겠습니다. 그러나 예약된 스크립트나 대화형 웹 응용 프로그램 내부의 일부 시스템 호출로 인해 발생해야 합니다. 다음 구조와 같이 "스크립트 내의 스크립트"일 수도 있습니다.

myVar=$($(some command here ($and here too))

그러나 이 문제는 RAM의 물리적 문제가 아닐 수도 있다고 생각합니다. 다른 무작위 충돌은 없고 이번 충돌만 발생했으며 2개의 별도 물리적 시스템에서 실행되는 2개의 별도 가상 시스템에서도 이 문제가 발생했습니다.

업데이트 2:

스택에서 문제가 연관 배열과 관련이 있을 수 있다고 생각합니다.

#1  0x000000000044f0b0 in hash_flush ()
#2  0x0000000000458870 in assoc_dispose ()
#3  0x0000000000434f55 in dispose_variable ()
#4  0x000000000044f0a7 in hash_flush ()

이러한 변수는 거의 모든 사용자 정의 스크립트에 존재합니다. 시스템에 일반적으로 사용되는 변수와 기능이 포함된 라이브러리를 사용하는 기본 스크립트가 있습니다.

우리가 가지고 있는 거의 모든 스크립트는 해당 스크립트에서 비롯됩니다.

답변1

gdb가 제안한 대로 debuginfo 도구를 설치했고 충돌을 일으킨 표현식을 얻었습니다.

#20 0x0000000000457ac8 in expand_compound_array_assignment (
    var=<value optimized out>, 
    value=0x150c660 "$(logPath \"$@\")", flags=<value optimized out>
)

이제 문제가 무엇인지, 어디에 있는지 알 수 있습니다. 내 경우에는 .bashrc의 함수에 있었고 근본 원인은 Bash에서 매핑된 변수를 잘못 재정의한 것이었습니다.

declare -A myMap
local myMap=""

...
for key in "${!myMap[@]}"; do 
  echo ${myMap[$key]}
done    

이 함수는 서브셸 내에서 호출되어 "세그먼트 오류" 오류 출력이 숨겨집니다.

답변2

이것은 전형적인 double free질문입니다. hash_flush()메모리 세그먼트에서 한 번 호출되고 0x000000000044f0a7에서 다시 호출됩니다 0x000000000044f0b0.

모든 호출을 검색 hash_flush()하고 호출 전의 연관 배열 값을 확인해야 합니다.

Shebang 라인에서 로깅을 활성화하고 매개변수 조합을 사용하면 -x문제가 발생합니다.

bash에 대해 100% 확신할 수는 없지만 힙에서 메모리를 정리합니다(Perl, Python, PHP 및 Java의 GC 또는 C/C++의 free(), dealloc() 등).

죄송합니다. 확실한 해결책은 아니지만 코드 등을 확인해야 합니다.

관련 정보