shell脚本部署想木

明白了!既然您需要使用 Shell 脚本 来完成部署,而不使用 Dockerfile,我将为您提供一个系统性的教程,帮助您优化部署步骤,并编写两个高效的 Shell 脚本来完成一键部署启动。

目录

  1. 前提条件
  2. 项目结构
  3. 准备 Conda 环境压缩包
  4. 编写部署脚本
  5. 执行部署脚本
  6. 优化建议
  7. 故障排除
  8. 总结

前提条件

在开始之前,请确保您具备以下条件:

  • 操作系统:Linux 或支持容器管理的类 Unix 系统。
  • Docker:已安装并正确配置。参考 Docker 官方安装文档
  • Docker Compose(可选):如果需要同时管理多个容器,建议安装 Docker Compose。参考 Docker Compose 安装指南
  • Conda:已安装在宿主机上。参考 Conda 官方安装指南
  • 项目文件:包括前台服务代码、大模型权重文件、以及两个 Conda 环境的 tar.gz 包。

项目结构

假设您的项目目录结构如下:

project-root/
├── frontend/
│   ├── startup.py
│   ├── start/
│   │   └── ... (其他代码文件)
│   └── ... (其他前台相关文件)
├── model/
│   ├── Qwen2___5-7B-Instruct/
│   │   └── ... (模型权重文件)
│   └── ... (其他模型相关文件)
├── conda_env_frontend.tar.gz
├── conda_env_model.tar.gz
├── deploy_frontend.sh
├── deploy_model.sh
└── README.md

准备 Conda 环境压缩包

确保您已经将两个 Conda 环境导出为 tar.gz 文件。如果尚未完成,请按照以下步骤操作:

  1. 安装 conda-pack 工具(如果尚未安装):

    conda install -c conda-forge conda-pack
    
  2. 打包前台服务的 Conda 环境

    conda activate frontend_env
    conda pack -o conda_env_frontend.tar.gz
    
  3. 打包大模型服务的 Conda 环境

    conda activate model_env
    conda pack -o conda_env_model.tar.gz
    

确保生成的 conda_env_frontend.tar.gzconda_env_model.tar.gz 位于项目根目录下。

编写部署脚本

接下来,我们将编写两个 Shell 脚本:一个用于部署前台服务,另一个用于部署大模型服务。这些脚本将自动执行以下操作:

  1. 创建容器。
  2. 复制必要的文件到容器中。
  3. 解压 Conda 环境并激活。
  4. 启动相应的服务。

部署前台服务的 Shell 脚本

创建一个名为 deploy_frontend.sh 的脚本,内容如下:

#!/bin/bash

# 部署前台服务脚本
# 使用方法: ./deploy_frontend.sh

# 设置变量
CONTAINER_NAME="frontend_service"
IMAGE_NAME="ubuntu:20.04"
CONDA_ENV_TAR="conda_env_frontend.tar.gz"
HOST_PORT=8000
CONTAINER_PORT=8000
FRONTEND_CODE_DIR="/app/frontend"
STARTUP_DIR="/app/frontend/start"
START_COMMAND="python startup.py -a"

# 检查是否以 root 或 sudo 用户运行
if [[ $EUID -ne 0 ]]; then
   echo "此脚本需要以 root 或 sudo 权限运行。" 
   exit 1
fi

# 检查 Docker 是否安装
if ! command -v docker &> /dev/null
then
    echo "Docker 未安装,请先安装 Docker。"
    exit 1
fi

# 检查 Conda 环境压缩包是否存在
if [ ! -f "$CONDA_ENV_TAR" ]; then
    echo "Conda 环境压缩包 $CONDA_ENV_TAR 不存在。"
    exit 1
fi

# 如果容器已存在,先停止并删除
if [ "$(docker ps -a | grep $CONTAINER_NAME)" ]; then
    echo "停止并删除已有的容器 $CONTAINER_NAME ..."
    docker stop $CONTAINER_NAME
    docker rm $CONTAINER_NAME
fi

# 创建容器
echo "创建容器 $CONTAINER_NAME ..."
docker run -d --name $CONTAINER_NAME -p $HOST_PORT:$CONTAINER_PORT $IMAGE_NAME sleep infinity

# 复制前台代码到容器
echo "复制前台代码到容器 ..."
docker cp frontend/ $CONTAINER_NAME:$FRONTEND_CODE_DIR/

# 复制 Conda 环境压缩包到容器
echo "复制 Conda 环境压缩包到容器 ..."
docker cp $CONDA_ENV_TAR $CONTAINER_NAME:/tmp/

# 在容器中安装必要的系统依赖和 Miniconda
echo "在容器中安装系统依赖和 Miniconda ..."
docker exec $CONTAINER_NAME bash -c "
    apt-get update && \
    apt-get install -y wget bzip2 ca-certificates curl git && \
    rm -rf /var/lib/apt/lists/* && \
    wget --quiet https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && \
    bash /tmp/miniconda.sh -b -p /opt/conda && \
    rm /tmp/miniconda.sh && \
    export PATH=/opt/conda/bin:\$PATH && \
    conda config --set always_yes yes --set changeps1 no && \
    mkdir -p /opt/conda_env && \
    tar -xzf /tmp/$CONDA_ENV_TAR -C /opt/conda_env && \
    rm /tmp/$CONDA_ENV_TAR
"

# 设置环境变量并启动前台服务
echo "设置环境变量并启动前台服务 ..."
docker exec $CONTAINER_NAME bash -c "
    export PATH=/opt/conda_env/bin:\$PATH && \
    cd $STARTUP_DIR && \
    $START_COMMAND &
"

echo "前台服务已成功部署并启动。访问 http://<宿主机IP>:$HOST_PORT 查看服务。"

脚本说明

  1. 变量设置:定义容器名称、基础镜像、Conda 环境压缩包路径、端口号等。
  2. 权限检查:确保脚本以 rootsudo 权限运行,因为 Docker 需要这些权限。
  3. 依赖检查:检查 Docker 是否已安装,Conda 环境压缩包是否存在。
  4. 容器管理:如果同名容器已存在,先停止并删除。
  5. 创建容器:基于指定的基础镜像(ubuntu:20.04)创建一个新的容器,并在后台运行。
  6. 文件复制:将前台服务代码和 Conda 环境压缩包复制到容器中。
  7. 容器内设置
    • 安装系统依赖(wget, bzip2, 等)。
    • 安装 Miniconda。
    • 解压 Conda 环境。
  8. 启动服务:激活 Conda 环境,进入前台服务的启动目录,执行启动命令。

部署大模型服务的 Shell 脚本

创建一个名为 deploy_model.sh 的脚本,内容如下:

#!/bin/bash

# 部署大模型服务脚本
# 使用方法: ./deploy_model.sh

# 设置变量
CONTAINER_NAME="model_service"
IMAGE_NAME="ubuntu:20.04"
CONDA_ENV_TAR="conda_env_model.tar.gz"
HOST_PORT=5000
CONTAINER_PORT=5000
MODEL_DIR="/app/model/Qwen2___5-7B-Instruct"
START_COMMAND="python -m vllm.entrypoints.openai.api_server --model /app/model/Qwen2___5-7B-Instruct --served-model-name Qwen2.5-7B-Instruct --max-model-len=2048"

# 检查是否以 root 或 sudo 用户运行
if [[ $EUID -ne 0 ]]; then
   echo "此脚本需要以 root 或 sudo 权限运行。" 
   exit 1
fi

# 检查 Docker 是否安装
if ! command -v docker &> /dev/null
then
    echo "Docker 未安装,请先安装 Docker。"
    exit 1
fi

# 检查 Conda 环境压缩包是否存在
if [ ! -f "$CONDA_ENV_TAR" ]; then
    echo "Conda 环境压缩包 $CONDA_ENV_TAR 不存在。"
    exit 1
fi

# 检查模型权重文件是否存在
if [ ! -d "model/Qwen2___5-7B-Instruct/" ]; then
    echo "模型权重目录 model/Qwen2___5-7B-Instruct/ 不存在。"
    exit 1
fi

# 如果容器已存在,先停止并删除
if [ "$(docker ps -a | grep $CONTAINER_NAME)" ]; then
    echo "停止并删除已有的容器 $CONTAINER_NAME ..."
    docker stop $CONTAINER_NAME
    docker rm $CONTAINER_NAME
fi

# 创建容器
echo "创建容器 $CONTAINER_NAME ..."
docker run -d --name $CONTAINER_NAME -p $HOST_PORT:$CONTAINER_PORT $IMAGE_NAME sleep infinity

# 复制模型权重到容器
echo "复制模型权重到容器 ..."
docker cp model/Qwen2___5-7B-Instruct/ $CONTAINER_NAME:$MODEL_DIR/

# 复制 Conda 环境压缩包到容器
echo "复制 Conda 环境压缩包到容器 ..."
docker cp $CONDA_ENV_TAR $CONTAINER_NAME:/tmp/

# 在容器中安装必要的系统依赖和 Miniconda
echo "在容器中安装系统依赖和 Miniconda ..."
docker exec $CONTAINER_NAME bash -c "
    apt-get update && \
    apt-get install -y wget bzip2 ca-certificates curl git && \
    rm -rf /var/lib/apt/lists/* && \
    wget --quiet https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && \
    bash /tmp/miniconda.sh -b -p /opt/conda && \
    rm /tmp/miniconda.sh && \
    export PATH=/opt/conda/bin:\$PATH && \
    conda config --set always_yes yes --set changeps1 no && \
    mkdir -p /opt/conda_env && \
    tar -xzf /tmp/$CONDA_ENV_TAR -C /opt/conda_env && \
    rm /tmp/$CONDA_ENV_TAR && \
    pip install vllm
"

# 设置环境变量并启动大模型服务
echo "设置环境变量并启动大模型服务 ..."
docker exec $CONTAINER_NAME bash -c "
    export PATH=/opt/conda_env/bin:\$PATH && \
    cd / && \
    $START_COMMAND &
"

echo "大模型服务已成功部署并启动。访问 http://<宿主机IP>:$HOST_PORT 查看服务。"

脚本说明

  1. 变量设置:定义容器名称、基础镜像、Conda 环境压缩包路径、端口号、模型路径等。
  2. 权限检查:确保脚本以 rootsudo 权限运行。
  3. 依赖检查:检查 Docker 是否已安装,Conda 环境压缩包和模型权重文件是否存在。
  4. 容器管理:如果同名容器已存在,先停止并删除。
  5. 创建容器:基于指定的基础镜像(ubuntu:20.04)创建一个新的容器,并在后台运行。
  6. 文件复制:将模型权重和 Conda 环境压缩包复制到容器中。
  7. 容器内设置
    • 安装系统依赖(wget, bzip2, 等)。
    • 安装 Miniconda。
    • 解压 Conda 环境。
    • 安装 vllm 包。
  8. 启动服务:激活 Conda 环境,进入根目录,执行启动命令。

注意

  • 请根据实际情况修改 START_COMMAND 中的模型路径和参数。
  • 确保模型权重路径和名称与实际一致。

执行部署脚本

1. 赋予脚本执行权限

在终端中导航到项目根目录,并为脚本赋予执行权限:

cd project-root/
chmod +x deploy_frontend.sh deploy_model.sh

2. 部署前台服务

rootsudo 权限运行前台服务部署脚本:

sudo ./deploy_frontend.sh

脚本执行过程

  • 检查权限、依赖和文件。
  • 创建并配置 Docker 容器。
  • 复制代码和环境到容器中。
  • 安装系统依赖和 Conda 环境。
  • 启动前台服务。

3. 部署大模型服务

同样,以 rootsudo 权限运行大模型服务部署脚本:

sudo ./deploy_model.sh

脚本执行过程

  • 检查权限、依赖和文件。
  • 创建并配置 Docker 容器。
  • 复制模型权重和环境到容器中。
  • 安装系统依赖、Conda 环境和 vllm
  • 启动大模型服务。

4. 验证部署

前台服务

打开浏览器,访问 http://<宿主机IP>:8000,检查前台是否正常运行。

大模型服务

使用工具(如 curl 或 Postman)发送请求到 http://<宿主机IP>:5000,确认大模型 API 是否正常响应。例如:

curl http://localhost:5000/v1/models

预期返回已加载的模型列表。

优化建议

  1. 脚本参数化

    为脚本添加参数,使其更灵活。例如,可以传递端口号、容器名称等参数,而不是在脚本中硬编码。

  2. 日志记录

    在脚本中添加日志记录功能,方便调试和监控。例如,将输出重定向到日志文件。

  3. 错误处理

    在关键步骤添加错误检查,确保每一步都成功执行,否则终止脚本并输出错误信息。

    if [ $? -ne 0 ]; then
        echo "某某步骤失败,退出脚本。"
        exit 1
    fi
    
  4. 环境变量管理

    将配置参数(如端口号、路径等)提取到配置文件或环境变量中,增强脚本的可维护性和灵活性。

  5. 容器重启策略

    在创建容器时,添加重启策略,确保容器在主机重启或容器崩溃时自动重启。

    docker run -d --name $CONTAINER_NAME -p $HOST_PORT:$CONTAINER_PORT --restart unless-stopped $IMAGE_NAME sleep infinity
    
  6. 安全性

    • 非 root 用户:在容器内创建非 root 用户运行应用,提升安全性。
    • 资源限制:为容器设置资源限制(如 CPU、内存),防止资源滥用。
  7. 并行部署

    考虑编写一个总的部署脚本,依次调用 deploy_frontend.shdeploy_model.sh,实现一键部署所有服务。

    # deploy_all.sh
    #!/bin/bash
    sudo ./deploy_frontend.sh
    sudo ./deploy_model.sh
    
  8. 自动化更新

    实现脚本自动检测代码或环境更新,并重新部署容器。例如,使用 git pull 更新代码后重启容器。

故障排除

  1. 容器未启动

    • 检查脚本执行过程中是否有错误信息。
    • 使用 docker ps -a 查看容器状态。
    • 使用 docker logs <容器名称> 查看容器日志。
  2. 服务无法访问

    • 确认宿主机的防火墙是否允许相应端口的流量。
    • 确认服务在容器内是否正确启动,并监听指定端口。
  3. Conda 环境问题

    • 确认 Conda 环境压缩包是否正确解压。
    • 确认所需的依赖是否已安装。
  4. 权限问题

    • 确认脚本以 rootsudo 权限运行。
    • 确认 Docker 有足够的权限访问宿主机的文件系统。

Shell指令

很高兴听到您的部署取得了成功!为了进一步提升您的技能,以下是一个系统性的指南,介绍 Shell 脚本 与部署相关的语法和重要操作。此指南涵盖基础知识、常用语法、控制结构、函数、错误处理、常用命令以及最佳实践,帮助您更高效地编写和管理部署脚本。

目录

  1. Shell 脚本基础
  2. Shell 脚本语法
  3. 控制结构
  4. 函数
  5. 错误处理
  6. 常用命令和操作
  7. 最佳实践
  8. 示例:常见部署任务
  9. 进一步学习资源

Shell 脚本基础

Shebang 和执行权限

Shebang 是脚本文件的第一行,用于指定解释器。例如:

#!/bin/bash
  • #!/bin/bash:使用 Bash 解释器。
  • #!/bin/sh:使用系统默认的 Shell,通常是 dashbash

赋予执行权限

在终端中,使用 chmod 命令为脚本赋予执行权限:

chmod +x script.sh

变量和数据类型

Shell 中变量无需声明类型,直接赋值即可。变量名通常使用大写字母。

# 变量赋值
NAME="前台服务"
PORT=8000

# 使用变量
echo "正在启动 $NAME,监听端口 $PORT"

注意

  • 变量赋值时等号 = 两边不能有空格。
  • 使用 ${VARIABLE}$VARIABLE 访问变量。

注释

使用 # 开始的行或行尾部分为注释。

# 这是一个注释
echo "Hello, World!" # 这是行尾注释

Shell 脚本语法

命令和命令替换

直接在脚本中执行系统命令。

# 执行 ls 命令
ls -l /home/user

命令替换:将命令的输出赋值给变量。

CURRENT_DIR=$(pwd)
# 或使用反引号
CURRENT_DIR=`pwd`

引号

  • 双引号 (" "): 保留大多数特殊字符的含义,支持变量和命令替换。

    NAME="前台服务"
    echo "服务名称:$NAME"
    
  • 单引号 (' '): 完全保留字符,不进行变量替换。

    echo '服务名称:$NAME'
    
  • **反引号 (\``):** 用于命令替换(较少使用,推荐使用 $()`)。

    DATE=`date`
    echo "当前日期:$DATE"
    

环境变量

将变量导出为环境变量,使其在子进程中可用。

export PATH="/usr/local/bin:$PATH"
export DATABASE_URL="mysql://user:pass@localhost/db"

控制结构

条件判断

使用 if, elif, else 进行条件判断。

if [ -f "/path/to/file" ]; then
    echo "文件存在"
elif [ -d "/path/to/directory" ]; then
    echo "目录存在"
else
    echo "文件和目录都不存在"
fi

常用测试表达式

  • 文件测试:
    • -f FILE:检查是否为常规文件。
    • -d DIRECTORY:检查是否为目录。
    • -e FILE:检查文件是否存在。
  • 字符串测试:
    • -z STRING:字符串长度为零。
    • -n STRING:字符串长度非零。
    • STRING1 = STRING2:字符串相等。
  • 数值测试:
    • -eq-ne-lt-le-gt-ge:等于、不等于、小于、小于等于、大于、大于等于。

循环结构

For 循环

for i in {1..5}; do
    echo "第 $i 次循环"
done

While 循环

COUNT=1
while [ $COUNT -le 5 ]; do
    echo "第 $COUNT 次循环"
    COUNT=$((COUNT + 1))
done

Until 循环

COUNT=1
until [ $COUNT -gt 5 ]; do
    echo "第 $COUNT 次循环"
    COUNT=$((COUNT + 1))
done

Case 语句

用于多条件匹配,类似于其他语言的 switch 语句。

read -p "请输入选项 (start/stop/restart): " OPTION
case $OPTION in
    start)
        echo "启动服务"
        ;;
    stop)
        echo "停止服务"
        ;;
    restart)
        echo "重启服务"
        ;;
    *)
        echo "无效选项"
        ;;
esac

函数

定义和调用函数,提高脚本的模块化和可重用性。

# 定义函数
greet() {
    echo "Hello, $1!"
}

# 调用函数
greet "前台服务"

带返回值的函数

add() {
    return $(($1 + $2))
}

add 5 3
echo "结果:$?"

注意return 用于返回状态码(0-255),要返回更大的数值,可以使用 echo

add() {
    echo $(($1 + $2))
}

RESULT=$(add 5 3)
echo "结果:$RESULT"

错误处理

退出状态码

每个命令执行后都有一个退出状态码,存储在 $? 中。0 表示成功,非零表示失败。

cp source.txt destination.txt
if [ $? -eq 0 ]; then
    echo "复制成功"
else
    echo "复制失败"
    exit 1
fi

set 命令

用于控制脚本的行为,提高错误处理能力。

  • set -e:一旦有命令返回非零状态,立即退出脚本。
  • set -u:使用未定义的变量时,立即退出。
  • set -o pipefail:如果管道中的任何命令失败,整个管道返回失败状态。
#!/bin/bash
set -euo pipefail

# 现在,如果有命令失败或使用未定义变量,脚本会立即退出

陷阱 (trap)

用于捕获和处理脚本中的信号或错误,执行清理操作。

#!/bin/bash

cleanup() {
    echo "清理临时文件..."
    rm -f /tmp/tempfile
}

trap cleanup EXIT

# 创建临时文件
touch /tmp/tempfile

# 模拟脚本执行
echo "执行脚本..."
# 如果脚本退出(无论成功或失败),都会执行 cleanup

常用命令和操作

文件和目录操作

  • 复制文件

    cp source.txt destination.txt
    cp -r source_dir/ destination_dir/
    
  • 移动文件

    mv source.txt destination.txt
    
  • 删除文件和目录

    rm file.txt
    rm -rf directory/
    
  • 创建目录

    mkdir -p /path/to/directory
    
  • 查找文件

    find /path -name "filename"
    

文本处理

  • 查找文本

    grep "pattern" file.txt
    
  • 替换文本

    sed -i 's/old/new/g' file.txt
    
  • 提取字段

    echo "a,b,c" | awk -F',' '{print $2}'
    

网络操作

  • 下载文件

    wget http://example.com/file.tar.gz
    curl -O http://example.com/file.tar.gz
    
  • 发送 HTTP 请求

    curl -X GET http://localhost:8000/health
    

进程控制

  • 查看进程

    ps aux | grep process_name
    
  • 停止进程

    kill PID
    kill -9 PID  # 强制杀死
    

Docker 操作

在部署脚本中常用的 Docker 命令包括:

  • 运行容器

    docker run -d --name container_name -p host_port:container_port image_name
    
  • 停止容器

    docker stop container_name
    
  • 删除容器

    docker rm container_name
    
  • 复制文件到容器

    docker cp source_path container_name:destination_path
    
  • 在容器内执行命令

    docker exec container_name command
    
  • 查看容器日志

    docker logs -f container_name
    

最佳实践

脚本可读性

  • 使用有意义的变量名:提高脚本的可读性和可维护性。

    CONTAINER_NAME="frontend_service"
    
  • 适当的缩进和格式:使代码结构清晰。

    if [ condition ]; then
        # 执行操作
    fi
    
  • 添加注释:解释复杂的逻辑或步骤。

    # 检查文件是否存在
    if [ -f "file.txt" ]; then
        echo "文件存在"
    fi
    

模块化和重用性

  • 使用函数:将重复的代码封装到函数中。

    backup_file() {
        cp "$1" "$1.bak"
    }
    
    backup_file "config.yaml"
    
  • 参数化脚本:使用参数传递不同的值,而不是硬编码。

    #!/bin/bash
    CONTAINER_NAME=$1
    IMAGE_NAME=$2
    

日志记录

  • 记录日志:将输出重定向到日志文件,便于调试和监控。

    LOG_FILE="/var/log/deploy.log"
    echo "部署开始" >> $LOG_FILE
    
  • 使用日志级别

    log_info() {
        echo "[INFO] $1" | tee -a $LOG_FILE
    }
    
    log_error() {
        echo "[ERROR] $1" | tee -a $LOG_FILE >&2
    }
    

安全性

  • 避免硬编码敏感信息:使用环境变量或配置文件管理密码和密钥。

    export DB_PASSWORD="your_password"
    
  • 使用最小权限:以非 root 用户运行脚本和服务,减少安全风险。

  • 验证输入:确保脚本接收到的参数和输入是有效和安全的。

    if [ -z "$1" ]; then
        echo "参数缺失"
        exit 1
    fi
    

示例:常见部署任务

示例 1:检查服务状态并重启

以下脚本检查某个服务是否在运行,如果未运行则启动服务。

#!/bin/bash
set -euo pipefail

SERVICE_NAME="frontend_service"
LOG_FILE="/var/log/service_monitor.log"

log_info() {
    echo "[INFO] $(date '+%Y-%m-%d %H:%M:%S') $1" | tee -a $LOG_FILE
}

log_error() {
    echo "[ERROR] $(date '+%Y-%m-%d %H:%M:%S') $1" | tee -a $LOG_FILE >&2
}

check_service() {
    if docker ps | grep -q "$SERVICE_NAME"; then
        log_info "$SERVICE_NAME 正在运行。"
    else
        log_error "$SERVICE_NAME 未运行,尝试启动。"
        start_service
    fi
}

start_service() {
    docker start "$SERVICE_NAME" && log_info "$SERVICE_NAME 启动成功。" || log_error "$SERVICE_NAME 启动失败。"
}

# 主程序
check_service

说明

  • 函数:定义日志函数和检查/启动服务的函数。
  • 日志记录:将信息和错误记录到日志文件。
  • 错误处理:使用 set -euo pipefail 提高脚本的健壮性。

示例 2:自动化备份和恢复

以下脚本实现数据库的备份和恢复。

#!/bin/bash
set -euo pipefail

ACTION=$1
BACKUP_DIR="/backup/db"
DB_CONTAINER="db_service"
DB_NAME="my_database"
LOG_FILE="/var/log/db_backup.log"

log_info() {
    echo "[INFO] $(date '+%Y-%m-%d %H:%M:%S') $1" | tee -a $LOG_FILE
}

log_error() {
    echo "[ERROR] $(date '+%Y-%m-%d %H:%M:%S') $1" | tee -a $LOG_FILE >&2
}

backup_db() {
    TIMESTAMP=$(date '+%Y%m%d%H%M%S')
    BACKUP_FILE="$BACKUP_DIR/$DB_NAME-$TIMESTAMP.sql.gz"
    mkdir -p "$BACKUP_DIR"
    docker exec "$DB_CONTAINER" pg_dump "$DB_NAME" | gzip > "$BACKUP_FILE"
    log_info "数据库备份完成:$BACKUP_FILE"
}

restore_db() {
    BACKUP_FILE=$2
    if [ ! -f "$BACKUP_FILE" ]; then
        log_error "备份文件不存在:$BACKUP_FILE"
        exit 1
    fi
    gunzip < "$BACKUP_FILE" | docker exec -i "$DB_CONTAINER" psql "$DB_NAME"
    log_info "数据库恢复完成:$BACKUP_FILE"
}

# 主程序
case $ACTION in
    backup)
        backup_db
        ;;
    restore)
        if [ $# -ne 2 ]; then
            echo "用法: $0 restore <backup_file>"
            exit 1
        fi
        restore_db "$2"
        ;;
    *)
        echo "用法: $0 {backup|restore <backup_file>}"
        exit 1
        ;;
esac

说明

  • 参数化:通过传递参数选择备份或恢复操作。
  • 备份:使用 pg_dump 导出数据库并压缩保存。
  • 恢复:解压备份文件并导入数据库。
  • 日志记录:记录操作日志,便于审计和调试。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值