linux安装优化
新增脚本
This commit is contained in:
48
init-db.sql
48
init-db.sql
@@ -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;
|
||||
|
||||
BIN
qrcode.png
BIN
qrcode.png
Binary file not shown.
|
Before Width: | Height: | Size: 3.3 KiB |
245
setup_linux.sh
Normal file
245
setup_linux.sh
Normal 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
105
start_linux.sh
Normal 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
67
stop_linux.sh
Normal 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 ""
|
||||
Reference in New Issue
Block a user