提交 733ef185 authored 作者: 陈泽健's avatar 陈泽健

```

fix(update): 修复程序更新脚本的安全覆盖问题

- 实现前端安全覆盖功能,只更新主文件不影响目标目录下的Bak*/bak*/new等原有目录
- 添加精准覆盖函数sync_overwrite_globs,支持按模式匹配更新特定文件
- 实现后端目录安全覆盖功能,保护目标目录中的备份文件不被误删
- 修改会议预定系统更新逻辑,前端使用安全覆盖,后端只更新.jar文件
- 修改运维集控和讯飞转录系统更新逻辑,使用相应安全覆盖函数
- 在PRD文档中添加重要提示说明只替换主服务文件
- 完成各系统前后端更新状态标记为已完成
```
上级 a7362ef7
......@@ -272,9 +272,45 @@ backup_db() {
backup_db "$DB_NAME"
# -------------------- 3.4 更新服务(传统平台) --------------------
# 安全移动:把 sourceDir 下内容覆盖到 targetDir
# 注意:按 PRD 是 mv * 覆盖;这里保持一致,但会做目录存在性/空目录校验
sync_overwrite_dir() {
# 精准覆盖:仅把 sourceDir 中匹配的文件/目录覆盖到 targetDir(不删除 targetDir 里其它内容)
# 用法:sync_overwrite_globs "/src" "/dst" "label" "glob1" "glob2" ...
sync_overwrite_globs() {
local sourceDir="$1"; shift
local targetDir="$1"; shift
local label="$1"; shift
if [[ ! -d "$sourceDir" ]]; then
log "ERROR: 更新源目录不存在:$sourceDir ($label)"
return 10
fi
mkdir -p "$targetDir"
log "UPDATE (globs) [$label]: $sourceDir -> $targetDir ; items=($*)"
local matched=0
local g p
shopt -s dotglob nullglob
for g in "$@"; do
for p in "$sourceDir"/$g; do
matched=1
# 覆盖同名项:先删再拷(避免 static 目录冲突)
rm -rf "$targetDir/$(basename "$p")"
cp -a "$p" "$targetDir/"
done
done
shopt -u dotglob nullglob
if [[ "$matched" -eq 0 ]]; then
log "ERROR: 未匹配到任何可更新内容:$sourceDir ($label)"
return 11
fi
}
# 前端安全覆盖(只更新主文件;不影响目标目录下 Bak*/bak*/new 等原有目录)
# 规则:
# - 覆盖:index.html、根目录 *.js
# - static:只同步 static/ 内部内容(不删除 static 目录本身)
sync_frontend_preserve() {
local sourceDir="$1"
local targetDir="$2"
local label="$3"
......@@ -283,7 +319,64 @@ sync_overwrite_dir() {
log "ERROR: 更新源目录不存在:$sourceDir ($label)"
return 10
fi
mkdir -p "$targetDir"
log "UPDATE (frontend-preserve) [$label]: $sourceDir -> $targetDir (preserve: Bak*/bak*/new)"
# 1) 覆盖 index.html(如果存在)
if [[ -f "$sourceDir/index.html" ]]; then
cp -a "$sourceDir/index.html" "$targetDir/index.html"
fi
# 2) 覆盖根目录 *.js(如果存在)
shopt -s nullglob
local f
for f in "$sourceDir"/*.js; do
cp -a "$f" "$targetDir/"
done
shopt -u nullglob
# 3) 同步 static(只同步内容,不 rm -rf static)
if [[ -d "$sourceDir/static" ]]; then
mkdir -p "$targetDir/static"
# 优先 rsync(不使用 --delete,避免误删目标里多余文件;并排除备份目录)
if command -v rsync >/dev/null 2>&1; then
rsync -a \
--exclude 'Bak*/' --exclude 'bak*/' --exclude 'new/' \
"${sourceDir%/}/static/" "${targetDir%/}/static/"
else
# 无 rsync:逐项覆盖复制 static 内部内容
shopt -s dotglob nullglob
for f in "$sourceDir/static/"*; do
# 源里如果也带 Bak/bak/new 目录,跳过
if [[ -d "$f" ]]; then
case "$(basename "$f")" in
Bak*|bak*|new) continue ;;
esac
fi
# 覆盖同名项:仅对 static 内的同名项处理,不涉及 targetDir 根目录的 Bak/new
rm -rf "$targetDir/static/$(basename "$f")"
cp -a "$f" "$targetDir/static/"
done
shopt -u dotglob nullglob
fi
fi
}
# 后端目录安全覆盖(适用于 cmdb / UbainsDevOps 这类“目录型后端”)
# - 覆盖 sourceDir 内的内容到 targetDir
# - 不清空 targetDir(不使用 rsync --delete)
# - 保护:不影响 targetDir 下 Bak*/bak*/new
sync_backend_dir_preserve() {
local sourceDir="$1"
local targetDir="$2"
local label="$3"
if [[ ! -d "$sourceDir" ]]; then
log "ERROR: 更新源目录不存在:$sourceDir ($label)"
return 10
fi
mkdir -p "$targetDir"
if [[ -z "$(ls -A "$sourceDir" 2>/dev/null || true)" ]]; then
......@@ -291,24 +384,28 @@ sync_overwrite_dir() {
return 11
fi
log "UPDATE [$label]: $sourceDir -> $targetDir"
log "UPDATE (backend-dir-preserve) [$label]: $sourceDir -> $targetDir (preserve: Bak*/bak*/new)"
# 1) 优先 rsync(能真正“覆盖 + 删除多余旧文件”,最接近“覆盖操作”
# 1) 优先 rsync(不 delete;排除 Bak/bak/new
if command -v rsync >/dev/null 2>&1; then
rsync -a --delete "${sourceDir%/}/" "${targetDir%/}/"
rsync -a \
--exclude 'Bak*/' --exclude 'bak*/' --exclude 'new/' \
"${sourceDir%/}/" "${targetDir%/}/"
return 0
fi
# 2) 无 rsync:退化方案
# 如果目标里存在同名目录且非空,cp -a 是可覆盖拷贝的,不需要删除目录;
# 但为了避免你遇到的 static 冲突残留问题,这里先删除常见冲突目录(仅删除目标的同名项)
# 注意:此处只会删除与源同名的一级条目,不会清空整个 targetDir。
local item base
# 2) 无 rsync:逐项覆盖复制(禁止删除 Bak/bak/new)
local item name
shopt -s dotglob nullglob
for item in "$sourceDir"/*; do
base="$(basename "$item")"
if [[ -e "$targetDir/$base" ]]; then
rm -rf "$targetDir/$base"
name="$(basename "$item")"
case "$name" in
Bak*|bak*|new) continue ;;
esac
# 仅删除将要覆盖的同名项(且上面已排除 Bak/bak/new)
if [[ -e "$targetDir/$name" ]]; then
rm -rf "$targetDir/$name"
fi
cp -a "$item" "$targetDir/"
done
......@@ -319,8 +416,6 @@ sync_overwrite_dir() {
do_update_traditional() {
case "$SYSTEM" in
"会议预定系统")
# workdir 里解压后的目录名按你 PRD 3.4 写的是 /home/Update/ubains-web-2.0 等
# 如果你的 zip 解压出来有一层 update/,请把 WORKDIR 调整为 /home/Update/update
local src_front1="${WORKDIR%/}/ubains-web-2.0"
local src_front2="${WORKDIR%/}/ubains-web-admin"
local src_back1="${WORKDIR%/}/api-java-meeting2.0"
......@@ -332,13 +427,14 @@ do_update_traditional() {
local dst_back2="/var/www/java/external-meeting-api"
if [[ "$UPDATE_TYPE" == "前端更新" || "$UPDATE_TYPE" == "全量更新" ]]; then
sync_overwrite_dir "$src_front1" "$dst_front1" "会议预定-前台前端"
sync_overwrite_dir "$src_front2" "$dst_front2" "会议预定-后台前端"
sync_frontend_preserve "$src_front1" "$dst_front1" "会议预定-前台前端"
sync_frontend_preserve "$src_front2" "$dst_front2" "会议预定-后台前端"
fi
if [[ "$UPDATE_TYPE" == "后端更新" || "$UPDATE_TYPE" == "全量更新" ]]; then
sync_overwrite_dir "$src_back1" "$dst_back1" "会议预定-对内后端"
sync_overwrite_dir "$src_back2" "$dst_back2" "会议预定-对外后端"
# 只更新 *.jar(严格只匹配以 .jar 结尾,避免 jar2/jarbak/jarBak)
sync_overwrite_globs "$src_back1" "$dst_back1" "会议预定-对内后端" "*.jar"
sync_overwrite_globs "$src_back2" "$dst_back2" "会议预定-对外后端" "*.jar"
fi
;;
......@@ -351,18 +447,16 @@ do_update_traditional() {
local dst_back_root="/var/www/html"
if [[ "$UPDATE_TYPE" == "前端更新" || "$UPDATE_TYPE" == "全量更新" ]]; then
sync_overwrite_dir "$src_front" "$dst_front" "运维集控-前端"
sync_frontend_preserve "$src_front" "$dst_front" "运维集控-前端"
fi
if [[ "$UPDATE_TYPE" == "后端更新" || "$UPDATE_TYPE" == "全量更新" ]]; then
# PRD 写的是 mv * /var/www/html/(覆盖操作),这里按子目录覆盖到 /var/www/html/cmdb 和 /var/www/html/UbainsDevOps
sync_overwrite_dir "$src_back_cmdb" "${dst_back_root%/}/cmdb" "运维集控-后端-cmdb"
sync_overwrite_dir "$src_back_devops" "${dst_back_root%/}/UbainsDevOps" "运维集控-后端-UbainsDevOps"
sync_backend_dir_preserve "$src_back_cmdb" "${dst_back_root%/}/cmdb" "运维集控-后端-cmdb"
sync_backend_dir_preserve "$src_back_devops" "${dst_back_root%/}/UbainsDevOps" "运维集控-后端-UbainsDevOps"
fi
;;
"讯飞转录系统")
# 按 4.1 映射表:web-vue-voice + UbainsDevOps
local src_front="${WORKDIR%/}/web-vue-voice"
local src_back_devops="${WORKDIR%/}/UbainsDevOps"
......@@ -370,11 +464,11 @@ do_update_traditional() {
local dst_back_root="/var/www/html"
if [[ "$UPDATE_TYPE" == "前端更新" || "$UPDATE_TYPE" == "全量更新" ]]; then
sync_overwrite_dir "$src_front" "$dst_front" "讯飞转录-前端"
sync_frontend_preserve "$src_front" "$dst_front" "讯飞转录-前端"
fi
if [[ "$UPDATE_TYPE" == "后端更新" || "$UPDATE_TYPE" == "全量更新" ]]; then
sync_overwrite_dir "$src_back_devops" "${dst_back_root%/}/UbainsDevOps" "讯飞转录-后端-UbainsDevOps"
sync_backend_dir_preserve "$src_back_devops" "${dst_back_root%/}/UbainsDevOps" "讯飞转录-后端-UbainsDevOps"
fi
;;
......
......@@ -42,18 +42,19 @@
#### 3.4.更新服务(program_update.sh)
- 根据系统类型和更新类型选择对应的更新脚本执行更新操作
- 前端更新操作:
-- 注意:只替换主服务文件,不要影响原有目录下其他文件!!!
-- 传统平台
1.会议预定系统:
- 前台前端:
- 前台前端:✅ 已完成
cd /home/Update/ubains-web-2.0
mv * /var/www/java/ubains-web-2.0/(覆盖操作)
- 后台前端:
- 后台前端:✅ 已完成
cd /home/Update/ubains-web-admin
mv * /var/www/java/ubains-web-admin/(覆盖操作)
- 对内后端:
- 对内后端:✅ 已完成
cd /home/Update/api-java-meeting2.0
mv * /var/www/java/api-java-meeting2.0/(覆盖操作)
- 对外后端:
- 对外后端:✅ 已完成
cd /home/Update/external-meeting-api
mv * /var/www/java/external-meeting-api/(覆盖操作)
2.运维集控系统:
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论