Files
mi-fitness-health/deploy/query-summary/update-health.sh
T

60 lines
3.2 KiB
Bash

#!/bin/sh
set -eu
umask 077
[ "$(id -u)" = 0 ] || { echo '请通过sudo在交互终端执行。'; exit 1; }
package=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd -P)
target=/vol2/1000/Soft/mi-fitness-health
cd "$package"
sha256sum -c manifest.sha256
python3 - "$target/compose.override.yml" "$package/expected-current.sha256" <<'PY'
import hashlib,sys
from pathlib import Path
assert hashlib.sha256(Path(sys.argv[1]).read_bytes()).hexdigest()==Path(sys.argv[2]).read_text().strip(), '现有覆盖配置已变化,停止避免覆盖'
PY
[ -d "$target/calendar" ] && [ ! -L "$target/calendar" ] || { echo '日历挂载目录缺失或异常,停止。'; exit 1; }
cd "$target"
compose() { docker compose --project-name mi-fitness-health --env-file .env -f compose.yml -f compose.override.yml "$@"; }
snapshot() { docker ps -aq --filter label=com.docker.compose.project=mi-fitness-health | sort | while read -r id; do docker inspect --format '{{index .Config.Labels "com.docker.compose.service"}} {{.Id}} {{.Image}}' "$id"; done | grep -v -E '^(backend|web) ' | sort; }
before=$(snapshot)
[ "$(docker inspect --format '{{.Config.Image}}' mi-fitness-health-worker-1)" = local/mi-fitness-nas:20261017-audit3 ] || { echo 'worker版本已变化,停止。'; exit 1; }
backup="$target/compose.override.pre-summary8-$(date +%Y%m%d-%H%M%S).yml"
cp compose.override.yml "$backup"
docker inspect --format '{{.Config.Image}} {{.Image}}' mi-fitness-health-backend-1 mi-fitness-health-web-1 > "$backup.images"
# 不清理旧镜像;覆盖配置和镜像ID均保留以便回退。
docker load -i "$package/health-summary8.tar"
read_image_id() {
python3 - "$1" <<'PY'
import re,sys
from pathlib import Path
value=Path(sys.argv[1]).read_bytes().rstrip(b'\r\n')
if re.fullmatch(rb'sha256:[0-9a-f]{64}',value) is None:
raise SystemExit('镜像身份文件格式无效')
sys.stdout.write(value.decode('ascii'))
PY
}
expected=$(read_image_id "$package/image-id.txt")
config_id=$(read_image_id "$package/image-config-id.txt")
actual=$(docker image inspect --format '{{.Id}}' local/mi-fitness-nas:20261017-summary8)
[ "$actual" = "$expected" ] || [ "$actual" = "$config_id" ] || { echo '导入镜像ID不符。'; exit 1; }
docker compose --project-name mi-fitness-health --env-file .env -f compose.yml -f "$package/compose.override.yml" config --quiet
complete=0
recover() {
if [ "$complete" = 0 ]; then
cp "$backup" "$target/compose.override.yml"
chown 1000:1001 "$target/compose.override.yml"
chmod 600 "$target/compose.override.yml"
compose up -d --no-deps --no-build --pull never backend web || true
echo "更新未通过,已恢复原配置并尝试回退backend/web。备份:$backup"
fi
}
trap recover EXIT
cp "$package/compose.override.yml" compose.override.yml
chown 1000:1001 compose.override.yml
chmod 600 compose.override.yml
compose up -d --no-deps --no-build --pull never --wait --wait-timeout 90 backend web
python3 "$package/check-ready.py" "$expected" "$config_id"
[ "$before" = "$(snapshot)" ] || { echo 'worker或其他健康服务发生变化,停止验收。'; exit 1; }
complete=1
trap - EXIT
printf '\nbackend/web更新完成;worker及其他健康服务未重建,原覆盖配置和旧镜像已保留。\n'