feat(deploy): 添加开发环境 systemd 服务,改进部署文档
This commit is contained in:
147
deploy.sh
147
deploy.sh
@@ -9,6 +9,8 @@
|
||||
# --dry-run 预览模式,不执行实际操作
|
||||
# --yes, -y 跳过确认提示
|
||||
# --skip-tests 跳过部署后测试
|
||||
# --rollback 回滚到上一个备份版本
|
||||
# --backup-list 列出可用备份
|
||||
# ===========================================
|
||||
|
||||
set -euo pipefail
|
||||
@@ -22,6 +24,8 @@ APP_ENV="${1:-production}"
|
||||
DRY_RUN=false
|
||||
SKIP_CONFIRM=false
|
||||
SKIP_TESTS=false
|
||||
ROLLBACK=false
|
||||
LIST_BACKUPS=false
|
||||
|
||||
# 解析选项
|
||||
shift 2>/dev/null || true
|
||||
@@ -36,6 +40,12 @@ while [[ $# -gt 0 ]]; do
|
||||
--skip-tests)
|
||||
SKIP_TESTS=true
|
||||
;;
|
||||
--rollback)
|
||||
ROLLBACK=true
|
||||
;;
|
||||
--backup-list)
|
||||
LIST_BACKUPS=true
|
||||
;;
|
||||
--help|-h)
|
||||
echo "用法: $0 [development|production] [options]"
|
||||
echo ""
|
||||
@@ -43,6 +53,8 @@ while [[ $# -gt 0 ]]; do
|
||||
echo " --dry-run 预览模式,不执行实际操作"
|
||||
echo " --yes, -y 跳过确认提示"
|
||||
echo " --skip-tests 跳过部署后测试"
|
||||
echo " --rollback 回滚到上一个备份版本"
|
||||
echo " --backup-list 列出可用备份"
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
@@ -98,6 +110,126 @@ get_git_info() {
|
||||
echo "$git_version"
|
||||
}
|
||||
|
||||
# 部署日志路径
|
||||
get_deploy_log() {
|
||||
echo "${REMOTE_DIR}/deploy.log"
|
||||
}
|
||||
|
||||
# 记录部署日志
|
||||
log_to_file() {
|
||||
if [ "$DRY_RUN" = true ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
local timestamp
|
||||
timestamp=$(date '+%Y-%m-%d %H:%M:%S')
|
||||
local log_entry="[${timestamp}] ${APP_ENV} ${GIT_VERSION} $1"
|
||||
|
||||
ssh "${REMOTE_USER}@${REMOTE_HOST}" "echo '${log_entry}' >> $(get_deploy_log)" 2>/dev/null || true
|
||||
}
|
||||
|
||||
# Webhook 通知
|
||||
send_webhook() {
|
||||
local status="$1"
|
||||
local message="$2"
|
||||
|
||||
if [ -z "${WEBHOOK_URL:-}" ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
local payload
|
||||
payload=$(cat <<EOF
|
||||
{
|
||||
"app": "rust-backend",
|
||||
"env": "${APP_ENV}",
|
||||
"status": "${status}",
|
||||
"version": "${GIT_VERSION}",
|
||||
"message": "${message}",
|
||||
"timestamp": "$(date -Iseconds)"
|
||||
}
|
||||
EOF
|
||||
)
|
||||
|
||||
if [ "$DRY_RUN" = true ]; then
|
||||
log_dry "curl -X POST '${WEBHOOK_URL}' -d '${payload}'"
|
||||
return 0
|
||||
fi
|
||||
|
||||
curl -s -X POST "${WEBHOOK_URL}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "${payload}" >/dev/null 2>&1 || true
|
||||
}
|
||||
|
||||
# 列出备份
|
||||
list_backups() {
|
||||
log_step "可用备份列表..."
|
||||
echo ""
|
||||
|
||||
if [ "$DRY_RUN" = true ]; then
|
||||
log_dry "ssh ${REMOTE_USER}@${REMOTE_HOST} 'ls -la ${REMOTE_DIR}/${PROJECT_NAME}.backup.*'"
|
||||
return 0
|
||||
fi
|
||||
|
||||
ssh "${REMOTE_USER}@${REMOTE_HOST}" "ls -la ${REMOTE_DIR}/${PROJECT_NAME}.backup.*" 2>/dev/null || echo "无备份文件"
|
||||
echo ""
|
||||
}
|
||||
|
||||
# 回滚
|
||||
rollback() {
|
||||
log_step "查找最新备份..."
|
||||
local latest_backup
|
||||
|
||||
if [ "$DRY_RUN" = true ]; then
|
||||
latest_backup="${REMOTE_DIR}/${PROJECT_NAME}.backup.20240101_120000"
|
||||
log_dry "latest_backup=${latest_backup}"
|
||||
else
|
||||
latest_backup=$(ssh "${REMOTE_USER}@${REMOTE_HOST}" \
|
||||
"ls -t ${REMOTE_DIR}/${PROJECT_NAME}.backup.* 2>/dev/null | head -1" || echo "")
|
||||
|
||||
if [ -z "$latest_backup" ]; then
|
||||
log_error "没有找到可用的备份"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo -e "${YELLOW}========== 回滚确认 ==========${NC}"
|
||||
echo -e " 将回滚到: ${latest_backup}"
|
||||
echo -e " 服务: ${SERVICE_NAME}"
|
||||
echo -e "================================${NC}"
|
||||
echo ""
|
||||
|
||||
if [ "$SKIP_CONFIRM" = false ]; then
|
||||
read -p "确认回滚? [y/N] " -n 1 -r
|
||||
echo
|
||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||
log_warn "回滚已取消"
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
log_step "停止服务..."
|
||||
ssh "${REMOTE_USER}@${REMOTE_HOST}" "systemctl stop ${SERVICE_NAME}" 2>/dev/null || log_warn "停止服务失败,继续尝试..."
|
||||
|
||||
log_step "恢复备份..."
|
||||
if [ "$DRY_RUN" = true ]; then
|
||||
log_dry "ssh ${REMOTE_USER}@${REMOTE_HOST} 'cp ${latest_backup} ${REMOTE_DIR}/${PROJECT_NAME}'"
|
||||
else
|
||||
ssh "${REMOTE_USER}@${REMOTE_HOST}" "cp ${latest_backup} ${REMOTE_DIR}/${PROJECT_NAME}"
|
||||
fi
|
||||
|
||||
log_step "启动服务..."
|
||||
if [ "$DRY_RUN" = true ]; then
|
||||
log_dry "ssh ${REMOTE_USER}@${REMOTE_HOST} 'systemctl start ${SERVICE_NAME}'"
|
||||
else
|
||||
ssh "${REMOTE_USER}@${REMOTE_HOST}" "systemctl start ${SERVICE_NAME}"
|
||||
fi
|
||||
|
||||
log_info "回滚完成"
|
||||
log_to_file "ROLLBACK to $(basename $latest_backup)"
|
||||
send_webhook "rollback" "回滚完成: $(basename $latest_backup)"
|
||||
}
|
||||
|
||||
# 检查依赖
|
||||
check_dependencies() {
|
||||
log_step "检查依赖..."
|
||||
@@ -323,6 +455,18 @@ trap cleanup EXIT
|
||||
main() {
|
||||
GIT_VERSION=$(get_git_info)
|
||||
|
||||
if [ "$LIST_BACKUPS" = true ]; then
|
||||
ssh_connect
|
||||
list_backups
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ "$ROLLBACK" = true ]; then
|
||||
ssh_connect
|
||||
rollback
|
||||
exit 0
|
||||
fi
|
||||
|
||||
show_deploy_info
|
||||
confirm_deploy
|
||||
|
||||
@@ -336,6 +480,9 @@ main() {
|
||||
restart_service
|
||||
run_tests
|
||||
|
||||
log_to_file "DEPLOY success"
|
||||
send_webhook "success" "部署完成"
|
||||
|
||||
echo ""
|
||||
log_info "========== 部署完成! =========="
|
||||
echo -e " Git: ${GIT_VERSION}"
|
||||
|
||||
Reference in New Issue
Block a user