start bash

This commit is contained in:
2026-04-09 09:43:21 +00:00
parent 5212cab8b6
commit 8409655e66
7 changed files with 245 additions and 7 deletions

2
.gitignore vendored
View File

@@ -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/*

View File

@@ -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 的环境中快速运行,直接使用:

View File

@@ -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/*

View File

@@ -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
View 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
View 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
View 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"