vLLM 지원 추가 및 통합 셋업/종료 스크립트
- setup.sh: 시스템 자동 감지 (Apple Silicon/NVIDIA GPU/RAM) → 최적 방식 선택 - stop.sh: 실행 중인 서비스 자동 감지 후 종료 - setup-vllm.sh / stop-vllm.sh: NVIDIA GPU + Docker 기반 vLLM 서빙 - docker-compose.vllm.yml 자동 생성 (vLLM + Open WebUI) - README 전면 개편 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
bcd17b2951
commit
f1890713a7
107
README.md
107
README.md
@ -1,53 +1,19 @@
|
||||
# Qwen3.5 로컬 서빙 + Open WebUI
|
||||
|
||||
로컬 Mac에서 Qwen3.5-35B 모델을 서빙하고, Open WebUI로 채팅할 수 있는 환경을 원클릭으로 구축합니다.
|
||||
Qwen3.5-35B 모델을 로컬에서 서빙하고, Open WebUI로 채팅할 수 있는 환경을 원클릭으로 구축합니다.
|
||||
|
||||
텍스트 대화 + 이미지 입력 모두 지원합니다.
|
||||
|
||||
---
|
||||
|
||||
## 방식 선택
|
||||
|
||||
| | Ollama | MLX (vllm-mlx) |
|
||||
|---|---|---|
|
||||
| 장점 | 간편, 설정 적음 | Mac GPU 최적화, 파라미터 직접 제어 |
|
||||
| 이미지 입력 | O | O |
|
||||
| 환경 | Homebrew + Docker | Python venv + Docker |
|
||||
| 셋업 | `./setup-ollama.sh` | `./setup-mlx.sh` |
|
||||
| 종료 | `./stop-ollama.sh` | `./stop-mlx.sh` |
|
||||
|
||||
---
|
||||
|
||||
## 사전 요구사항
|
||||
|
||||
- **Mac** (MLX 방식은 Apple Silicon 필수)
|
||||
- **Docker Desktop** 설치 및 실행
|
||||
- **Homebrew** (Ollama 방식)
|
||||
- **Python 3.10+** (MLX 방식)
|
||||
- **RAM 32GB 이상** 권장 (4bit 모델 기준 ~20GB 사용)
|
||||
|
||||
---
|
||||
|
||||
## 사용법
|
||||
|
||||
### Ollama 방식
|
||||
## 빠른 시작
|
||||
|
||||
```bash
|
||||
# 셋업 (Ollama 설치 → 모델 다운로드 → Open WebUI 실행)
|
||||
./setup-ollama.sh
|
||||
# 시스템 환경을 자동 감지하여 최적의 방식을 선택합니다
|
||||
./setup.sh
|
||||
|
||||
# 종료
|
||||
./stop-ollama.sh
|
||||
```
|
||||
|
||||
### MLX 방식
|
||||
|
||||
```bash
|
||||
# 셋업 (venv → vllm-mlx 설치 → 패치 → Open WebUI → 서버 시작)
|
||||
./setup-mlx.sh
|
||||
|
||||
# 종료
|
||||
./stop-mlx.sh
|
||||
# 종료 (실행 중인 서비스를 자동 감지하여 종료)
|
||||
./stop.sh
|
||||
```
|
||||
|
||||
셋업 완료 후 **http://localhost:3000** 접속
|
||||
@ -56,17 +22,68 @@
|
||||
|
||||
---
|
||||
|
||||
## 자동 감지 기준
|
||||
|
||||
| 조건 | 선택 | 이유 |
|
||||
|------|------|------|
|
||||
| NVIDIA GPU 있음 | **vLLM** | CUDA 가속, 가장 빠름 |
|
||||
| Apple Silicon + RAM 32GB↑ | **MLX** | Mac GPU 최적화 |
|
||||
| Apple Silicon + RAM 부족 | **Ollama** | 메모리 관리 우수 |
|
||||
| 그 외 | **Ollama** | 범용, CPU에서도 동작 |
|
||||
|
||||
---
|
||||
|
||||
## 방식별 비교
|
||||
|
||||
| | Ollama | MLX (vllm-mlx) | vLLM |
|
||||
|---|---|---|---|
|
||||
| 환경 | Mac / Linux | Apple Silicon Mac | NVIDIA GPU (Linux) |
|
||||
| 장점 | 간편, 설정 적음 | Mac GPU 최적화 | CUDA 가속, 고성능 |
|
||||
| 이미지 입력 | O | O | O |
|
||||
| 개별 셋업 | `./setup-ollama.sh` | `./setup-mlx.sh` | `./setup-vllm.sh` |
|
||||
| 개별 종료 | `./stop-ollama.sh` | `./stop-mlx.sh` | `./stop-vllm.sh` |
|
||||
|
||||
---
|
||||
|
||||
## 사전 요구사항
|
||||
|
||||
**공통:**
|
||||
- Docker Desktop (또는 Docker Engine) 설치 및 실행
|
||||
|
||||
**Ollama:**
|
||||
- Homebrew
|
||||
|
||||
**MLX:**
|
||||
- Apple Silicon Mac (M1/M2/M3/M4)
|
||||
- Python 3.10+
|
||||
- RAM 32GB 이상 권장
|
||||
|
||||
**vLLM:**
|
||||
- NVIDIA GPU (VRAM 20GB 이상 권장)
|
||||
- nvidia-container-toolkit
|
||||
|
||||
---
|
||||
|
||||
## 파일 구조
|
||||
|
||||
```
|
||||
├── setup-ollama.sh # Ollama 원클릭 셋업
|
||||
├── setup-mlx.sh # MLX 원클릭 셋업
|
||||
├── setup.sh # 통합 셋업 (자동 감지)
|
||||
├── stop.sh # 통합 종료 (자동 감지)
|
||||
│
|
||||
├── setup-ollama.sh # Ollama 셋업
|
||||
├── setup-mlx.sh # MLX 셋업
|
||||
├── setup-vllm.sh # vLLM 셋업
|
||||
│
|
||||
├── stop-ollama.sh # Ollama 종료
|
||||
├── stop-mlx.sh # MLX 종료
|
||||
├── docker-compose.yml # Ollama용 Open WebUI
|
||||
├── docker-compose.mlx.yml # MLX용 Open WebUI
|
||||
├── stop-vllm.sh # vLLM 종료
|
||||
│
|
||||
├── docker-compose.yml # Ollama용
|
||||
├── docker-compose.mlx.yml # MLX용
|
||||
├── docker-compose.vllm.yml # vLLM용 (자동 생성)
|
||||
│
|
||||
├── SETUP_OLLAMA.md # Ollama 상세 가이드
|
||||
└── SETUP_MLX.md # MLX 상세 가이드 (파라미터, 트러블슈팅)
|
||||
└── SETUP_MLX.md # MLX 상세 가이드
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
166
setup-vllm.sh
Executable file
166
setup-vllm.sh
Executable file
@ -0,0 +1,166 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
#====================================================================
|
||||
# Qwen3.5 + Open WebUI (vLLM + NVIDIA GPU) 원클릭 셋업
|
||||
# 환경: Linux / NVIDIA GPU / Docker
|
||||
#====================================================================
|
||||
|
||||
PROJECT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
MODEL="Qwen/Qwen3.5-35B-A3B"
|
||||
PORT=8090
|
||||
WEBUI_PORT=3000
|
||||
MAX_TOKENS=8192
|
||||
MAX_MODEL_LEN=8192
|
||||
|
||||
echo "============================================"
|
||||
echo " Qwen3.5 + Open WebUI (vLLM) 셋업"
|
||||
echo "============================================"
|
||||
echo ""
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# 1. 사전 요구사항 확인
|
||||
#--------------------------------------------------------------------
|
||||
echo "[1/4] 사전 요구사항 확인..."
|
||||
|
||||
# Docker
|
||||
if ! command -v docker &>/dev/null; then
|
||||
echo "❌ Docker가 설치되어 있지 않습니다."
|
||||
exit 1
|
||||
fi
|
||||
if ! docker info &>/dev/null; then
|
||||
echo "❌ Docker 데몬이 실행 중이 아닙니다."
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Docker"
|
||||
|
||||
# NVIDIA GPU
|
||||
if ! command -v nvidia-smi &>/dev/null; then
|
||||
echo "❌ nvidia-smi를 찾을 수 없습니다. NVIDIA 드라이버가 설치되어 있는지 확인하세요."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
GPU_NAME=$(nvidia-smi --query-gpu=name --format=csv,noheader | head -1)
|
||||
GPU_VRAM=$(nvidia-smi --query-gpu=memory.total --format=csv,noheader,nounits | head -1)
|
||||
echo " ✓ GPU: $GPU_NAME (${GPU_VRAM}MB)"
|
||||
|
||||
if [ "$GPU_VRAM" -lt 20000 ]; then
|
||||
echo " ⚠️ VRAM이 20GB 미만입니다. 4bit 양자화 모델을 사용하세요."
|
||||
fi
|
||||
|
||||
# nvidia-container-toolkit
|
||||
if ! docker run --rm --gpus all nvidia/cuda:12.0.0-base-ubuntu22.04 nvidia-smi &>/dev/null; then
|
||||
echo "❌ nvidia-container-toolkit이 설치되어 있지 않습니다."
|
||||
echo " 설치: https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ nvidia-container-toolkit"
|
||||
|
||||
echo ""
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# 2. Docker Compose 설정
|
||||
#--------------------------------------------------------------------
|
||||
echo "[2/4] Docker Compose 설정..."
|
||||
|
||||
if [ ! -f "$PROJECT_DIR/docker-compose.vllm.yml" ]; then
|
||||
cat > "$PROJECT_DIR/docker-compose.vllm.yml" << EOF
|
||||
services:
|
||||
vllm:
|
||||
image: vllm/vllm-openai:latest
|
||||
container_name: vllm-server
|
||||
ports:
|
||||
- "${PORT}:8000"
|
||||
volumes:
|
||||
- vllm-models:/root/.cache/huggingface
|
||||
environment:
|
||||
- HUGGING_FACE_HUB_TOKEN=\${HUGGING_FACE_HUB_TOKEN:-}
|
||||
deploy:
|
||||
resources:
|
||||
reservations:
|
||||
devices:
|
||||
- driver: nvidia
|
||||
count: all
|
||||
capabilities: [gpu]
|
||||
command: >
|
||||
--model ${MODEL}
|
||||
--max-model-len ${MAX_MODEL_LEN}
|
||||
--max-num-seqs 4
|
||||
--gpu-memory-utilization 0.9
|
||||
--trust-remote-code
|
||||
restart: unless-stopped
|
||||
|
||||
open-webui:
|
||||
image: ghcr.io/open-webui/open-webui:main
|
||||
container_name: open-webui-vllm
|
||||
ports:
|
||||
- "${WEBUI_PORT}:8080"
|
||||
environment:
|
||||
- OPENAI_API_BASE_URL=http://vllm:8000/v1
|
||||
- OPENAI_API_KEY=none
|
||||
- OLLAMA_BASE_URL=
|
||||
volumes:
|
||||
- open-webui-vllm-data:/app/backend/data
|
||||
depends_on:
|
||||
- vllm
|
||||
restart: unless-stopped
|
||||
|
||||
volumes:
|
||||
vllm-models:
|
||||
open-webui-vllm-data:
|
||||
EOF
|
||||
echo " ✓ docker-compose.vllm.yml 생성"
|
||||
else
|
||||
echo " ✓ docker-compose.vllm.yml 이미 존재"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# 3. 서비스 실행
|
||||
#--------------------------------------------------------------------
|
||||
echo "[3/4] vLLM + Open WebUI 실행..."
|
||||
echo " (첫 실행 시 Docker 이미지 pull + 모델 다운로드로 시간이 걸립니다)"
|
||||
|
||||
cd "$PROJECT_DIR"
|
||||
docker compose -f docker-compose.vllm.yml up -d 2>&1 | grep -v "^$"
|
||||
|
||||
echo ""
|
||||
echo " 서버 준비 대기 중..."
|
||||
for i in $(seq 1 300); do
|
||||
if curl -s http://localhost:$PORT/v1/models > /dev/null 2>&1; then
|
||||
echo ""
|
||||
echo " ✓ vLLM 서버 준비 완료!"
|
||||
break
|
||||
fi
|
||||
# 컨테이너가 죽었는지 확인
|
||||
if ! docker ps -q --filter name=vllm-server | grep -q .; then
|
||||
echo ""
|
||||
echo " ❌ vLLM 서버 시작 실패. 로그를 확인하세요:"
|
||||
echo " docker logs vllm-server"
|
||||
exit 1
|
||||
fi
|
||||
printf "."
|
||||
sleep 1
|
||||
done
|
||||
|
||||
if ! curl -s http://localhost:$PORT/v1/models > /dev/null 2>&1; then
|
||||
echo ""
|
||||
echo " ⚠️ 서버가 아직 준비 중입니다. (모델 다운로드 중일 수 있음)"
|
||||
echo " 로그 확인: docker logs -f vllm-server"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# 4. 완료
|
||||
#--------------------------------------------------------------------
|
||||
echo "[4/4] 셋업 완료!"
|
||||
echo ""
|
||||
echo "============================================"
|
||||
echo " 브라우저에서 http://localhost:${WEBUI_PORT} 접속"
|
||||
echo " (첫 접속 시 회원가입 → 첫 계정이 admin)"
|
||||
echo ""
|
||||
echo " 로그 확인: docker logs -f vllm-server"
|
||||
echo " 종료: ./stop-vllm.sh"
|
||||
echo "============================================"
|
||||
129
setup.sh
Executable file
129
setup.sh
Executable file
@ -0,0 +1,129 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
#====================================================================
|
||||
# Qwen3.5 + Open WebUI 통합 셋업
|
||||
# 시스템 환경을 자동 감지하여 최적의 방식을 선택합니다.
|
||||
#
|
||||
# Apple Silicon + RAM 32GB↑ → MLX (vllm-mlx)
|
||||
# Apple Silicon + RAM 부족 → Ollama
|
||||
# NVIDIA GPU → vLLM (Docker)
|
||||
# 그 외 → Ollama
|
||||
#====================================================================
|
||||
|
||||
PROJECT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
|
||||
echo "============================================"
|
||||
echo " Qwen3.5 + Open WebUI 통합 셋업"
|
||||
echo " 시스템 환경을 자동 감지합니다..."
|
||||
echo "============================================"
|
||||
echo ""
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# 시스템 감지
|
||||
#--------------------------------------------------------------------
|
||||
OS=$(uname -s)
|
||||
ARCH=$(uname -m)
|
||||
HAS_APPLE_SILICON=false
|
||||
HAS_NVIDIA_GPU=false
|
||||
RAM_GB=0
|
||||
|
||||
# Apple Silicon 감지
|
||||
if [ "$OS" = "Darwin" ] && [ "$ARCH" = "arm64" ]; then
|
||||
if sysctl -n machdep.cpu.brand_string 2>/dev/null | grep -q "Apple"; then
|
||||
HAS_APPLE_SILICON=true
|
||||
RAM_GB=$(sysctl -n hw.memsize | awk '{printf "%.0f", $1/1024/1024/1024}')
|
||||
fi
|
||||
fi
|
||||
|
||||
# Linux RAM 감지
|
||||
if [ "$OS" = "Linux" ]; then
|
||||
RAM_GB=$(free -g | awk '/^Mem:/{print $2}')
|
||||
fi
|
||||
|
||||
# NVIDIA GPU 감지
|
||||
if command -v nvidia-smi &>/dev/null; then
|
||||
if nvidia-smi &>/dev/null; then
|
||||
HAS_NVIDIA_GPU=true
|
||||
fi
|
||||
fi
|
||||
|
||||
echo " OS: $OS ($ARCH)"
|
||||
echo " Apple Silicon: $HAS_APPLE_SILICON"
|
||||
echo " NVIDIA GPU: $HAS_NVIDIA_GPU"
|
||||
echo " RAM: ${RAM_GB}GB"
|
||||
echo ""
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# 방식 결정
|
||||
#--------------------------------------------------------------------
|
||||
SELECTED=""
|
||||
|
||||
if [ "$HAS_NVIDIA_GPU" = true ]; then
|
||||
SELECTED="vllm"
|
||||
echo " → NVIDIA GPU 감지 → vLLM 선택"
|
||||
elif [ "$HAS_APPLE_SILICON" = true ] && [ "$RAM_GB" -ge 32 ]; then
|
||||
SELECTED="mlx"
|
||||
echo " → Apple Silicon + RAM ${RAM_GB}GB → MLX (vllm-mlx) 선택"
|
||||
elif [ "$HAS_APPLE_SILICON" = true ]; then
|
||||
SELECTED="ollama"
|
||||
echo " → Apple Silicon + RAM ${RAM_GB}GB (32GB 미만) → Ollama 선택"
|
||||
else
|
||||
SELECTED="ollama"
|
||||
echo " → 범용 환경 → Ollama 선택"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# 사용자 확인
|
||||
#--------------------------------------------------------------------
|
||||
read -p " $SELECTED 방식으로 진행할까요? [Y/n] (직접 선택: o=ollama, m=mlx, v=vllm): " CONFIRM
|
||||
CONFIRM=${CONFIRM:-Y}
|
||||
|
||||
case "$CONFIRM" in
|
||||
[Yy]|"")
|
||||
# 자동 선택 유지
|
||||
;;
|
||||
[Oo])
|
||||
SELECTED="ollama"
|
||||
echo " → Ollama로 변경"
|
||||
;;
|
||||
[Mm])
|
||||
SELECTED="mlx"
|
||||
echo " → MLX로 변경"
|
||||
;;
|
||||
[Vv])
|
||||
SELECTED="vllm"
|
||||
echo " → vLLM으로 변경"
|
||||
;;
|
||||
[Nn])
|
||||
echo " 취소됨."
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo " 알 수 없는 입력. 취소됨."
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
echo ""
|
||||
echo "============================================"
|
||||
echo " $SELECTED 방식으로 셋업을 시작합니다"
|
||||
echo "============================================"
|
||||
echo ""
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# 선택된 스크립트 실행
|
||||
#--------------------------------------------------------------------
|
||||
case "$SELECTED" in
|
||||
ollama)
|
||||
exec "$PROJECT_DIR/setup-ollama.sh"
|
||||
;;
|
||||
mlx)
|
||||
exec "$PROJECT_DIR/setup-mlx.sh"
|
||||
;;
|
||||
vllm)
|
||||
exec "$PROJECT_DIR/setup-vllm.sh"
|
||||
;;
|
||||
esac
|
||||
25
stop-vllm.sh
Executable file
25
stop-vllm.sh
Executable file
@ -0,0 +1,25 @@
|
||||
#!/bin/bash
|
||||
|
||||
#====================================================================
|
||||
# vLLM + Open WebUI 종료
|
||||
#====================================================================
|
||||
|
||||
PROJECT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
|
||||
echo "============================================"
|
||||
echo " vLLM + Open WebUI 종료"
|
||||
echo "============================================"
|
||||
echo ""
|
||||
|
||||
cd "$PROJECT_DIR"
|
||||
|
||||
if [ -f "$PROJECT_DIR/docker-compose.vllm.yml" ]; then
|
||||
docker compose -f docker-compose.vllm.yml down 2>&1 | grep -v "^$"
|
||||
echo " ✓ vLLM + Open WebUI 종료"
|
||||
else
|
||||
echo " - docker-compose.vllm.yml 없음"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo " 완료. 재시작하려면: ./setup-vllm.sh"
|
||||
echo ""
|
||||
75
stop.sh
Executable file
75
stop.sh
Executable file
@ -0,0 +1,75 @@
|
||||
#!/bin/bash
|
||||
|
||||
#====================================================================
|
||||
# 통합 종료 — 실행 중인 서비스를 자동 감지하여 종료
|
||||
#====================================================================
|
||||
|
||||
PROJECT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
STOPPED=false
|
||||
|
||||
echo "============================================"
|
||||
echo " Open WebUI 서비스 종료"
|
||||
echo "============================================"
|
||||
echo ""
|
||||
|
||||
# vLLM 컨테이너 확인
|
||||
if docker ps -q --filter name=vllm-server 2>/dev/null | grep -q .; then
|
||||
echo " [vLLM] 감지됨 → 종료 중..."
|
||||
cd "$PROJECT_DIR"
|
||||
docker compose -f docker-compose.vllm.yml down 2>&1 | grep -v "^$"
|
||||
echo " ✓ vLLM + Open WebUI 종료"
|
||||
STOPPED=true
|
||||
fi
|
||||
|
||||
# MLX Open WebUI 컨테이너 확인
|
||||
if docker ps -q --filter name=open-webui-mlx 2>/dev/null | grep -q .; then
|
||||
echo " [MLX] Open WebUI 감지됨 → 종료 중..."
|
||||
cd "$PROJECT_DIR"
|
||||
docker compose -f docker-compose.mlx.yml down 2>&1 | grep -v "^$"
|
||||
echo " ✓ Open WebUI (MLX) 종료"
|
||||
STOPPED=true
|
||||
fi
|
||||
|
||||
# MLX vllm-mlx 서버 확인
|
||||
PIDS=$(lsof -ti :8090 2>/dev/null || true)
|
||||
if [ -n "$PIDS" ]; then
|
||||
echo " [MLX] vllm-mlx 서버 감지됨 → 종료 중..."
|
||||
echo "$PIDS" | xargs kill -9 2>/dev/null || true
|
||||
echo " ✓ vllm-mlx 서버 종료"
|
||||
STOPPED=true
|
||||
fi
|
||||
|
||||
# MLX 로그 파일 정리
|
||||
if [ -f "$PROJECT_DIR/vllm-mlx.log" ]; then
|
||||
rm "$PROJECT_DIR/vllm-mlx.log"
|
||||
echo " ✓ MLX 로그 파일 정리"
|
||||
fi
|
||||
|
||||
# Ollama Open WebUI 컨테이너 확인
|
||||
if docker ps -q --filter name=open-webui 2>/dev/null | grep -q .; then
|
||||
# open-webui-mlx나 open-webui-vllm이 아닌 경우만
|
||||
if ! docker ps -q --filter name=open-webui-mlx 2>/dev/null | grep -q . && \
|
||||
! docker ps -q --filter name=open-webui-vllm 2>/dev/null | grep -q .; then
|
||||
echo " [Ollama] Open WebUI 감지됨 → 종료 중..."
|
||||
cd "$PROJECT_DIR"
|
||||
docker compose down 2>&1 | grep -v "^$"
|
||||
echo " ✓ Open WebUI (Ollama) 종료"
|
||||
STOPPED=true
|
||||
fi
|
||||
fi
|
||||
|
||||
# Ollama 서비스 확인
|
||||
if command -v brew &>/dev/null && brew services list 2>/dev/null | grep ollama | grep -q started; then
|
||||
echo " [Ollama] 서비스 감지됨 → 종료 중..."
|
||||
brew services stop ollama
|
||||
echo " ✓ Ollama 서비스 종료"
|
||||
STOPPED=true
|
||||
fi
|
||||
|
||||
if [ "$STOPPED" = false ]; then
|
||||
echo " 실행 중인 서비스가 없습니다."
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo " 완료. 재시작하려면: ./setup.sh"
|
||||
echo ""
|
||||
Loading…
Reference in New Issue
Block a user