pipeline { agent any parameters { gitParameter( branchFilter: 'origin/(.*)', defaultValue: 'zhangze-init', name: 'GIT_BRANCH', type: 'PT_BRANCH_TAG', selectedValue: 'DEFAULT', sortMode: 'NONE', description: '选择代码分支: ', quickFilterEnabled: true, tagFilter: '*', listSize: "5" ) } environment { REMOTE_HOST = '49.51.41.243' REMOTE_PROJECT_PATH = '/data/webapps/lessie-email' } stages { stage('Checkout 代码') { steps { git branch: "${params.GIT_BRANCH}", credentialsId: 'fly_gitlab_auth', url: 'http://172.24.16.20/python/lessie-email.git' } } stage('同步文件') { steps { sh """ rsync -avz --exclude '.venv' --exclude '.git' ${WORKSPACE}/ ${REMOTE_HOST}:${REMOTE_PROJECT_PATH}/ """ } } stage('安装 & 启动服务') { steps { sh """ ssh ${REMOTE_HOST} ' cd ${REMOTE_PROJECT_PATH} # 1. 同步依赖 uv sync # 2. 先尝试 delete 再 start pm2 delete "lessie-email" || true # 3. 使用 PM2 启动/重启服务,正确的 PM2 语法: pm2 start <程序> --name <名字> -- <程序参数> # --name: 任务名称 # -o / -e: 将标准输出和错误输出打到同一个固定文件,方便 Filebeat 采集 # --restart-delay: 崩溃后等 5 秒再重启,防止死循环刷屏 ENV=production pm2 start uv --name "lessie-email" \ -o "/data/webapps/lessie-email/logs/lessie_email.log" \ -e "/data/webapps/lessie-email/logs/lessie_email.log" \ --restart-delay 5000 \ -- run uvicorn app.main:app --host 0.0.0.0 --port 8031 --log-config logging_config.json # 3. 保存当前列表,确保服务器重启后能自动恢复这些进程 pm2 save ' """ } } stage('检查服务') { steps { script { def checkResult = sh returnStatus: true, script: """ ssh ${REMOTE_HOST} ' set -e LOG_LATEST="${REMOTE_PROJECT_PATH}/logs/lessie_email.log" # 1. 检查端口是否监听(用 ss 原生过滤,精准可靠) echo "【检查 1/3】检测端口 8031 是否监听..." if ! ss -tnl \'sport = :8031\' >/dev/null 2>&1; then echo "端口 8031 未监听!" # 显示当前监听状态供排查 echo "当前监听情况:" ss -tnl | grep -E ":(8031|LISTEN)" exit 1 fi echo "端口 8031 正在监听" # 2. 检查进程是否存在 echo "【检查 2/3】检测 uvicorn 进程是否存活..." if ! pgrep -f "uvicorn.*app.main:app" >/dev/null; then echo "未找到 uvicorn 进程!" exit 1 fi echo "uvicorn 进程存在" # 3. 显示最新日志(最后 20 行) echo "【检查 3/3】显示启动日志(最后 20 行)..." echo "────────────────────────────" if [ -f "\$LOG_LATEST" ]; then tail -n 20 "\$LOG_LATEST" else echo "日志文件不存在:\$LOG_LATEST" exit 1 fi echo "────────────────────────────" echo "服务启动成功!" ' """ if (checkResult != 0) { error "服务启动检查失败!请查看上述日志排查问题。" } } } } } post { success { echo '部署成功' } failure { echo '部署失败,请检查日志' } } }