741 lines
22 KiB
Bash
741 lines
22 KiB
Bash
#!/bin/bash
|
||
# ========================================
|
||
# 智能矿山标签监测系统 - 一键升级脚本
|
||
# ========================================
|
||
# 使用方法:
|
||
# bash upgrade.sh # 升级到最新master分支
|
||
# bash upgrade.sh v1.2.0 # 升级到指定标签版本
|
||
# bash upgrade.sh abc123def # 升级到指定commit
|
||
# ========================================
|
||
|
||
set -e
|
||
|
||
# 颜色定义
|
||
RED='\033[0;31m'
|
||
GREEN='\033[0;32m'
|
||
YELLOW='\033[1;33m'
|
||
BLUE='\033[0;34m'
|
||
NC='\033[0m' # No Color
|
||
|
||
# 打印带颜色的消息
|
||
info() {
|
||
echo -e "${BLUE}[INFO]${NC} $1"
|
||
}
|
||
|
||
success() {
|
||
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
||
}
|
||
|
||
warn() {
|
||
echo -e "${YELLOW}[WARN]${NC} $1"
|
||
}
|
||
|
||
error() {
|
||
echo -e "${RED}[ERROR]${NC} $1"
|
||
}
|
||
|
||
# ========================================
|
||
# 配置区域
|
||
# ========================================
|
||
|
||
# Git仓库地址(根据实际情况修改)
|
||
GIT_REPO="http://10.224.35.147:3000/redline/program.git"
|
||
|
||
# 服务名称(systemd)
|
||
SERVICE_NAME="mining-system"
|
||
|
||
# 需要保留的文件(不会被git覆盖)
|
||
PRESERVE_FILES=(
|
||
"config.py"
|
||
"mining_data.db"
|
||
".env"
|
||
)
|
||
|
||
# 需要保留的目录
|
||
PRESERVE_DIRS=(
|
||
"outputs"
|
||
"logs"
|
||
)
|
||
|
||
# ========================================
|
||
# 函数定义
|
||
# ========================================
|
||
|
||
# 获取项目根目录
|
||
get_project_dir() {
|
||
echo "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
}
|
||
|
||
# 检查是否安装了git
|
||
check_git() {
|
||
if ! command -v git &> /dev/null; then
|
||
error "Git未安装,请先安装: sudo apt-get install -y git"
|
||
exit 1
|
||
fi
|
||
}
|
||
|
||
# 检查当前是否在git仓库中
|
||
check_git_repo() {
|
||
if ! git rev-parse --is-inside-work-tree &> /dev/null; then
|
||
error "当前目录不是Git仓库"
|
||
echo ""
|
||
echo "如果需要首次使用Git升级方式,请先初始化:"
|
||
echo " cd $PROJECT_DIR"
|
||
echo " git init"
|
||
echo " git remote add origin $GIT_REPO"
|
||
echo " git pull origin master"
|
||
exit 1
|
||
fi
|
||
}
|
||
|
||
# 获取当前版本信息
|
||
get_current_version() {
|
||
if git rev-parse --is-inside-work-tree &> /dev/null; then
|
||
local commit=$(git rev-parse --short HEAD 2>/dev/null || echo "unknown")
|
||
local branch=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "unknown")
|
||
local dirty=""
|
||
if ! git diff --quiet &>/dev/null; then
|
||
dirty=" (有未提交的修改)"
|
||
fi
|
||
echo "分支: $branch, 提交: $commit$dirty"
|
||
else
|
||
echo "未知(非Git仓库)"
|
||
fi
|
||
}
|
||
|
||
# 备份当前系统
|
||
backup() {
|
||
local DATE=$(date +%Y%m%d_%H%M%S)
|
||
local BACKUP_DIR="${PROJECT_DIR}/backups"
|
||
local BACKUP_FILE="${BACKUP_DIR}/backup-${DATE}.tar.gz"
|
||
|
||
info "开始备份当前系统..."
|
||
|
||
# 创建备份目录
|
||
mkdir -p "$BACKUP_DIR"
|
||
|
||
# 收集需要备份的文件
|
||
local FILES_TO_BACKUP=()
|
||
for file in "${PRESERVE_FILES[@]}"; do
|
||
if [ -f "${PROJECT_DIR}/${file}" ]; then
|
||
FILES_TO_BACKUP+=("$file")
|
||
fi
|
||
done
|
||
|
||
# 备份配置文件和环境变量
|
||
{
|
||
echo "# 升级备份 - $DATE"
|
||
echo "# 项目目录: $PROJECT_DIR"
|
||
echo ""
|
||
|
||
for file in "${FILES_TO_BACKUP[@]}"; do
|
||
echo "===== $file ====="
|
||
cat "${PROJECT_DIR}/${file}" 2>/dev/null || echo "(文件不存在)"
|
||
echo ""
|
||
done
|
||
|
||
# 备份requirements.txt用于对比
|
||
echo "===== requirements.txt ====="
|
||
cat "${PROJECT_DIR}/requirements.txt" 2>/dev/null || echo "(文件不存在)"
|
||
echo ""
|
||
|
||
# 备份当前git信息
|
||
echo "===== git info ====="
|
||
echo "branch: $(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo 'N/A')"
|
||
echo "commit: $(git rev-parse HEAD 2>/dev/null || echo 'N/A')"
|
||
echo ""
|
||
} > "${BACKUP_DIR}/config-backup-${DATE}.txt"
|
||
|
||
# 复制需要保留的文件到备份目录
|
||
for file in "${PRESERVE_FILES[@]}"; do
|
||
if [ -f "${PROJECT_DIR}/${file}" ]; then
|
||
cp "${PROJECT_DIR}/${file}" "${BACKUP_DIR}/${file}.${DATE}.bak"
|
||
fi
|
||
done
|
||
|
||
# 备份数据库(单独备份,确保完整)
|
||
if [ -f "${PROJECT_DIR}/mining_data.db" ]; then
|
||
cp "${PROJECT_DIR}/mining_data.db" "${BACKUP_DIR}/mining_data.db.${DATE}.bak"
|
||
info "数据库已备份: mining_data.db.${DATE}.bak"
|
||
fi
|
||
|
||
# 保留当前outputs目录
|
||
if [ -d "${PROJECT_DIR}/outputs" ]; then
|
||
tar -czf "${BACKUP_DIR}/outputs-${DATE}.tar.gz" -C "$PROJECT_DIR" outputs 2>/dev/null || true
|
||
fi
|
||
|
||
# 保留最近的10个备份,清理旧备份
|
||
cd "$BACKUP_DIR"
|
||
ls -t *.tar.gz 2>/dev/null | tail -n +11 | xargs -r rm -f
|
||
ls -t *.txt 2>/dev/null | tail -n +11 | xargs -r rm -f
|
||
ls -t *.bak 2>/dev/null | tail -n +20 | xargs -r rm -f
|
||
cd "$PROJECT_DIR"
|
||
|
||
success "备份完成: ${BACKUP_DIR}/"
|
||
echo ""
|
||
}
|
||
|
||
# 停止服务
|
||
stop_service() {
|
||
info "停止服务..."
|
||
|
||
# 尝试systemd方式
|
||
if systemctl list-unit-files | grep -q "${SERVICE_NAME}.service" 2>/dev/null; then
|
||
sudo systemctl stop "$SERVICE_NAME" 2>/dev/null && \
|
||
success "已通过systemd停止服务" && return
|
||
fi
|
||
|
||
# 尝试kill端口进程
|
||
if command -v lsof &> /dev/null; then
|
||
local PIDS=$(lsof -ti:5000 2>/dev/null || true)
|
||
if [ -n "$PIDS" ]; then
|
||
echo "$PIDS" | xargs kill -TERM 2>/dev/null || true
|
||
sleep 2
|
||
echo "$PIDS" | xargs kill -KILL 2>/dev/null || true
|
||
success "已停止端口5000上的进程"
|
||
return
|
||
fi
|
||
fi
|
||
|
||
# 尝试ps方式
|
||
local PIDS=$(ps aux | grep '[p]ython.*app.py' | awk '{print $2}' || true)
|
||
if [ -n "$PIDS" ]; then
|
||
echo "$PIDS" | xargs kill -TERM 2>/dev/null || true
|
||
sleep 2
|
||
echo "$PIDS" | xargs kill -KILL 2>/dev/null || true
|
||
success "已停止Python应用进程"
|
||
return
|
||
fi
|
||
|
||
warn "未发现运行中的服务进程"
|
||
echo ""
|
||
}
|
||
|
||
# 保存需要保留的文件
|
||
save_preserved_files() {
|
||
info "保存需要保留的文件..."
|
||
|
||
local STAGING_DIR="${PROJECT_DIR}/.upgrade_staging"
|
||
mkdir -p "$STAGING_DIR"
|
||
|
||
# 保存文件
|
||
for file in "${PRESERVE_FILES[@]}"; do
|
||
if [ -f "${PROJECT_DIR}/${file}" ]; then
|
||
cp -f "${PROJECT_DIR}/${file}" "${STAGING_DIR}/${file}"
|
||
info " 已保存: $file"
|
||
fi
|
||
done
|
||
|
||
# 保存目录内容
|
||
for dir in "${PRESERVE_DIRS[@]}"; do
|
||
if [ -d "${PROJECT_DIR}/${dir}" ]; then
|
||
# 先删除staging中的旧目录(如果有),再复制
|
||
rm -rf "${STAGING_DIR}/${dir}" 2>/dev/null || true
|
||
cp -r "${PROJECT_DIR}/${dir}" "${STAGING_DIR}/${dir}"
|
||
info " 已保存目录: $dir/"
|
||
fi
|
||
done
|
||
|
||
echo ""
|
||
}
|
||
|
||
# 从Git拉取最新代码
|
||
pull_latest_code() {
|
||
local TARGET="${1:-master}"
|
||
|
||
info "从Git拉取最新代码 (目标: $TARGET)..."
|
||
|
||
# 检查远程仓库
|
||
if ! git remote -v | grep -q "origin" 2>/dev/null; then
|
||
error "未找到Git远程仓库 'origin'"
|
||
echo "添加远程仓库: git remote add origin $GIT_REPO"
|
||
git remote add origin "$GIT_REPO" 2>/dev/null || true
|
||
fi
|
||
|
||
# 如果远程地址不正确,更新它
|
||
local CURRENT_REMOTE=$(git remote get-url origin 2>/dev/null || echo "")
|
||
if [ "$CURRENT_REMOTE" != "$GIT_REPO" ] && [ -n "$CURRENT_REMOTE" ]; then
|
||
warn "远程地址已更新: $CURRENT_REMOTE -> $GIT_REPO"
|
||
git remote set-url origin "$GIT_REPO"
|
||
fi
|
||
|
||
# 拉取最新代码
|
||
# 先stash本地修改(已保存到staging,所以可以强制)
|
||
git stash --include-untracked 2>/dev/null || true
|
||
|
||
# 根据目标拉取
|
||
if [[ "$TARGET" == *"."* ]] || [[ "$TARGET" == v* ]]; then
|
||
# 可能是tag
|
||
git fetch origin --tags 2>&1 | grep -v "already up" || true
|
||
if git tag -l | grep -q "^${TARGET}\$"; then
|
||
info "切换到标签: $TARGET"
|
||
git checkout tags/"$TARGET" -- . 2>&1 || git pull origin "$TARGET" 2>&1 || true
|
||
else
|
||
info "拉取master分支最新代码"
|
||
git checkout master 2>&1 || true
|
||
git pull origin master 2>&1 || true
|
||
fi
|
||
elif [[ "$TARGET" =~ ^[0-9a-f]{7,40}$ ]]; then
|
||
# 可能是commit hash
|
||
info "切换到commit: $TARGET"
|
||
git fetch origin 2>&1 | grep -v "already up" || true
|
||
git checkout "$TARGET" -- . 2>&1 || git pull origin master 2>&1 || true
|
||
else
|
||
# 分支名
|
||
info "拉取分支: $TARGET"
|
||
git checkout "$TARGET" 2>&1 || git checkout master 2>&1 || true
|
||
git pull origin "$TARGET" 2>&1 || git pull origin master 2>&1 || true
|
||
fi
|
||
|
||
success "代码拉取完成"
|
||
echo ""
|
||
}
|
||
|
||
# 恢复保留的文件
|
||
restore_preserved_files() {
|
||
info "恢复保留的文件..."
|
||
|
||
local STAGING_DIR="${PROJECT_DIR}/.upgrade_staging"
|
||
|
||
if [ ! -d "$STAGING_DIR" ]; then
|
||
warn "暂存目录不存在,跳过恢复"
|
||
return
|
||
fi
|
||
|
||
# 恢复文件
|
||
for file in "${PRESERVE_FILES[@]}"; do
|
||
if [ -f "${STAGING_DIR}/${file}" ]; then
|
||
cp -f "${STAGING_DIR}/${file}" "${PROJECT_DIR}/${file}"
|
||
info " 已恢复: $file"
|
||
fi
|
||
done
|
||
|
||
# 恢复目录内容(合并方式)
|
||
for dir in "${PRESERVE_DIRS[@]}"; do
|
||
if [ -d "${STAGING_DIR}/${dir}" ]; then
|
||
mkdir -p "${PROJECT_DIR}/${dir}"
|
||
rsync -a "${STAGING_DIR}/${dir}/" "${PROJECT_DIR}/${dir}/" 2>/dev/null || \
|
||
cp -r "${STAGING_DIR}/${dir}"/* "${PROJECT_DIR}/${dir}/" 2>/dev/null || true
|
||
info " 已恢复目录: $dir/"
|
||
fi
|
||
done
|
||
|
||
# 清理暂存目录
|
||
rm -rf "$STAGING_DIR"
|
||
|
||
echo ""
|
||
}
|
||
|
||
# 更新Python依赖
|
||
update_dependencies() {
|
||
info "检查并更新Python依赖..."
|
||
|
||
local VENV_DIR="${PROJECT_DIR}/venv"
|
||
|
||
# 检查虚拟环境是否存在
|
||
if [ ! -d "$VENV_DIR" ]; then
|
||
info "创建Python虚拟环境..."
|
||
python3 -m venv "$VENV_DIR"
|
||
fi
|
||
|
||
# 激活虚拟环境
|
||
source "${VENV_DIR}/bin/activate"
|
||
|
||
# 升级pip
|
||
pip install --upgrade pip -q 2>&1 | grep -v "already satisfied" || true
|
||
|
||
# 检查requirements.txt是否有变化
|
||
if [ -f "${PROJECT_DIR}/requirements.txt" ]; then
|
||
pip install -r "${PROJECT_DIR}/requirements.txt" 2>&1 | grep -v "already satisfied" || true
|
||
success "依赖更新完成"
|
||
else
|
||
error "requirements.txt 不存在!"
|
||
exit 1
|
||
fi
|
||
|
||
# 退出虚拟环境(不影响后续命令)
|
||
deactivate 2>/dev/null || true
|
||
|
||
echo ""
|
||
}
|
||
|
||
# 运行数据库迁移(如有需要)
|
||
run_migrations() {
|
||
info "检查数据库迁移..."
|
||
|
||
# 如果有migration目录,执行迁移
|
||
if [ -d "${PROJECT_DIR}/migrations" ]; then
|
||
info "发现迁移目录,执行迁移..."
|
||
source "${PROJECT_DIR}/venv/bin/activate"
|
||
cd "${PROJECT_DIR}/migrations"
|
||
python3 migrate.py 2>/dev/null || warn "迁移脚本执行失败或无需迁移"
|
||
cd "$PROJECT_DIR"
|
||
deactivate 2>/dev/null || true
|
||
else
|
||
success "无需数据库迁移"
|
||
fi
|
||
|
||
echo ""
|
||
}
|
||
|
||
# 重启服务
|
||
restart_service() {
|
||
info "重启服务..."
|
||
|
||
# 尝试systemd方式
|
||
if systemctl list-unit-files | grep -q "${SERVICE_NAME}.service" 2>/dev/null; then
|
||
sudo systemctl daemon-reload
|
||
sudo systemctl restart "$SERVICE_NAME"
|
||
sleep 2
|
||
if sudo systemctl is-active --quiet "$SERVICE_NAME"; then
|
||
success "已通过systemd重启服务"
|
||
else
|
||
error "systemd服务启动失败,请查看日志: sudo journalctl -u $SERVICE_NAME -f"
|
||
fi
|
||
return
|
||
fi
|
||
|
||
# 如果没有systemd服务,提示手动启动
|
||
warn "未检测到systemd服务,请手动启动:"
|
||
echo ""
|
||
echo " cd $PROJECT_DIR"
|
||
echo " source venv/bin/activate"
|
||
echo " python3 app.py"
|
||
echo ""
|
||
echo "或使用启动脚本:"
|
||
echo " bash $PROJECT_DIR/start.sh"
|
||
echo ""
|
||
}
|
||
|
||
# 验证升级结果
|
||
verify_upgrade() {
|
||
info "验证升级结果..."
|
||
|
||
sleep 3
|
||
|
||
# 检查API是否可访问
|
||
if command -v curl &> /dev/null; then
|
||
local RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:5000/ 2>/dev/null || echo "000")
|
||
if [ "$RESPONSE" = "200" ] || [ "$RESPONSE" = "302" ]; then
|
||
success "API响应正常 (HTTP $RESPONSE)"
|
||
else
|
||
warn "API响应异常 (HTTP $RESPONSE),请检查服务状态"
|
||
fi
|
||
|
||
# 检查stats API
|
||
local STATS_RESPONSE=$(curl -s http://localhost:5000/api/stats/all 2>/dev/null || echo "")
|
||
if echo "$STATS_RESPONSE" | python3 -m json.tool &>/dev/null; then
|
||
success "统计API正常"
|
||
fi
|
||
fi
|
||
|
||
# 显示新版本信息
|
||
echo ""
|
||
info "新版本信息:"
|
||
if git rev-parse --is-inside-work-tree &> /dev/null; then
|
||
echo " 分支: $(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo 'unknown')"
|
||
echo " 提交: $(git rev-parse --short HEAD 2>/dev/null || echo 'unknown')"
|
||
echo " 时间: $(git log -1 --format='%ci' 2>/dev/null || echo 'unknown')"
|
||
echo " 信息: $(git log -1 --format='%s' 2>/dev/null || echo 'unknown')"
|
||
fi
|
||
|
||
echo ""
|
||
}
|
||
|
||
# 显示回滚说明
|
||
show_rollback_info() {
|
||
local BACKUP_DIR="${PROJECT_DIR}/backups"
|
||
|
||
echo "======================================"
|
||
echo " 回滚方案(如需)"
|
||
echo "======================================"
|
||
echo ""
|
||
echo "如果升级后发现问题,可以执行回滚:"
|
||
echo ""
|
||
echo " # 方式1: 使用升级脚本回滚到上一个备份"
|
||
echo " bash $PROJECT_DIR/upgrade.sh rollback"
|
||
echo ""
|
||
echo " # 方式2: 手动回滚"
|
||
echo " cd $PROJECT_DIR/backups"
|
||
echo " ls -lt # 找到最新的备份"
|
||
echo " # 恢复配置文件"
|
||
echo " cp config.py.YYYYMMDD_HHMMSS.bak $PROJECT_DIR/"
|
||
echo " # 恢复数据库"
|
||
echo " cp mining_data.db.YYYYMMDD_HHMMSS.bak $PROJECT_DIR/"
|
||
echo " # 回滚git代码"
|
||
echo " git checkout <旧版本commit>"
|
||
echo " # 重启服务"
|
||
echo " sudo systemctl restart $SERVICE_NAME"
|
||
echo ""
|
||
}
|
||
|
||
# 回滚到上一个备份
|
||
rollback() {
|
||
local BACKUP_DIR="${PROJECT_DIR}/backups"
|
||
|
||
if [ ! -d "$BACKUP_DIR" ]; then
|
||
error "备份目录不存在,无法回滚"
|
||
exit 1
|
||
fi
|
||
|
||
# 找到最新的配置备份
|
||
local LATEST_CONFIG=$(ls -t "${BACKUP_DIR}"/config-backup-*.txt 2>/dev/null | head -1)
|
||
if [ -z "$LATEST_CONFIG" ]; then
|
||
error "未找到配置备份文件"
|
||
exit 1
|
||
fi
|
||
|
||
info "找到备份: $LATEST_CONFIG"
|
||
|
||
# 询问确认
|
||
echo ""
|
||
echo "备份内容预览:"
|
||
head -5 "$LATEST_CONFIG"
|
||
echo "..."
|
||
echo ""
|
||
read -p "确认回滚到此备份? (y/N) " -n 1 -r
|
||
echo
|
||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||
info "回滚已取消"
|
||
exit 0
|
||
fi
|
||
|
||
# 停止服务
|
||
stop_service
|
||
|
||
# 提取备份中的日期
|
||
local BACKUP_DATE=$(basename "$LATEST_CONFIG" | sed 's/config-backup-//;s/.txt//')
|
||
|
||
# 恢复配置文件
|
||
for file in "${PRESERVE_FILES[@]}"; do
|
||
local BAK_FILE="${BACKUP_DIR}/${file}.${BACKUP_DATE}.bak"
|
||
if [ -f "$BAK_FILE" ]; then
|
||
cp -f "$BAK_FILE" "${PROJECT_DIR}/${file}"
|
||
info "已恢复: $file"
|
||
fi
|
||
done
|
||
|
||
# 恢复outputs目录
|
||
local OUTPUTS_BACKUP=$(ls -t "${BACKUP_DIR}"/outputs-*.tar.gz 2>/dev/null | head -1)
|
||
if [ -n "$OUTPUTS_BACKUP" ]; then
|
||
tar -xzf "$OUTPUTS_BACKUP" -C "$PROJECT_DIR" 2>/dev/null && \
|
||
info "已恢复: outputs/"
|
||
fi
|
||
|
||
# 回滚git(尝试回到上一个commit)
|
||
if git rev-parse --is-inside-work-tree &> /dev/null; then
|
||
# 从备份文件中获取之前的commit
|
||
local OLD_COMMIT=$(grep "^commit:" "$LATEST_CONFIG" | awk '{print $2}' | head -1)
|
||
if [ -n "$OLD_COMMIT" ] && [ "$OLD_COMMIT" != "N/A" ]; then
|
||
info "回滚Git到commit: $OLD_COMMIT"
|
||
git checkout "$OLD_COMMIT" 2>/dev/null || \
|
||
git reset --hard "$OLD_COMMIT" 2>/dev/null || \
|
||
warn "Git回滚失败,请手动操作"
|
||
fi
|
||
fi
|
||
|
||
# 更新依赖
|
||
update_dependencies
|
||
|
||
# 重启服务
|
||
restart_service
|
||
|
||
success "回滚完成"
|
||
}
|
||
|
||
# 显示帮助
|
||
show_help() {
|
||
echo "======================================"
|
||
echo " 智能矿山标签监测系统 - 升级脚本"
|
||
echo "======================================"
|
||
echo ""
|
||
echo "使用方法:"
|
||
echo " bash upgrade.sh [选项]"
|
||
echo ""
|
||
echo "选项:"
|
||
echo " (无参数) 升级到master分支最新版本"
|
||
echo " <version> 升级到指定版本(tag/commit/分支)"
|
||
echo " rollback 回滚到上一个备份"
|
||
echo " status 显示当前版本状态"
|
||
echo " backup 仅执行备份"
|
||
echo " help 显示此帮助信息"
|
||
echo ""
|
||
echo "示例:"
|
||
echo " bash upgrade.sh # 升级到最新"
|
||
echo " bash upgrade.sh v1.2.0 # 升级到v1.2.0标签"
|
||
echo " bash upgrade.sh abc123def # 升级到指定commit"
|
||
echo " bash upgrade.sh develop # 切换到develop分支"
|
||
echo " bash upgrade.sh rollback # 回滚"
|
||
echo " bash upgrade.sh status # 查看版本状态"
|
||
echo ""
|
||
echo "配置:"
|
||
echo " Git仓库: $GIT_REPO"
|
||
echo " 服务名: $SERVICE_NAME"
|
||
echo ""
|
||
echo "保留文件(升级时不覆盖):"
|
||
for file in "${PRESERVE_FILES[@]}"; do
|
||
echo " - $file"
|
||
done
|
||
echo ""
|
||
echo "保留目录:"
|
||
for dir in "${PRESERVE_DIRS[@]}"; do
|
||
echo " - $dir/"
|
||
done
|
||
echo ""
|
||
}
|
||
|
||
# 显示当前状态
|
||
show_status() {
|
||
echo "======================================"
|
||
echo " 当前版本状态"
|
||
echo "======================================"
|
||
echo ""
|
||
echo "项目目录: $PROJECT_DIR"
|
||
echo ""
|
||
|
||
if git rev-parse --is-inside-work-tree &> /dev/null; then
|
||
echo "Git信息:"
|
||
echo " 分支: $(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo 'unknown')"
|
||
echo " 提交: $(git rev-parse --short HEAD 2>/dev/null || echo 'unknown')"
|
||
echo " 完整哈希: $(git rev-parse HEAD 2>/dev/null || echo 'unknown')"
|
||
echo " 时间: $(git log -1 --format='%ci' 2>/dev/null || echo 'unknown')"
|
||
echo " 信息: $(git log -1 --format='%s' 2>/dev/null || echo 'unknown')"
|
||
echo " 远程: $(git remote get-url origin 2>/dev/null || echo 'unknown')"
|
||
|
||
# 检查是否有更新
|
||
echo ""
|
||
info "检查远程仓库更新..."
|
||
git fetch origin 2>&1 | grep -v "already up" || true
|
||
local LOCAL=$(git rev-parse HEAD 2>/dev/null)
|
||
local REMOTE=$(git rev-parse @{upstream} 2>/dev/null || echo "")
|
||
if [ "$LOCAL" = "$REMOTE" ]; then
|
||
success "已是最新版本"
|
||
elif [ -n "$REMOTE" ]; then
|
||
local AHEAD=$(git rev-list_count ..@{upstream} 2>/dev/null || echo "?")
|
||
warn "有可用更新"
|
||
fi
|
||
|
||
# 检查工作区状态
|
||
echo ""
|
||
if git diff --quiet &>/dev/null; then
|
||
echo "工作区: 干净"
|
||
else
|
||
warn "工作区有未提交的修改"
|
||
git status --short 2>/dev/null | head -10
|
||
fi
|
||
else
|
||
echo "非Git仓库"
|
||
fi
|
||
|
||
echo ""
|
||
echo "服务状态:"
|
||
if systemctl is-active --quiet "$SERVICE_NAME" 2>/dev/null; then
|
||
echo " systemd服务: 运行中"
|
||
else
|
||
echo " systemd服务: 未运行或未配置"
|
||
fi
|
||
|
||
# 检查进程
|
||
local PIDS=$(ps aux | grep '[p]ython.*app.py' | wc -l || echo "0")
|
||
echo " Python进程: $PIDS"
|
||
|
||
echo ""
|
||
echo "备份信息:"
|
||
local BACKUP_DIR="${PROJECT_DIR}/backups"
|
||
if [ -d "$BACKUP_DIR" ]; then
|
||
local BACKUP_COUNT=$(ls -1 "$BACKUP_DIR" 2>/dev/null | wc -l)
|
||
echo " 备份数量: $BACKUP_COUNT"
|
||
echo " 最新备份: $(ls -t "$BACKUP_DIR" 2>/dev/null | head -1)"
|
||
else
|
||
echo " 暂无备份"
|
||
fi
|
||
|
||
echo ""
|
||
}
|
||
|
||
# ========================================
|
||
# 主流程
|
||
# ========================================
|
||
|
||
# 获取项目目录
|
||
PROJECT_DIR=$(get_project_dir)
|
||
|
||
echo "======================================"
|
||
echo " 智能矿山标签监测系统"
|
||
echo " 一键升级脚本"
|
||
echo "======================================"
|
||
echo ""
|
||
echo "项目目录: $PROJECT_DIR"
|
||
echo ""
|
||
|
||
# 处理特殊命令
|
||
case "${1:-}" in
|
||
rollback)
|
||
check_git
|
||
check_git_repo
|
||
rollback
|
||
exit 0
|
||
;;
|
||
status)
|
||
check_git
|
||
check_git_repo
|
||
show_status
|
||
exit 0
|
||
;;
|
||
backup)
|
||
check_git
|
||
check_git_repo
|
||
backup
|
||
exit 0
|
||
;;
|
||
help|--help|-h)
|
||
show_help
|
||
exit 0
|
||
;;
|
||
esac
|
||
|
||
# 前置检查
|
||
check_git
|
||
check_git_repo
|
||
|
||
# 显示当前版本
|
||
echo "当前版本: $(get_current_version)"
|
||
TARGET="${1:-master}"
|
||
echo "目标版本: $TARGET"
|
||
echo ""
|
||
|
||
# 步骤1: 备份
|
||
backup
|
||
|
||
# 步骤2: 停止服务
|
||
stop_service
|
||
|
||
# 步骤3: 保存需要保留的文件
|
||
save_preserved_files
|
||
|
||
# 步骤4: 拉取最新代码
|
||
pull_latest_code "$TARGET"
|
||
|
||
# 步骤5: 恢复保留的文件
|
||
restore_preserved_files
|
||
|
||
# 步骤6: 更新依赖
|
||
update_dependencies
|
||
|
||
# 步骤7: 数据库迁移
|
||
run_migrations
|
||
|
||
# 步骤8: 重启服务
|
||
restart_service
|
||
|
||
# 步骤9: 验证
|
||
verify_upgrade
|
||
|
||
# 完成
|
||
echo "======================================"
|
||
echo -e "${GREEN} 升级完成!${NC}"
|
||
echo "======================================"
|
||
echo ""
|
||
|
||
# 显示回滚说明
|
||
show_rollback_info |