#!/bin/bash # ============================================================ # GUARDiA SM | was_tomcat_sm.sh # 대상: Apache Tomcat WAS # 파라미터: CATALINA_HOME=/opt/tomcat APP_PORT=8080 AJP_PORT=8009 # JMX_PORT=9090 HEALTH_URL=http://localhost:8080/health # TOMCAT_USER=tomcat LOG_DIR=/opt/tomcat/logs # ============================================================ set -euo pipefail CATALINA_HOME=${CATALINA_HOME:-/opt/tomcat} APP_PORT=${APP_PORT:-8080} AJP_PORT=${AJP_PORT:-8009} JMX_PORT=${JMX_PORT:-9090} HEALTH_URL=${HEALTH_URL:-"http://localhost:${APP_PORT}/health"} LOG_DIR=${LOG_DIR:-"${CATALINA_HOME}/logs"} OK="[OK]"; WARN="[WARN]"; CRIT="[CRIT]" SEP="─────────────────────────────────────────" RESULT=0 echo "======================================================" echo " GUARDiA SM 점검 | Apache Tomcat | $(hostname -s)" echo " 점검 시각: $(date '+%Y-%m-%d %H:%M:%S %Z')" echo "======================================================" # ── 1. 프로세스 ─────────────────────────────────────────── echo; echo "[$SEP] 1. Tomcat 프로세스" TOMCAT_PID=$(pgrep -f "catalina|tomcat" 2>/dev/null | head -1 || echo "") if [ -n "$TOMCAT_PID" ]; then echo " ${OK} Tomcat 실행 중 (PID: ${TOMCAT_PID})" # 프로세스 시작 시간 START_TIME=$(ps -p "$TOMCAT_PID" -o lstart= 2>/dev/null || echo "N/A") echo " 시작 시각: ${START_TIME}" else echo " ${CRIT} Tomcat 프로세스 없음" RESULT=2 fi # ── 2. 포트 리스닝 ──────────────────────────────────────── echo; echo "[$SEP] 2. 포트 리스닝" for PORT in $APP_PORT $AJP_PORT; do if ss -tlnp 2>/dev/null | grep -q ":${PORT} "; then echo " ${OK} 포트 ${PORT} LISTEN" else echo " ${WARN} 포트 ${PORT} LISTEN 없음" [ $RESULT -lt 1 ] && RESULT=1 fi done # ── 3. 헬스체크 ─────────────────────────────────────────── echo; echo "[$SEP] 3. 헬스체크" if command -v curl &>/dev/null; then HTTP_CODE=$(curl -sk -o /dev/null -w "%{http_code}" \ --max-time 10 "${HEALTH_URL}" 2>/dev/null || echo "ERR") RESP_TIME=$(curl -sk -o /dev/null -w "%{time_total}" \ --max-time 10 "${HEALTH_URL}" 2>/dev/null || echo "N/A") if echo "$HTTP_CODE" | grep -qE "^[23]"; then echo " ${OK} 헬스체크 ${HTTP_CODE} — ${RESP_TIME}s (${HEALTH_URL})" elif [ "$HTTP_CODE" = "ERR" ]; then echo " ${CRIT} 헬스체크 연결 실패" RESULT=2 else echo " ${WARN} 헬스체크 HTTP ${HTTP_CODE}" [ $RESULT -lt 1 ] && RESULT=1 fi fi # ── 4. JVM 메모리 (JMX 없이 /proc 활용) ──────────────────── echo; echo "[$SEP] 4. JVM 메모리 (프로세스 기준)" if [ -n "$TOMCAT_PID" ]; then RSS_KB=$(awk '/VmRSS/{print $2}' /proc/${TOMCAT_PID}/status 2>/dev/null || echo 0) RSS_MB=$(( RSS_KB / 1024 )) VIRT_KB=$(awk '/VmSize/{print $2}' /proc/${TOMCAT_PID}/status 2>/dev/null || echo 0) VIRT_MB=$(( VIRT_KB / 1024 )) echo " RSS (상주 메모리) : ${RSS_MB} MB" echo " 가상 메모리 : ${VIRT_MB} MB" # JVM 힙 (jcmd/jmap 사용 가능 시) if command -v jcmd &>/dev/null 2>&1; then HEAP=$(jcmd "$TOMCAT_PID" GC.heap_info 2>/dev/null | grep -E "used|capacity" | head -4 || true) [ -n "$HEAP" ] && echo "$HEAP" | sed 's/^/ 힙 /' fi fi # ── 5. 스레드 풀 점검 ───────────────────────────────────── echo; echo "[$SEP] 5. 스레드 수" if [ -n "$TOMCAT_PID" ]; then THREAD_COUNT=$(ls /proc/${TOMCAT_PID}/task 2>/dev/null | wc -l || echo 0) echo " 전체 스레드 수: ${THREAD_COUNT}" if [ "$THREAD_COUNT" -gt 300 ]; then echo " ${WARN} 스레드 과다 (${THREAD_COUNT} > 300)" [ $RESULT -lt 1 ] && RESULT=1 else echo " ${OK} 스레드 수 정상" fi fi # ── 6. catalina.out 에러 점검 ──────────────────────────── echo; echo "[$SEP] 6. catalina.out 오류 (최근 1시간)" CATALINA_LOG="${LOG_DIR}/catalina.out" if [ -r "$CATALINA_LOG" ]; then # 최근 1000줄에서 ERROR/WARN 집계 ERRORS=$(tail -1000 "$CATALINA_LOG" | grep -cE "ERROR|EXCEPTION|OutOfMemory" || echo 0) WARNS=$(tail -1000 "$CATALINA_LOG" | grep -c "WARN" || echo 0) echo " ERROR/EXCEPTION 수: ${ERRORS}" echo " WARN 수: ${WARNS}" if [ "$ERRORS" -gt 10 ]; then echo " ${CRIT} 다수 에러 감지 (${ERRORS}건)" RESULT=2 elif [ "$ERRORS" -gt 0 ]; then echo " ${WARN} 일부 에러 감지:" tail -1000 "$CATALINA_LOG" | grep -E "ERROR|EXCEPTION|OutOfMemory" | tail -5 | sed 's/^/ /' [ $RESULT -lt 1 ] && RESULT=1 else echo " ${OK} 최근 에러 없음" fi # OOM 감지 OOM=$(tail -1000 "$CATALINA_LOG" | grep -i "OutOfMemoryError" | tail -3 || true) [ -n "$OOM" ] && { echo " ${CRIT} OOM 감지:"; echo "$OOM" | sed 's/^/ /'; RESULT=2; } else echo " ${WARN} catalina.out 없음: ${CATALINA_LOG}" [ $RESULT -lt 1 ] && RESULT=1 fi # ── 7. 배포된 앱 목록 ───────────────────────────────────── echo; echo "[$SEP] 7. 배포 앱 목록" WEBAPPS="${CATALINA_HOME}/webapps" if [ -d "$WEBAPPS" ]; then ls "$WEBAPPS" 2>/dev/null | sed 's/^/ - /' | head -20 else echo " ${WARN} webapps 디렉터리 없음: ${WEBAPPS}" fi # ── 요약 ───────────────────────────────────────────────── echo echo "======================================================" case $RESULT in 0) echo " 최종 결과: ${OK} Tomcat 정상" ;; 1) echo " 최종 결과: ${WARN} 주의 항목 있음" ;; 2) echo " 최종 결과: ${CRIT} 즉시 조치 필요" ;; esac echo " 점검 완료: $(date '+%Y-%m-%d %H:%M:%S')" echo "======================================================" exit $RESULT