378 lines
13 KiB
Bash
Executable File
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
|