489 lines
15 KiB
Bash
Executable File
489 lines
15 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# 인페인팅 서버 시작 스크립트
|
|
# Jetson Xavier와 x86 시스템을 모두 지원합니다.
|
|
# Usage: ./start_server.sh [options]
|
|
|
|
set -e
|
|
|
|
# 색상 코드
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
NC='\033[0m' # No Color
|
|
|
|
# 로그 함수들
|
|
log_info() {
|
|
echo -e "${BLUE}[INFO]${NC} $1"
|
|
}
|
|
|
|
log_success() {
|
|
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
|
}
|
|
|
|
log_warning() {
|
|
echo -e "${YELLOW}[WARNING]${NC} $1"
|
|
}
|
|
|
|
log_error() {
|
|
echo -e "${RED}[ERROR]${NC} $1"
|
|
}
|
|
|
|
# 기본 설정
|
|
PROJECT_ROOT="/home/ckh08045/work/inpaintServer"
|
|
VENV_PATH="$PROJECT_ROOT"
|
|
MAIN_SERVER_PORT=8000
|
|
MONITORING_PORT=8001
|
|
LOG_DIR="$PROJECT_ROOT/logs"
|
|
|
|
# 시스템 감지
|
|
detect_system() {
|
|
if [ "$(uname -m)" = "aarch64" ] && uname -a | grep -q "tegra"; then
|
|
SYSTEM_TYPE="jetson"
|
|
log_info "🚀 Jetson Xavier (ARM64) 모드로 시작합니다"
|
|
|
|
# Jetson 전용 설정
|
|
WORKERS=1
|
|
MAX_WORKERS=4
|
|
MIN_WORKERS=1
|
|
VRAM_THRESHOLD_HIGH=0.7
|
|
VRAM_THRESHOLD_LOW=0.3
|
|
VRAM_CHECK_INTERVAL=20
|
|
MAX_FILE_SIZE=25
|
|
|
|
elif [ "$(uname -m)" = "x86_64" ]; then
|
|
SYSTEM_TYPE="x86"
|
|
log_info "💻 x86_64 모드로 시작합니다"
|
|
|
|
# x86 전용 설정
|
|
WORKERS=1
|
|
MAX_WORKERS=8
|
|
MIN_WORKERS=2
|
|
VRAM_THRESHOLD_HIGH=0.8
|
|
VRAM_THRESHOLD_LOW=0.4
|
|
VRAM_CHECK_INTERVAL=30
|
|
MAX_FILE_SIZE=50
|
|
|
|
else
|
|
log_error "지원되지 않는 시스템 아키텍처: $(uname -m)"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# 옵션 파싱
|
|
PRODUCTION=false
|
|
MONITORING_ENABLED=true
|
|
WORKERS=1
|
|
GPU_DEVICE=0
|
|
JETSON_OPTIMIZE=false
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
case $1 in
|
|
-p|--production)
|
|
PRODUCTION=true
|
|
shift
|
|
;;
|
|
--no-monitoring)
|
|
MONITORING_ENABLED=false
|
|
shift
|
|
;;
|
|
-w|--workers)
|
|
WORKERS="$2"
|
|
shift 2
|
|
;;
|
|
-g|--gpu)
|
|
GPU_DEVICE="$2"
|
|
shift 2
|
|
;;
|
|
--jetson-optimize)
|
|
JETSON_OPTIMIZE=true
|
|
shift
|
|
;;
|
|
-h|--help)
|
|
echo "Usage: $0 [options]"
|
|
echo "Options:"
|
|
echo " -p, --production 프로덕션 모드로 실행"
|
|
echo " --no-monitoring 모니터링 대시보드 비활성화"
|
|
echo " -w, --workers NUM 워커 수 설정 (기본값: 시스템별 자동)"
|
|
echo " -g, --gpu DEVICE GPU 디바이스 ID (기본값: 0)"
|
|
echo " --jetson-optimize Jetson 최적화 설정 (Jetson 전용)"
|
|
echo " -h, --help 이 도움말 표시"
|
|
exit 0
|
|
;;
|
|
*)
|
|
log_error "알 수 없는 옵션: $1"
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
# 환경 확인
|
|
check_environment() {
|
|
log_info "환경 확인 중..."
|
|
|
|
# 프로젝트 디렉토리 확인
|
|
if [ ! -d "$PROJECT_ROOT" ]; then
|
|
log_error "프로젝트 디렉토리를 찾을 수 없습니다: $PROJECT_ROOT"
|
|
exit 1
|
|
fi
|
|
|
|
# 가상환경 확인
|
|
if [ ! -f "$VENV_PATH/bin/activate" ]; then
|
|
log_error "가상환경을 찾을 수 없습니다: $VENV_PATH"
|
|
exit 1
|
|
fi
|
|
|
|
# GPU 확인 (시스템별)
|
|
if [ "$SYSTEM_TYPE" = "jetson" ]; then
|
|
log_info "Jetson Xavier GPU 확인 중..."
|
|
|
|
# Jetson 전용 확인 방법들
|
|
jetson_gpu_checks=0
|
|
|
|
# 1. tegrastats 확인
|
|
if command -v tegrastats &> /dev/null; then
|
|
log_info "tegrastats 사용 가능"
|
|
jetson_gpu_checks=$((jetson_gpu_checks + 1))
|
|
else
|
|
log_warning "tegrastats를 찾을 수 없습니다"
|
|
fi
|
|
|
|
# 2. nvpmodel 확인
|
|
if command -v nvpmodel &> /dev/null; then
|
|
log_info "nvpmodel 사용 가능"
|
|
jetson_gpu_checks=$((jetson_gpu_checks + 1))
|
|
else
|
|
log_warning "nvpmodel을 찾을 수 없습니다"
|
|
fi
|
|
|
|
# 3. GPU 디바이스 확인 (Jetson 전용 경로들)
|
|
gpu_detected=false
|
|
|
|
# Jetson GPU 클래스 확인
|
|
if [ -d "/sys/class/nvidia-gpu" ]; then
|
|
log_info "Jetson GPU 클래스 감지됨: /sys/class/nvidia-gpu"
|
|
gpu_detected=true
|
|
fi
|
|
|
|
# Jetson GPU 디바이스 확인
|
|
if [ -d "/sys/devices/platform/*/nvidia-gpu" ]; then
|
|
log_info "Jetson GPU 디바이스 감지됨"
|
|
gpu_detected=true
|
|
fi
|
|
|
|
# GV11B GPU 확인 (Jetson Xavier)
|
|
if [ -d "/sys/firmware/devicetree/base/gv11b" ]; then
|
|
log_info "GV11B GPU (Jetson Xavier) 감지됨"
|
|
gpu_detected=true
|
|
fi
|
|
|
|
# 디버그 GPU 경로 확인 (권한이 있는 경우)
|
|
if [ -r "/sys/kernel/debug/gpu" ]; then
|
|
log_info "GPU 디버그 경로 접근 가능: /sys/kernel/debug/gpu"
|
|
gpu_detected=true
|
|
fi
|
|
|
|
if [ "$gpu_detected" = true ]; then
|
|
log_info "GPU 디바이스 감지됨"
|
|
jetson_gpu_checks=$((jetson_gpu_checks + 1))
|
|
else
|
|
log_warning "GPU 디바이스를 찾을 수 없습니다 (권한 문제일 수 있음)"
|
|
log_info "sudo 권한으로 실행하거나 시스템을 재부팅해보세요"
|
|
fi
|
|
|
|
# 4. CUDA 확인
|
|
if command -v nvcc &> /dev/null; then
|
|
log_info "CUDA 컴파일러 사용 가능"
|
|
jetson_gpu_checks=$((jetson_gpu_checks + 1))
|
|
else
|
|
log_warning "CUDA 컴파일러를 찾을 수 없습니다"
|
|
fi
|
|
|
|
if [ $jetson_gpu_checks -ge 2 ]; then
|
|
log_success "Jetson Xavier GPU 확인 완료 ($jetson_gpu_checks/4 체크 통과)"
|
|
|
|
# Jetson 정보 표시 (에러 방지)
|
|
if command -v tegrastats &> /dev/null; then
|
|
log_info "Jetson 시스템 정보:"
|
|
tegrastats 2>/dev/null | head -5 || log_warning "tegrastats 실행 중 오류 발생"
|
|
fi
|
|
|
|
if command -v nvpmodel &> /dev/null; then
|
|
log_info "Jetson 전력 모드:"
|
|
nvpmodel -q 2>/dev/null || log_warning "nvpmodel 실행 중 오류 발생"
|
|
fi
|
|
else
|
|
log_warning "Jetson Xavier GPU 확인 부분 실패 ($jetson_gpu_checks/4 체크 통과)"
|
|
fi
|
|
|
|
else
|
|
# x86 시스템용 기존 확인 방법
|
|
if ! command -v nvidia-smi &> /dev/null; then
|
|
log_warning "nvidia-smi를 찾을 수 없습니다. GPU 기능이 제한될 수 있습니다."
|
|
else
|
|
log_info "GPU 정보:"
|
|
nvidia-smi --query-gpu=name,memory.total,memory.used --format=csv,noheader
|
|
fi
|
|
fi
|
|
|
|
# 로그 디렉토리 생성
|
|
mkdir -p "$LOG_DIR"
|
|
|
|
log_success "환경 확인 완료"
|
|
}
|
|
|
|
# 가상환경 활성화
|
|
activate_venv() {
|
|
log_info "가상환경 활성화 중..."
|
|
cd "$PROJECT_ROOT"
|
|
source "$VENV_PATH/bin/activate"
|
|
|
|
# Python 버전 확인
|
|
PYTHON_VERSION=$(python --version 2>&1)
|
|
log_info "Python 버전: $PYTHON_VERSION"
|
|
|
|
log_success "가상환경 활성화 완료"
|
|
}
|
|
|
|
# 포트 확인
|
|
check_ports() {
|
|
log_info "포트 사용 상태 확인 중..."
|
|
|
|
if lsof -Pi :$MAIN_SERVER_PORT -sTCP:LISTEN -t >/dev/null; then
|
|
log_error "메인 서버 포트 $MAIN_SERVER_PORT가 이미 사용 중입니다"
|
|
lsof -Pi :$MAIN_SERVER_PORT -sTCP:LISTEN
|
|
exit 1
|
|
fi
|
|
|
|
if [ "$MONITORING_ENABLED" = true ] && lsof -Pi :$MONITORING_PORT -sTCP:LISTEN -t >/dev/null; then
|
|
log_error "모니터링 포트 $MONITORING_PORT가 이미 사용 중입니다"
|
|
lsof -Pi :$MONITORING_PORT -sTCP:LISTEN
|
|
exit 1
|
|
fi
|
|
|
|
log_success "포트 확인 완료"
|
|
}
|
|
|
|
# 의존성 확인
|
|
check_dependencies() {
|
|
log_info "의존성 확인 중..."
|
|
|
|
# requirements.txt가 있는지 확인
|
|
if [ -f "$PROJECT_ROOT/requirements.txt" ]; then
|
|
log_info "필수 패키지 설치 확인 중..."
|
|
|
|
# 이미 설치된 패키지들 확인
|
|
if python -c "import fastapi, uvicorn, torch, cv2, PIL" 2>/dev/null; then
|
|
log_success "필수 패키지들이 이미 설치되어 있습니다"
|
|
else
|
|
log_warning "일부 패키지가 누락되었습니다. 수동으로 설치가 필요할 수 있습니다"
|
|
fi
|
|
else
|
|
log_warning "requirements.txt를 찾을 수 없습니다"
|
|
fi
|
|
}
|
|
|
|
# Jetson 최적화
|
|
setup_jetson_optimization() {
|
|
if [ "$SYSTEM_TYPE" != "jetson" ] || [ "$JETSON_OPTIMIZE" != true ]; then
|
|
return 0
|
|
fi
|
|
|
|
log_info "🚀 Jetson Xavier 최적화 설정 중..."
|
|
|
|
# 전력 모드 설정
|
|
if command -v nvpmodel &> /dev/null; then
|
|
log_info "전력 모드를 MAXN으로 설정 중..."
|
|
sudo nvpmodel -m 0 # MAXN 모드
|
|
sudo nvpmodel -q
|
|
else
|
|
log_warning "nvpmodel을 찾을 수 없습니다"
|
|
fi
|
|
|
|
# 팬 제어 설정
|
|
if [ -f "/sys/devices/pwm-fan/target_pwm" ]; then
|
|
log_info "팬 제어 활성화 중..."
|
|
echo 128 | sudo tee /sys/devices/pwm-fan/target_pwm > /dev/null
|
|
fi
|
|
|
|
# GPU 클럭 설정
|
|
if [ -f "/sys/kernel/debug/clk/gpcclk/clk_rate" ]; then
|
|
log_info "GPU 클럭 최적화 중..."
|
|
echo 1200000000 | sudo tee /sys/kernel/debug/clk/gpcclk/clk_rate > /dev/null
|
|
fi
|
|
|
|
# 메모리 클럭 설정
|
|
if [ -f "/sys/kernel/debug/clk/emc/clk_rate" ]; then
|
|
log_info "메모리 클럭 최적화 중..."
|
|
echo 1600000000 | sudo tee /sys/kernel/debug/clk/emc/clk_rate > /dev/null
|
|
fi
|
|
|
|
log_success "Jetson 최적화 설정 완료"
|
|
}
|
|
|
|
# 환경 변수 설정
|
|
setup_environment() {
|
|
log_info "환경 변수 설정 중..."
|
|
|
|
# CUDA 설정
|
|
export CUDA_VISIBLE_DEVICES=$GPU_DEVICE
|
|
export CUDA_DEVICE_ORDER=PCI_BUS_ID
|
|
|
|
# PyTorch 설정
|
|
export TORCH_CUDA_ARCH_LIST="6.0;6.1;7.0;7.5;8.0;8.6"
|
|
|
|
# Jetson 전용 설정
|
|
if [ "$SYSTEM_TYPE" = "jetson" ]; then
|
|
export CUDA_LAUNCH_BLOCKING=1
|
|
export CUDA_CACHE_DISABLE=0
|
|
export CUDA_CACHE_PATH="/tmp/cuda_cache"
|
|
|
|
# Jetson 메모리 최적화
|
|
export PYTORCH_CUDA_ALLOC_CONF=max_split_size_mb:128
|
|
fi
|
|
|
|
# TensorRT 설정 (있는 경우)
|
|
if [ -d "/usr/local/tensorrt" ]; then
|
|
export LD_LIBRARY_PATH=/usr/local/tensorrt/lib:$LD_LIBRARY_PATH
|
|
fi
|
|
|
|
# 프로덕션 설정
|
|
if [ "$PRODUCTION" = true ]; then
|
|
export PYTHONOPTIMIZE=1
|
|
export PYTHONDONTWRITEBYTECODE=1
|
|
fi
|
|
|
|
log_success "환경 변수 설정 완료"
|
|
}
|
|
|
|
# 서버 시작
|
|
start_servers() {
|
|
log_info "서버 시작 중..."
|
|
|
|
# 메인 서버 시작
|
|
log_info "메인 인페인팅 서버 시작 (포트: $MAIN_SERVER_PORT, 워커: $WORKERS)..."
|
|
|
|
if [ "$PRODUCTION" = true ]; then
|
|
# 프로덕션 모드: Gunicorn 사용
|
|
gunicorn app.api.endpoints:app \
|
|
--bind 0.0.0.0:$MAIN_SERVER_PORT \
|
|
--workers $WORKERS \
|
|
--worker-class uvicorn.workers.UvicornWorker \
|
|
--max-requests 1000 \
|
|
--max-requests-jitter 50 \
|
|
--preload \
|
|
--access-logfile "$LOG_DIR/access.log" \
|
|
--error-logfile "$LOG_DIR/error.log" \
|
|
--log-level info \
|
|
--daemon \
|
|
--pid "$LOG_DIR/main_server.pid"
|
|
else
|
|
# 개발 모드: Uvicorn 사용
|
|
nohup python -m uvicorn app.api.endpoints:app \
|
|
--host 0.0.0.0 \
|
|
--port $MAIN_SERVER_PORT \
|
|
--workers $WORKERS \
|
|
--log-level info \
|
|
--access-log \
|
|
> "$LOG_DIR/main_server.log" 2>&1 &
|
|
echo $! > "$LOG_DIR/main_server.pid"
|
|
fi
|
|
|
|
sleep 3
|
|
|
|
# 메인 서버 상태 확인
|
|
if curl -s "http://localhost:$MAIN_SERVER_PORT/health" > /dev/null; then
|
|
log_success "메인 서버 시작 완료 (PID: $(cat $LOG_DIR/main_server.pid))"
|
|
else
|
|
log_error "메인 서버 시작 실패"
|
|
exit 1
|
|
fi
|
|
|
|
# 모니터링 서버 시작 (활성화된 경우)
|
|
if [ "$MONITORING_ENABLED" = true ]; then
|
|
log_info "모니터링 대시보드 시작 (포트: $MONITORING_PORT)..."
|
|
|
|
nohup python -m uvicorn app.monitoring.dashboard:monitor_app \
|
|
--host 0.0.0.0 \
|
|
--port $MONITORING_PORT \
|
|
--log-level info \
|
|
> "$LOG_DIR/monitoring.log" 2>&1 &
|
|
echo $! > "$LOG_DIR/monitoring.pid"
|
|
|
|
sleep 2
|
|
|
|
# 모니터링 서버 상태 확인
|
|
if curl -s "http://localhost:$MONITORING_PORT/" > /dev/null; then
|
|
log_success "모니터링 대시보드 시작 완료 (PID: $(cat $LOG_DIR/monitoring.pid))"
|
|
log_info "모니터링 URL: http://localhost:$MONITORING_PORT"
|
|
else
|
|
log_warning "모니터링 대시보드 시작 실패"
|
|
fi
|
|
fi
|
|
}
|
|
|
|
# 상태 정보 출력
|
|
print_status() {
|
|
echo ""
|
|
echo "=========================================="
|
|
echo "🚀 인페인팅 서버 시작 완료!"
|
|
echo "=========================================="
|
|
echo "시스템 타입: $SYSTEM_TYPE"
|
|
echo "메인 서버: http://localhost:$MAIN_SERVER_PORT"
|
|
echo "API 문서: http://localhost:$MAIN_SERVER_PORT/docs"
|
|
echo "헬스 체크: http://localhost:$MAIN_SERVER_PORT/health"
|
|
|
|
if [ "$MONITORING_ENABLED" = true ]; then
|
|
echo "모니터링: http://localhost:$MONITORING_PORT"
|
|
fi
|
|
|
|
echo ""
|
|
echo "로그 디렉토리: $LOG_DIR"
|
|
echo "GPU 디바이스: $GPU_DEVICE"
|
|
echo "워커 수: $WORKERS"
|
|
echo "프로덕션 모드: $PRODUCTION"
|
|
|
|
if [ "$SYSTEM_TYPE" = "jetson" ]; then
|
|
echo ""
|
|
echo "🚀 Jetson Xavier 최적화:"
|
|
echo " - 전력 모드: MAXN"
|
|
echo " - GPU 클럭: 1200MHz"
|
|
echo " - 메모리 클럭: 1600MHz"
|
|
echo " - 팬 제어: 활성화"
|
|
echo " - VRAM 임계값: 70%/30%"
|
|
echo " - 파일 크기 제한: 25MB"
|
|
fi
|
|
|
|
echo ""
|
|
echo "서버 중지: ./scripts/stop_server.sh"
|
|
echo "상태 확인: ./scripts/status.sh"
|
|
|
|
if [ "$SYSTEM_TYPE" = "jetson" ]; then
|
|
echo "Jetson 모니터링: jtop"
|
|
echo "전력 모드 확인: nvpmodel -q"
|
|
fi
|
|
|
|
echo "=========================================="
|
|
}
|
|
|
|
# 메인 실행
|
|
main() {
|
|
log_info "인페인팅 서버 시작 스크립트 실행"
|
|
|
|
detect_system
|
|
check_environment
|
|
activate_venv
|
|
check_ports
|
|
check_dependencies
|
|
setup_jetson_optimization
|
|
setup_environment
|
|
start_servers
|
|
print_status
|
|
|
|
log_success "모든 서버가 성공적으로 시작되었습니다!"
|
|
}
|
|
|
|
# 스크립트 실행
|
|
main "$@"
|