CASTAD-v0.1/startserver.sh

378 lines
13 KiB
Bash
Executable File

#!/bin/bash
#
# CaStAD Production Server Startup Script
# Target: castad1.ktenterprise.net
# Version: 3.4.0
#
# ═══════════════════════════════════════════════════════════════
# 설정 (필요시 수정)
# ═══════════════════════════════════════════════════════════════
APP_NAME="castad"
APP_DIR="$(cd "$(dirname "$0")" && pwd)"
NODE_PORT=3001 # Express 백엔드 포트
INSTAGRAM_PORT=5001 # Instagram Python 서비스 포트
LOG_DIR="$APP_DIR/logs"
PID_DIR="$APP_DIR/pids"
# 색상 정의
GREEN='\033[0;32m'
RED='\033[0;31m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
BOLD='\033[1m'
NC='\033[0m'
# ═══════════════════════════════════════════════════════════════
# 함수
# ═══════════════════════════════════════════════════════════════
log() { echo -e "${GREEN}[CaStAD]${NC} $(date '+%Y-%m-%d %H:%M:%S') $1"; }
error() { echo -e "${RED}[ERROR]${NC} $(date '+%Y-%m-%d %H:%M:%S') $1"; }
warn() { echo -e "${YELLOW}[WARN]${NC} $(date '+%Y-%m-%d %H:%M:%S') $1"; }
info() { echo -e "${CYAN}[INFO]${NC} $(date '+%Y-%m-%d %H:%M:%S') $1"; }
# 디렉토리 생성
init_dirs() {
mkdir -p "$LOG_DIR" "$PID_DIR"
mkdir -p "$APP_DIR/server/downloads"
mkdir -p "$APP_DIR/server/temp"
}
# 포트 사용 중인지 확인
is_port_in_use() {
lsof -i:$1 >/dev/null 2>&1
}
# PID 파일에서 프로세스 확인
is_running() {
local pid_file="$1"
if [ -f "$pid_file" ]; then
local pid=$(cat "$pid_file")
if ps -p "$pid" > /dev/null 2>&1; then
return 0
fi
fi
return 1
}
# ═══════════════════════════════════════════════════════════════
# Instagram 서비스 관리
# ═══════════════════════════════════════════════════════════════
start_instagram() {
local pid_file="$PID_DIR/instagram.pid"
if is_running "$pid_file"; then
info "Instagram 서비스가 이미 실행 중입니다 (PID: $(cat $pid_file))"
return 0
fi
if [ ! -f "$APP_DIR/server/instagram/instagram_service.py" ]; then
warn "Instagram 서비스 파일 없음 - 건너뜁니다"
return 1
fi
log "Instagram 서비스 시작 중 (포트: $INSTAGRAM_PORT)..."
# Python 캐시 삭제
find "$APP_DIR/server/instagram" -name "*.pyc" -delete 2>/dev/null
find "$APP_DIR/server/instagram" -name "__pycache__" -type d -exec rm -rf {} + 2>/dev/null
# Python 의존성 확인
if ! python3 -c "import instagrapi" 2>/dev/null; then
warn "Instagram Python 의존성 설치 중..."
pip3 install --break-system-packages -q -r "$APP_DIR/server/instagram/requirements.txt" 2>/dev/null || \
pip3 install -q -r "$APP_DIR/server/instagram/requirements.txt" 2>/dev/null
fi
# 백그라운드 실행
cd "$APP_DIR/server/instagram"
nohup python3 instagram_service.py >> "$LOG_DIR/instagram.log" 2>&1 &
echo $! > "$pid_file"
cd "$APP_DIR"
sleep 2
if curl -s http://localhost:$INSTAGRAM_PORT/health >/dev/null 2>&1; then
info "Instagram 서비스 시작됨 (PID: $(cat $pid_file))"
return 0
else
error "Instagram 서비스 시작 실패"
rm -f "$pid_file"
return 1
fi
}
stop_instagram() {
local pid_file="$PID_DIR/instagram.pid"
if is_running "$pid_file"; then
local pid=$(cat "$pid_file")
log "Instagram 서비스 중지 중 (PID: $pid)..."
kill "$pid" 2>/dev/null
sleep 1
kill -9 "$pid" 2>/dev/null
rm -f "$pid_file"
info "Instagram 서비스 중지됨"
else
info "Instagram 서비스가 실행 중이 아닙니다"
fi
}
# ═══════════════════════════════════════════════════════════════
# Node.js 백엔드 관리
# ═══════════════════════════════════════════════════════════════
start_backend() {
local pid_file="$PID_DIR/backend.pid"
if is_running "$pid_file"; then
info "백엔드가 이미 실행 중입니다 (PID: $(cat $pid_file))"
return 0
fi
if is_port_in_use $NODE_PORT; then
error "포트 $NODE_PORT 가 이미 사용 중입니다!"
error "다른 프로세스 확인: lsof -i:$NODE_PORT"
return 1
fi
log "백엔드 서버 시작 중 (포트: $NODE_PORT)..."
cd "$APP_DIR/server"
# 환경변수 설정
export NODE_ENV=production
export PORT=$NODE_PORT
export FRONTEND_URL="https://castad1.ktenterprise.net"
# 백그라운드 실행
nohup node index.js >> "$LOG_DIR/backend.log" 2>&1 &
echo $! > "$pid_file"
cd "$APP_DIR"
sleep 3
if curl -s http://localhost:$NODE_PORT/api/health >/dev/null 2>&1; then
info "백엔드 서버 시작됨 (PID: $(cat $pid_file))"
return 0
else
# 헬스체크 없어도 프로세스가 있으면 OK
if is_running "$pid_file"; then
info "백엔드 서버 시작됨 (PID: $(cat $pid_file))"
return 0
fi
error "백엔드 서버 시작 실패 - 로그 확인: $LOG_DIR/backend.log"
rm -f "$pid_file"
return 1
fi
}
stop_backend() {
local pid_file="$PID_DIR/backend.pid"
if is_running "$pid_file"; then
local pid=$(cat "$pid_file")
log "백엔드 서버 중지 중 (PID: $pid)..."
kill "$pid" 2>/dev/null
sleep 2
kill -9 "$pid" 2>/dev/null
rm -f "$pid_file"
info "백엔드 서버 중지됨"
else
info "백엔드 서버가 실행 중이 아닙니다"
fi
}
# ═══════════════════════════════════════════════════════════════
# 빌드
# ═══════════════════════════════════════════════════════════════
build_frontend() {
log "프론트엔드 빌드 중..."
cd "$APP_DIR"
# 의존성 확인
if [ ! -d "node_modules" ]; then
log "npm 패키지 설치 중..."
npm install --legacy-peer-deps --silent
fi
# 빌드
npm run build
if [ $? -eq 0 ]; then
info "프론트엔드 빌드 완료 (dist/ 폴더)"
return 0
else
error "프론트엔드 빌드 실패"
return 1
fi
}
# ═══════════════════════════════════════════════════════════════
# 메인 명령어
# ═══════════════════════════════════════════════════════════════
do_start() {
echo ""
echo -e "${BOLD}${CYAN}╔════════════════════════════════════════════════════════╗${NC}"
echo -e "${BOLD}${CYAN}║ CaStAD v3.4.0 - Production Server ║${NC}"
echo -e "${BOLD}${CYAN}║ Target: castad1.ktenterprise.net ║${NC}"
echo -e "${BOLD}${CYAN}╚════════════════════════════════════════════════════════╝${NC}"
echo ""
init_dirs
# 환경변수 파일 확인
if [ ! -f "$APP_DIR/.env" ]; then
error ".env 파일이 없습니다! .env.example을 참고하여 생성해주세요."
return 1
fi
# .env 로드
set -a
source "$APP_DIR/.env"
set +a
# 서버 의존성 확인
if [ ! -d "$APP_DIR/server/node_modules" ]; then
log "서버 npm 패키지 설치 중..."
cd "$APP_DIR/server" && npm install --legacy-peer-deps --silent && cd "$APP_DIR"
fi
# 빌드 확인
if [ ! -d "$APP_DIR/dist" ]; then
warn "dist 폴더가 없습니다. 빌드를 먼저 실행하세요: ./startserver.sh build"
fi
# 서비스 시작
start_instagram
start_backend
echo ""
echo -e "${CYAN}═══════════════════════════════════════════════════════════${NC}"
echo -e " ${BOLD}상태${NC}: RUNNING"
echo -e " ${BOLD}백엔드${NC}: http://localhost:${NODE_PORT}"
echo -e " ${BOLD}Instagram${NC}: http://localhost:${INSTAGRAM_PORT}"
echo -e " ${BOLD}로그${NC}: ${LOG_DIR}/"
echo -e "${CYAN}═══════════════════════════════════════════════════════════${NC}"
echo ""
echo -e " ${YELLOW}Nginx 리버스 프록시 설정 필요:${NC}"
echo -e " location / { proxy_pass http://127.0.0.1:${NODE_PORT}; }"
echo ""
}
do_stop() {
echo ""
log "CaStAD 서비스 중지 중..."
stop_backend
stop_instagram
info "모든 서비스 중지 완료"
echo ""
}
do_restart() {
do_stop
sleep 2
do_start
}
do_status() {
echo ""
echo -e "${BOLD}CaStAD 서비스 상태${NC}"
echo -e "${CYAN}───────────────────────────────────────${NC}"
# 백엔드
if is_running "$PID_DIR/backend.pid"; then
echo -e " 백엔드: ${GREEN}실행 중${NC} (PID: $(cat $PID_DIR/backend.pid))"
else
echo -e " 백엔드: ${RED}중지됨${NC}"
fi
# Instagram
if is_running "$PID_DIR/instagram.pid"; then
echo -e " Instagram: ${GREEN}실행 중${NC} (PID: $(cat $PID_DIR/instagram.pid))"
else
echo -e " Instagram: ${RED}중지됨${NC}"
fi
# 포트 상태
echo ""
echo -e "${CYAN}포트 상태:${NC}"
if is_port_in_use $NODE_PORT; then
echo -e " 포트 $NODE_PORT: ${GREEN}사용 중${NC}"
else
echo -e " 포트 $NODE_PORT: ${YELLOW}사용 안함${NC}"
fi
if is_port_in_use $INSTAGRAM_PORT; then
echo -e " 포트 $INSTAGRAM_PORT: ${GREEN}사용 중${NC}"
else
echo -e " 포트 $INSTAGRAM_PORT: ${YELLOW}사용 안함${NC}"
fi
echo ""
}
do_logs() {
local service="${1:-backend}"
local log_file="$LOG_DIR/${service}.log"
if [ -f "$log_file" ]; then
echo -e "${CYAN}=== $service 로그 (최근 50줄) ===${NC}"
tail -50 "$log_file"
echo ""
echo -e "${YELLOW}실시간 로그 보기: tail -f $log_file${NC}"
else
error "로그 파일 없음: $log_file"
fi
}
show_help() {
echo ""
echo -e "${BOLD}CaStAD 프로덕션 서버 관리 스크립트${NC}"
echo ""
echo -e "${CYAN}사용법:${NC}"
echo " ./startserver.sh <command>"
echo ""
echo -e "${CYAN}명령어:${NC}"
echo " start - 모든 서비스 시작"
echo " stop - 모든 서비스 중지"
echo " restart - 모든 서비스 재시작"
echo " status - 서비스 상태 확인"
echo " build - 프론트엔드 빌드"
echo " logs - 백엔드 로그 보기"
echo " logs instagram - Instagram 서비스 로그 보기"
echo ""
echo -e "${CYAN}설정:${NC}"
echo " 백엔드 포트: $NODE_PORT"
echo " Instagram 포트: $INSTAGRAM_PORT"
echo " 로그 디렉토리: $LOG_DIR"
echo ""
echo -e "${CYAN}예시:${NC}"
echo " ./startserver.sh build # 먼저 빌드"
echo " ./startserver.sh start # 서비스 시작"
echo " ./startserver.sh status # 상태 확인"
echo ""
}
# ═══════════════════════════════════════════════════════════════
# 메인
# ═══════════════════════════════════════════════════════════════
case "$1" in
start)
do_start
;;
stop)
do_stop
;;
restart)
do_restart
;;
status)
do_status
;;
build)
build_frontend
;;
logs)
do_logs "$2"
;;
*)
show_help
;;
esac