#!/bin/bash # FlaskFarm + Celery Gunicorn 정밀 재시작 스크립트 (v2) # "한 번에 정확하게" - PID 기반 제어 및 포트 자동 대기 포함 cd /Volumes/WD/Users/Work/python/flaskfarm # 색상 및 스타일 RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' BOLD='\033[1m' echo -e "${YELLOW}${BOLD}========================================${NC}" echo -e "${YELLOW}${BOLD} FlaskFarm Gunicorn Precise Launcher${NC}" echo -e "${YELLOW}${BOLD}========================================${NC}" # 1. 환경 및 의존성 검증 echo -e "\n${BLUE}[1/5] 환경 및 의존성 검증...${NC}" # pyenv 초기화 export PYENV_ROOT="$HOME/.pyenv" export PATH="$PYENV_ROOT/bin:$PATH" if command -v pyenv &> /dev/null; then eval "$(pyenv init -)" eval "$(pyenv virtualenv-init -)" 2>/dev/null pyenv rehash fi # 필수 패키지 체크 및 버전 강제 (Gunicorn gevent worker 요구사항 대응) PYTHON_EXE=$(which python) if ! $PYTHON_EXE -c "import gevent; from packaging import version; exit(0) if version.parse(gevent.__version__) >= version.parse('24.10.1') else exit(1)" &>/dev/null; then echo -e "${YELLOW} ! gevent 버전 낮음 또는 미설치 감지. 업그레이드를 진행합니다 (>=24.10.1)...${NC}" $PYTHON_EXE -m pip install "gevent>=24.10.1" gevent-websocket gunicorn --upgrade fi echo -e " ✓ Python: $($PYTHON_EXE --version)" echo -e " ✓ Gunicorn: $($PYTHON_EXE -m gunicorn --version | head -n 1)" # 2. 기존 프로세스 정밀 종료 echo -e "\n${RED}[2/5] 기존 프로세스 종료 중...${NC}" # PID 파일 기반 종료 (Gunicorn) PID_FILE="data/gunicorn.pid" if [ -f "$PID_FILE" ]; then OLD_PID=$(cat "$PID_FILE") if ps -p $OLD_PID > /dev/null; then echo " - PID $OLD_PID 종료 시도 (SIGTERM)..." kill -15 $OLD_PID 2>/dev/null sleep 2 if ps -p $OLD_PID > /dev/null; then echo " - PID $OLD_PID 강제 종료 (SIGKILL)..." kill -9 $OLD_PID 2>/dev/null fi fi rm -f "$PID_FILE" fi # 남은 고아 프로세스 정리 pkill -9 -f "gunicorn.*wsgi:app" 2>/dev/null echo " ✓ FlaskFarm Gunicorn 프로세스 정리 완료" # Celery 워커 종료 pkill -9 -f "celery.*worker" 2>/dev/null pkill -9 -f "celery -A flaskfarm" 2>/dev/null echo " ✓ Celery 워커 프로세스 정리 완료" # 3. 포트 가용성 확인 (9099) echo -e "\n${BLUE}[3/5] 포트(9099) 상태 확인...${NC}" MAX_WAIT=10 COUNT=0 while lsof -i :9099 > /dev/null; do if [ $COUNT -ge $MAX_WAIT ]; then echo -e "${RED} ! 포트 9099가 여전히 점유 중입니다. 강제 해제 시도...${NC}" lsof -ti :9099 | xargs kill -9 2>/dev/null break fi echo " - 포트 해제 대기 중... ($COUNT/$MAX_WAIT)" sleep 1 COUNT=$((COUNT+1)) done echo " ✓ 포트 9099 사용 가능" # 4. Celery 워커 시작 (백그라운드) echo -e "\n${GREEN}[4/5] Celery 워커 시작 중...${NC}" CELERY_LOG_FILE="data/log/celery_worker.log" mkdir -p "data/log" export GEVENT_NOWAITPID=1 nohup celery -A main.celery worker \ --loglevel=info \ --pool=gevent \ --concurrency=4 \ --config_filepath=data/config_mac.yaml \ --running_type=local \ > "$CELERY_LOG_FILE" 2>&1 & echo " ✓ Celery 워커 시작됨 (Log: $CELERY_LOG_FILE)" # 5. Gunicorn 정밀 기동 echo -e "\n${GREEN}[5/5] Gunicorn 기동...${NC}" echo -e "${YELLOW}========================================${NC}" # 프레임워크 우회 환경변수 export FF_CONFIG="data/config_mac.yaml" export FF_GUNICORN="true" export FF_REPEAT="0" # 실행 (exec을 통해 셸을 gunicorn으로 대체하여 신호 전달 보장) exec $PYTHON_EXE -m gunicorn -c gunicorn_config.py wsgi:app