Files
Genesis_GameServer/deploy/healthcheck.sh
2026-09-04 01:44:59 +09:00

116 lines
4.2 KiB
Bash

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