#!/bin/bash # ============================================================ # GUARDiA SM | db_oracle_sm.sh # 대상: Oracle Database (11g/12c/19c/21c) # 파라미터: ORACLE_HOME=/opt/oracle/product/19c/dbhome_1 # ORACLE_SID=orcl ORACLE_USER=oracle # DB_USER=system DB_PASS=oracle DB_CONN=localhost:1521/orcl # LISTENER_PORT=1521 ARCHIVE_WARN=80 # ============================================================ set -euo pipefail ORACLE_HOME=${ORACLE_HOME:-/opt/oracle/product/19c/dbhome_1} ORACLE_SID=${ORACLE_SID:-orcl} ORACLE_USER=${ORACLE_USER:-oracle} DB_USER=${DB_USER:-system} DB_PASS=${DB_PASS:-oracle} DB_CONN=${DB_CONN:-"localhost:1521/${ORACLE_SID}"} LISTENER_PORT=${LISTENER_PORT:-1521} ARCHIVE_WARN=${ARCHIVE_WARN:-80} OK="[OK]"; WARN="[WARN]"; CRIT="[CRIT]" SEP="─────────────────────────────────────────" RESULT=0 export ORACLE_HOME ORACLE_SID export PATH="${ORACLE_HOME}/bin:${PATH}" # sqlplus 헬퍼 (결과만 반환) _sql() { sqlplus -s "${DB_USER}/${DB_PASS}@${DB_CONN}" </dev/null SET PAGESIZE 0 FEEDBACK OFF VERIFY OFF HEADING OFF ECHO OFF TRIMOUT ON $1 EXIT; EOF } echo "======================================================" echo " GUARDiA SM 점검 | Oracle DB | $(hostname -s)" echo " 점검 시각: $(date '+%Y-%m-%d %H:%M:%S %Z')" echo "======================================================" # ── 1. 리스너 프로세스 ──────────────────────────────────── echo; echo "[$SEP] 1. 리스너 상태" LSNR_PROC=$(pgrep -c "tnslsnr" 2>/dev/null || echo 0) if [ "$LSNR_PROC" -gt 0 ]; then echo " ${OK} 리스너 실행 중 (PID: $(pgrep tnslsnr | head -1))" if command -v lsnrctl &>/dev/null; then LSNR_STAT=$(lsnrctl status 2>/dev/null | grep -E "Alias|Status|Uptime|Version" | \ sed 's/^/ /' | head -6 || echo "") echo "$LSNR_STAT" fi else echo " ${CRIT} 리스너 프로세스 없음" RESULT=2 fi # ── 2. 포트 리스닝 ──────────────────────────────────────── echo; echo "[$SEP] 2. 포트 리스닝" if ss -tlnp 2>/dev/null | grep -q ":${LISTENER_PORT} "; then echo " ${OK} 포트 ${LISTENER_PORT} LISTEN" else echo " ${CRIT} 포트 ${LISTENER_PORT} LISTEN 없음" RESULT=2 fi # ── 3. DB 프로세스 + 인스턴스 상태 ────────────────────── echo; echo "[$SEP] 3. 인스턴스 상태" ORA_PROC=$(pgrep -c "ora_pmon_\|ora_smon_" 2>/dev/null || echo 0) if [ "$ORA_PROC" -gt 0 ]; then echo " ${OK} Oracle 백그라운드 프로세스 실행 중 (${ORA_PROC}개)" else echo " ${CRIT} Oracle 백그라운드 프로세스 없음" RESULT=2 fi # sqlplus 접속 테스트 if command -v sqlplus &>/dev/null && [ "$RESULT" -lt 2 ]; then DB_STATUS=$(_sql "SELECT status FROM v\$instance;" 2>/dev/null | tr -d ' ') if echo "$DB_STATUS" | grep -qi "OPEN"; then echo " ${OK} DB 인스턴스 상태: OPEN" else echo " ${WARN} DB 인스턴스 상태: ${DB_STATUS}" [ $RESULT -lt 1 ] && RESULT=1 fi fi # ── 4. 세션 현황 ───────────────────────────────────────── echo; echo "[$SEP] 4. 세션 현황" if command -v sqlplus &>/dev/null && [ "$RESULT" -lt 2 ]; then SESSION_INFO=$(_sql " SELECT 'TOTAL:'||count(*)||' ACTIVE:'|| sum(CASE WHEN status='ACTIVE' THEN 1 ELSE 0 END)||' INACTIVE:'|| sum(CASE WHEN status='INACTIVE' THEN 1 ELSE 0 END) FROM v\$session WHERE type='USER';" 2>/dev/null | tr -d ' ') echo " ${SESSION_INFO}" # 세션 한도 MAX_SESS=$(_sql "SELECT value FROM v\$parameter WHERE name='sessions';" 2>/dev/null | tr -d ' ') CURR_SESS=$(_sql "SELECT count(*) FROM v\$session;" 2>/dev/null | tr -d ' ') echo " 세션 한도: ${MAX_SESS}, 현재: ${CURR_SESS}" if [ -n "$MAX_SESS" ] && [ "$MAX_SESS" -gt 0 ]; then SESS_PCT=$(( CURR_SESS * 100 / MAX_SESS )) [ "$SESS_PCT" -ge 80 ] && echo " ${WARN} 세션 사용률 ${SESS_PCT}%" && [ $RESULT -lt 1 ] && RESULT=1 fi fi # ── 5. 테이블스페이스 사용률 ───────────────────────────── echo; echo "[$SEP] 5. 테이블스페이스 사용률" if command -v sqlplus &>/dev/null && [ "$RESULT" -lt 2 ]; then TS_INFO=$(_sql " SELECT df.tablespace_name, round(df.total_mb,1)||'MB' AS total, round(df.total_mb - fs.free_mb,1)||'MB' AS used, round((df.total_mb - fs.free_mb) * 100 / df.total_mb,1)||'%' AS pct FROM (SELECT tablespace_name, sum(bytes)/1048576 total_mb FROM dba_data_files GROUP BY tablespace_name) df, (SELECT tablespace_name, sum(bytes)/1048576 free_mb FROM dba_free_space GROUP BY tablespace_name) fs WHERE df.tablespace_name = fs.tablespace_name(+) ORDER BY 4 DESC FETCH FIRST 10 ROWS ONLY;" 2>/dev/null | sed 's/^/ /' || echo " 조회 실패") echo "$TS_INFO" # 90% 초과 체크 CRIT_TS=$(_sql " SELECT count(*) FROM ( SELECT df.tablespace_name, round((df.total_mb - nvl(fs.free_mb,0)) * 100 / df.total_mb,1) pct FROM (SELECT tablespace_name, sum(bytes)/1048576 total_mb FROM dba_data_files GROUP BY tablespace_name) df, (SELECT tablespace_name, sum(bytes)/1048576 free_mb FROM dba_free_space GROUP BY tablespace_name) fs WHERE df.tablespace_name = fs.tablespace_name(+) ) WHERE pct >= 90;" 2>/dev/null | tr -d ' ' || echo 0) [ "${CRIT_TS:-0}" -gt 0 ] && echo " ${CRIT} 테이블스페이스 90% 초과 ${CRIT_TS}개" && RESULT=2 fi # ── 6. 아카이브 로그 사용률 ────────────────────────────── echo; echo "[$SEP] 6. 아카이브 로그 사용률" if command -v sqlplus &>/dev/null && [ "$RESULT" -lt 2 ]; then ARCH_PCT=$(_sql " SELECT round(space_used * 100 / space_limit,1) FROM v\$recovery_file_dest;" 2>/dev/null | tr -d ' ' || echo "N/A") if echo "$ARCH_PCT" | grep -qE "^[0-9]"; then if [ "${ARCH_PCT%.*}" -ge 90 ]; then echo " ${CRIT} FRA 사용률 ${ARCH_PCT}%" RESULT=2 elif [ "${ARCH_PCT%.*}" -ge "$ARCHIVE_WARN" ]; then echo " ${WARN} FRA 사용률 ${ARCH_PCT}%" [ $RESULT -lt 1 ] && RESULT=1 else echo " ${OK} FRA 사용률 ${ARCH_PCT}%" fi else echo " FRA 정보 없음 (아카이브 모드 미사용 또는 미권한)" fi fi # ── 7. 알람 로그 오류 (최근 100줄) ─────────────────────── echo; echo "[$SEP] 7. Alert 로그 오류" ALERT_LOG="${ORACLE_HOME}/../diag/rdbms/${ORACLE_SID}/${ORACLE_SID}/trace/alert_${ORACLE_SID}.log" if [ -r "$ALERT_LOG" ]; then ERR_CNT=$(tail -200 "$ALERT_LOG" | grep -icE "ORA-[0-9]+|error" || echo 0) echo " 최근 오류 수: ${ERR_CNT}" tail -200 "$ALERT_LOG" | grep -iE "ORA-[0-9]+" | tail -5 | sed 's/^/ /' || true [ "$ERR_CNT" -gt 5 ] && [ $RESULT -lt 1 ] && RESULT=1 else # ADR 기반 경로 시도 for P in /opt/oracle/diag/rdbms/${ORACLE_SID}/${ORACLE_SID}/trace/alert_${ORACLE_SID}.log \ /u01/app/oracle/diag/rdbms/${ORACLE_SID}/${ORACLE_SID}/trace/alert_${ORACLE_SID}.log; do [ -r "$P" ] && tail -200 "$P" | grep -iE "ORA-[0-9]+" | tail -5 | sed 's/^/ /' && break done echo " Alert 로그 경로 확인 필요: ${ALERT_LOG}" fi # ── 요약 ───────────────────────────────────────────────── echo echo "======================================================" case $RESULT in 0) echo " 최종 결과: ${OK} Oracle DB 정상" ;; 1) echo " 최종 결과: ${WARN} 주의 항목 있음" ;; 2) echo " 최종 결과: ${CRIT} 즉시 조치 필요" ;; esac echo " 점검 완료: $(date '+%Y-%m-%d %H:%M:%S')" echo "======================================================" exit $RESULT