# [Guide] SM 운영용 원격 제어 쉘 스크립트 > 중계 PC에서 내부망 WEB/WAS/DB 서버를 원격 제어하는 표준 스크립트 모음. > 모든 스크립트는 **JSON 출력** → AI 에이전트가 파싱하여 메신저로 전달. > > **v2.0+**: 스크립트는 파일 뿐 아니라 `TB_SHELL_SCRIPT` DB 테이블에 등록·관리된다. > ITSM 웹 UI에서 CRUD 가능하며, 작업 타임테이블과 연계 가능하다. --- ## 쉘 스크립트 DB 관리 (신규) ### API 엔드포인트 | 메서드 | URL | 권한 | 설명 | |--------|-----|------|------| | `GET` | `/api/shell-scripts` | 전체 | 스크립트 목록 조회 (카테고리·레이어 필터) | | `GET` | `/api/shell-scripts/{id}` | 전체 | 스크립트 상세 (스크립트 본문 포함) | | `POST` | `/api/shell-scripts` | ENGINEER, ADMIN | 신규 스크립트 등록 | | `PATCH` | `/api/shell-scripts/{id}` | ENGINEER, ADMIN | 스크립트 수정 | | `DELETE` | `/api/shell-scripts/{id}` | ADMIN | 비활성화 | | `POST` | `/api/shell-scripts/{id}/run` | ENGINEER, ADMIN | 대상 서버에 즉시 실행 (HITL 승인 포함) | ### 카테고리별 분류 | category | 설명 | 예시 sub_category | |----------|------|-------------------| | `SM` | 일상 운영 관리 | DISK_CHECK, PROCESS_KILL, LOG_ROTATE | | `REGULAR` | 정기점검 (계획) | MONTHLY_CHECK, QUARTERLY_AUDIT | | `ADHOC` | 수시점검·긴급 대응 | OOM_ANALYZE, NETWORK_CHECK | | `DEPLOY` | 배포 관련 | ROLLING_RESTART, FILE_COPY | | `SECURITY` | 보안 점검 | ACCOUNT_AUDIT, PORT_SCAN, FILE_INTEGRITY | | `MONITORING` | 상태 감시 | HEALTH_CHECK, SSL_EXPIRY, CRON_CHECK | ### 프론트엔드 화면 구성 (`view-scripts`) ``` ┌─────────────────────────────────────────────────────────┐ │ 🖥️ 쉘 스크립트 관리 [+ 스크립트 등록] │ ├─────────────────────────────────────────────────────────┤ │ [카테고리▼] [레이어▼] [OS▼] [키워드 검색] │ ├──────┬──────────────────────┬────────┬────────┬─────────┤ │ ID │ 스크립트명 │ 카테고리│ 레이어 │ 위험도 │ ├──────┼──────────────────────┼────────┼────────┼─────────┤ │ 1 │ check_infra_health │ SM │ ALL │ 안전 │ │ 2 │ manage_service │ SM │ WAS │ 보통 │ │ 3 │ collect_target_logs │ SM │ ALL │ 안전 │ │ 4 │ backup_and_clear │ SM │ WAS │ ⚠ 주의 │ │ 5 │ 정기점검_WAS_재기동 │ REGULAR│ WAS │ ⚠ 주의 │ └──────┴──────────────────────┴────────┴────────┴─────────┘ ``` --- --- ## 스크립트 목록 | 번호 | 파일명 | 역할 | |------|--------|------| | 1 | `check_infra_health.sh` | WEB/WAS/DB 포트·Ping 일괄 헬스체크 | | 2 | `manage_service.sh` | 서비스 데몬 상태/기동/중지/재기동 | | 3 | `monitor_resources.sh` | CPU/메모리/디스크 임계치 감시 | | 4 | `collect_target_logs.sh` | 에러 로그 원격 추출 (grep + tail) | | 5 | `check_db_status.sh` | DB 커넥션·Lock 세션 진단/해제 | | 6 | `backup_and_clear.sh` | 로그 로테이션 및 오래된 파일 정비 | | 7 | `security_audit.sh` | 계정 잠금·포트 스캔·파일 위변조 감사 | | 8 | `ssl_expiry_detector.sh` | SSL 인증서 만료일 사전 감지 | | 9 | `self_healing_defense.sh` | 디스크 임계치 초과 시 자동 정비 트리거 | | 10 | `config_integrity_check.sh` | 설정 파일 SHA-256 무결성 검증 | | 11 | `cron_health_checker.sh` | 크론탭 배치 가동성 진단 | | 12 | `esb_channel_monitor.sh` | ESB 연계 채널 상태 및 큐 임계치 감시 | | 13 | `audit_session_logger.sh` | 원격 명령 실행 이력 감사 기록 | --- ## 공통 규칙 ```bash # 모든 스크립트 공통 패턴 #!/bin/bash declare -A SERVER_HOSTS=([WEB]="192.168.10.11" [WAS]="192.168.10.12" [DB]="192.168.10.13") declare -A SERVER_USERS=([WEB]="webadmin" [WAS]="wasadmin" [DB]="postgres") # SSH 실행 공통 함수 execute_remote_cmd() { local host=$1; local user=$2; local cmd=$3 ssh -o StrictHostKeyChecking=no -o ConnectTimeout=3 "${user}@${host}" "${cmd}" 2>/dev/null } # 출력: JSON (AI 파싱용) # 로그: /app/agent/logs/YYYYMMDD.log ``` --- ## 1. check_infra_health.sh ```bash #!/bin/bash # 사용법: ./check_infra_health.sh # 출력: {"timestamp":"...","results":[{"server":"WEB","ping":"UP","port_status":"OPEN"}, ...]} check_node() { local name=$1 ip=$2 port=$3 ping -c 1 -W 1 "${ip}" > /dev/null 2>&1 && ping_s="UP" || ping_s="DOWN" timeout 2 bash -c "cat < /dev/null > /dev/tcp/${ip}/${port}" 2>/dev/null && port_s="OPEN" || port_s="CLOSED" echo "{\"server\":\"${name}\",\"ip\":\"${ip}\",\"ping\":\"${ping_s}\",\"port_status\":\"${port_s}\"}" } WEB_J=$(check_node "WEB" "192.168.10.11" "80") WAS_J=$(check_node "WAS" "192.168.10.12" "8080") DB_J=$(check_node "DB" "192.168.10.13" "5432") echo "{\"timestamp\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"results\":[${WEB_J},${WAS_J},${DB_J}]}" ``` --- ## 2. manage_service.sh ```bash #!/bin/bash # 사용법: ./manage_service.sh [WEB|WAS|DB] [status|start|stop|restart] TARGET=$1; ACTION=$2 declare -A SERVICE_NAMES=([WEB]="nginx" [WAS]="tomcat" [DB]="postgresql") HOST=${SERVER_HOSTS[$TARGET]}; USER=${SERVER_USERS[$TARGET]}; SVC=${SERVICE_NAMES[$TARGET]} case ${ACTION} in status) RAW=$(execute_remote_cmd "$HOST" "$USER" "systemctl is-active ${SVC}") [ "$RAW" = "active" ] && STATUS="RUNNING" || STATUS="STOPPED" echo "{\"server\":\"${TARGET}\",\"service\":\"${SVC}\",\"status\":\"${STATUS}\"}" ;; start|stop|restart) RAW=$(execute_remote_cmd "$HOST" "$USER" "sudo systemctl ${ACTION} ${SVC}") [ $? -eq 0 ] && RESULT="SUCCESS" || RESULT="FAILED" echo "{\"server\":\"${TARGET}\",\"service\":\"${SVC}\",\"result\":\"${RESULT}\",\"action\":\"${ACTION}\"}" ;; esac ``` --- ## 3. collect_target_logs.sh ```bash #!/bin/bash # 사용법: ./collect_target_logs.sh [WEB|WAS|DB] [라인수(기본100)] TARGET=$1; LINES=${2:-100} declare -A LOG_PATHS=([WEB]="/var/log/nginx/error.log" [WAS]="/app/tomcat/logs/catalina.out" [DB]="/var/log/postgresql/postgresql.log") HOST=${SERVER_HOSTS[$TARGET]}; USER=${SERVER_USERS[$TARGET]}; LOG=${LOG_PATHS[$TARGET]} REMOTE_CMD="tail -n ${LINES} ${LOG} | awk '/Exception|ERROR|Error|CRITICAL|FATAL/{print \"[ALERT] \" \$0; next}{print \$0}'" OUTPUT=$(execute_remote_cmd "$HOST" "$USER" "$REMOTE_CMD") CLEAN=$(echo "$OUTPUT" | sed 's/\\/\\\\/g' | sed 's/"/\\"/g' | awk '{printf "%s\\n", $0}') echo "{\"server\":\"${TARGET}\",\"log_path\":\"${LOG}\",\"lines\":${LINES},\"log_data\":\"${CLEAN}\"}" ``` --- ## 5. check_db_status.sh ```bash #!/bin/bash # 사용법: ./check_db_status.sh DB check (Lock 세션 조회) # ./check_db_status.sh DB kill 1234 (PID 강제 해제) TARGET=$1; ACTION=$2; PID=$3 HOST=${SERVER_HOSTS[$TARGET]}; USER=${SERVER_USERS[$TARGET]} case $ACTION in check) SQL="SELECT json_build_object('total_connections',(SELECT count(*) FROM pg_stat_activity),'locked_sessions',(SELECT coalesce(json_agg(json_build_object('blocked_pid',pid,'age',clock_timestamp()-query_start,'query',query)),'{}'::json) FROM pg_stat_activity WHERE wait_event_type='Lock'));" execute_remote_cmd "$HOST" "$USER" "psql -d mes_db -t -c \"${SQL}\"" | tr -d '\n' | sed 's/ //g' ;; kill) [ -z "$PID" ] && echo '{"status":"ERROR","message":"PID 필요"}' && exit 1 OUT=$(execute_remote_cmd "$HOST" "$USER" "psql -d mes_db -t -c \"SELECT pg_terminate_backend(${PID});\"") [[ "$OUT" == *"t"* ]] && RESULT="SUCCESS" || RESULT="FAILED" echo "{\"server\":\"${TARGET}\",\"action\":\"KILL\",\"pid\":${PID},\"result\":\"${RESULT}\"}" ;; esac ``` --- ## 크론탭 스케줄러 등록 ```bash #!/bin/bash # agent_self_scheduler.sh install — 모든 감시 스크립트 자동 등록 cat << EOF > /tmp/agent_cron.tmp # 5분마다: 자원 감시 + 자가 치유 */5 * * * * /app/agent/bin/self_healing_defense.sh WEB > /dev/null 2>&1 */5 * * * * /app/agent/bin/self_healing_defense.sh WAS > /dev/null 2>&1 */5 * * * * /app/agent/bin/self_healing_defense.sh DB > /dev/null 2>&1 # 1시간마다: 보안 감사 0 */1 * * * /app/agent/bin/security_audit.sh WEB > /dev/null 2>&1 0 */1 * * * /app/agent/bin/security_audit.sh WAS > /dev/null 2>&1 0 */1 * * * /app/agent/bin/security_audit.sh DB > /dev/null 2>&1 # 매일 03:00: 로그 정비 0 3 * * * /app/agent/bin/backup_and_clear.sh WAS > /dev/null 2>&1 # 매일 04:00: SSL 인증서 만료 스캔 0 4 * * * /app/agent/bin/ssl_expiry_detector.sh WEB > /dev/null 2>&1 # 10분마다: ESB 연계 감시 */10 * * * * /app/agent/bin/esb_channel_monitor.sh 192.168.10.21 > /dev/null 2>&1 EOF crontab /tmp/agent_cron.tmp rm /tmp/agent_cron.tmp echo '{"status":"SUCCESS","message":"크론탭 스케줄 등록 완료"}' ``` --- ## 알림 웹훅 전송 (`alert_webhook_sender.sh`) ```bash #!/bin/bash # 사용법: ./alert_webhook_sender.sh "WAS" "CRITICAL" "디스크 95% 초과" SERVER=$1; LEVEL=$2; MSG=$3 WEBHOOK="http://192.168.10.50:8080/api/v1/infrastructure/alerts" PAYLOAD="{\"system_source\":\"PC_MIDDLEWARE_AGENT\",\"target_node\":\"${SERVER}\",\"severity_level\":\"${LEVEL}\",\"incident_message\":\"${MSG}\",\"occurred_at\":\"$(date '+%Y-%m-%d %H:%M:%S')\"}" CODE=$(curl -s -o /dev/null -w "%{http_code}" -X POST -H "Content-Type: application/json" -d "${PAYLOAD}" --connect-timeout 3 "${WEBHOOK}") [ "$CODE" -eq 200 ] || [ "$CODE" -eq 201 ] \ && echo "{\"status\":\"SUCCESS\",\"code\":\"${CODE}\"}" \ || echo "{\"status\":\"FAILED\",\"code\":\"${CODE}\"}" ```