start bash
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -3,6 +3,8 @@ __pycache__/
|
|||||||
backend/.venv/
|
backend/.venv/
|
||||||
frontend/node_modules/
|
frontend/node_modules/
|
||||||
frontend/dist/
|
frontend/dist/
|
||||||
|
logs/
|
||||||
|
.run/
|
||||||
storage/uploads/*
|
storage/uploads/*
|
||||||
storage/processed/*
|
storage/processed/*
|
||||||
storage/covers/*
|
storage/covers/*
|
||||||
|
|||||||
31
README.md
31
README.md
@@ -201,6 +201,37 @@ npm run dev
|
|||||||
- 后端:http://localhost:8000
|
- 后端:http://localhost:8000
|
||||||
- 健康检查:http://localhost:8000/api/health
|
- 健康检查:http://localhost:8000/api/health
|
||||||
|
|
||||||
|
## 后台启动脚本
|
||||||
|
|
||||||
|
如果你不想用 Docker,可以直接用项目根目录下的脚本把前后端挂到后台:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
chmod +x start.sh stop.sh status.sh
|
||||||
|
./start.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
脚本会做这些事:
|
||||||
|
|
||||||
|
- 后台启动 FastAPI,默认端口 `8000`
|
||||||
|
- 后台启动 Vite,默认端口 `8451`
|
||||||
|
- 把 PID 写到 `.run/`
|
||||||
|
- 把日志写到 `logs/`
|
||||||
|
|
||||||
|
常用命令:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./status.sh
|
||||||
|
./stop.sh
|
||||||
|
tail -f logs/backend.log
|
||||||
|
tail -f logs/frontend.log
|
||||||
|
```
|
||||||
|
|
||||||
|
如果你要改端口,可以在启动前传环境变量,前端代理也会自动跟着后端端口变化:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
BACKEND_PORT=9000 FRONTEND_PORT=8451 ./start.sh
|
||||||
|
```
|
||||||
|
|
||||||
## Docker 启动
|
## Docker 启动
|
||||||
|
|
||||||
如果你希望在 Ubuntu 24.04 或其他装有 Docker 的环境中快速运行,直接使用:
|
如果你希望在 Ubuntu 24.04 或其他装有 Docker 的环境中快速运行,直接使用:
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
# syntax=docker/dockerfile:1.7
|
|
||||||
|
|
||||||
FROM python:3.12-slim-bookworm
|
FROM python:3.12-slim-bookworm
|
||||||
|
|
||||||
ENV PYTHONDONTWRITEBYTECODE=1
|
ENV PYTHONDONTWRITEBYTECODE=1
|
||||||
@@ -10,9 +8,7 @@ WORKDIR /app/backend
|
|||||||
RUN sed -i 's|deb.debian.org|mirrors.aliyun.com|g' /etc/apt/sources.list.d/debian.sources \
|
RUN sed -i 's|deb.debian.org|mirrors.aliyun.com|g' /etc/apt/sources.list.d/debian.sources \
|
||||||
&& sed -i 's|security.debian.org|mirrors.aliyun.com|g' /etc/apt/sources.list.d/debian.sources
|
&& sed -i 's|security.debian.org|mirrors.aliyun.com|g' /etc/apt/sources.list.d/debian.sources
|
||||||
|
|
||||||
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
|
RUN apt-get update \
|
||||||
--mount=type=cache,target=/var/lib/apt,sharing=locked \
|
|
||||||
apt-get update \
|
|
||||||
&& apt-get install -y --no-install-recommends ffmpeg \
|
&& apt-get install -y --no-install-recommends ffmpeg \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import { defineConfig } from 'vite'
|
import { defineConfig } from 'vite'
|
||||||
import react from '@vitejs/plugin-react'
|
import react from '@vitejs/plugin-react'
|
||||||
|
|
||||||
|
const proxyTarget = process.env.VITE_PROXY_TARGET || 'http://localhost:8000'
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [react()],
|
plugins: [react()],
|
||||||
server: {
|
server: {
|
||||||
@@ -8,11 +10,11 @@ export default defineConfig({
|
|||||||
port: 8451,
|
port: 8451,
|
||||||
proxy: {
|
proxy: {
|
||||||
'/api': {
|
'/api': {
|
||||||
target: 'http://localhost:8000',
|
target: proxyTarget,
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
},
|
},
|
||||||
'/media': {
|
'/media': {
|
||||||
target: 'http://localhost:8000',
|
target: proxyTarget,
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
148
start.sh
Executable file
148
start.sh
Executable file
@@ -0,0 +1,148 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
RUN_DIR="$ROOT_DIR/.run"
|
||||||
|
LOG_DIR="$ROOT_DIR/logs"
|
||||||
|
|
||||||
|
BACKEND_PID_FILE="$RUN_DIR/backend.pid"
|
||||||
|
FRONTEND_PID_FILE="$RUN_DIR/frontend.pid"
|
||||||
|
BACKEND_LOG_FILE="$LOG_DIR/backend.log"
|
||||||
|
FRONTEND_LOG_FILE="$LOG_DIR/frontend.log"
|
||||||
|
|
||||||
|
BACKEND_HOST="${BACKEND_HOST:-0.0.0.0}"
|
||||||
|
BACKEND_PORT="${BACKEND_PORT:-8000}"
|
||||||
|
FRONTEND_HOST="${FRONTEND_HOST:-0.0.0.0}"
|
||||||
|
FRONTEND_PORT="${FRONTEND_PORT:-8451}"
|
||||||
|
CORS_ORIGINS="${CORS_ORIGINS:-http://localhost:${FRONTEND_PORT},http://127.0.0.1:${FRONTEND_PORT}}"
|
||||||
|
VITE_PROXY_TARGET="${VITE_PROXY_TARGET:-http://127.0.0.1:${BACKEND_PORT}}"
|
||||||
|
|
||||||
|
mkdir -p "$RUN_DIR" "$LOG_DIR"
|
||||||
|
|
||||||
|
require_command() {
|
||||||
|
if ! command -v "$1" >/dev/null 2>&1; then
|
||||||
|
echo "Missing command: $1" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup_stale_pid() {
|
||||||
|
local pid_file="$1"
|
||||||
|
if [[ -f "$pid_file" ]]; then
|
||||||
|
local pid
|
||||||
|
pid="$(cat "$pid_file")"
|
||||||
|
if [[ -n "$pid" ]] && kill -0 "$pid" >/dev/null 2>&1; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
rm -f "$pid_file"
|
||||||
|
fi
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
wait_for_port() {
|
||||||
|
local host="$1"
|
||||||
|
local port="$2"
|
||||||
|
local name="$3"
|
||||||
|
local retries=30
|
||||||
|
|
||||||
|
while (( retries > 0 )); do
|
||||||
|
if python3 - "$host" "$port" <<'PY'
|
||||||
|
import socket
|
||||||
|
import sys
|
||||||
|
|
||||||
|
host = sys.argv[1]
|
||||||
|
port = int(sys.argv[2])
|
||||||
|
sock = socket.socket()
|
||||||
|
sock.settimeout(0.5)
|
||||||
|
try:
|
||||||
|
sock.connect((host, port))
|
||||||
|
except OSError:
|
||||||
|
sys.exit(1)
|
||||||
|
finally:
|
||||||
|
sock.close()
|
||||||
|
sys.exit(0)
|
||||||
|
PY
|
||||||
|
then
|
||||||
|
echo "$name is ready on ${host}:${port}"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
sleep 1
|
||||||
|
retries=$((retries - 1))
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "$name failed to start on ${host}:${port}. Check logs in $LOG_DIR" >&2
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
require_command python3
|
||||||
|
require_command node
|
||||||
|
require_command npm
|
||||||
|
require_command ffmpeg
|
||||||
|
|
||||||
|
if ! python3 - <<'PY' >/dev/null 2>&1
|
||||||
|
import fastapi
|
||||||
|
import uvicorn
|
||||||
|
import multipart
|
||||||
|
PY
|
||||||
|
then
|
||||||
|
echo "Missing Python packages. Run: cd backend && python3 -m pip install --user -r requirements.txt" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! -d "$ROOT_DIR/frontend/node_modules" ]]; then
|
||||||
|
echo "Installing frontend dependencies..."
|
||||||
|
(
|
||||||
|
cd "$ROOT_DIR/frontend"
|
||||||
|
npm install
|
||||||
|
)
|
||||||
|
fi
|
||||||
|
|
||||||
|
if cleanup_stale_pid "$BACKEND_PID_FILE"; then
|
||||||
|
echo "Backend already running with PID $(cat "$BACKEND_PID_FILE")"
|
||||||
|
else
|
||||||
|
echo "Starting backend..."
|
||||||
|
(
|
||||||
|
cd "$ROOT_DIR/backend"
|
||||||
|
nohup env \
|
||||||
|
CORS_ORIGINS="$CORS_ORIGINS" \
|
||||||
|
python3 -m uvicorn app.main:app \
|
||||||
|
--host "$BACKEND_HOST" \
|
||||||
|
--port "$BACKEND_PORT" \
|
||||||
|
>"$BACKEND_LOG_FILE" 2>&1 &
|
||||||
|
echo $! > "$BACKEND_PID_FILE"
|
||||||
|
)
|
||||||
|
fi
|
||||||
|
|
||||||
|
wait_for_port "127.0.0.1" "$BACKEND_PORT" "backend"
|
||||||
|
|
||||||
|
if cleanup_stale_pid "$FRONTEND_PID_FILE"; then
|
||||||
|
echo "Frontend already running with PID $(cat "$FRONTEND_PID_FILE")"
|
||||||
|
else
|
||||||
|
echo "Starting frontend..."
|
||||||
|
(
|
||||||
|
cd "$ROOT_DIR/frontend"
|
||||||
|
nohup env \
|
||||||
|
VITE_PROXY_TARGET="$VITE_PROXY_TARGET" \
|
||||||
|
npm run dev -- --host "$FRONTEND_HOST" --port "$FRONTEND_PORT" \
|
||||||
|
>"$FRONTEND_LOG_FILE" 2>&1 &
|
||||||
|
echo $! > "$FRONTEND_PID_FILE"
|
||||||
|
)
|
||||||
|
fi
|
||||||
|
|
||||||
|
wait_for_port "127.0.0.1" "$FRONTEND_PORT" "frontend"
|
||||||
|
|
||||||
|
SERVER_IP="$(hostname -I 2>/dev/null | awk '{print $1}')"
|
||||||
|
if [[ -z "$SERVER_IP" ]]; then
|
||||||
|
SERVER_IP="127.0.0.1"
|
||||||
|
fi
|
||||||
|
|
||||||
|
cat <<EOF
|
||||||
|
VPlatform started in background.
|
||||||
|
Frontend: http://${SERVER_IP}:${FRONTEND_PORT}
|
||||||
|
Backend: http://${SERVER_IP}:${BACKEND_PORT}
|
||||||
|
|
||||||
|
Logs:
|
||||||
|
$BACKEND_LOG_FILE
|
||||||
|
$FRONTEND_LOG_FILE
|
||||||
|
EOF
|
||||||
28
status.sh
Executable file
28
status.sh
Executable file
@@ -0,0 +1,28 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
RUN_DIR="$ROOT_DIR/.run"
|
||||||
|
|
||||||
|
show_status() {
|
||||||
|
local name="$1"
|
||||||
|
local pid_file="$2"
|
||||||
|
|
||||||
|
if [[ ! -f "$pid_file" ]]; then
|
||||||
|
echo "$name: stopped"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
local pid
|
||||||
|
pid="$(cat "$pid_file")"
|
||||||
|
|
||||||
|
if [[ -n "$pid" ]] && kill -0 "$pid" >/dev/null 2>&1; then
|
||||||
|
echo "$name: running (PID $pid)"
|
||||||
|
else
|
||||||
|
echo "$name: stale pid file"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
show_status "backend" "$RUN_DIR/backend.pid"
|
||||||
|
show_status "frontend" "$RUN_DIR/frontend.pid"
|
||||||
31
stop.sh
Executable file
31
stop.sh
Executable file
@@ -0,0 +1,31 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
RUN_DIR="$ROOT_DIR/.run"
|
||||||
|
|
||||||
|
stop_one() {
|
||||||
|
local name="$1"
|
||||||
|
local pid_file="$2"
|
||||||
|
|
||||||
|
if [[ ! -f "$pid_file" ]]; then
|
||||||
|
echo "$name is not running"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
local pid
|
||||||
|
pid="$(cat "$pid_file")"
|
||||||
|
|
||||||
|
if [[ -n "$pid" ]] && kill -0 "$pid" >/dev/null 2>&1; then
|
||||||
|
kill "$pid"
|
||||||
|
echo "Stopped $name (PID $pid)"
|
||||||
|
else
|
||||||
|
echo "$name pid file was stale"
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -f "$pid_file"
|
||||||
|
}
|
||||||
|
|
||||||
|
stop_one "backend" "$RUN_DIR/backend.pid"
|
||||||
|
stop_one "frontend" "$RUN_DIR/frontend.pid"
|
||||||
Reference in New Issue
Block a user