linux安装优化

新增脚本
This commit is contained in:
2026-03-17 09:41:37 +08:00
parent 2f2d5c3795
commit 846d35d112
5 changed files with 441 additions and 24 deletions

View File

@@ -1,15 +1,24 @@
-- Weibo-HotSign Database Initialization Script for MySQL
-- Create tables according to development document specification
-- 创建数据库和表结构
CREATE DATABASE IF NOT EXISTS weibo_hotsign DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
USE weibo_hotsign;
-- Users table
CREATE TABLE IF NOT EXISTS users (
id CHAR(36) PRIMARY KEY,
username VARCHAR(50) UNIQUE NOT NULL,
email VARCHAR(255) UNIQUE NOT NULL,
hashed_password VARCHAR(255) NOT NULL,
email VARCHAR(255) UNIQUE,
hashed_password VARCHAR(255),
wx_openid VARCHAR(64) UNIQUE,
wx_nickname VARCHAR(100),
wx_avatar VARCHAR(500),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
is_active BOOLEAN DEFAULT TRUE
);
is_active BOOLEAN DEFAULT TRUE,
INDEX idx_users_email (email),
INDEX idx_users_username (username),
INDEX idx_users_wx_openid (wx_openid)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- Accounts table
CREATE TABLE IF NOT EXISTS accounts (
@@ -22,8 +31,10 @@ CREATE TABLE IF NOT EXISTS accounts (
status VARCHAR(20) DEFAULT 'pending',
last_checked_at TIMESTAMP NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX idx_accounts_user_id (user_id),
INDEX idx_accounts_status (status),
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- Tasks table
CREATE TABLE IF NOT EXISTS tasks (
@@ -32,8 +43,10 @@ CREATE TABLE IF NOT EXISTS tasks (
cron_expression VARCHAR(50) NOT NULL,
is_enabled BOOLEAN DEFAULT TRUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX idx_tasks_account_id (account_id),
INDEX idx_tasks_is_enabled (is_enabled),
FOREIGN KEY (account_id) REFERENCES accounts(id) ON DELETE CASCADE
);
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- Signin logs table
CREATE TABLE IF NOT EXISTS signin_logs (
@@ -44,21 +57,8 @@ CREATE TABLE IF NOT EXISTS signin_logs (
reward_info JSON,
error_message TEXT,
signed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX idx_signin_logs_account_id (account_id),
INDEX idx_signin_logs_signed_at (signed_at),
INDEX idx_signin_logs_status (status),
FOREIGN KEY (account_id) REFERENCES accounts(id)
);
-- Create indexes for better performance
CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_users_username ON users(username);
CREATE INDEX idx_accounts_user_id ON accounts(user_id);
CREATE INDEX idx_accounts_status ON accounts(status);
CREATE INDEX idx_tasks_account_id ON tasks(account_id);
CREATE INDEX idx_tasks_is_enabled ON tasks(is_enabled);
CREATE INDEX idx_signin_logs_account_id ON signin_logs(account_id);
CREATE INDEX idx_signin_logs_signed_at ON signin_logs(signed_at);
CREATE INDEX idx_signin_logs_status ON signin_logs(status);
-- Insert sample data for testing (optional)
-- Note: UUIDs must be provided by the application
-- INSERT INTO users (id, username, email, hashed_password) VALUES
-- ('your-uuid-here', 'testuser', 'test@example.com', '$2b$12$hashed_password_here');
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

245
setup_linux.sh Normal file
View File

@@ -0,0 +1,245 @@
#!/bin/bash
set -e
# ============================================================
# Weibo-HotSign Linux 安装运行脚本
# 使用方式: chmod +x setup_linux.sh && ./setup_linux.sh
# ============================================================
# ===================== 请在此处填写配置 =====================
MYSQL_HOST="127.0.0.1"
MYSQL_PORT="3306"
MYSQL_USER="root"
MYSQL_PASSWORD="" # ← 填写你的 MySQL 密码
REDIS_HOST="127.0.0.1"
REDIS_PORT="6379"
REDIS_PASSWORD="" # ← 填写你的 Redis 密码(没有密码留空)
# JWT 密钥(生产环境请改成随机长字符串)
JWT_SECRET="change-me-to-a-random-string-in-production"
# Cookie 加密密钥32 字节)
COOKIE_KEY="change-me-to-a-32byte-key-prod!"
# 微信小程序(可选,暂时留空)
WX_APPID=""
WX_SECRET=""
# 服务端口
AUTH_PORT=8001
API_PORT=8000
FRONTEND_PORT=5000
# ===================== 配置结束 =====================
PROJECT_DIR="$(cd "$(dirname "$0")" && pwd)"
DB_NAME="weibo_hotsign"
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
info() { echo -e "${GREEN}[✓]${NC} $1"; }
warn() { echo -e "${YELLOW}[!]${NC} $1"; }
error() { echo -e "${RED}[✗]${NC} $1"; exit 1; }
echo ""
echo "========================================"
echo " Weibo-HotSign Linux 安装脚本"
echo "========================================"
echo ""
# ------ 1. 检查系统依赖 ------
echo "--- 检查系统依赖 ---"
command -v python3 >/dev/null 2>&1 || error "未找到 python3请先安装 Python 3.8+"
PYTHON_VER=$(python3 -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")')
info "Python $PYTHON_VER"
command -v pip3 >/dev/null 2>&1 || command -v pip >/dev/null 2>&1 || error "未找到 pip请先安装 pip"
PIP_CMD=$(command -v pip3 || command -v pip)
info "pip: $PIP_CMD"
# ------ 2. 检查 MySQL ------
echo ""
echo "--- 检查 MySQL ---"
command -v mysql >/dev/null 2>&1 || error "未找到 mysql 客户端,请先安装 mysql-client"
MYSQL_CMD="mysql -h${MYSQL_HOST} -P${MYSQL_PORT} -u${MYSQL_USER}"
if [ -n "$MYSQL_PASSWORD" ]; then
MYSQL_CMD="$MYSQL_CMD -p${MYSQL_PASSWORD}"
fi
# 测试连接
if $MYSQL_CMD -e "SELECT 1" >/dev/null 2>&1; then
info "MySQL 连接成功 (${MYSQL_HOST}:${MYSQL_PORT})"
else
error "MySQL 连接失败,请检查地址、端口和密码"
fi
# ------ 3. 检查 Redis ------
echo ""
echo "--- 检查 Redis ---"
command -v redis-cli >/dev/null 2>&1 || error "未找到 redis-cli请先安装 redis-tools"
REDIS_CLI="redis-cli -h ${REDIS_HOST} -p ${REDIS_PORT}"
if [ -n "$REDIS_PASSWORD" ]; then
REDIS_CLI="$REDIS_CLI -a ${REDIS_PASSWORD}"
fi
REDIS_PING=$($REDIS_CLI --no-auth-warning PING 2>/dev/null || true)
if [ "$REDIS_PING" = "PONG" ]; then
info "Redis 连接成功 (${REDIS_HOST}:${REDIS_PORT})"
else
error "Redis 连接失败,请检查地址、端口和密码"
fi
# ------ 4. 初始化 MySQL 数据库 ------
echo ""
echo "--- 初始化 MySQL 数据库 ---"
if $MYSQL_CMD -e "USE ${DB_NAME}" >/dev/null 2>&1; then
# 数据库已存在,检查是否需要加微信字段
HAS_WX=$($MYSQL_CMD -N -e "SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA='${DB_NAME}' AND TABLE_NAME='users' AND COLUMN_NAME='wx_openid'" 2>/dev/null)
if [ "$HAS_WX" = "0" ]; then
warn "数据库已存在,正在添加微信登录字段..."
$MYSQL_CMD ${DB_NAME} -e "
ALTER TABLE users ADD COLUMN wx_openid VARCHAR(64) UNIQUE AFTER hashed_password;
ALTER TABLE users ADD COLUMN wx_nickname VARCHAR(100) AFTER wx_openid;
ALTER TABLE users ADD COLUMN wx_avatar VARCHAR(500) AFTER wx_nickname;
ALTER TABLE users MODIFY COLUMN email VARCHAR(255) NULL;
ALTER TABLE users MODIFY COLUMN hashed_password VARCHAR(255) NULL;
" 2>/dev/null || true
info "微信字段已添加"
else
info "数据库 ${DB_NAME} 已存在且结构完整"
fi
else
info "正在创建数据库和表..."
$MYSQL_CMD < "${PROJECT_DIR}/init-db.sql"
info "数据库 ${DB_NAME} 创建完成"
fi
# 创建测试用户(如果 users 表为空)
USER_COUNT=$($MYSQL_CMD -N -e "SELECT COUNT(*) FROM ${DB_NAME}.users" 2>/dev/null)
if [ "$USER_COUNT" = "0" ]; then
info "正在创建测试用户..."
# 用 python 生成 bcrypt 密码
HASHED_PW=$(python3 -c "import bcrypt; print(bcrypt.hashpw(b'Admin123!', bcrypt.gensalt(12)).decode())")
USER_ID=$(python3 -c "import uuid; print(str(uuid.uuid4()))")
$MYSQL_CMD ${DB_NAME} -e "
INSERT INTO users (id, username, email, hashed_password, is_active)
VALUES ('${USER_ID}', 'admin', 'admin@example.com', '${HASHED_PW}', 1);
"
info "测试用户: admin / Admin123!"
fi
# ------ 5. 构建 Redis URL ------
if [ -n "$REDIS_PASSWORD" ]; then
REDIS_URL="redis://:${REDIS_PASSWORD}@${REDIS_HOST}:${REDIS_PORT}/0"
else
REDIS_URL="redis://${REDIS_HOST}:${REDIS_PORT}/0"
fi
# ------ 6. 构建 MySQL URL ------
if [ -n "$MYSQL_PASSWORD" ]; then
MYSQL_URL="mysql+aiomysql://${MYSQL_USER}:${MYSQL_PASSWORD}@${MYSQL_HOST}:${MYSQL_PORT}/${DB_NAME}?charset=utf8mb4"
else
MYSQL_URL="mysql+aiomysql://${MYSQL_USER}@${MYSQL_HOST}:${MYSQL_PORT}/${DB_NAME}?charset=utf8mb4"
fi
# ------ 7. 生成 .env 文件 ------
echo ""
echo "--- 生成配置文件 ---"
cat > "${PROJECT_DIR}/backend/.env" << EOF
# ===== 由 setup_linux.sh 自动生成 =====
# MySQL
DATABASE_URL=${MYSQL_URL}
# Redis
USE_REDIS=true
REDIS_URL=${REDIS_URL}
# JWT
JWT_SECRET_KEY=${JWT_SECRET}
JWT_ALGORITHM=HS256
JWT_EXPIRATION_HOURS=24
# Cookie 加密
COOKIE_ENCRYPTION_KEY=${COOKIE_KEY}
# 微信小程序
WX_APPID=${WX_APPID}
WX_SECRET=${WX_SECRET}
# 环境
ENVIRONMENT=production
EOF
info "backend/.env 已生成"
cat > "${PROJECT_DIR}/frontend/.env" << EOF
# ===== 由 setup_linux.sh 自动生成 =====
FLASK_ENV=production
FLASK_DEBUG=False
SECRET_KEY=$(python3 -c "import secrets; print(secrets.token_hex(32))")
API_BASE_URL=http://127.0.0.1:${API_PORT}
AUTH_BASE_URL=http://127.0.0.1:${AUTH_PORT}
SESSION_TYPE=filesystem
EOF
info "frontend/.env 已生成"
# ------ 8. 创建虚拟环境并安装依赖 ------
echo ""
echo "--- 安装 Python 依赖 ---"
# 后端
if [ ! -d "${PROJECT_DIR}/backend/venv" ]; then
info "创建后端虚拟环境..."
python3 -m venv "${PROJECT_DIR}/backend/venv"
fi
source "${PROJECT_DIR}/backend/venv/bin/activate"
pip install -q --upgrade pip
pip install -q -r "${PROJECT_DIR}/backend/requirements.txt"
deactivate
info "后端依赖安装完成"
# 前端
if [ ! -d "${PROJECT_DIR}/frontend/venv" ]; then
info "创建前端虚拟环境..."
python3 -m venv "${PROJECT_DIR}/frontend/venv"
fi
source "${PROJECT_DIR}/frontend/venv/bin/activate"
pip install -q --upgrade pip
pip install -q -r "${PROJECT_DIR}/frontend/requirements.txt"
deactivate
info "前端依赖安装完成"
echo ""
echo "========================================"
echo " 安装完成!"
echo "========================================"
echo ""
echo " MySQL: ${MYSQL_HOST}:${MYSQL_PORT} / ${DB_NAME}"
echo " Redis: ${REDIS_HOST}:${REDIS_PORT}"
echo ""
echo " 启动服务: ./start_linux.sh"
echo " 停止服务: ./stop_linux.sh"
echo ""

105
start_linux.sh Normal file
View File

@@ -0,0 +1,105 @@
#!/bin/bash
# ============================================================
# Weibo-HotSign Linux 启动脚本
# 使用方式: chmod +x start_linux.sh && ./start_linux.sh
# ============================================================
PROJECT_DIR="$(cd "$(dirname "$0")" && pwd)"
PID_DIR="${PROJECT_DIR}/.pids"
LOG_DIR="${PROJECT_DIR}/logs"
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
info() { echo -e "${GREEN}[✓]${NC} $1"; }
warn() { echo -e "${YELLOW}[!]${NC} $1"; }
error() { echo -e "${RED}[✗]${NC} $1"; exit 1; }
# 创建目录
mkdir -p "$PID_DIR" "$LOG_DIR"
# 检查是否已在运行
check_running() {
local name=$1
local pidfile="${PID_DIR}/${name}.pid"
if [ -f "$pidfile" ]; then
local pid=$(cat "$pidfile")
if kill -0 "$pid" 2>/dev/null; then
warn "${name} 已在运行 (PID: ${pid}),跳过"
return 0
else
rm -f "$pidfile"
fi
fi
return 1
}
echo ""
echo "========================================"
echo " Weibo-HotSign 启动服务"
echo "========================================"
echo ""
# ------ 1. 启动 Auth Service (端口 8001) ------
if ! check_running "auth_service"; then
info "启动 Auth Service (端口 8001)..."
source "${PROJECT_DIR}/backend/venv/bin/activate"
cd "${PROJECT_DIR}/backend"
PYTHONPATH="${PROJECT_DIR}/backend" nohup python -m uvicorn auth_service.app.main:app \
--host 0.0.0.0 --port 8001 \
> "${LOG_DIR}/auth_service.log" 2>&1 &
echo $! > "${PID_DIR}/auth_service.pid"
deactivate
cd "${PROJECT_DIR}"
sleep 2
info "Auth Service 已启动 (PID: $(cat ${PID_DIR}/auth_service.pid))"
fi
# ------ 2. 启动 API Service (端口 8000) ------
if ! check_running "api_service"; then
info "启动 API Service (端口 8000)..."
source "${PROJECT_DIR}/backend/venv/bin/activate"
cd "${PROJECT_DIR}/backend"
PYTHONPATH="${PROJECT_DIR}/backend" nohup python -m uvicorn api_service.app.main:app \
--host 0.0.0.0 --port 8000 \
> "${LOG_DIR}/api_service.log" 2>&1 &
echo $! > "${PID_DIR}/api_service.pid"
deactivate
cd "${PROJECT_DIR}"
sleep 2
info "API Service 已启动 (PID: $(cat ${PID_DIR}/api_service.pid))"
fi
# ------ 3. 启动 Frontend (端口 5000) ------
if ! check_running "frontend"; then
info "启动 Frontend (端口 5000)..."
source "${PROJECT_DIR}/frontend/venv/bin/activate"
cd "${PROJECT_DIR}/frontend"
nohup python app.py \
> "${LOG_DIR}/frontend.log" 2>&1 &
echo $! > "${PID_DIR}/frontend.pid"
deactivate
cd "${PROJECT_DIR}"
sleep 2
info "Frontend 已启动 (PID: $(cat ${PID_DIR}/frontend.pid))"
fi
echo ""
echo "========================================"
echo " 所有服务已启动"
echo "========================================"
echo ""
echo " 前端界面: http://localhost:5000"
echo " API Service: http://localhost:8000"
echo " Auth Service: http://localhost:8001"
echo ""
echo " 日志目录: ${LOG_DIR}/"
echo " 停止服务: ./stop_linux.sh"
echo " 查看日志: tail -f logs/auth_service.log"
echo ""

67
stop_linux.sh Normal file
View File

@@ -0,0 +1,67 @@
#!/bin/bash
# ============================================================
# Weibo-HotSign Linux 停止脚本
# 使用方式: chmod +x stop_linux.sh && ./stop_linux.sh
# ============================================================
PROJECT_DIR="$(cd "$(dirname "$0")" && pwd)"
PID_DIR="${PROJECT_DIR}/.pids"
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
info() { echo -e "${GREEN}[✓]${NC} $1"; }
warn() { echo -e "${YELLOW}[!]${NC} $1"; }
echo ""
echo "========================================"
echo " Weibo-HotSign 停止服务"
echo "========================================"
echo ""
SERVICES=("auth_service" "api_service" "frontend")
SERVICE_NAMES=("Auth Service" "API Service" "Frontend")
stopped=0
for i in "${!SERVICES[@]}"; do
name="${SERVICES[$i]}"
display="${SERVICE_NAMES[$i]}"
pidfile="${PID_DIR}/${name}.pid"
if [ -f "$pidfile" ]; then
pid=$(cat "$pidfile")
if kill -0 "$pid" 2>/dev/null; then
kill "$pid" 2>/dev/null
# 等待进程退出(最多 5 秒)
for j in $(seq 1 10); do
if ! kill -0 "$pid" 2>/dev/null; then
break
fi
sleep 0.5
done
# 如果还没退出,强制杀
if kill -0 "$pid" 2>/dev/null; then
kill -9 "$pid" 2>/dev/null
fi
info "${display} 已停止 (PID: ${pid})"
stopped=$((stopped + 1))
else
warn "${display} 进程不存在 (PID: ${pid})"
fi
rm -f "$pidfile"
else
warn "${display} 未在运行"
fi
done
echo ""
if [ $stopped -gt 0 ]; then
info "已停止 ${stopped} 个服务"
else
warn "没有正在运行的服务"
fi
echo ""