#!/usr/bin/env bash # 개발서버(zio-server)에서 실행 — 운영 웹서버로 정적 리소스를 배포한다. # # 설치 위치: /opt/arko-dev/bin/arko-prodweb-deploy.sh # 호출 주체: Gitea Actions(.gitea/workflows/deploy-dev.yml) 마지막 단계, 또는 수동 # # 흐름: git push → CI → 개발 WAS 배포 → (헬스체크 통과) → 이 스크립트 → 운영 웹 반영 # # 방향이 개발 → 운영이다. 운영 웹서버(211.37.173.197)는 NAT 밖 공인망에 있고 # SSH 9271이 열려 있어 개발서버에서 바로 접속할 수 있다. # 반대로 개발서버는 NAT 뒤라 운영에서 먼저 접속할 수 없다. # # 배포 대상은 방금 개발 WAS에 전개된 ROOT의 정적 리소스다. # WAR를 다시 풀지 않고 실제 서비스 중인 파일을 그대로 복사하므로 # 개발과 운영 웹이 항상 같은 산출물을 바라본다. set -euo pipefail PROD_HOST=211.37.173.197 PROD_PORT=9271 PROD_USER=root KEY=/root/.ssh/id_arko_prodweb SRC_ROOT=/opt/arko-dev/tomcat/webapps/ROOT DEST=/var/www/csv.wise.ai.kr/static SITE=https://csv.wise.ai.kr/ DIRS="images css js fonts new" log() { echo "[$(date +'%F %T')] $*"; } die() { echo "[$(date +'%F %T')] ERROR: $*"; exit 1; } SSH_OPTS="-p $PROD_PORT -i $KEY -o IdentitiesOnly=yes -o StrictHostKeyChecking=accept-new -o ConnectTimeout=20 -o BatchMode=yes" # ------------------------------------------------------------ 1. 사전 확인 [ -f "$KEY" ] || die "배포 키가 없다: $KEY" [ -d "$SRC_ROOT" ] || die "전개된 ROOT가 없다: $SRC_ROOT (개발 배포가 선행되어야 한다)" log "운영 웹서버 접속 확인 ($PROD_HOST:$PROD_PORT)" ssh $SSH_OPTS "$PROD_USER@$PROD_HOST" "test -d $DEST" \ || die "접속 또는 대상 디렉토리 확인 실패 — 운영 웹에서 05-prodweb-prepare.sh 를 먼저 실행할 것" # ------------------------------------------------------------ 2. 동기화 # --delete 는 쓰지 않는다. 운영 웹에만 있는 파일(수동 배치분)을 지워버릴 수 있고, # 정적 리소스는 누적되어도 문제가 없다. 대신 크기·시각이 다른 것만 전송한다. TOTAL=0 for d in $DIRS; do if [ ! -d "$SRC_ROOT/$d" ]; then log "건너뜀(원본 없음): $d" continue fi SIZE=$(du -sh "$SRC_ROOT/$d" | cut -f1) log "동기화: $d ($SIZE)" OUT=$(rsync -az --stats --human-readable \ -e "ssh $SSH_OPTS" \ "$SRC_ROOT/$d/" "$PROD_USER@$PROD_HOST:$DEST/$d/" 2>&1) || die "rsync 실패: $d" N=$(echo "$OUT" | grep -oE "Number of regular files transferred: [0-9,]+" | grep -oE "[0-9,]+$" | tr -d ',') N=${N:-0} TOTAL=$((TOTAL + N)) log " 전송 $N 개" done log "총 전송 파일 수: $TOTAL" # ------------------------------------------------------------ 3. 검증 log "운영 웹 확인" CODE=$(curl -s -o /dev/null -w "%{http_code}" --max-time 30 "$SITE" || echo 000) log "$SITE → HTTP $CODE" [ "$CODE" = "200" ] || [ "$CODE" = "302" ] || die "운영 웹이 정상 응답하지 않는다 (HTTP $CODE)" # 정적 파일이 실제로 운영 웹에서 나오는지 표본 확인. # X-Cache 헤더가 없으므로 nginx access_log 대신 응답 코드로만 판단한다. SAMPLE=$(find "$SRC_ROOT/images" -maxdepth 2 -type f \( -name "*.png" -o -name "*.jpg" -o -name "*.gif" \) 2>/dev/null | head -1) if [ -n "$SAMPLE" ]; then REL=${SAMPLE#$SRC_ROOT} SCODE=$(curl -s -o /dev/null -w "%{http_code}" --max-time 20 "https://csv.wise.ai.kr$REL" || echo 000) log "표본 정적 파일 $REL → HTTP $SCODE" fi log "운영 웹 배포 완료"