zioinfo-mail/docs/shell_scripts_guide.md
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

10 KiB

[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 원격 명령 실행 이력 감사 기록

공통 규칙

# 모든 스크립트 공통 패턴
#!/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

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

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

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

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

크론탭 스케줄러 등록

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

#!/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}\"}"