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>
157 lines
7.2 KiB
Bash
157 lines
7.2 KiB
Bash
#!/bin/bash
|
|
# ============================================================
|
|
# GUARDiA SM | db_mysql_sm.sh
|
|
# 대상: MySQL / MariaDB
|
|
# 파라미터: MYSQL_HOST=localhost MYSQL_PORT=3306
|
|
# MYSQL_USER=root MYSQL_PASS=password
|
|
# SLOW_QUERY_WARN=100 MAX_CONN_WARN=80
|
|
# ============================================================
|
|
set -euo pipefail
|
|
MYSQL_HOST=${MYSQL_HOST:-localhost}
|
|
MYSQL_PORT=${MYSQL_PORT:-3306}
|
|
MYSQL_USER=${MYSQL_USER:-root}
|
|
MYSQL_PASS=${MYSQL_PASS:-""}
|
|
SLOW_QUERY_WARN=${SLOW_QUERY_WARN:-100}
|
|
MAX_CONN_WARN=${MAX_CONN_WARN:-80}
|
|
OK="[OK]"; WARN="[WARN]"; CRIT="[CRIT]"
|
|
SEP="─────────────────────────────────────────"
|
|
RESULT=0
|
|
|
|
# mysql 실행 헬퍼
|
|
MY="mysql -h${MYSQL_HOST} -P${MYSQL_PORT} -u${MYSQL_USER}"
|
|
[ -n "$MYSQL_PASS" ] && MY="${MY} -p${MYSQL_PASS}"
|
|
MY="${MY} --batch --silent"
|
|
|
|
echo "======================================================"
|
|
echo " GUARDiA SM 점검 | MySQL/MariaDB | $(hostname -s)"
|
|
echo " 점검 시각: $(date '+%Y-%m-%d %H:%M:%S %Z')"
|
|
echo "======================================================"
|
|
|
|
# ── 1. 프로세스 ───────────────────────────────────────────
|
|
echo; echo "[$SEP] 1. MySQL/MariaDB 프로세스"
|
|
MYSQL_PROC=$(pgrep -c "mysqld\|mariadbd" 2>/dev/null || echo 0)
|
|
if [ "$MYSQL_PROC" -gt 0 ]; then
|
|
echo " ${OK} MySQL/MariaDB 실행 중 (${MYSQL_PROC}개)"
|
|
else
|
|
echo " ${CRIT} MySQL/MariaDB 프로세스 없음"
|
|
RESULT=2
|
|
fi
|
|
|
|
# ── 2. 포트 리스닝 + 접속 테스트 ─────────────────────────
|
|
echo; echo "[$SEP] 2. 포트 리스닝 및 접속"
|
|
if ss -tlnp 2>/dev/null | grep -q ":${MYSQL_PORT} "; then
|
|
echo " ${OK} 포트 ${MYSQL_PORT} LISTEN"
|
|
else
|
|
echo " ${CRIT} 포트 ${MYSQL_PORT} LISTEN 없음"
|
|
RESULT=2
|
|
fi
|
|
if command -v mysql &>/dev/null; then
|
|
VERSION=$(${MY} -e "SELECT @@version;" 2>/dev/null | head -1 || echo "접속 실패")
|
|
if echo "$VERSION" | grep -qE "[0-9]+\.[0-9]+"; then
|
|
echo " ${OK} DB 접속 성공 — 버전: ${VERSION}"
|
|
else
|
|
echo " ${CRIT} DB 접속 실패"
|
|
RESULT=2
|
|
fi
|
|
else
|
|
echo " ${WARN} mysql 클라이언트 없음"
|
|
[ $RESULT -lt 1 ] && RESULT=1
|
|
fi
|
|
|
|
# ── 3. 연결 현황 ─────────────────────────────────────────
|
|
echo; echo "[$SEP] 3. 연결 현황"
|
|
if command -v mysql &>/dev/null && [ "$RESULT" -lt 2 ]; then
|
|
MAX_CONN=$(${MY} -e "SHOW VARIABLES LIKE 'max_connections';" 2>/dev/null | awk '{print $2}')
|
|
CURR_CONN=$(${MY} -e "SHOW STATUS LIKE 'Threads_connected';" 2>/dev/null | awk '{print $2}')
|
|
RUNNING=$(${MY} -e "SHOW STATUS LIKE 'Threads_running';" 2>/dev/null | awk '{print $2}')
|
|
echo " 최대 연결: ${MAX_CONN}"
|
|
echo " 현재 연결: ${CURR_CONN} (실행 중: ${RUNNING})"
|
|
if [ -n "$MAX_CONN" ] && [ "$MAX_CONN" -gt 0 ]; then
|
|
CONN_PCT=$(( CURR_CONN * 100 / MAX_CONN ))
|
|
if [ "$CONN_PCT" -ge "$MAX_CONN_WARN" ]; then
|
|
echo " ${WARN} 연결 사용률 ${CONN_PCT}%"
|
|
[ $RESULT -lt 1 ] && RESULT=1
|
|
else
|
|
echo " ${OK} 연결 사용률 ${CONN_PCT}%"
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
# ── 4. 슬로우 쿼리 ────────────────────────────────────────
|
|
echo; echo "[$SEP] 4. 슬로우 쿼리"
|
|
if command -v mysql &>/dev/null && [ "$RESULT" -lt 2 ]; then
|
|
SLOW_CNT=$(${MY} -e "SHOW STATUS LIKE 'Slow_queries';" 2>/dev/null | awk '{print $2}' || echo 0)
|
|
SLOW_LOG=$(${MY} -e "SHOW VARIABLES LIKE 'slow_query_log';" 2>/dev/null | awk '{print $2}')
|
|
LONG_TIME=$(${MY} -e "SHOW VARIABLES LIKE 'long_query_time';" 2>/dev/null | awk '{print $2}')
|
|
echo " 슬로우 쿼리 로그: ${SLOW_LOG} (임계: ${LONG_TIME}s)"
|
|
if [ "${SLOW_CNT:-0}" -gt "$SLOW_QUERY_WARN" ]; then
|
|
echo " ${WARN} 슬로우 쿼리 누적: ${SLOW_CNT}건"
|
|
[ $RESULT -lt 1 ] && RESULT=1
|
|
else
|
|
echo " ${OK} 슬로우 쿼리: ${SLOW_CNT}건"
|
|
fi
|
|
fi
|
|
|
|
# ── 5. InnoDB 상태 ────────────────────────────────────────
|
|
echo; echo "[$SEP] 5. InnoDB 주요 상태"
|
|
if command -v mysql &>/dev/null && [ "$RESULT" -lt 2 ]; then
|
|
INNODB=$(${MY} -e "
|
|
SHOW STATUS WHERE Variable_name IN
|
|
('Innodb_buffer_pool_reads','Innodb_buffer_pool_read_requests',
|
|
'Innodb_row_lock_waits','Innodb_deadlocks','Innodb_log_waits');" \
|
|
2>/dev/null | sed 's/^/ /' || echo "")
|
|
echo "$INNODB"
|
|
# 데드락 체크
|
|
DEADLOCKS=$(${MY} -e "SHOW STATUS LIKE 'Innodb_deadlocks';" 2>/dev/null | awk '{print $2}' || echo 0)
|
|
[ "${DEADLOCKS:-0}" -gt 0 ] && echo " ${WARN} 데드락 발생: ${DEADLOCKS}건" && [ $RESULT -lt 1 ] && RESULT=1
|
|
fi
|
|
|
|
# ── 6. 복제(Replication) 상태 ────────────────────────────
|
|
echo; echo "[$SEP] 6. 복제 상태"
|
|
if command -v mysql &>/dev/null && [ "$RESULT" -lt 2 ]; then
|
|
SLAVE_STATUS=$(${MY} -e "SHOW SLAVE STATUS\G" 2>/dev/null || \
|
|
${MY} -e "SHOW REPLICA STATUS\G" 2>/dev/null || echo "")
|
|
if [ -n "$SLAVE_STATUS" ]; then
|
|
IO_RUNNING=$(echo "$SLAVE_STATUS" | grep "Slave_IO_Running\|Replica_IO_Running" | awk '{print $2}')
|
|
SQL_RUNNING=$(echo "$SLAVE_STATUS" | grep "Slave_SQL_Running\|Replica_SQL_Running" | awk '{print $2}')
|
|
BEHIND=$(echo "$SLAVE_STATUS" | grep "Seconds_Behind_Master\|Seconds_Behind_Source" | awk '{print $2}')
|
|
echo " IO Thread: ${IO_RUNNING}, SQL Thread: ${SQL_RUNNING}"
|
|
echo " 복제 지연: ${BEHIND}초"
|
|
if [ "$IO_RUNNING" != "Yes" ] || [ "$SQL_RUNNING" != "Yes" ]; then
|
|
echo " ${CRIT} 복제 비정상"
|
|
RESULT=2
|
|
elif [ "${BEHIND:-0}" -gt 60 ]; then
|
|
echo " ${WARN} 복제 지연 과다 (${BEHIND}s)"
|
|
[ $RESULT -lt 1 ] && RESULT=1
|
|
else
|
|
echo " ${OK} 복제 정상"
|
|
fi
|
|
else
|
|
echo " 복제 미설정 (Standalone)"
|
|
fi
|
|
fi
|
|
|
|
# ── 7. DB 크기 ────────────────────────────────────────────
|
|
echo; echo "[$SEP] 7. DB 크기 (상위 5)"
|
|
if command -v mysql &>/dev/null && [ "$RESULT" -lt 2 ]; then
|
|
${MY} -e "
|
|
SELECT table_schema AS db,
|
|
ROUND(SUM(data_length + index_length)/1024/1024, 1) AS size_mb
|
|
FROM information_schema.tables
|
|
GROUP BY table_schema
|
|
ORDER BY size_mb DESC
|
|
LIMIT 5;" 2>/dev/null | sed 's/^/ /' || true
|
|
fi
|
|
|
|
# ── 요약 ─────────────────────────────────────────────────
|
|
echo
|
|
echo "======================================================"
|
|
case $RESULT in
|
|
0) echo " 최종 결과: ${OK} MySQL/MariaDB 정상" ;;
|
|
1) echo " 최종 결과: ${WARN} 주의 항목 있음" ;;
|
|
2) echo " 최종 결과: ${CRIT} 즉시 조치 필요" ;;
|
|
esac
|
|
echo " 점검 완료: $(date '+%Y-%m-%d %H:%M:%S')"
|
|
echo "======================================================"
|
|
exit $RESULT
|