본문 바로가기
IT/Linux

[Linux] strace로 리눅스 애플리케이션 장애 진단: 실제 디버깅 사례 분석

by 수누다 2026. 7. 30.
반응형

[리눅스] strace로 리눅스 애플리케이션 장애 진단

리눅스 서버를 오래 보다 보면, 로그는 멀쩡한데 애플리케이션만 묘하게 멈춰 있는 순간이 꼭 옵니다. 저도 실제 운영 환경과 홈랩에서 이런 상황을 여러 번 겪었고요. 그럴 때 꽤 자주 꺼내는 도구가 바로 strace 리눅스 디버깅입니다. 시스템 콜 추적(System Call Trace, 커널에 요청하는 함수 흐름 추적)을 보면, 애플리케이션이 지금 무엇을 하다가 막혔는지가 생각보다 적나라하게 드러나거든요.

처음엔 저도 이게 뭔가 싶었어요. 출력은 엄청 많고, 괄호 투성이고, 에러처럼 보이는 줄도 많아서 겁부터 났거든요. 근데 몇 번 삽질하고 나니까 패턴이 보이더라고요. 특히 시스템 콜 추적은 로그가 없는 장애, 시작은 되는데 응답이 없는 문제, 파일 권한 꼬임, DNS 지연, 소켓 연결 실패 같은 상황에서 정말 강력하더라고요.

이번 글에서는 제가 실제로 자주 쓰는 방식으로 리눅스 장애 해결에 strace를 어떻게 적용하는지, 그리고 애플리케이션 문제 진단을 할 때 어떤 흐름으로 보면 되는지 사례 중심으로 정리해보겠습니다.

strace 리눅스 디버깅 개요를 보여주는 시스템 콜 추적 다이어그램

애플리케이션, 커널, 파일 시스템, 네트워크 호출 흐름을 한눈에 보여주는 strace 리눅스 디버깅 개요 이미지입니다.

1. 왜 strace가 장애 분석에서 강력한가

쉽게 말해 strace는 애플리케이션이 커널에게 어떤 부탁을 하는지 보여주는 도구예요. 예를 들면 파일을 여는 <code>openat(), 네트워크에 연결하는 connect(), 데이터를 읽는 read(), 잠깐 멈추는 poll() 같은 호출이 보이거든요. 로그는 개발자가 남겨야 보이지만, 시스템 콜은 애플리케이션이 실제로 살아 움직이려면 거의 피할 수가 없거든요.

여기서 중요한 포인트! 로그가 없다고 해서 단서가 없는 건 아닙니다. 오히려 strace를 보면 로그를 못 남길 정도로 초반에 죽는 문제도 잡히는 경우가 많아요. 제가 직접 해보니 특히 아래 같은 상황에서 체감이 컸습니다.

  • 프로세스는 살아 있는데 응답이 없음
  • 시작 직후 바로 종료됨
  • 특정 파일이나 소켓 접근에서 실패함
  • DNS 조회나 외부 API 연결에서 지연됨
  • 권한(Permission) 문제인데 로그가 부실함

2. strace 핵심 개념 쉽게 이해하기

저도 처음엔 옵션이 너무 많아서 헷갈렸는데, 실무에서 자주 보는 개념은 몇 개 안 돼요.

2-1. attach와 exec의 차이

  • attach: 이미 실행 중인 프로세스에 붙어서 봅니다. -p PID를 씁니다.
  • exec: 프로그램 실행부터 추적합니다. 서비스가 시작하면서 죽는 문제에 좋아요.

2-2. 자주 보는 시스템 콜

  • openat(): 파일 열기
  • read() / write(): 데이터 읽기/쓰기
  • connect(): TCP/UDP/Unix Socket 연결
  • stat() 계열: 파일 존재 여부, 메타데이터 확인
  • futex(): 스레드 동기화 대기
  • poll() / select() / epoll_wait(): 이벤트 대기

2-3. 어떤 도구와 비교하면 좋을까

도구 주요 용도 강점 주의점
strace 시스템 콜 추적 파일, 네트워크, 권한 문제를 빠르게 확인 출력이 많아 필터링이 필요
ltrace 라이브러리 호출 추적 유저 공간 함수 흐름 확인 환경에 따라 활용 범위가 제한적
journalctl 서비스 로그 확인 systemd 서비스 분석에 편함 로그가 없으면 한계가 명확

제 경험상 순서는 보통 이래요. 로그 먼저 보고, 안 나오면 ss, lsof, strace로 들어갑니다. 즉, strace는 마지막 수단이라기보다 애매할 때 바로 꺼내는 실전 도구에 가까워요.

3. strace 기본 사용법: 이 정도만 알아도 바로 써먹습니다

실전에서 가장 많이 쓰는 명령어부터 보겠습니다.

  1. 실행 중인 프로세스에 붙기
  2. 새로 실행되는 프로그램 추적하기
  3. 출력을 파일로 저장하기
  4. 파일/네트워크 관련 시스템 콜만 필터링하기
# 실행 중인 PID에 붙기
strace -p 1234

# 자식 프로세스까지 함께 추적
strace -f -p 1234

# 실행부터 추적
strace -f ./app

# 타임스탬프와 소요 시간 보기
strace -tt -T -f -p 1234

# 결과를 파일로 저장
strace -f -tt -T -o /tmp/strace.log -p 1234

# 파일/네트워크 관련 호출만 보기
strace -f -e trace=file,network -p 1234

여기서 -f는 정말 자주 써요. 요즘 애플리케이션은 멀티프로세스나 워커(worker, 작업 프로세스) 구조가 많아서 부모만 보면 핵심이 안 보일 때가 많거든요.

또 하나 팁을 드리면, 처음부터 모든 걸 보려고 하지 마세요. 출력이 너무 많아요 ㅎㅎ 저는 보통 file, network, process 정도부터 좁혀서 봐요.

strace 리눅스 디버깅 명령 옵션과 추적 흐름을 설명하는 이미지

PID attach, 자식 프로세스 추적, 파일 출력, trace 필터링 같은 핵심 옵션을 설명하는 터미널 구성 이미지입니다.

4. 실제 디버깅 사례 분석: 로그는 멀쩡한데 서비스가 시작되지 않던 문제

이제 실전 얘기를 해보겠습니다. 예전에 제가 홈랩에서 돌리던 간단한 Python 웹 애플리케이션이 있었는데, systemd로 서비스는 올라온 것처럼 보이는데 정작 포트에서 응답이 없었어요. 로그도 거의 안 찍히더라고요. 처음엔 애플리케이션 버그인 줄 알았는데, strace로 보니까 전혀 다른 문제였습니다.

4-1. 증상 확인

systemctl status myapp
ss -lntp | grep 8000
journalctl -u myapp -n 50 --no-pager

결과를 보면 서비스 프로세스는 잠깐 떴다가 다시 죽는 식이었어요. 포트 바인딩(bind, 포트 점유)도 안 됐고요. journalctl에는 결정적인 힌트가 없었습니다. 여기서 strace를 붙였어요.

4-2. 실행부터 추적

strace -f -tt -T -o /tmp/myapp.strace /usr/bin/python3 /opt/myapp/app.py

로그 파일이 만들어졌으면, 그다음엔 실패 패턴부터 찾아요. 제가 자주 쓰는 방법은 ENOENT, EACCES, ECONNREFUSED 같은 에러 코드를 먼저 찾는 거예요.

grep -E 'ENOENT|EACCES|ECONNREFUSED|ETIMEDOUT' /tmp/myapp.strace

그때 보였던 핵심 패턴은 이런 형태였습니다.

openat(AT_FDCWD, "/opt/myapp/config/settings.yml", O_RDONLY) = -1 ENOENT (No such file or directory)
write(2, "failed to load config\n", 22) = 22
exit_group(1) = ?

처음엔 진짜 허무했어요. 코드 문제인 줄 알았는데, 실제로는 설정 파일 경로 오타였던 거더라고요. 애플리케이션 로그 레벨이 낮아서 stderr 출력이 서비스 로그에 제대로 안 남던 상황이었고요. 애플리케이션 문제 진단이라고 생각했는데, 실상은 배포 경로 불일치였습니다.

이런 경험 있으신가요? 분명히 코드 바꾼 건 없는데 배포 후에만 죽는 경우요. 이런 건 strace가 정말 빨리 답을 주더라고요.

4-3. 문제 수정

ls -l /opt/myapp/config/
mkdir -p /opt/myapp/config
cp /opt/myapp/deploy/settings.yml /opt/myapp/config/settings.yml
systemctl restart myapp

설정 파일을 맞는 위치에 두고 다시 실행하니 바로 정상 동작했어요. 드디어 됐다! 이런 케이스는 코드 디버거보다 strace가 훨씬 빠르더라고요.

5. 네트워크 지연 분석에도 strace가 꽤 유용합니다

strace는 파일만 보는 도구가 아니에요. 네트워크 지연도 흐름을 잡는 데 도움 돼요. 예를 들면 외부 API 호출 전 단계에서 connect()가 오래 걸리는지, DNS 조회 과정에서 대기하는지, Unix Socket 연결이 실패하는지 확인할 수 있습니다.

strace -f -tt -T -e trace=network -p 1234

예를 들어 출력이 아래처럼 보인다면, 연결 자체에서 문제가 나는 거예요.

connect(7, {sa_family=AF_UNIX, sun_path="/run/myapp/backend.sock"}, 25) = -1 ENOENT (No such file or directory)
connect(7, {sa_family=AF_INET, sin_port=htons(443), sin_addr=...}, 16) = -1 ECONNREFUSED (Connection refused)

반대로 poll()이나 epoll_wait()에서 오래 머무는 건, 꼭 장애라고 단정하면 안 돼요. 정상적으로 요청을 기다리는 상태일 수도 있거든요. 그래서 저는 항상 이 호출이 비정상적인 막힘인지, 원래 대기 상태인지를 같이 봅니다.

strace 리눅스 디버깅으로 파일 누락과 소켓 오류를 분석하는 예시 이미지

ENOENT, EACCES, ECONNREFUSED 같은 대표 장애 패턴을 strace 출력으로 해석하는 예시 이미지입니다.

6. ⚠️ 주의사항과 트러블슈팅: strace가 만능은 아닙니다

여기서 많이들 헷갈리는 포인트가 있어요. 저도 처음엔 그랬고요.

6-1. futex()가 보인다고 무조건 데드락은 아닙니다

멀티스레드 프로그램을 보면 futex()가 엄청 자주 나와요. 이걸 보고 바로 데드락(deadlock, 상호 대기)이라고 판단하면 위험해요. 정상적인 스레드 대기일 수도 있거든요. 이럴 땐 CPU 사용률, 스레드 덤프, 애플리케이션 구조를 같이 봐야 합니다.

6-2. 성능 오버헤드가 있습니다

strace는 추적 도구라서 당연히 부하가 있어요. 운영 서버에 장시간 전체 추적은 조심해야 합니다. 특히 트래픽이 높은 프로세스는 출력량도 많고, 체감 성능에 영향이 생길 수 있습니다.

  • 짧게 붙어서 패턴만 확인하기
  • -e trace=...로 범위 줄이기
  • -o로 파일 저장 후 오프라인 분석하기

6-3. 권한 문제로 attach가 안 될 수 있습니다

strace: attach: ptrace(PTRACE_SEIZE, 1234): Operation not permitted

이 경우엔 보통 권한이나 보안 설정을 확인해야 해요. 컨테이너나 보안 정책이 걸린 환경에서는 ptrace 자체가 제한될 수 있거든요. 저도 컨테이너 환경에서 왜 안 붙나 한참 봤던 적이 있어요. 삽질 좀 했습니다 ㅎㅎ

6-4. 너무 많은 출력은 오히려 독입니다

무작정 전체 로그를 보면 눈이 먼저 지쳐요. 그래서 저는 아래 순서로 봅니다.

  1. 에러 코드부터 검색합니다
  2. 마지막 수십 줄 흐름을 봅니다
  3. 반복되는 패턴이 있는지 확인합니다
  4. 파일, 네트워크, 프로세스 관련 호출로 좁힙니다

7. 검증: 수정 후 무엇을 확인해야 하나

장애 원인을 찾았다고 끝은 아니에요. 수정 후에는 반드시 재현 경로와 정상 동작을 같이 확인해야 합니다. 제가 보통 체크하는 항목은 아래와 같습니다.

  1. 서비스 프로세스가 바로 종료되지 않는지 확인
  2. 포트가 정상적으로 리슨(listen, 대기) 상태인지 확인
  3. 에러가 발생하던 요청이 정상 응답하는지 확인
  4. strace에서 보이던 실패 패턴이 사라졌는지 확인
systemctl restart myapp
systemctl status myapp --no-pager
ss -lntp | grep 8000
curl -I http://127.0.0.1:8000/

필요하면 다시 짧게 추적해서 차이를 봐요.

strace -f -tt -T -e trace=file,network -o /tmp/after_fix.strace -p 1234

수정 전에는 ENOENT가 보였는데, 수정 후에는 해당 파일을 정상적으로 openat() 하는 흐름이 보이면 꽤 확신을 가질 수 있어요. 이런 식으로 리눅스 장애 해결은 추정이 아니라 근거로 밀어붙여야 나중에 덜 흔들립니다.

strace 리눅스 디버깅 결과를 수정 전후로 비교하는 검증 이미지

에러 코드가 사라지고 포트 리슨 및 HTTP 응답이 복구된 결과를 비교하는 검증 이미지입니다.

8. 자주 묻는 질문 정리

Q1. strace 리눅스 디버깅은 언제 가장 먼저 써야 할까요?

로그가 비어 있거나, 시작 직후 종료되거나, 파일/권한/소켓 문제로 의심될 때 바로 써볼 만해요. 특히 시스템 콜 추적이 필요한 상황은 애플리케이션 외부 의존성이 꼬였을 때예요.

Q2. 운영 서버에서도 써도 될까요?

짧고 제한적으로는 가능해요. 다만 전체 추적을 오래 거는 건 조심하셔야 합니다. 필터링이 정말 중요합니다.

Q3. strace만으로 모든 문제가 해결되나요?

아니에요. CPU 바운드 문제, 메모리 누수, 애플리케이션 내부 로직 버그는 다른 도구와 함께 봐야 합니다. strace는 커널 경계에서 보이는 행동을 잘 보여주는 도구니까요.

9. 마무리: strace는 로그가 말해주지 않는 걸 보여줍니다

정리해보면, strace는 화려한 도구는 아니에요. 근데 장애 순간에 진짜 실용적이더라고요. 제가 직접 써보니 특히 파일 경로 오류, 권한 문제, 소켓 연결 실패, 시작 직후 종료 같은 문제에서는 체감상 가장 빠르게 본질에 닿는 도구였어요.

혹시 지금도 프로세스는 떠 있는데 왜 안 되는지 감이 안 오신다면, 너무 복잡하게 가지 말고 짧게 strace 한 번 붙여보세요. 의외로 답은 이미 시스템 콜에 나와 있는 경우가 많아요. 이거 진짜 편하더라고요.

다음 글에서는 lsof로 열린 파일과 소켓 추적하는 방법, 그리고 이전 글에서 다뤘던 systemd 서비스 로그 읽는 법과 어떻게 조합하면 좋은지도 이어서 정리해보겠습니다.

strace 사용 시점, 자주 보는 에러 코드, 검증 절차를 요약한 인포그래픽 이미지입니다.

반응형