Files
aitsc/scripts/port_manager.sh

329 lines
7.9 KiB
Bash
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
# 端口管理脚本
# 用于管理Flask应用的端口占用问题
# 配置
PORT=5002
APP_NAME="flask_prompt_master"
PID_FILE="logs/gunicorn.pid"
LOG_DIR="logs"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# 日志函数
log_info() {
echo -e "${GREEN}[INFO]${NC} $1"
}
log_warn() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
log_debug() {
echo -e "${BLUE}[DEBUG]${NC} $1"
}
# 检查端口是否被占用
check_port() {
log_info "检查端口 $PORT 占用情况..."
if ss -tlnp | grep -q ":$PORT "; then
log_warn "端口 $PORT 已被占用"
ss -tlnp | grep ":$PORT "
return 1
else
log_info "端口 $PORT 未被占用"
return 0
fi
}
# 获取占用端口的进程
get_port_processes() {
log_info "获取占用端口 $PORT 的进程信息..."
local processes=$(ss -tlnp | grep ":$PORT " | awk '{print $7}' | sed 's/.*pid=\([0-9]*\).*/\1/' | sort -u)
if [ -n "$processes" ]; then
log_warn "占用端口 $PORT 的进程:"
for pid in $processes; do
if ps -p $pid > /dev/null 2>&1; then
ps -p $pid -o pid,ppid,cmd --no-headers
fi
done
return 1
else
log_info "没有进程占用端口 $PORT"
return 0
fi
}
# 清理端口占用
clean_port() {
log_info "清理端口 $PORT 占用..."
local processes=$(ss -tlnp | grep ":$PORT " | awk '{print $7}' | sed 's/.*pid=\([0-9]*\).*/\1/' | sort -u)
if [ -n "$processes" ]; then
log_warn "发现占用端口 $PORT 的进程,正在清理..."
for pid in $processes; do
if ps -p $pid > /dev/null 2>&1; then
local cmd=$(ps -p $pid -o cmd --no-headers)
log_info "终止进程 $pid: $cmd"
kill -TERM $pid
# 等待进程终止
local count=0
while ps -p $pid > /dev/null 2>&1 && [ $count -lt 10 ]; do
sleep 1
count=$((count + 1))
done
# 强制终止
if ps -p $pid > /dev/null 2>&1; then
log_warn "强制终止进程 $pid"
kill -KILL $pid
fi
fi
done
# 验证清理结果
sleep 2
if check_port; then
log_info "端口 $PORT 清理成功"
return 0
else
log_error "端口 $PORT 清理失败"
return 1
fi
else
log_info "端口 $PORT 未被占用,无需清理"
return 0
fi
}
# 检查Gunicorn进程
check_gunicorn() {
log_info "检查Gunicorn进程状态..."
if [ -f "$PID_FILE" ]; then
local pid=$(cat "$PID_FILE")
if ps -p $pid > /dev/null 2>&1; then
log_info "Gunicorn主进程 $pid 正在运行"
local workers=$(ps aux | grep "gunicorn.*run_dev:app" | grep -v grep | wc -l)
log_info "工作进程数量: $workers"
return 0
else
log_warn "PID文件存在但进程不存在: $pid"
return 1
fi
else
log_warn "PID文件不存在: $PID_FILE"
return 1
fi
}
# 启动应用
start_app() {
log_info "启动Flask应用..."
# 切换到项目目录
cd "$PROJECT_DIR" || {
log_error "无法切换到项目目录: $PROJECT_DIR"
return 1
}
# 激活conda环境
if command -v conda > /dev/null 2>&1; then
log_info "激活conda环境..."
eval "$(/home/renjianbo/miniconda3/bin/conda shell.bash hook)" && conda activate myenv
fi
# 检查端口
if ! check_port; then
log_warn "端口被占用,尝试清理..."
if ! clean_port; then
log_error "无法清理端口占用,启动失败"
return 1
fi
fi
# 启动Gunicorn
log_info "启动Gunicorn服务..."
nohup gunicorn -c gunicorn.conf.py run_dev:app > "$LOG_DIR/gunicorn_startup.log" 2>&1 &
# 等待启动
sleep 5
# 验证启动
if check_gunicorn; then
log_info "应用启动成功"
return 0
else
log_error "应用启动失败"
return 1
fi
}
# 停止应用
stop_app() {
log_info "停止Flask应用..."
if [ -f "$PID_FILE" ]; then
local pid=$(cat "$PID_FILE")
if ps -p $pid > /dev/null 2>&1; then
log_info "停止Gunicorn主进程 $pid"
kill -TERM $pid
# 等待进程终止
local count=0
while ps -p $pid > /dev/null 2>&1 && [ $count -lt 10 ]; do
sleep 1
count=$((count + 1))
done
# 强制终止
if ps -p $pid > /dev/null 2>&1; then
log_warn "强制终止进程 $pid"
kill -KILL $pid
fi
fi
fi
# 清理所有相关进程
local gunicorn_pids=$(ps aux | grep "gunicorn.*run_dev:app" | grep -v grep | awk '{print $2}')
if [ -n "$gunicorn_pids" ]; then
log_info "清理Gunicorn工作进程..."
for pid in $gunicorn_pids; do
kill -TERM $pid 2>/dev/null
done
fi
log_info "应用停止完成"
}
# 重启应用
restart_app() {
log_info "重启Flask应用..."
stop_app
sleep 2
start_app
}
# 状态检查
status() {
log_info "=== Flask应用状态检查 ==="
echo "1. 端口占用检查:"
if check_port; then
echo " ✅ 端口 $PORT 可用"
else
echo " ❌ 端口 $PORT 被占用"
get_port_processes
fi
echo ""
echo "2. Gunicorn进程检查:"
if check_gunicorn; then
echo " ✅ Gunicorn正在运行"
else
echo " ❌ Gunicorn未运行"
fi
echo ""
echo "3. 服务响应检查:"
if curl -s http://localhost:$PORT/ > /dev/null 2>&1; then
echo " ✅ 服务正常响应"
else
echo " ❌ 服务无响应"
fi
}
# 监控模式
monitor() {
log_info "启动端口监控模式..."
while true; do
if ! check_gunicorn; then
log_warn "检测到Gunicorn进程异常尝试重启..."
restart_app
fi
if ! curl -s http://localhost:$PORT/ > /dev/null 2>&1; then
log_warn "检测到服务无响应,尝试重启..."
restart_app
fi
sleep 30
done
}
# 帮助信息
show_help() {
echo "端口管理脚本使用方法:"
echo ""
echo " $0 check - 检查端口占用情况"
echo " $0 clean - 清理端口占用"
echo " $0 start - 启动应用"
echo " $0 stop - 停止应用"
echo " $0 restart - 重启应用"
echo " $0 status - 查看应用状态"
echo " $0 monitor - 启动监控模式"
echo " $0 help - 显示帮助信息"
echo ""
echo "示例:"
echo " $0 status # 检查当前状态"
echo " $0 restart # 重启应用"
echo " $0 monitor # 后台监控"
}
# 主函数
main() {
case "${1:-help}" in
check)
check_port
;;
clean)
clean_port
;;
start)
start_app
;;
stop)
stop_app
;;
restart)
restart_app
;;
status)
status
;;
monitor)
monitor
;;
help|--help|-h)
show_help
;;
*)
log_error "未知命令: $1"
show_help
exit 1
;;
esac
}
# 执行主函数
main "$@"