如何编写自动部署服务端脚本

wen 实用脚本 2

本文目录导读:

如何编写自动部署服务端脚本

  1. 基础Shell部署脚本
  2. Docker部署脚本
  3. CI/CD管道脚本(GitHub Actions)
  4. 自动化部署平台(Ansible)
  5. 使用方法
  6. 最佳实践建议

我来帮你编写一个自动部署服务端脚本,这里提供几种常见场景的脚本示例:

基础Shell部署脚本

示例1:Java应用部署

#!/bin/bash
# 自动部署脚本 - Java应用
# 作者:AI助手
# 日期:2024
# 配置变量
APP_NAME="myapp"
APP_VERSION="1.0.0"
JAR_NAME="${APP_NAME}-${APP_VERSION}.jar"
DEPLOY_DIR="/opt/${APP_NAME}"
BACKUP_DIR="${DEPLOY_DIR}/backup"
LOG_DIR="${DEPLOY_DIR}/logs"
REMOTE_HOST="your-server.com"
REMOTE_USER="deploy"
REMOTE_PATH="/opt/${APP_NAME}"
# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
# 日志函数
log_info() {
    echo -e "${GREEN}[INFO]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
}
log_warn() {
    echo -e "${YELLOW}[WARNING]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
}
log_error() {
    echo -e "${RED}[ERROR]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
}
# 错误处理
set -e
trap 'log_error "脚本执行失败,在第 $LINENO 行"' ERR
# 1. 检查环境
check_environment() {
    log_info "检查部署环境..."
    # 检查Java环境
    if ! command -v java &> /dev/null; then
        log_error "Java未安装"
        exit 1
    fi
    # 检查目录
    for dir in "${DEPLOY_DIR}" "${BACKUP_DIR}" "${LOG_DIR}"; do
        if [ ! -d "$dir" ]; then
            mkdir -p "$dir"
            log_info "创建目录: $dir"
        fi
    done
    log_info "环境检查完成"
}
# 2. 备份当前版本
backup_current() {
    log_info "备份当前版本..."
    if [ -f "${DEPLOY_DIR}/${JAR_NAME}" ]; then
        local timestamp=$(date '+%Y%m%d_%H%M%S')
        cp "${DEPLOY_DIR}/${JAR_NAME}" "${BACKUP_DIR}/${JAR_NAME}.${timestamp}"
        log_info "已备份到: ${BACKUP_DIR}/${JAR_NAME}.${timestamp}"
    else
        log_warn "未找到当前版本,跳过备份"
    fi
}
# 3. 停止应用
stop_application() {
    log_info "停止应用..."
    local pid=$(pgrep -f "${JAR_NAME}" || true)
    if [ -n "$pid" ]; then
        kill -15 "$pid"
        sleep 5
        # 检查是否成功停止
        if pgrep -f "${JAR_NAME}" > /dev/null; then
            kill -9 "$pid"
            log_warn "强制停止应用"
        fi
        log_info "应用已停止"
    else
        log_warn "应用未运行"
    fi
}
# 4. 部署新版本
deploy_new_version() {
    log_info "部署新版本..."
    # 从远程服务器或构建产物复制
    if [ -f "./build/libs/${JAR_NAME}" ]; then
        cp "./build/libs/${JAR_NAME}" "${DEPLOY_DIR}/"
        log_info "从本地构建目录复制"
    elif [ -f "/tmp/${JAR_NAME}" ]; then
        cp "/tmp/${JAR_NAME}" "${DEPLOY_DIR}/"
        log_info "从临时目录复制"
    else
        log_error "未找到新版本文件"
        exit 1
    fi
    # 设置权限
    chmod 755 "${DEPLOY_DIR}/${JAR_NAME}"
}
# 5. 配置应用
configure_application() {
    log_info "配置应用..."
    # 读取配置文件
    if [ -f "${DEPLOY_DIR}/application.yml" ]; then
        log_info "使用现有配置"
    else
        log_warn "未找到配置文件,使用默认配置"
    fi
    # 设置环境变量
    export JAVA_OPTS="-Xms512m -Xmx1024m -XX:+UseG1GC"
    export APP_ENV="${APP_ENV:-production}"
}
# 6. 启动应用
start_application() {
    log_info "启动应用..."
    cd "${DEPLOY_DIR}"
    nohup java ${JAVA_OPTS} \
        -jar "${DEPLOY_DIR}/${JAR_NAME}" \
        --spring.profiles.active="${APP_ENV}" \
        >> "${LOG_DIR}/${APP_NAME}.log" 2>&1 &
    sleep 10
    # 检查启动状态
    if pgrep -f "${JAR_NAME}" > /dev/null; then
        log_info "应用启动成功"
        return 0
    else
        log_error "应用启动失败"
        return 1
    fi
}
# 7. 健康检查
health_check() {
    log_info "执行健康检查..."
    local retries=5
    local wait_time=5
    for i in $(seq 1 $retries); do
        if curl -s "http://localhost:8080/actuator/health" | grep -q "UP"; then
            log_info "健康检查通过"
            return 0
        fi
        log_warn "等待服务就绪... (${i}/${retries})"
        sleep $wait_time
    done
    log_error "健康检查失败"
    return 1
}
# 8. 清理旧文件
cleanup() {
    log_info "清理旧文件..."
    # 保留最近5个备份
    cd "${BACKUP_DIR}"
    ls -t *.jar.* | tail -n +6 | xargs -r rm -f
    # 清理超过30天的日志
    find "${LOG_DIR}" -name "*.log" -mtime +30 -delete
    log_info "清理完成"
}
# 主部署流程
main() {
    log_info "=== 开始自动部署 ==="
    # 执行部署步骤
    check_environment
    backup_current
    stop_application
    deploy_new_version
    configure_application
    start_application
    health_check
    cleanup
    log_info "=== 部署完成 ==="
}
# 执行主函数
main

示例2:Node.js应用部署

#!/bin/bash
# Node.js应用自动部署脚本
NODE_ENV="production"
APP_DIR="/var/www/app"
GIT_REPO="https://github.com/yourusername/yourapp.git"
BRANCH="main"
# 部署函数
deploy() {
    echo "开始部署 Node.js 应用..."
    # 1. 拉取最新代码
    cd "$APP_DIR" || exit
    git fetch --all
    git checkout "$BRANCH"
    git pull origin "$BRANCH"
    # 2. 安装依赖
    npm ci --only=production
    # 3. 构建(如果需要)
    if [ -f "package.json" ]; then
        if grep -q '"build"' "package.json"; then
            npm run build
        fi
    fi
    # 4. 数据库迁移
    if [ -f "node_modules/.bin/prisma" ]; then
        npx prisma migrate deploy
    fi
    # 5. 重启应用
    pm2 restart ecosystem.config.js --env production
    echo "部署完成!"
}
# 执行部署
deploy

Docker部署脚本

#!/bin/bash
# Docker自动化部署脚本
IMAGE_NAME="myapp"
CONTAINER_NAME="myapp-container"
REGISTRY="your-registry.com"
# 部署函数
deploy_docker() {
    echo "Docker自动部署..."
    # 1. 拉取最新镜像
    docker pull ${REGISTRY}/${IMAGE_NAME}:latest
    # 2. 停止并删除旧容器
    docker stop ${CONTAINER_NAME} || true
    docker rm ${CONTAINER_NAME} || true
    # 3. 启动新容器
    docker run -d \
        --name ${CONTAINER_NAME} \
        -p 8080:8080 \
        -e NODE_ENV=production \
        --restart unless-stopped \
        ${REGISTRY}/${IMAGE_NAME}:latest
    # 4. 清理旧镜像
    docker image prune -f
    echo "Docker部署完成"
}
deploy_docker

CI/CD管道脚本(GitHub Actions)

# .github/workflows/deploy.yml
name: Auto Deploy
on:
  push:
    branches: [ main ]
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Setup SSH
        run: |
          mkdir -p ~/.ssh
          echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa
          chmod 600 ~/.ssh/id_rsa
      - name: Deploy to Server
        run: |
          ssh -o StrictHostKeyChecking=no user@server '
            cd /opt/app &&
            git pull origin main &&
            ./deploy.sh
          '

自动化部署平台(Ansible)

# deploy.yml
---
- name: Auto Deploy Application
  hosts: webservers
  become: yes
  vars:
    app_name: myapp
    deploy_path: /opt/{{ app_name }}
    git_repo: https://github.com/yourusername/yourapp.git
  tasks:
    - name: Pull latest code
      git:
        repo: "{{ git_repo }}"
        dest: "{{ deploy_path }}"
        version: main
        force: yes
    - name: Install dependencies
      npm:
        path: "{{ deploy_path }}"
        state: present
    - name: Build application
      command: npm run build
      args:
        chdir: "{{ deploy_path }}"
    - name: Restart service
      systemd:
        name: "{{ app_name }}"
        state: restarted

使用方法

  1. 保存脚本:将脚本保存为 deploy.sh
  2. 添加执行权限chmod +x deploy.sh
  3. 配置参数:修改变量为你的实际配置
  4. 执行部署./deploy.sh

最佳实践建议

  1. 版本控制:使用Git标记版本
  2. 回滚机制:保留至少3个历史版本
  3. 日志记录:记录所有操作日志
  4. 通知机制:部署成功/失败发送通知
  5. 灰度发布:先部署到少量服务器测试

需要我针对特定场景或技术栈提供更详细的脚本吗?

抱歉,评论功能暂时关闭!