第4步远端命令用双引号包裹,内部 $(curl ...) 与 $API_CODE 会被本地 bash 提前展开、嵌套双引号导致引号错乱,远端命令被污染后卡死。 - 移除 API 验证的 $(curl)/$API_CODE(历史一直未在远端执行过,属可选增强) - nginx 验证改为无嵌套引号的 (grep && echo || echo) 结构 - 保留去 sudo 化与 models 排除,全流程免密
117 lines
5.2 KiB
Bash
117 lines
5.2 KiB
Bash
#!/bin/bash
|
||
|
||
# === 配置项 ===
|
||
SERVER="dxc@172.16.0.198"
|
||
REMOTE_DIR="/opt/inventory-app"
|
||
TIMESTAMP=$(date +%Y%m%d_%H%M)
|
||
REMOTE_BACKUP_BASE="$REMOTE_DIR/data_copy"
|
||
REMOTE_BACKUP_DIR="$REMOTE_BACKUP_BASE/$TIMESTAMP"
|
||
|
||
echo "==================================================="
|
||
echo "🚀 开始自动化增量部署 (含自我修复与依赖瘦身)"
|
||
echo "==================================================="
|
||
|
||
# 1. 远端备份与环境急救
|
||
echo "[1/4] 正在服务器上备份旧代码 (全程免密)..."
|
||
ssh $SERVER "mkdir -p $REMOTE_BACKUP_DIR && \
|
||
cd $REMOTE_DIR && \
|
||
echo '>> 检查并修复缺失目录 (防止 tar 崩溃)...' && \
|
||
mkdir -p inventory-backend inventory-web models_prod && \
|
||
echo '>> 执行代码备份...' && \
|
||
# ★ 排除大目录/模型(与本地打包一致):inventory-backend/models 含 605MB onnx,不排除会导致 gzip 卡死
|
||
tar -czf $REMOTE_BACKUP_DIR/code_backup.tar.gz \
|
||
--exclude='inventory-backend/models' \
|
||
--exclude='inventory-backend/uploads' \
|
||
--exclude='inventory-backend/pgdata' \
|
||
--exclude='inventory-backend/pgdata_docker' \
|
||
inventory-backend inventory-web docker-compose.prod.yml && \
|
||
echo '>> 备份 SSL 证书...' && \
|
||
(tar -czf $REMOTE_BACKUP_DIR/ssl_backup.tar.gz ssl 2>/dev/null || echo '⚠️ ssl 目录不可读(属主 root)或不存在,跳过该备份') && \
|
||
echo '>> 检查 CLIP 模型文件...' && \
|
||
if [ ! -f models_prod/clip_vision.onnx ]; then \
|
||
echo '⚠️ 警告: models_prod/clip_vision.onnx 不存在!拍照识图功能将无法使用。'; \
|
||
echo '⚠️ 请手动上传: scp inventory-backend/models/clip_vision.onnx ${SERVER}:${REMOTE_DIR}/models_prod/'; \
|
||
else \
|
||
echo '✅ CLIP 模型文件已存在'; \
|
||
fi && \
|
||
echo '>> 执行清理:仅保留 data_copy 下最新的 2 个备份...' && \
|
||
cd $REMOTE_BACKUP_BASE && \
|
||
sh -c 'ls -dt */ 2>/dev/null | tail -n +3 | xargs -I {} rm -rf {} || true'"
|
||
|
||
if [ $? -ne 0 ]; then echo "❌ 服务器备份或清理失败,终止部署!"; exit 1; fi
|
||
|
||
# 2. 本地精准打包 (绝对屏蔽垃圾文件)
|
||
echo "[2/4] 正在本地打包新代码 (执行终极瘦身)..."
|
||
|
||
tar -czf deploy.tar.gz \
|
||
--exclude="*/node_modules" \
|
||
--exclude="*/venv" \
|
||
--exclude="*/.venv" \
|
||
--exclude="*/__pycache__" \
|
||
--exclude="*.pyc" \
|
||
--exclude="*/.git" \
|
||
--exclude="*/.idea" \
|
||
--exclude="*/.vscode" \
|
||
--exclude="inventory-backend/uploads" \
|
||
--exclude="inventory-backend/models" \
|
||
--exclude="inventory-backend/pgdata" \
|
||
--exclude="inventory-backend/pgdata_docker" \
|
||
--exclude="inventory-backend/test_*.py" \
|
||
--exclude="inventory-backend/fix_*.sql" \
|
||
--exclude="inventory-backend/*.sql" \
|
||
--exclude="inventory-backend/import_test_edge_cases.xlsx" \
|
||
--exclude="inventory-backend/import_edge_case_test.xlsx" \
|
||
--exclude="inventory-web/tsc-out.txt" \
|
||
--exclude="deploy.tar.gz" \
|
||
--exclude="data_copy" \
|
||
inventory-backend inventory-web docker-compose.prod.yml
|
||
|
||
# 检查压缩包大小是否正常 (如果超过 50MB 则发出警告)
|
||
FILESIZE=$(stat -c%s "deploy.tar.gz" 2>/dev/null || stat -f%z "deploy.tar.gz")
|
||
MB_SIZE=$((FILESIZE / 1024 / 1024))
|
||
echo ">> 打包完成,当前传输包大小: ${MB_SIZE} MB"
|
||
if [ "$MB_SIZE" -gt 50 ]; then
|
||
echo "⚠️ 警告:包体积仍大于 50MB,可能存在未排除的大文件,但继续执行..."
|
||
fi
|
||
|
||
# 3. 传输到生产环境的 /tmp 目录
|
||
echo "[3/4] 正在传输代码到服务器的临时目录..."
|
||
scp deploy.tar.gz $SERVER:/tmp/deploy.tar.gz
|
||
if [ $? -ne 0 ]; then
|
||
echo "❌ 传输失败!可能是网络中断,终止部署!"
|
||
rm -f deploy.tar.gz
|
||
exit 1
|
||
fi
|
||
|
||
# 4. 服务器执行替换与重启
|
||
# ★ 注意:ssh 远端命令用双引号包裹,内部绝不能出现 $(...) 或嵌套双引号,
|
||
# 否则会被本地 bash 提前展开/引号错乱(历史 bug:API_CODE 被本地 curl 展开导致远端命令污染)
|
||
echo "[4/4] 正在生产环境执行热更新 (全程免密)..."
|
||
ssh $SERVER "cd $REMOTE_DIR && \
|
||
echo '>> 移除历史旧目录...' && \
|
||
rm -rf inventory-backend_old inventory-web_old && \
|
||
echo '>> 备份当前目录为 old...' && \
|
||
(mv inventory-backend inventory-backend_old 2>/dev/null || true) && \
|
||
(mv inventory-web inventory-web_old 2>/dev/null || true) && \
|
||
echo '>> 部署新代码...' && \
|
||
mv /tmp/deploy.tar.gz . && \
|
||
tar -xzf deploy.tar.gz && \
|
||
echo '>> 重启 Docker 容器...' && \
|
||
docker compose -f docker-compose.prod.yml up -d --build backend frontend && \
|
||
echo '>> 等待服务就绪...' && \
|
||
sleep 5 && \
|
||
echo '>> 验证 nginx 代理配置...' && \
|
||
(docker exec inventory_ui_prod grep -q inventory_api_prod /etc/nginx/conf.d/default.conf && echo '✅ nginx 代理已指向 inventory_api_prod' || echo '⚠️ 警告: nginx 代理仍是 backend,可能出现 /api/ 404!请检查 nginx.conf') && \
|
||
rm deploy.tar.gz"
|
||
|
||
if [ $? -ne 0 ]; then
|
||
echo "❌ 远端启动失败,请检查 Docker 日志!"
|
||
else
|
||
echo "==================================================="
|
||
echo "✅ 部署完美完成!请刷新网页查看效果。"
|
||
echo "==================================================="
|
||
fi
|
||
|
||
# 扫尾清理本地文件
|
||
rm -f deploy.tar.gz
|