- itsm/ -> workspace/guardia-itsm/ - manager/ -> workspace/guardia-manager/ - app/ -> workspace/guardia-messenger/ - manual/ -> workspace/guardia-docs/ workspace/zioinfo-web/ unchanged. git mv preserves full commit history. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
152 lines
6.9 KiB
Bash
152 lines
6.9 KiB
Bash
#!/bin/bash
|
|
# ============================================================
|
|
# GUARDiA SM | search_solr_sm.sh
|
|
# 대상: Apache Solr (7.x / 8.x / 9.x)
|
|
# 파라미터: SOLR_HOME=/opt/solr SOLR_HOST=localhost SOLR_PORT=8983
|
|
# SOLR_USER=solr SOLR_PASS=SolrRocks
|
|
# QUERY_TIME_WARN=1000
|
|
# ============================================================
|
|
set -euo pipefail
|
|
SOLR_HOME=${SOLR_HOME:-/opt/solr}
|
|
SOLR_HOST=${SOLR_HOST:-localhost}
|
|
SOLR_PORT=${SOLR_PORT:-8983}
|
|
SOLR_USER=${SOLR_USER:-""}
|
|
SOLR_PASS=${SOLR_PASS:-""}
|
|
QUERY_TIME_WARN=${QUERY_TIME_WARN:-1000}
|
|
SOLR_BASE="http://${SOLR_HOST}:${SOLR_PORT}"
|
|
OK="[OK]"; WARN="[WARN]"; CRIT="[CRIT]"
|
|
SEP="─────────────────────────────────────────"
|
|
RESULT=0
|
|
|
|
_solr() {
|
|
local URL="$1"
|
|
local AUTH=""
|
|
[ -n "$SOLR_USER" ] && AUTH="-u ${SOLR_USER}:${SOLR_PASS}"
|
|
curl -sk --max-time 10 $AUTH "${SOLR_BASE}${URL}" 2>/dev/null
|
|
}
|
|
|
|
echo "======================================================"
|
|
echo " GUARDiA SM 점검 | Apache Solr | $(hostname -s)"
|
|
echo " 점검 시각: $(date '+%Y-%m-%d %H:%M:%S %Z')"
|
|
echo "======================================================"
|
|
|
|
# ── 1. 프로세스 ───────────────────────────────────────────
|
|
echo; echo "[$SEP] 1. Solr 프로세스"
|
|
SOLR_PROC=$(pgrep -f "solr\|start.jar" 2>/dev/null | wc -l || echo 0)
|
|
if [ "$SOLR_PROC" -gt 0 ]; then
|
|
SOLR_PID=$(pgrep -f "solr" | head -1)
|
|
echo " ${OK} Solr 실행 중 (PID: ${SOLR_PID})"
|
|
RSS_MB=$(awk '/VmRSS/{print $2}' /proc/${SOLR_PID}/status 2>/dev/null | \
|
|
awk '{printf "%d", $1/1024}' || echo "N/A")
|
|
echo " RSS 메모리: ${RSS_MB} MB"
|
|
else
|
|
echo " ${CRIT} Solr 프로세스 없음"
|
|
RESULT=2
|
|
fi
|
|
|
|
# ── 2. 포트 리스닝 ────────────────────────────────────────
|
|
echo; echo "[$SEP] 2. 포트 리스닝"
|
|
ss -tlnp 2>/dev/null | grep -q ":${SOLR_PORT} " && \
|
|
echo " ${OK} 포트 ${SOLR_PORT} LISTEN" || \
|
|
{ echo " ${CRIT} 포트 ${SOLR_PORT} LISTEN 없음"; RESULT=2; }
|
|
|
|
# ── 3. 시스템 정보 ────────────────────────────────────────
|
|
echo; echo "[$SEP] 3. Solr 시스템 정보"
|
|
if command -v curl &>/dev/null; then
|
|
SYS=$(_solr "/solr/admin/info/system?wt=json")
|
|
if [ -n "$SYS" ]; then
|
|
SOLR_VER=$(echo "$SYS" | python3 -c \
|
|
"import sys,json; d=json.load(sys.stdin); print(d.get('lucene',{}).get('solr-spec-version','?'))" 2>/dev/null)
|
|
UPTIME=$(echo "$SYS" | python3 -c \
|
|
"import sys,json; d=json.load(sys.stdin); ms=d.get('jvm',{}).get('jmx',{}).get('upTimeMS',0); \
|
|
h=ms//3600000; m=(ms%3600000)//60000; print(f'{h}h {m}m')" 2>/dev/null || echo "N/A")
|
|
echo " ${OK} Solr 버전: ${SOLR_VER}, 가동 시간: ${UPTIME}"
|
|
# JVM 힙
|
|
HEAP=$(echo "$SYS" | python3 -c \
|
|
"import sys,json; d=json.load(sys.stdin); jvm=d.get('jvm',{}).get('memory',{}).get('raw',{}); \
|
|
used=jvm.get('used',0)//1048576; max_=jvm.get('max',1)//1048576; \
|
|
pct=used*100//max_ if max_>0 else 0; print(f'used={used}MB max={max_}MB ({pct}%)')" 2>/dev/null)
|
|
echo " JVM 힙: ${HEAP}"
|
|
if echo "$HEAP" | grep -oP '\d+(?=%)' | awk '{exit !($1>=85)}'; then
|
|
echo " ${WARN} JVM 힙 사용률 85% 초과"
|
|
[ $RESULT -lt 1 ] && RESULT=1
|
|
fi
|
|
else
|
|
echo " ${CRIT} Solr 응답 없음"
|
|
RESULT=2
|
|
fi
|
|
fi
|
|
|
|
# ── 4. 코어/컬렉션 상태 ─────────────────────────────────
|
|
echo; echo "[$SEP] 4. 코어/컬렉션 상태"
|
|
if command -v curl &>/dev/null; then
|
|
CORES=$(_solr "/solr/admin/cores?wt=json&indexInfo=false")
|
|
if [ -n "$CORES" ]; then
|
|
CORE_LIST=$(echo "$CORES" | python3 -c "
|
|
import sys, json
|
|
d = json.load(sys.stdin)
|
|
status = d.get('status', {})
|
|
for name, info in status.items():
|
|
sz = info.get('index', {}).get('sizeInBytes', 0) // 1048576
|
|
docs = info.get('index', {}).get('numDocs', 0)
|
|
print(f' {name:20s} docs={docs:>10,d} size={sz}MB')
|
|
" 2>/dev/null || echo " 파싱 실패")
|
|
echo "$CORE_LIST"
|
|
CORE_COUNT=$(echo "$CORES" | python3 -c \
|
|
"import sys,json; d=json.load(sys.stdin); print(len(d.get('status',{})))" 2>/dev/null)
|
|
echo " 총 코어 수: ${CORE_COUNT}"
|
|
fi
|
|
fi
|
|
|
|
# ── 5. 쿼리 성능 통계 ────────────────────────────────────
|
|
echo; echo "[$SEP] 5. 쿼리 성능 통계"
|
|
if command -v curl &>/dev/null; then
|
|
# 첫 번째 코어의 성능 지표
|
|
FIRST_CORE=$(echo "$CORES" 2>/dev/null | python3 -c \
|
|
"import sys,json; d=json.load(sys.stdin); print(list(d.get('status',{}).keys())[0])" 2>/dev/null || echo "")
|
|
if [ -n "$FIRST_CORE" ]; then
|
|
METRICS=$(_solr "/solr/${FIRST_CORE}/admin/mbeans?stats=true&cat=QUERYHANDLER&wt=json")
|
|
AVG_TIME=$(echo "$METRICS" | python3 -c "
|
|
import sys, json
|
|
d = json.load(sys.stdin)
|
|
beans = d.get('solr-mbeans', [])
|
|
for i in range(0, len(beans), 2):
|
|
if beans[i] == 'QUERYHANDLER':
|
|
handlers = beans[i+1] if i+1 < len(beans) else {}
|
|
for name, stats in handlers.items():
|
|
if '/select' in name:
|
|
qs = stats.get('stats', {})
|
|
avg = qs.get('avgTimePerRequest', 0)
|
|
rpc = qs.get('requests', 0)
|
|
print(f' /select: requests={rpc} avg={avg:.1f}ms')
|
|
" 2>/dev/null || echo " 쿼리 통계 없음")
|
|
echo "$AVG_TIME"
|
|
fi
|
|
fi
|
|
|
|
# ── 6. 로그 오류 ─────────────────────────────────────────
|
|
echo; echo "[$SEP] 6. 로그 오류"
|
|
for LOGDIR in "${SOLR_HOME}/server/logs" "${SOLR_HOME}/logs" "/var/log/solr"; do
|
|
if [ -d "$LOGDIR" ]; then
|
|
LOGFILE=$(ls -t "${LOGDIR}"/solr.log 2>/dev/null | head -1 || echo "")
|
|
if [ -n "$LOGFILE" ] && [ -r "$LOGFILE" ]; then
|
|
ERR=$(tail -1000 "$LOGFILE" | grep -cE "ERROR|WARN|Exception" || echo 0)
|
|
echo " 최근 오류/경고: ${ERR}건 (${LOGFILE})"
|
|
tail -1000 "$LOGFILE" | grep -E "ERROR|WARN" | tail -5 | sed 's/^/ /' || true
|
|
fi
|
|
break
|
|
fi
|
|
done
|
|
|
|
# ── 요약 ─────────────────────────────────────────────────
|
|
echo
|
|
echo "======================================================"
|
|
case $RESULT in
|
|
0) echo " 최종 결과: ${OK} Solr 정상" ;;
|
|
1) echo " 최종 결과: ${WARN} 주의 항목 있음" ;;
|
|
2) echo " 최종 결과: ${CRIT} 즉시 조치 필요" ;;
|
|
esac
|
|
echo " 점검 완료: $(date '+%Y-%m-%d %H:%M:%S')"
|
|
echo "======================================================"
|
|
exit $RESULT
|