zioinfo-mail/itsm/scripts/sm/common/system_health.sh
DESKTOP-TKLFCPR\ython e228faabf5 feat(itsm): G-1~G-12 확장 기능 + 하네스/봇/설치스크립트 구현
G-1: 메신저 Webhook Relay + _send_to_room 실제 httpx 호출 구현
G-2: POST /api/tasks/bulk SR 대량작업 엔드포인트 (최대 100건)
G-3: 라이선스 만료 알림 스케줄러 (매일 09:00 KST)
G-4: 체험판 upgrade_banner 필드 + license.py 배너 로직
G-5: core/auto_rca.py + incidents/problem auto-rca 엔드포인트
G-6: core/deploy_impact.py + vibe impact-analysis 엔드포인트
G-7: core/ticket_classifier.py + SR 생성 시 AI 분류 + ai-suggestion API
G-8: VulnPatchRecord 모델 + vuln_scan 패치추적 4개 엔드포인트
G-9: core/jira_sync.py + gateway Jira/Confluence 연동 엔드포인트
G-10: core/push_notify.py + routers/push.py + PushSubscription 모델
G-11: approvals 다중승인 (위임/서명/기한초과/마감연장)
G-12: alembic.ini + migrations/ + cicd/migrate_to_postgres.sh

하네스: guardia-orchestrator 확장기능 Phase 반영
봇명령어: /sr /status /license /bulk 슬래시 명령어 추가
설치스크립트: setup/ (Ubuntu, CentOS, RHEL, Windows) --test 옵션 포함

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-29 18:18:52 +09:00

140 lines
7.1 KiB
Bash

#!/bin/bash
# ============================================================
# GUARDiA SM | system_health.sh
# 대상: 모든 Linux 서버
# 내용: CPU / 메모리 / 디스크 / 네트워크 I/O / 로드 평균
# 파라미터: DISK_WARN=80 DISK_CRIT=90 MEM_WARN=85 CPU_WARN=90
# ============================================================
set -euo pipefail
DISK_WARN=${DISK_WARN:-80}; DISK_CRIT=${DISK_CRIT:-90}
MEM_WARN=${MEM_WARN:-85}; CPU_WARN=${CPU_WARN:-90}
SEP="─────────────────────────────────────────"
OK="[OK]"; WARN="[WARN]"; CRIT="[CRIT]"
RESULT=0 # 0=OK 1=WARN 2=CRIT
echo "======================================================"
echo " GUARDiA SM 점검 | 시스템 리소스 | $(hostname -s)"
echo " 점검 시각: $(date '+%Y-%m-%d %H:%M:%S %Z')"
echo "======================================================"
# ── 1. CPU 로드 ───────────────────────────────────────────
echo; echo "[$SEP] 1. CPU / 로드 평균"
CORES=$(nproc 2>/dev/null || grep -c ^processor /proc/cpuinfo)
LOAD1=$(awk '{print $1}' /proc/loadavg)
LOAD5=$(awk '{print $2}' /proc/loadavg)
LOAD15=$(awk '{print $3}' /proc/loadavg)
# CPU 사용률 (1초 샘플)
CPU_IDLE=$(top -bn2 -d0.5 | grep "Cpu(s)" | tail -1 | awk '{for(i=1;i<=NF;i++) if($i~/%id/) print $(i-1)}' | tr -d ',')
CPU_USE=$(echo "100 - ${CPU_IDLE:-0}" | bc 2>/dev/null || echo "N/A")
echo " CPU 코어 수 : ${CORES}"
echo " 로드 평균 : ${LOAD1} / ${LOAD5} / ${LOAD15} (1/5/15분)"
echo " CPU 사용률 : ${CPU_USE}%"
LOAD_THRESH=$(echo "$CORES * 2" | bc)
if awk "BEGIN{exit !($LOAD5 > $LOAD_THRESH)}" 2>/dev/null; then
echo " 로드 상태 : ${CRIT} 로드 평균이 코어 수 2배 초과 (${LOAD5} > ${LOAD_THRESH})"
RESULT=2
elif awk "BEGIN{exit !($LOAD5 > $CORES)}" 2>/dev/null; then
echo " 로드 상태 : ${WARN} 로드 평균이 코어 수 초과 (${LOAD5} > ${CORES})"
[ $RESULT -lt 1 ] && RESULT=1
else
echo " 로드 상태 : ${OK}"
fi
# ── 2. 메모리 ────────────────────────────────────────────
echo; echo "[$SEP] 2. 메모리"
MEM_TOTAL=$(awk '/MemTotal/{print $2}' /proc/meminfo)
MEM_AVAIL=$(awk '/MemAvailable/{print $2}' /proc/meminfo)
MEM_FREE=$(awk '/MemFree/{print $2}' /proc/meminfo)
MEM_BUFCACHE=$(( $(awk '/Buffers/{print $2}' /proc/meminfo) + $(awk '/^Cached:/{print $2}' /proc/meminfo) ))
MEM_USED=$(( MEM_TOTAL - MEM_AVAIL ))
MEM_PCT=$(( MEM_USED * 100 / MEM_TOTAL ))
SWAP_TOTAL=$(awk '/SwapTotal/{print $2}' /proc/meminfo)
SWAP_FREE=$(awk '/SwapFree/{print $2}' /proc/meminfo)
SWAP_USED=$(( SWAP_TOTAL - SWAP_FREE ))
echo " 전체 메모리 : $(( MEM_TOTAL / 1024 )) MB"
echo " 사용 메모리 : $(( MEM_USED / 1024 )) MB (${MEM_PCT}%)"
echo " 가용 메모리 : $(( MEM_AVAIL / 1024 )) MB"
echo " 버퍼/캐시 : $(( MEM_BUFCACHE / 1024 )) MB"
[ $SWAP_TOTAL -gt 0 ] && echo " 스왑 사용 : $(( SWAP_USED / 1024 )) MB / $(( SWAP_TOTAL / 1024 )) MB"
if [ $MEM_PCT -ge $((MEM_WARN + 10)) ]; then
echo " 메모리 상태 : ${CRIT} ${MEM_PCT}% 사용 중"
RESULT=2
elif [ $MEM_PCT -ge $MEM_WARN ]; then
echo " 메모리 상태 : ${WARN} ${MEM_PCT}% 사용 중"
[ $RESULT -lt 1 ] && RESULT=1
else
echo " 메모리 상태 : ${OK} ${MEM_PCT}%"
fi
# ── 3. 디스크 ────────────────────────────────────────────
echo; echo "[$SEP] 3. 디스크 사용량"
DF_OUT=$(df -h --output=source,size,used,avail,pcent,target 2>/dev/null | grep -v tmpfs | grep -v udev | grep -v "Filesystem")
echo "$DF_OUT" | head -1 | awk '{printf " %-20s %6s %6s %6s %5s %s\n","마운트포인트","전체","사용","가용","사용%","장치"}'
echo "$DF_OUT" | while read line; do
PCENT=$(echo "$line" | awk '{print $5}' | tr -d '%')
MP=$(echo "$line" | awk '{print $6}')
if [ -n "$PCENT" ] && [ "$PCENT" -ge $DISK_CRIT ] 2>/dev/null; then
echo " ${CRIT} $line"
echo "DISK_CRIT_FOUND" >/tmp/.guardia_disk_crit_$$
elif [ -n "$PCENT" ] && [ "$PCENT" -ge $DISK_WARN ] 2>/dev/null; then
echo " ${WARN} $line"
else
echo " ${OK} $line"
fi
done
[ -f /tmp/.guardia_disk_crit_$$ ] && { RESULT=2; rm -f /tmp/.guardia_disk_crit_$$; }
# ── 4. 주요 마운트 inode ─────────────────────────────────
echo; echo "[$SEP] 4. inode 사용률"
df -i 2>/dev/null | grep -v tmpfs | grep -v udev | tail -n +2 | while read line; do
IPCT=$(echo "$line" | awk '{print $5}' | tr -d '%')
if [ -n "$IPCT" ] && [ "$IPCT" -ge 90 ] 2>/dev/null; then
echo " ${WARN} inode 부족: $line"
fi
done
echo " inode 점검 완료"
# ── 5. 네트워크 I/O ──────────────────────────────────────
echo; echo "[$SEP] 5. 네트워크 인터페이스"
ip -s link show 2>/dev/null | awk '
/^[0-9]+:/{name=$2; gsub(/:$/,"",name)}
/RX:/{rx_bytes=0; getline; rx_bytes=$1}
/TX:/{tx_bytes=0; getline; tx_bytes=$1;
if (name != "lo") printf " %-12s RX: %s bytes TX: %s bytes\n", name, rx_bytes, tx_bytes}' \
| head -5
# ── 6. 상위 프로세스 (CPU) ──────────────────────────────
echo; echo "[$SEP] 6. CPU 상위 5개 프로세스"
ps aux --sort=-%cpu 2>/dev/null | awk 'NR==1{print " ",$0} NR>1 && NR<=6{printf " %-8s %5s%% %5s%% %s\n",$1,$3,$4,substr($0,index($0,$11))}' 2>/dev/null || \
ps -eo user,pcpu,pmem,comm --sort=-pcpu 2>/dev/null | head -6 | awk '{printf " %-10s %5s%% %5s%% %s\n",$1,$2,$3,$4}'
# ── 7. 열린 파일 수 ──────────────────────────────────────
echo; echo "[$SEP] 7. 파일 디스크립터"
OPEN_FILES=$(ls /proc/*/fd 2>/dev/null | wc -l)
MAX_FILES=$(cat /proc/sys/fs/file-max 2>/dev/null || echo "N/A")
echo " 열린 파일 수 : ${OPEN_FILES}"
echo " 시스템 최대 : ${MAX_FILES}"
# ── 8. 최근 커널 OOM ─────────────────────────────────────
echo; echo "[$SEP] 8. OOM / 커널 오류 (최근 1시간)"
OOM=$(dmesg --since="1 hour ago" 2>/dev/null | grep -i "oom\|out of memory\|killed process" | tail -5 || true)
if [ -n "$OOM" ]; then
echo " ${WARN} OOM 이벤트 감지:"
echo "$OOM" | sed 's/^/ /'
[ $RESULT -lt 1 ] && RESULT=1
else
echo " ${OK} OOM 없음"
fi
# ── 요약 ─────────────────────────────────────────────────
echo
echo "======================================================"
case $RESULT in
0) echo " 최종 결과: ${OK} 시스템 정상" ;;
1) echo " 최종 결과: ${WARN} 주의 항목 있음 — 모니터링 강화 권고" ;;
2) echo " 최종 결과: ${CRIT} 즉시 조치 필요" ;;
esac
echo " 점검 완료: $(date '+%Y-%m-%d %H:%M:%S')"
echo "======================================================"
exit $RESULT