Skip to Content
Infra & DevOps안정적인 서비스 배포를 위한 톰캣(Tomcat) 안전 종료 스크립트
☁️ Infra & DevOps2018년 11월 2일

안정적인 서비스 배포를 위한 톰캣(Tomcat) 안전 종료 스크립트

#tomcat#shell#infra#automation#flamingo

과거 사내 빅데이터 모니터링 플랫폼의 전면 UI 서버는 무거운 자바 스프링(Spring) 백엔드와 맞물려 동작하는 아파치 톰캣(Apache Tomcat) 기반이었습니다.

당시 수백 개의 하둡 데이터노드(DataNode)에서 초당 쏟아지는 메트릭 데이터를 플랫폼 서버가 화면에 뿌려주는 과정에서, 간혹 가비지 컬렉션(GC) 튜닝 실패나 메모리 릭(Memory Leak)으로 인해 톰캣 프로세스가 이른바 ‘좀비(Zombie)’ 상태에 빠져 행업(Hang-up)되는 현상이 있었습니다.

이때 관리자가 단순히 /bin/shutdown.sh를 실행해도 톰캣은 “나 아직 처리할 쓰레드 남았으니 종료 못해” 라면서 버티고, 그 위에 startup.sh를 또 때리면 “해당 포트는 이미 사용중입니다” 라며 에러를 뿜는 최악의 교착 상태가 벌어졌습니다. 서버 재기동 스크립트를 Crontab에 걸어두거나 CI/CD 자동 배포(Jenkins) 파이프라인을 탈 때, 이 톰캣 좀비 이슈는 치명적인 배포 실패 원인이 됩니다.

아래 스크립트는 이 문제를 해결하기 위해, 톰캣에게 먼저 신사적인 종료(SIGTERM)를 5번 요청하고 그래도 말을 안 들으면 강제로 목줄을 끊어버리는(SIGKILL, -9) 형태의 안전 래퍼(Wrapper) 쉘 스크립트입니다.


Tomcat Restart Shell Script (restart.sh)

bash
#!/bin/bash # ps 목록에서 다른 자바 프로세스(Elasticsearch, Zookeeper 등)가 잡히지 않도록 키워드 조합 필수 TOMCAT_DIR="/opt/flamingo/web" TOMCAT_PID=$(ps aux | grep org.apache.catalina.startup.Bootstrap | grep $TOMCAT_DIR | grep -v grep | awk '{ print $2 }') stop() { echo "Attempting to shutdown Tomcat gracefully..." "$TOMCAT_DIR"/bin/shutdown.sh >& /dev/null # 2초마다 핑을 찔러가며 총 5번(최대 10초) 동안 정상 종료를 기다려줌 for i in {1..5} do # PID가 사라졌다면 즉시 함수 종료 (성공) [ -z "$TOMCAT_PID" ] && return echo "Waiting for Tomcat to stop... ($i/5)" sleep 2 # 프로세스가 여전히 살아있는지 재확인 TOMCAT_PID=$(ps aux | grep org.apache.catalina.startup.Bootstrap | grep $TOMCAT_DIR | grep -v grep | awk '{ print $2 }') done # 10초가 지났음에도 변수가 남아 있다면, 톰캣이 Hang 상태에 빠진 것! if [ -n "$TOMCAT_PID" ]; then echo "Tomcat did not stop gracefully. Executing Force Kill (SIGKILL) on PID: $TOMCAT_PID" # 자비 없는 킬 kill -9 $TOMCAT_PID sleep 1 fi echo "Tomcat is completely stopped." } start() { echo "Starting Tomcat..." "$TOMCAT_DIR"/bin/startup.sh >& /dev/null echo "Tomcat started successfully." } # Main 로직 실행부 # PID가 존재하면 먼저 끄고 시작하고, 없으면 바로 시작 if [ -n "$TOMCAT_PID" ]; then stop fi start

왜 유니크 키워드(grep $TOMCAT_DIR)가 중요한가?

보통 구글링을 하면 PID를 딸 때 단순히 grep tomcat이나 grep java를 쓰라고 나옵니다. 하지만, 하둡 엣지 장비 하나에는 Oozie 데몬, 하이브 하이브메타스토어, 심지어 타 부서의 웹 엔진까지 수많은 JVM 데몬이 돌고 있습니다.

스프링 부트(Spring Boot)의 진입점인 org.apache.catalina.startup.Bootstrap과 함께 구동 디렉터리 경로(/opt/flamingo/web)를 And 조건식으로 교차 검증하지 않으면, 엉뚱한 하둡 메인 데몬을 팀킬(kill -9)해버리는 대형 사고가 생길 수 있으니 PID 파싱은 보수적으로 짜는 것이 핵심입니다.

Last updated on