#!/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