#!/usr/bin/env bash # 배포 후 서버가 제대로 떴는지 확인한다. 서버에서 실행한다. # # ./healthcheck.sh # 기본 http://localhost:5000 # ./healthcheck.sh 5281 # 포트만 바꿔서 # ./healthcheck.sh 5000 GameServer # 서비스 이름까지 지정 # ./healthcheck.sh 5000 GameServer /home/ubuntu/gameserver # 앱 폴더까지 # # 실패한 항목이 하나라도 있으면 종료 코드 1 을 돌려준다. BASE="http://localhost:${1:-5000}" SERVICE="${2:-GameServer}" # 앱 폴더(GameServer 실행 파일과 wwwroot 가 있는 곳). 기본은 이 스크립트가 있는 폴더. APPDIR="${3:-$(cd "$(dirname "$0")" && pwd)}" PASS=0 FAIL=0 ok() { PASS=$((PASS+1)); printf ' \033[32mOK \033[0m %s\n' "$1"; } bad() { FAIL=$((FAIL+1)); printf ' \033[31m실패\033[0m %s\n %s\n' "$1" "$2"; } # code URL -> 응답 코드만 code() { curl -s -o /dev/null -w '%{http_code}' --max-time 10 "$1" 2>/dev/null; } echo echo "=== 1. 서비스 상태 ===" if systemctl is-active --quiet "$SERVICE" 2>/dev/null; then ok "$SERVICE 실행 중" since=$(systemctl show -p ActiveEnterTimestamp --value "$SERVICE" 2>/dev/null) [ -n "$since" ] && echo " 시작: $since" # 계속 죽었다 살아나는 중인지 n=$(systemctl show -p NRestarts --value "$SERVICE" 2>/dev/null || echo 0) if [ "${n:-0}" -gt 0 ]; then echo " 재시작 횟수: $n (반복되면 로그를 확인하세요)" fi else bad "$SERVICE 가 실행 중이 아님" "sudo systemctl status $SERVICE" fi echo echo "=== 2. 포트 열림 ===" PORT="${1:-5000}" if ss -tln 2>/dev/null | grep -q ":$PORT "; then ok "포트 $PORT 수신 중" ss -tlnp 2>/dev/null | grep ":$PORT " | sed 's/^/ /' else bad "포트 $PORT 가 열려 있지 않음" "sudo ss -tlnp | grep $PORT" fi echo echo "=== 3. 기존 게임 API (회귀 확인) ===" for p in /myGame/playableCharacters /myGame/userCharacters; do c=$(code "$BASE$p") if [ "$c" = "200" ]; then ok "GET $p" else bad "GET $p -> $c" "DB 연결이나 라우팅을 확인하세요"; fi done echo echo "=== 4. 포트폴리오 ===" c=$(code "$BASE/api/portfolio/categories") if [ "$c" = "200" ]; then ok "카테고리 API" n=$(curl -s --max-time 10 "$BASE/api/portfolio/categories" | grep -o '"categoryNo"' | wc -l) echo " 카테고리 $n 개" [ "$n" -eq 0 ] && echo " (0 개면 DB 스키마 생성이 실패했을 수 있습니다. 로그를 보세요)" else bad "카테고리 API -> $c" "DB 연결 실패일 가능성이 큽니다" fi c=$(code "$BASE/api/portfolio/posts") [ "$c" = "200" ] && ok "게시물 API" || bad "게시물 API -> $c" "" echo echo "=== 5. 사이트 (정적 파일) ===" for p in / /css/style.css /js/app.js; do c=$(code "$BASE$p") if [ "$c" = "200" ]; then ok "GET $p" else bad "GET $p -> $c" "wwwroot 가 함께 배포됐는지 확인하세요"; fi done echo echo "=== 6. 업로드 폴더 쓰기 권한 ===" UPDIR="$APPDIR/wwwroot/uploads" if [ -d "$UPDIR" ]; then if [ -w "$UPDIR" ]; then ok "쓰기 가능 ($UPDIR)" else bad "쓰기 불가 ($UPDIR)" "서비스 실행 사용자에게 권한을 주세요"; fi echo " 보관된 파일 $(find "$UPDIR" -type f ! -name '.gitkeep' 2>/dev/null | wc -l) 개" else bad "업로드 폴더 없음 ($UPDIR)" "mkdir -p '$UPDIR'" fi echo echo "=== 7. 최근 오류 로그 ===" # grep -c 는 일치가 없으면 0 을 출력하고 종료코드 1 을 낸다. # '|| echo 0' 을 붙이면 0 이 두 번 나와 숫자 비교가 깨지므로 쓰지 않는다. errs=$(journalctl -u "$SERVICE" -n 200 --no-pager 2>/dev/null | grep -icE 'fail|error|exception') errs=$(printf '%s' "${errs:-0}" | head -1) case "$errs" in ''|*[!0-9]*) errs=0 ;; esac if [ "$errs" -eq 0 ]; then ok "최근 200줄에 오류 없음" else echo " 오류로 보이는 줄 $errs 개 — 확인:" journalctl -u "$SERVICE" -n 200 --no-pager 2>/dev/null \ | grep -iE 'fail|error|exception' | tail -5 | sed 's/^/ /' fi echo echo "================================" printf ' 통과 %d 실패 %d\n' "$PASS" "$FAIL" echo "================================" if [ "$FAIL" -gt 0 ]; then echo echo "로그 전체 보기: sudo journalctl -u $SERVICE -n 100 --no-pager" exit 1 fi