first commit

This commit is contained in:
2026-02-13 12:33:43 +08:00
commit a614102de3
29 changed files with 17053 additions and 0 deletions

415
remote_deploy_script.sh Normal file
View File

@@ -0,0 +1,415 @@
#!/bin/bash
# 设置颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
log_info() {
echo -e "${GREEN}[远程INFO]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
}
log_error() {
echo -e "${RED}[远程ERROR]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
}
log_warn() {
echo -e "${YELLOW}[远程WARN]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
}
# 检查端口占用并杀死进程
check_and_kill_port() {
log_info "检查端口 8888 是否被占用..."
# 查找占用端口的进程
PID=$(lsof -ti:8888 2>/dev/null)
if [ ! -z "$PID" ]; then
log_warn "发现端口 8888 被进程 $PID 占用,正在终止..."
kill -TERM $PID
sleep 3
# 检查进程是否还存在
if kill -0 $PID 2>/dev/null; then
log_warn "进程仍然存在,强制终止..."
kill -KILL $PID
sleep 2
fi
# 再次检查
NEW_PID=$(lsof -ti:8888 2>/dev/null)
if [ ! -z "$NEW_PID" ]; then
log_error "无法终止占用端口 8888 的进程"
exit 1
else
log_info "端口 8888 已释放"
fi
else
log_info "端口 8888 未被占用"
fi
}
# 检查环境是否已安装
check_environment() {
log_info "检查服务器环境..."
# 检查Python3
if ! python3 --version &> /dev/null; then
log_info "Python3 未安装,需要安装..."
return 1
fi
# 检查是否存在虚拟环境
if [ -d "/home/ubuntu/host_message_venv" ]; then
log_info "发现已存在的虚拟环境"
return 0
fi
# 检查supervisor
if ! command -v supervisorctl &> /dev/null; then
log_info "Supervisor 未安装,需要安装..."
return 1
fi
log_info "基础环境检查通过,但需要创建虚拟环境"
return 2
}
# 安装系统依赖
install_dependencies() {
log_info "安装系统依赖..."
# 更新包列表
sudo apt-get update -qq
# 安装Python3、pip和相关开发工具
log_info "安装 Python3 和相关工具..."
sudo apt-get install -y python3 python3-pip python3-venv python3-dev build-essential python3-full
# 安装supervisor用于进程保活
if ! command -v supervisorctl &> /dev/null; then
log_info "安装 supervisor..."
sudo apt-get install -y supervisor
sudo systemctl enable supervisor
sudo systemctl start supervisor
fi
# 安装其他必要工具
sudo apt-get install -y curl wget unzip lsof net-tools
log_info "系统依赖安装完成"
}
# 创建和管理虚拟环境
setup_virtual_environment() {
local venv_path="/home/ubuntu/host_message_venv"
log_info "设置Python虚拟环境..."
# 如果虚拟环境已存在,询问是否重新创建
if [ -d "$venv_path" ]; then
log_info "虚拟环境已存在,删除旧环境并重新创建..."
rm -rf "$venv_path"
fi
# 创建虚拟环境
log_info "创建新的虚拟环境..."
python3 -m venv "$venv_path"
if [ $? -eq 0 ]; then
log_info "虚拟环境创建成功: $venv_path"
else
log_error "虚拟环境创建失败"
exit 1
fi
# 激活虚拟环境并升级pip
log_info "激活虚拟环境并升级pip..."
source "$venv_path/bin/activate"
pip install --upgrade pip setuptools wheel
log_info "虚拟环境设置完成"
}
# 主要部署逻辑
main_deploy() {
# 检查并终止端口进程
check_and_kill_port
# 检查环境状态
check_environment
env_status=$?
case $env_status in
0)
log_info "环境已完整安装,跳过依赖安装"
;;
1)
log_info "需要安装基础环境"
install_dependencies
setup_virtual_environment
;;
2)
log_info "基础环境已安装,只需创建虚拟环境"
setup_virtual_environment
;;
esac
# 备份旧代码(如果存在)
if [ -d "/home/ubuntu/host_message" ]; then
log_info "备份现有代码..."
sudo mv "/home/ubuntu/host_message" "/home/ubuntu/host_message_backup_$(date +%Y%m%d_%H%M%S)" 2>/dev/null || true
fi
# 创建部署目录
log_info "创建部署目录..."
sudo mkdir -p "/home/ubuntu/host_message"
sudo chown $USER:$USER "/home/ubuntu/host_message"
# 解压代码包
log_info "解压代码包..."
cd "/home/ubuntu/host_message"
unzip -q "/tmp/$1"
if [ $? -eq 0 ]; then
log_info "代码解压成功"
else
log_error "代码解压失败"
exit 1
fi
# 创建必要的目录
mkdir -p logs uploads chat_history database
# 激活虚拟环境并安装Python依赖
log_info "激活虚拟环境并安装Python依赖..."
source "/home/ubuntu/host_message_venv/bin/activate"
if [ -f "requirements.txt" ]; then
log_info "发现 requirements.txt安装依赖包..."
pip install -r requirements.txt
if [ $? -eq 0 ]; then
log_info "Python依赖安装成功"
else
log_error "Python依赖安装失败"
# 尝试单独安装每个包
log_info "尝试单独安装依赖包..."
while IFS= read -r package; do
if [[ ! $package =~ ^[[:space:]]*# ]] && [[ ! -z $package ]]; then
log_info "安装: $package"
pip install $package || log_warn "安装 $package 失败"
fi
done < requirements.txt
fi
else
log_warn "未找到 requirements.txt 文件"
fi
# 验证关键依赖
log_info "验证Python依赖..."
python -c "import fastapi, uvicorn; print('关键依赖验证成功')" || {
log_error "关键依赖验证失败,手动安装..."
pip install fastapi uvicorn
}
# 检查main.py文件
if [ ! -f "main.py" ]; then
log_error "main.py 文件不存在!"
exit 1
fi
# 测试Python应用是否可以启动
log_info "测试Python应用..."
source "/home/ubuntu/host_message_venv/bin/activate"
timeout 10 python -c "
import sys
sys.path.insert(0, '.')
try:
import main
print('应用模块导入成功')
except Exception as e:
print(f'应用模块导入失败: {e}')
sys.exit(1)
" || log_warn "应用模块测试失败,但继续部署..."
# 创建启动脚本
log_info "创建应用启动脚本..."
cat > start_app.sh <<'SCRIPT_EOF'
#!/bin/bash
set -e
# 进入应用目录
cd "/home/ubuntu/host_message"
# 激活虚拟环境
source "/home/ubuntu/host_message_venv/bin/activate"
# 设置环境变量
export PYTHONPATH="/home/ubuntu/host_message:$PYTHONPATH"
# 记录启动信息
echo "[$(date)] 应用启动开始..."
echo "当前目录: $(pwd)"
echo "Python版本: $(python --version)"
echo "虚拟环境: $VIRTUAL_ENV"
# 检查必要文件
if [ ! -f "main.py" ]; then
echo "错误: main.py 文件不存在"
exit 1
fi
# 启动应用
echo "[$(date)] 启动Python应用..."
python main.py
SCRIPT_EOF
chmod +x start_app.sh
# 创建调试脚本
log_info "创建调试脚本..."
cat > debug_app.sh <<'DEBUG_EOF'
#!/bin/bash
cd "/home/ubuntu/host_message"
echo "=== 调试信息 ==="
echo "当前目录: $(pwd)"
# 激活虚拟环境
source "/home/ubuntu/host_message_venv/bin/activate" 2>/dev/null || echo "虚拟环境激活失败"
echo "Python版本: $(python --version 2>/dev/null || python3 --version)"
echo "pip版本: $(pip --version 2>/dev/null || echo '无pip')"
echo "虚拟环境: $VIRTUAL_ENV"
echo "文件列表:"
ls -la
echo "=== 尝试导入测试 ==="
python -c "
import sys
print('Python路径:', sys.path)
try:
import fastapi
print('fastapi版本:', fastapi.__version__)
except ImportError as e:
print('fastapi导入失败:', e)
try:
import uvicorn
print('uvicorn版本:', uvicorn.__version__)
except ImportError as e:
print('uvicorn导入失败:', e)
" 2>/dev/null || python3 -c "
import sys
print('Python路径:', sys.path)
try:
import fastapi
print('fastapi版本:', fastapi.__version__)
except ImportError as e:
print('fastapi导入失败:', e)
try:
import uvicorn
print('uvicorn版本:', uvicorn.__version__)
except ImportError as e:
print('uvicorn导入失败:', e)
"
echo "=== 检查端口占用 ==="
netstat -tlnp | grep 8888 || echo '端口8888未被占用'
echo "=== 尝试启动应用5秒后停止 ==="
timeout 5 python main.py 2>/dev/null || timeout 5 python3 main.py || echo '应用启动测试完成'
DEBUG_EOF
chmod +x debug_app.sh
# 创建supervisor配置
log_info "配置进程保活监控..."
sudo tee /etc/supervisor/conf.d/host_message.conf > /dev/null <<SUPERVISOR_EOF
[program:host_message]
command=/home/ubuntu/host_message/start_app.sh
directory=/home/ubuntu/host_message
user=ubuntu
autostart=true
autorestart=true
redirect_stderr=true
stdout_logfile=/home/ubuntu/host_message/logs/supervisor.log
stdout_logfile_maxbytes=10MB
stdout_logfile_backups=3
environment=PATH="/home/ubuntu/host_message_venv/bin:/usr/local/bin:/usr/bin:/bin",PYTHONPATH="/home/ubuntu/host_message"
startsecs=10
startretries=3
SUPERVISOR_EOF
# 停止可能存在的旧进程
sudo supervisorctl stop host_message 2>/dev/null || true
# 重新加载supervisor配置
sudo supervisorctl reread
sudo supervisorctl update
# 启动应用
log_info "启动应用..."
sudo supervisorctl start host_message
# 等待应用启动并检查状态
log_info "等待应用启动..."
for i in {1..30}; do
sleep 2
STATUS=$(sudo supervisorctl status host_message 2>/dev/null || echo "ERROR")
log_info "$i 次检查: $STATUS"
if echo "$STATUS" | grep -q "RUNNING"; then
log_info "应用启动成功!"
break
elif echo "$STATUS" | grep -q "FATAL\|BACKOFF"; then
log_error "应用启动失败: $STATUS"
log_error "查看详细日志:"
tail -20 "/home/ubuntu/host_message/logs/supervisor.log" 2>/dev/null || echo "无法读取日志文件"
# 运行调试脚本
log_info "运行调试脚本获取详细信息:"
cd "/home/ubuntu/host_message"
./debug_app.sh 2>&1 || true
# 检查supervisor错误日志
log_info "检查supervisor错误日志:"
sudo tail -20 /var/log/supervisor/supervisord.log 2>/dev/null || echo "无法读取supervisor日志"
exit 1
fi
if [ $i -eq 30 ]; then
log_error "应用启动超时"
log_error "最终状态: $STATUS"
exit 1
fi
done
# 检查端口监听
log_info "检查端口监听状态..."
for i in {1..10}; do
if netstat -tlnp 2>/dev/null | grep -q ":8888" || ss -tlnp 2>/dev/null | grep -q ":8888"; then
log_info "端口 8888 监听正常"
log_info "部署完成!您可以通过 http://6.6.6.86:8888 访问应用"
break
else
log_warn "等待端口 8888 开始监听... ($i/10)"
sleep 2
fi
if [ $i -eq 10 ]; then
log_warn "端口 8888 未在监听,请检查应用日志"
log_info "当前监听的端口:"
netstat -tlnp 2>/dev/null | grep LISTEN || ss -tlnp 2>/dev/null | grep LISTEN || echo "无法获取监听端口信息"
fi
done
# 清理临时文件
rm -f "/tmp/$1"
log_info "部署脚本执行完成"
}
# 执行主要部署逻辑
main_deploy "$1"