From 6168a488facb30d413cc2e5bb77ed318f1b36925 Mon Sep 17 00:00:00 2001 From: jingrow Date: Fri, 8 Aug 2025 07:21:05 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96pm2=E7=9A=84=E6=A3=80?= =?UTF-8?q?=E6=B5=8B=E6=9C=BA=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- install_jsite.sh | 196 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 142 insertions(+), 54 deletions(-) diff --git a/install_jsite.sh b/install_jsite.sh index be2e646..deb96a5 100755 --- a/install_jsite.sh +++ b/install_jsite.sh @@ -783,59 +783,36 @@ start_project_with_pm2() { pm2 list | grep -w '$SITE_NAME' | grep -c 'online' || echo '0' ") - if [ "$PM2_STATUS" != "0" ] && [ -n "$PM2_STATUS" ] && [ "$PM2_RUNNING" != "0" ]; then - if [ "$FORCE_UPDATE" = true ]; then - log_warning "项目已在PM2中运行,重新启动..." - su - jingrow -c " - export NVM_DIR=\"\$HOME/.nvm\" - [ -s \"\$NVM_DIR/nvm.sh\" ] && \. \"\$NVM_DIR/nvm.sh\" - cd /home/jingrow/jsite/$SITE_NAME - pm2 delete $SITE_NAME 2>/dev/null || true - pm2 start ecosystem.config.cjs - " - if [ $? -ne 0 ]; then - log_error "PM2启动失败,请检查项目配置和依赖" - log_info "检查PM2日志:" - su - jingrow -c " - export NVM_DIR=\"\$HOME/.nvm\" - [ -s \"\$NVM_DIR/nvm.sh\" ] && \. \"\$NVM_DIR/nvm.sh\" - pm2 logs $SITE_NAME --lines 10 - " - return 1 - fi - else - log_warning "项目已在PM2中运行,跳过启动" - log_success "现有PM2进程运行正常" - return 0 - fi - else - # 如果项目存在但不在运行状态,先删除再重新启动 - if [ "$PM2_STATUS" != "0" ] && [ -n "$PM2_STATUS" ]; then - log_warning "项目存在于PM2中但未正常运行,重新启动..." - su - jingrow -c " - export NVM_DIR=\"\$HOME/.nvm\" - [ -s \"\$NVM_DIR/nvm.sh\" ] && \. \"\$NVM_DIR/nvm.sh\" - pm2 delete $SITE_NAME 2>/dev/null || true - " - fi - - log_info "启动新项目..." + # 如果项目存在,先删除它(不管状态如何) + if [ "$PM2_STATUS" != "0" ] && [ -n "$PM2_STATUS" ]; then + log_warning "项目已存在于PM2中,删除旧进程..." su - jingrow -c " export NVM_DIR=\"\$HOME/.nvm\" [ -s \"\$NVM_DIR/nvm.sh\" ] && \. \"\$NVM_DIR/nvm.sh\" - cd /home/jingrow/jsite/$SITE_NAME - pm2 start ecosystem.config.cjs + pm2 delete $SITE_NAME 2>/dev/null || true " - if [ $? -ne 0 ]; then - log_error "PM2启动失败,请检查项目配置和依赖" - log_info "检查PM2日志:" - su - jingrow -c " - export NVM_DIR=\"\$HOME/.nvm\" - [ -s \"\$NVM_DIR/nvm.sh\" ] && \. \"\$NVM_DIR/nvm.sh\" - pm2 logs $SITE_NAME --lines 10 - " - return 1 - fi + # 等待一下确保删除完成 + sleep 2 + fi + + # 启动新项目 + log_info "启动项目: $SITE_NAME..." + su - jingrow -c " + export NVM_DIR=\"\$HOME/.nvm\" + [ -s \"\$NVM_DIR/nvm.sh\" ] && \. \"\$NVM_DIR/nvm.sh\" + cd /home/jingrow/jsite/$SITE_NAME + pm2 start ecosystem.config.cjs + " + + if [ $? -ne 0 ]; then + log_error "PM2启动失败,请检查项目配置和依赖" + log_info "检查PM2日志:" + su - jingrow -c " + export NVM_DIR=\"\$HOME/.nvm\" + [ -s \"\$NVM_DIR/nvm.sh\" ] && \. \"\$NVM_DIR/nvm.sh\" + pm2 logs $SITE_NAME --lines 10 + " + return 1 fi # 等待PM2启动完成,最多等待60秒 @@ -843,11 +820,14 @@ start_project_with_pm2() { local wait_time=0 local max_wait=60 local pm2_running="0" + local max_retries=3 + local retry_count=0 while [ $wait_time -lt $max_wait ] && [ "$pm2_running" = "0" ]; do sleep 2 wait_time=$((wait_time + 2)) + # 检查PM2进程状态 pm2_running=$(su - jingrow -c " export NVM_DIR=\"\$HOME/.nvm\" [ -s \"\$NVM_DIR/nvm.sh\" ] && \. \"\$NVM_DIR/nvm.sh\" @@ -856,6 +836,35 @@ start_project_with_pm2() { if [ "$pm2_running" = "0" ]; then log_info "等待PM2启动... (${wait_time}s/${max_wait}s)" + + # 如果等待时间超过30秒,检查是否有错误 + if [ $wait_time -gt 30 ] && [ $retry_count -lt $max_retries ]; then + log_warning "启动时间较长,检查PM2状态和日志..." + + # 检查PM2状态 + local pm2_status=$(su - jingrow -c " + export NVM_DIR=\"\$HOME/.nvm\" + [ -s \"\$NVM_DIR/nvm.sh\" ] && \. \"\$NVM_DIR/nvm.sh\" + pm2 list | grep -w '$SITE_NAME' || echo 'not_found' + ") + + if [ "$pm2_status" != "not_found" ]; then + log_info "PM2状态: $pm2_status" + fi + + # 检查PM2日志 + local pm2_logs=$(su - jingrow -c " + export NVM_DIR=\"\$HOME/.nvm\" + [ -s \"\$NVM_DIR/nvm.sh\" ] && \. \"\$NVM_DIR/nvm.sh\" + pm2 logs $SITE_NAME --lines 5 --nostream 2>/dev/null || echo 'no_logs' + ") + + if [ "$pm2_logs" != "no_logs" ]; then + log_info "PM2日志: $pm2_logs" + fi + + retry_count=$((retry_count + 1)) + fi fi done @@ -877,20 +886,34 @@ start_project_with_pm2() { return 1 fi - # 额外检查:验证项目是否真的在监听端口 - local project_port=$(get_or_assign_port "$SITE_NAME") - log_info "验证项目是否在端口 $project_port 上正常运行..." + log_success "PM2进程已启动,开始健康检查..." - # 等待一下让应用完全启动 + # 获取项目端口 + local project_port=$(get_or_assign_port "$SITE_NAME") + + # 等待应用完全启动 sleep 3 - # 检查端口是否被监听 + # 1. 检查端口是否被监听(使用多种方法) + log_info "检查端口 $project_port 是否被监听..." local port_check=0 local max_port_checks=10 local port_check_count=0 while [ $port_check_count -lt $max_port_checks ] && [ $port_check -eq 0 ]; do + # 方法1: 使用netstat port_check=$(netstat -tlnp 2>/dev/null | grep ":$project_port " | wc -l || echo "0") + + # 方法2: 如果netstat失败,使用ss + if [ $port_check -eq 0 ]; then + port_check=$(ss -tlnp 2>/dev/null | grep ":$project_port " | wc -l || echo "0") + fi + + # 方法3: 如果ss也失败,使用lsof + if [ $port_check -eq 0 ]; then + port_check=$(lsof -i :$project_port 2>/dev/null | wc -l || echo "0") + fi + if [ $port_check -eq 0 ]; then sleep 1 port_check_count=$((port_check_count + 1)) @@ -915,6 +938,71 @@ start_project_with_pm2() { return 1 fi + log_success "端口 $project_port 已被监听" + + # 2. HTTP健康检查(如果应用支持) + log_info "执行HTTP健康检查..." + local health_check_success=false + local health_check_attempts=0 + local max_health_checks=5 + + # 获取本地IP地址 + local local_ip=$(get_optimal_host_ip) + + while [ $health_check_attempts -lt $max_health_checks ] && [ "$health_check_success" = false ]; do + # 尝试HTTP健康检查 + local http_response=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 5 --max-time 10 "http://$local_ip:$project_port/" 2>/dev/null || echo "000") + + if [ "$http_response" = "200" ] || [ "$http_response" = "302" ] || [ "$http_response" = "404" ]; then + health_check_success=true + log_success "HTTP健康检查通过 (状态码: $http_response)" + else + health_check_attempts=$((health_check_attempts + 1)) + log_info "HTTP健康检查失败 (状态码: $http_response),重试 ${health_check_attempts}/${max_health_checks}" + sleep 2 + fi + done + + # 如果HTTP健康检查失败,但端口已监听,仍然认为启动成功 + if [ "$health_check_success" = false ]; then + log_warning "HTTP健康检查失败,但端口已监听,认为启动成功" + fi + + # 3. 检查PM2进程状态和资源使用情况 + log_info "检查PM2进程状态和资源使用情况..." + local pm2_status=$(su - jingrow -c " + export NVM_DIR=\"\$HOME/.nvm\" + [ -s \"\$NVM_DIR/nvm.sh\" ] && \. \"\$NVM_DIR/nvm.sh\" + pm2 list | grep -w '$SITE_NAME' || echo 'not_found' + ") + + if [ "$pm2_status" != "not_found" ]; then + log_success "PM2进程状态正常: $pm2_status" + else + log_error "PM2进程状态异常" + return 1 + fi + + # 4. 检查应用是否在正常运行(通过进程ID) + local app_pid=$(su - jingrow -c " + export NVM_DIR=\"\$HOME/.nvm\" + [ -s \"\$NVM_DIR/nvm.sh\" ] && \. \"\$NVM_DIR/nvm.sh\" + pm2 list | grep -w '$SITE_NAME' | awk '{print \$6}' || echo '0' + ") + + if [ "$app_pid" != "0" ] && [ -n "$app_pid" ]; then + # 检查进程是否真的在运行 + if kill -0 "$app_pid" 2>/dev/null; then + log_success "应用进程正在运行 (PID: $app_pid)" + else + log_error "应用进程不存在 (PID: $app_pid)" + return 1 + fi + else + log_error "无法获取应用进程ID" + return 1 + fi + log_success "项目已成功启动并监听端口 $project_port" # 保存PM2配置