提交 b151dba1 authored 作者: 陈泽健's avatar 陈泽健

chore(deploy): Tengine 部署脚本改为 docker load 模式,更新达梦部署及集群部署文档

- X86/ARM tengine 部署脚本重构为 v2.0:docker load 替代源码编译,部署时间从 10 分钟降至 1 分钟
- 新增 X86 集群中间件安装脚本 (auto_middleware_install.sh)
- 更新 X86/ARM 达梦数据库部署脚本及 README
- 新增 Redis 集群配置说明文档
Co-Authored-By: 's avatarClaude <noreply@anthropic.com>
上级 54ee0f0d
# Redis 集群 1主2从3哨兵 部署文档
## 一、背景与目标
本文档描述如何在三台 X86 服务器上搭建 Redis 高可用集群,实现**1主2从 + 3哨兵**(1 Master + 2 Slave + 3 Sentinel)模式,满足以下目标:
- **读写分离**:主节点处理写请求,从节点分担读请求
- **自动故障转移**:主节点宕机后,哨兵自动投票选举新主节点,无需人工干预
- **数据高可用**:主从实时同步,数据不丢失
## 二、架构概览
```
┌──────────────────────┐ ┌──────────────────────┐ ┌──────────────────────┐
│ 5.41 (主节点) │ │ 5.42 (从节点1) │ │ 5.43 (从节点2) │
│ │ │ │ │ │
│ ┌────────────────┐ │ │ ┌────────────────┐ │ │ ┌────────────────┐ │
│ │ redis-master │ │ │ │ redis-slave-1 │ │ │ │ redis-slave-2 │ │
│ │ Redis :6379 │◄─┼────┼──│ Redis :6379 │ │ │ │ Redis :6379 │ │
│ │ (read/write) │ │ │ │ (read-only) │ │ │ │ (read-only) │ │
│ └────────────────┘ │ │ └────────────────┘ │ │ └────────────────┘ │
│ │ │ │ │ │
│ ┌────────────────┐ │ │ ┌────────────────┐ │ │ ┌────────────────┐ │
│ │ redis-sentinel │ │ │ │redis-sentinel-2│ │ │ │redis-sentinel-3│ │
│ │ Sentinel :26379│◄─┼────┼─►│ Sentinel :26379│◄─┼────┼─►│ Sentinel :26379│ │
│ └────────────────┘ │ │ └────────────────┘ │ │ └────────────────┘ │
└──────────────────────┘ └──────────────────────┘ └──────────────────────┘
哨兵数量: 3 (奇数,满足 quorum=2,避免脑裂)
自动故障转移: 主节点宕机 → 哨兵投票 → 从节点晋升为新主节点(10~20秒内完成)
```
### 端口说明
| 端口 | 协议 | 用途 |
|------|------|------|
| 6379 | TCP | Redis 服务端口 |
| 26379 | TCP | Sentinel 哨兵端口 |
### 服务器信息(部署时填写)
| 服务器 | 角色 | 内网 IP | 容器名 | 哨兵容器名 |
|--------|------|---------|--------|------------|
| 5.41 | Master + Sentinel1 | `___` | redis-master | redis-sentinel |
| 5.42 | Slave1 + Sentinel2 | `___` | redis-slave-1 | redis-sentinel-2 |
| 5.43 | Slave2 + Sentinel3 | `___` | redis-slave-2 | redis-sentinel-3 |
> **注意**:`sentinel monitor mymaster` 中的 IP 始终填写主节点(5.41)的 IP;
> `sentinel announce-ip` 填写各自服务器自己的 IP。
---
## 三、前置条件
### 3.1 网络互通
三台服务器之间必须网络互通,以下端口需要在防火墙/安全组中放行:
| 端口 | 协议 | 用途 |
|------|------|------|
| 6379 | TCP | Redis 服务(主从复制 + 客户端连接) |
| 26379 | TCP | Sentinel 哨兵间通信 |
### 3.2 各服务器准备
```bash
# 1. 确保 Docker 已安装
docker --version
# 2. 确认 Redis 镜像可用(三台都要能拉取)
docker pull redis:8
# 或者确认离线镜像已导入
docker images | grep redis
# 3. 检查目标端口未被占用
ss -tlnp | grep -E '6379|26379'
```
---
## 四、部署步骤
> **执行顺序**:先三台 Redis 容器(主→从1→从2)→ 再三台哨兵容器。
### 步骤一:创建 Docker 网络
**三台服务器分别执行**(因为三台服务器还需要部署其他服务集群,各自创建独立容器网络):
```bash
docker network create redis-net
```
### 步骤二:创建目录和用户
**三台服务器分别执行**
```bash
# 创建配置和数据目录
mkdir -p /data/middleware/redis/config
mkdir -p /data/middleware/redis/data
mkdir -p /data/middleware/redis/sentinel-data
# 创建 redis 用户组和用户
sudo groupadd redis 2>/dev/null
sudo useradd -r -g redis -s /sbin/nologin redis 2>/dev/null
# 赋予目录权限
chmod 755 /data/middleware/redis/sentinel-data
chown -R redis:redis /data/middleware/redis/sentinel-data
```
### 步骤三:准备 Redis 配置文件
`redis.conf` 放到每台服务器的 `/data/middleware/redis/config/redis.conf`
**三台服务器的 redis.conf 关键差异化配置**
| 配置项 | 5.41(主) | 5.42(从1) | 5.43(从2) |
|--------|-----------|------------|------------|
| `bind` | `0.0.0.0` | `0.0.0.0` | `0.0.0.0` |
| `port` | `6379` | `6379` | `6379` |
| `requirepass` | `dNrprU&2S` | `dNrprU&2S` | `dNrprU&2S` |
| `masterauth` | `dNrprU&2S` | `dNrprU&2S` | `dNrprU&2S` |
| `replicaof` | 不需要 | `5.41的内网IP 6379` | `5.41的内网IP 6379` |
```bash
# 修改配置文件的归属和权限(三台都要执行)
sudo chown redis:redis /data/middleware/redis/config/redis.conf
sudo chmod 644 /data/middleware/redis/config/redis.conf
```
### 步骤四:启动 Redis 容器
**4.1 先在 5.41 上启动主节点**
```bash
docker run -itd \
--restart=always \
--name redis-master \
--network redis-net \
-p 6379:6379 \
--memory 4g --cpus 2 \
-v /data/middleware/redis/config/redis.conf:/etc/redis/redis.conf \
-v /data/middleware/redis/data:/data \
-v /etc/localtime:/etc/localtime:ro \
redis:8 \
redis-server /etc/redis/redis.conf
```
**4.2 在 5.42 上启动从节点1**
```bash
docker run -itd \
--restart=always \
--name redis-slave-1 \
--network redis-net \
-p 6379:6379 \
--memory 4g --cpus 2 \
-v /data/middleware/redis/config/redis.conf:/etc/redis/redis.conf \
-v /data/middleware/redis/data:/data \
-v /etc/localtime:/etc/localtime:ro \
redis:8 \
redis-server /etc/redis/redis.conf
```
**4.3 在 5.43 上启动从节点2**
```bash
docker run -itd \
--restart=always \
--name redis-slave-2 \
--network redis-net \
-p 6379:6379 \
--memory 4g --cpus 2 \
-v /data/middleware/redis/config/redis.conf:/etc/redis/redis.conf \
-v /data/middleware/redis/data:/data \
-v /etc/localtime:/etc/localtime:ro \
redis:8 \
redis-server /etc/redis/redis.conf
```
### 步骤五:准备 Sentinel 配置文件
`sentinel.conf` 放到每台服务器的 `/data/middleware/redis/sentinel-data/sentinel.conf`
> **关键**:`sentinel monitor mymaster` 的 IP **始终填主节点 5.41 的内网 IP**;
> `sentinel announce-ip` 填**各自服务器的内网 IP**。
**5.41 的 sentinel.conf**
```conf
port 26379
dir "/data"
sentinel monitor mymaster 192.168.5.41 6379 2
sentinel resolve-hostnames yes
sentinel auth-pass mymaster dNrprU&2S
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000
# 关键:哨兵对外宣称的 IP,必须填本机真实内网 IP
sentinel announce-ip "192.168.5.41"
sentinel announce-port 26379
user default on nopass sanitize-payload ~* &* +@all
```
**5.42 的 sentinel.conf**
```conf
port 26379
dir "/data"
sentinel monitor mymaster 192.168.5.41 6379 2
sentinel resolve-hostnames yes
sentinel auth-pass mymaster dNrprU&2S
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000
# 关键:哨兵对外宣称的 IP,必须填本机真实内网 IP
sentinel announce-ip "192.168.5.42"
sentinel announce-port 26379
user default on nopass sanitize-payload ~* &* +@all
```
**5.43 的 sentinel.conf**
```conf
port 26379
dir "/data"
sentinel monitor mymaster 192.168.5.41 6379 2
sentinel resolve-hostnames yes
sentinel auth-pass mymaster dNrprU&2S
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000
# 关键:哨兵对外宣称的 IP,必须填本机真实内网 IP
sentinel announce-ip "192.168.5.43"
sentinel announce-port 26379
user default on nopass sanitize-payload ~* &* +@all
```
### 步骤六:启动 Sentinel 容器
**6.1 在 5.41 上启动哨兵1**
```bash
docker run -itd \
--restart=always \
--name redis-sentinel \
--network redis-net \
-p 26379:26379 \
-v /data/middleware/redis/sentinel-data:/data \
-v /etc/localtime:/etc/localtime:ro \
redis:8 \
redis-sentinel /data/sentinel.conf
```
**6.2 在 5.42 上启动哨兵2**
```bash
docker run -itd \
--restart=always \
--name redis-sentinel-2 \
--network redis-net \
-p 26379:26379 \
-v /data/middleware/redis/sentinel-data:/data \
-v /etc/localtime:/etc/localtime:ro \
redis:8 \
redis-sentinel /data/sentinel.conf
```
**6.3 在 5.43 上启动哨兵3**
```bash
docker run -itd \
--restart=always \
--name redis-sentinel-3 \
--network redis-net \
-p 26379:26379 \
-v /data/middleware/redis/sentinel-data:/data \
-v /etc/localtime:/etc/localtime:ro \
redis:8 \
redis-sentinel /data/sentinel.conf
```
---
## 五、验证
### 5.1 验证 Redis 主从复制状态
确认 1 主 2 从是否正常建立连接。
**在主节点(5.41)上执行**
```bash
docker exec -it redis-master redis-cli -a 'dNrprU&2S' info replication
```
**预期结果**
- `role:master`
- `connected_slaves:2`
- 下面能看到两个从节点的 IP 和端口
**正确输出示例**
```
# Replication
role:master
connected_slaves:2
slave0:ip=172.18.0.x,port=6379,state=online,offset=...,lag=0
slave1:ip=172.18.0.y,port=6379,state=online,offset=...,lag=0
```
### 5.2 验证哨兵集群状态
确认 3 个哨兵已互相发现并监控主节点。
**任意一台服务器执行**
```bash
docker exec -it redis-sentinel redis-cli -p 26379 info sentinel
```
**预期结果**
- `sentinel_masters=1`
- `sentinel_tilt=0`
- `master0:name=mymaster,status=ok,address=<5.41的IP>:6379,slaves=2,sentinels=3`
### 5.3 验证数据同步
**在主节点写入测试数据**
```bash
docker exec -it redis-master redis-cli -a 'dNrprU&2S' set test_key "hello_redis_cluster"
```
**在从节点读取**
```bash
docker exec -it redis-slave-1 redis-cli -a 'dNrprU&2S' get test_key
docker exec -it redis-slave-2 redis-cli -a 'dNrprU&2S' get test_key
```
**预期结果**:两个从节点都返回 `"hello_redis_cluster"`
### 5.4 故障转移演练(可选,建议低峰期操作)
**模拟主节点宕机**(在 5.41 上执行):
```bash
docker stop redis-master
```
**观察哨兵日志**(在 5.42 或 5.43 上执行):
```bash
docker logs -f redis-sentinel-2
```
你会看到哨兵开始投票(`+sdown``+odown``+vote-for-leader``+switch-master`)。
**确认新主节点**(等待 10~20 秒后):
```bash
docker exec -it redis-sentinel-2 redis-cli -p 26379 sentinel get-master-addr-by-name mymaster
```
**预期结果**
- 输出的 IP 变为 5.42 或 5.43 的 IP(某个从节点被自动晋升为新主节点)
**恢复旧主节点**
```bash
docker start redis-master
```
旧主节点重新启动后会自动作为**从节点**加入集群,跟随新主节点同步数据。
---
## 六、配置参数说明
| 参数 | 值 | 说明 |
|------|-----|------|
| `sentinel monitor mymaster` | `<主IP> 6379 2` | 监控主节点,quorum=2(至少2个哨兵同意才故障转移) |
| `sentinel down-after-milliseconds` | `5000` | 主节点 5 秒无响应判定主观下线 |
| `sentinel failover-timeout` | `60000` | 故障转移超时 60 秒 |
| `sentinel announce-ip` | 各自内网 IP | 哨兵对外宣告的 IP(Docker 容器内必须配置,否则哨兵间通信用容器内 IP 导致连接失败) |
| `sentinel auth-pass` | `dNrprU&2S` | Redis 密码(6.0+ ACL 也可用 `sentinel auth-user`) |
| `--memory` | `4g` | 容器内存限制 |
| `--cpus` | `2` | 容器 CPU 限制 |
---
## 七、常见问题
### Q1: 哨兵日志报 `Address already in use`
检查是否有残留的哨兵进程或容器,先停掉旧容器再重新启动。
```bash
docker stop redis-sentinel redis-sentinel-2 redis-sentinel-3 2>/dev/null
docker rm redis-sentinel redis-sentinel-2 redis-sentinel-3 2>/dev/null
```
### Q2: 哨兵显示 `sentinels=1` 而不是 `3`
可能原因:
1. **防火墙**未开放 26379 端口(三台之间互相 telnet 测试)
2. **`sentinel announce-ip` 填错**(填了容器内 IP 而不是物理内网 IP)
3. 哨兵配置文件格式有误(检查是否有 BOM 头或特殊字符)
### Q3: 从节点连不上主节点
检查:
1. 从节点的 `replicaof` 配置是否指向正确的主节点 IP
2. 主节点 `bind` 是否为 `0.0.0.0` 或包含从节点能访问的 IP
3. 防火墙 6379 端口是否开放
### Q4: 故障转移后客户端怎么知道新主节点?
客户端应通过**哨兵**来发现主节点,而不是直连 Redis。Java 用 JedisSentinelPool,Python 用 redis-py 的 Sentinel 支持。
### Q5: 哨兵的 sentinel.conf 被 CONFIG REWRITE 覆盖了怎么办?
`CONFIG REWRITE` 是正常行为——哨兵会在运行时自动更新配置文件(如记录已知的从节点和哨兵)。只要 `sentinel announce-ip``sentinel monitor` 这两行不被意外修改就没有问题。
---
## 八、后续运维
### 8.1 监控脚本
项目已有 Redis 监控脚本,可加入 crontab 定时检查:
```bash
# 预定系统 Redis 监控
/data/scripts/monitor_redis_service.sh
# 新统一平台 Redis 监控
/data/scripts/monitor_redis_service.sh
```
### 8.2 中间件深度检测
```bash
# 服务自检 Redis 基础检查
bash AuxiliaryTool/ScriptTool/ServiceSelfInspection/check_redis.sh
# 中间件验证(自动化验证+修复)
python AuxiliaryTool/ScriptTool/MiddlewareVerify/checks/redis.py
```
### 8.3 日常检查命令
```bash
# 查看容器状态
docker ps | grep redis
# 查看 Redis 日志
docker logs --tail 100 redis-master
# 查看哨兵日志
docker logs --tail 100 redis-sentinel
# 查看主从状态
docker exec -it redis-master redis-cli -a dNrprU&2S info replication
```
#!/bin/bash
# ============================================================
# Tengine 容器一键部署脚本 (ARM 架构)
# Tengine 容器一键部署脚本 (ARM)
# 适用于:openEuler 24.03 (aarch64)
# 版本:1.0
# 日期:2026-07-06
# 版本:2.0 — docker load 模式,无需从源码编译
# 日期:2026-07-07
# ============================================================
set -e
# ==================== 配置变量 ====================
# ARM 服务器 docker 需 sudo(admin 用户),X86 设为空
# ARM 服务器 docker 需 sudo(admin 用户)
DOCKER_CMD="sudo docker"
# DOCKER_CMD="docker" # X86 用这行
DEPLOY_DIR="/data/temp/tengine"
IMAGE_FILE="${DEPLOY_DIR}/utengine_v1_arm.tar"
IMAGE_NAME="utengine:v1"
CONTAINER_NAME="utengine"
OLD_CONTAINER="unginx"
BUILD_DIR="/data/tengine_build"
DOCKERFILE_SRC="/data/Dockerfile.utengine"
TENGINE_TAR="/data/tengine-3.1.0.tar.gz"
# 容器运行参数
HOST_PORT="443"
CONTAINER_PORT="443"
# 挂载映射(宿主机:容器:模式)
# 格式: "source:dest:mode" (mode: ro/rw)
declare -a MOUNTS=(
"/data/security/nginx_cert:/data/security/nginx_cert:ro"
"/data/services/web:/data/services/web:rw"
......@@ -36,7 +31,6 @@ declare -a MOUNTS=(
"/data/middleware/nginx/log:/var/log/tengine:rw"
)
# Tengine 主配置文件(覆盖默认配置)
TENGINE_MAIN_CONF='user root;
worker_processes auto;
......@@ -80,30 +74,16 @@ log_step() { echo -e "${BLUE}[STEP]${NC} $1"; }
preflight_check() {
log_step "执行前置检查..."
# 检查 Docker
if ! command -v ${DOCKER_CMD%% *} &> /dev/null; then
log_error "Docker 未安装"
exit 1
fi
# 检查基础镜像
if ! ${DOCKER_CMD} image inspect nginx:1.30.2 &> /dev/null; then
log_error "基础镜像 nginx:1.30.2 不存在"
if [ ! -f "$IMAGE_FILE" ]; then
log_error "镜像文件不存在: $IMAGE_FILE"
exit 1
fi
# 检查源码包
if [ ! -f "$TENGINE_TAR" ]; then
log_error "Tengine 源码包不存在: $TENGINE_TAR"
exit 1
fi
if [ ! -f "$DOCKERFILE_SRC" ]; then
log_error "Dockerfile 不存在: $DOCKERFILE_SRC"
exit 1
fi
# 检查挂载源目录
for mount in "${MOUNTS[@]}"; do
IFS=':' read -r src dest mode <<< "$mount"
if [ ! -d "$src" ] && [ ! -f "$src" ]; then
......@@ -112,58 +92,34 @@ preflight_check() {
fi
done
# 检查端口是否被占用
if ss -tlnp | grep -q ":${HOST_PORT} "; then
if ss -tlnp 2>/dev/null | grep -q ":${HOST_PORT} " || netstat -tlnp 2>/dev/null | grep -q ":${HOST_PORT} "; then
log_warn "端口 ${HOST_PORT} 已被占用,将先停止旧容器"
fi
log_info "前置检查通过"
}
# ==================== 构建镜像 ====================
build_image() {
# 如果镜像已存在,询问是否重建
# ==================== 加载镜像 ====================
load_image() {
if ${DOCKER_CMD} image inspect "$IMAGE_NAME" &> /dev/null; then
log_warn "镜像 $IMAGE_NAME 已存在"
read -p "是否重新构建?[y/N]: " rebuild
if [ "$rebuild" != "y" ] && [ "$rebuild" != "Y" ]; then
log_info "跳过构建,使用已有镜像"
read -p "是否重新加载?[y/N]: " reload
if [ "$reload" != "y" ] && [ "$reload" != "Y" ]; then
log_info "跳过加载,使用已有镜像"
return 0
fi
${DOCKER_CMD} rmi "$IMAGE_NAME" 2>/dev/null || true
fi
log_step "准备构建目录..."
# 清理并创建构建目录
rm -rf "$BUILD_DIR"
mkdir -p "$BUILD_DIR"
cp "$DOCKERFILE_SRC" "$BUILD_DIR/Dockerfile"
cp "$TENGINE_TAR" "$BUILD_DIR/"
# 创建 .dockerignore
cat > "$BUILD_DIR/.dockerignore" << 'DOCKERIGNORE'
*
!Dockerfile
!tengine-3.1.0.tar.gz
DOCKERIGNORE
log_step "开始构建镜像(预计 5-10 分钟)..."
cd "$BUILD_DIR"
if ${DOCKER_CMD} build -t "$IMAGE_NAME" . ; then
log_info "镜像构建成功: $IMAGE_NAME"
else
log_error "镜像构建失败"
exit 1
fi
log_step "加载镜像..."
${DOCKER_CMD} load -i "$IMAGE_FILE"
log_info "镜像加载完成"
}
# ==================== 停止旧容器 ====================
stop_old_container() {
log_step "停止旧容器..."
# 停止 utengine(如果正在运行)
if ${DOCKER_CMD} ps --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
log_info "停止现有 ${CONTAINER_NAME} 容器..."
${DOCKER_CMD} stop "$CONTAINER_NAME" 2>/dev/null || true
......@@ -172,11 +128,10 @@ stop_old_container() {
${DOCKER_CMD} rm "$CONTAINER_NAME" 2>/dev/null || true
fi
# 停止旧 unginx(如果正在运行)
if ${DOCKER_CMD} ps --format '{{.Names}}' | grep -q "^${OLD_CONTAINER}$"; then
log_info "停止旧 ${OLD_CONTAINER} 容器..."
${DOCKER_CMD} stop "$OLD_CONTAINER"
log_info "${OLD_CONTAINER} 已停止(保留容器,可回滚用 ${DOCKER_CMD} start ${OLD_CONTAINER})"
log_info "${OLD_CONTAINER} 已停止(保留容器,回滚: ${DOCKER_CMD} start ${OLD_CONTAINER})"
fi
}
......@@ -184,7 +139,6 @@ stop_old_container() {
start_tengine() {
log_step "启动 Tengine 容器..."
# 构建 docker run 命令
local run_cmd="${DOCKER_CMD} run -d --name ${CONTAINER_NAME}"
run_cmd+=" --restart always"
run_cmd+=" --network bridge"
......@@ -208,7 +162,6 @@ start_tengine() {
sleep 2
# 检查容器是否启动
if ${DOCKER_CMD} ps --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
log_info "容器已启动"
else
......@@ -222,14 +175,10 @@ start_tengine() {
configure_tengine() {
log_step "配置 Tengine 主配置文件..."
# 写入主配置文件到临时文件
echo "$TENGINE_MAIN_CONF" > /tmp/tengine_main.conf
# 拷入容器
${DOCKER_CMD} cp /tmp/tengine_main.conf "${CONTAINER_NAME}:/etc/tengine/tengine.conf"
rm -f /tmp/tengine_main.conf
# 测试配置
if ${DOCKER_CMD} exec "$CONTAINER_NAME" nginx -t 2>&1; then
log_info "配置文件语法检查通过"
else
......@@ -237,7 +186,6 @@ configure_tengine() {
exit 1
fi
# 重载配置
${DOCKER_CMD} exec "$CONTAINER_NAME" nginx -s reload 2>&1
log_info "配置已重载"
}
......@@ -246,17 +194,14 @@ configure_tengine() {
verify_deployment() {
log_step "验证部署..."
# 1. 容器状态
echo ""
echo "=== 容器状态 ==="
${DOCKER_CMD} ps --filter "name=${CONTAINER_NAME}" --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
# 2. Tengine 版本
echo ""
echo "=== Tengine 版本 ==="
${DOCKER_CMD} exec "$CONTAINER_NAME" nginx -v 2>&1
# 3. HTTPS 连通性测试
echo ""
echo "=== HTTPS 连通性测试 ==="
if curl -skI --connect-timeout 5 https://127.0.0.1/ 2>&1 | head -5; then
......@@ -265,7 +210,6 @@ verify_deployment() {
log_warn "HTTPS 测试异常,请检查"
fi
# 4. Server 头验证
echo ""
SERVER_HEADER=$(curl -skI --connect-timeout 5 https://127.0.0.1/ 2>&1 | grep -i "Server:" || echo "")
if echo "$SERVER_HEADER" | grep -qi "Tengine"; then
......@@ -274,7 +218,6 @@ verify_deployment() {
log_warn "Server 头未确认为 Tengine: $SERVER_HEADER"
fi
# 5. 编译模块
echo ""
echo "=== 编译的模块 ==="
${DOCKER_CMD} exec "$CONTAINER_NAME" nginx -V 2>&1
......@@ -282,7 +225,7 @@ verify_deployment() {
echo ""
log_info "======== 部署完成 ========"
echo ""
echo " 访问地址: https://192.168.9.76"
echo " 访问地址: https://$(hostname -I 2>/dev/null | awk '{print $1}' || echo 'YOUR_IP')"
echo " 容器名称: ${CONTAINER_NAME}"
echo " 查看日志: ${DOCKER_CMD} logs -f ${CONTAINER_NAME}"
echo " 配置目录: /data/middleware/nginx/config/"
......@@ -296,18 +239,18 @@ main() {
echo ""
echo "============================================"
echo " Tengine 容器一键部署脚本 (ARM)"
echo " 版本: 2.0 (docker load 模式)"
echo " 目标服务器: $(hostname)"
echo " 时间: $(date '+%Y-%m-%d %H:%M:%S')"
echo "============================================"
echo ""
preflight_check
build_image
load_image
stop_old_container
start_tengine
configure_tengine
verify_deployment
}
# 执行
main "$@"
......@@ -42,10 +42,10 @@ chmod +x auto_deploy_dm8.sh
```bash
# 容器内连接
docker exec -it dm8-server /usr/local/dm8/bin/disql SYSDBA/Dameng123@localhost:5236
docker exec -it dm8-server /usr/local/dm8/bin/disql SYSDBA/dNrprU\&2S!@localhost:5236
# 远程连接
disql SYSDBA/Dameng123@<服务器IP>:5236
disql SYSDBA/dNrprU\&2S!@<服务器IP>:5236
```
## 配置参数
......@@ -57,7 +57,7 @@ CONTAINER_NAME="dm8-server" # 容器名称
DM_PORT=5236 # 端口
DM_INSTALL_DIR="/usr/local/dm8" # DM8 安装目录
DM_DATA_DIR="/data/middleware/dm8" # 数据目录
SYSDBA_PWD="Dameng123" # SYSDBA 密码
SYSDBA_PWD="dNrprU&2S!" # SYSDBA 密码
MEMORY_LIMIT="4g" # 内存限制
```
......
......@@ -25,7 +25,7 @@ DM_PORT=5236 # 端口
DM_INSTALL_DIR="/usr/local/dm8" # DM8 安装目录(宿主机目标路径)
DM_DATA_DIR="/data/middleware/dm8" # 数据持久化目录
IMAGE_NAME="dm8:arm64" # 镜像名称
SYSDBA_PWD="Dameng123" # SYSDBA 密码
SYSDBA_PWD="dNrprU&2S!" # SYSDBA 密码
MEMORY_LIMIT="4g" # 内存限制
# ========================================================
......@@ -216,6 +216,20 @@ while [ $RETRY_COUNT -lt $MAX_RETRY ]; do
echo " 容器内: docker exec -it ${CONTAINER_NAME} ${DM_INSTALL_DIR}/bin/disql SYSDBA/${SYSDBA_PWD}@localhost:${DM_PORT}"
echo " 远程: disql SYSDBA/${SYSDBA_PWD}@<服务器IP>:${DM_PORT}"
echo "=============================================="
# --------------------------------
# 导入业务数据库(如果 databases/ 存在)
# --------------------------------
IMPORT_SCRIPT_SRC="$SCRIPT_DIR/import_dm8_databases.sh"
if [[ -d "$SCRIPT_DIR/databases" ]] && ls "$SCRIPT_DIR/databases"/*_ddl.sql >/dev/null 2>&1; then
echo ""
echo "[步骤7] 导入业务数据库表结构..."
if [[ -f "$IMPORT_SCRIPT_SRC" ]]; then
bash "$IMPORT_SCRIPT_SRC"
else
echo "[WARN] 导入脚本不存在: $IMPORT_SCRIPT_SRC"
fi
fi
exit 0
fi
......
#!/bin/bash
# ============================================================
# Tengine 容器一键部署脚本
# Tengine 容器一键部署脚本 (X86)
# 适用于:UOS Server 20 / 麒麟 V10 (x86_64)
# 版本:1.0
# 日期:2026-07-06
# 版本:2.0 — docker load 模式,无需从源码编译
# 日期:2026-07-07
# ============================================================
set -e
# ==================== 配置变量 ====================
DEPLOY_DIR="/data/temp/tengine"
IMAGE_FILE="${DEPLOY_DIR}/utengine_v1_x86.tar"
IMAGE_NAME="utengine:v1"
CONTAINER_NAME="utengine"
OLD_CONTAINER="unginx"
BUILD_DIR="/data/tengine_build"
DOCKERFILE_SRC="/data/Dockerfile.utengine"
TENGINE_TAR="/data/tengine-3.1.0.tar.gz"
# 容器运行参数
HOST_PORT="443"
CONTAINER_PORT="443"
# 挂载映射(宿主机:容器:模式)
# 格式: "source:dest:mode" (mode: ro/rw)
declare -a MOUNTS=(
"/data/security/nginx_cert:/data/security/nginx_cert:ro"
"/data/services/web:/data/services/web:rw"
......@@ -32,7 +28,6 @@ declare -a MOUNTS=(
"/data/middleware/nginx/log:/var/log/tengine:rw"
)
# Tengine 主配置文件(覆盖默认配置)
TENGINE_MAIN_CONF='user root;
worker_processes auto;
......@@ -76,30 +71,16 @@ log_step() { echo -e "${BLUE}[STEP]${NC} $1"; }
preflight_check() {
log_step "执行前置检查..."
# 检查 Docker
if ! command -v docker &> /dev/null; then
log_error "Docker 未安装"
exit 1
fi
# 检查基础镜像
if ! docker image inspect nginx:1.30.2 &> /dev/null; then
log_error "基础镜像 nginx:1.30.2 不存在"
if [ ! -f "$IMAGE_FILE" ]; then
log_error "镜像文件不存在: $IMAGE_FILE"
exit 1
fi
# 检查源码包
if [ ! -f "$TENGINE_TAR" ]; then
log_error "Tengine 源码包不存在: $TENGINE_TAR"
exit 1
fi
if [ ! -f "$DOCKERFILE_SRC" ]; then
log_error "Dockerfile 不存在: $DOCKERFILE_SRC"
exit 1
fi
# 检查挂载源目录
for mount in "${MOUNTS[@]}"; do
IFS=':' read -r src dest mode <<< "$mount"
if [ ! -d "$src" ] && [ ! -f "$src" ]; then
......@@ -108,58 +89,34 @@ preflight_check() {
fi
done
# 检查端口是否被占用
if ss -tlnp | grep -q ":${HOST_PORT} "; then
if ss -tlnp 2>/dev/null | grep -q ":${HOST_PORT} " || netstat -tlnp 2>/dev/null | grep -q ":${HOST_PORT} "; then
log_warn "端口 ${HOST_PORT} 已被占用,将先停止旧容器"
fi
log_info "前置检查通过"
}
# ==================== 构建镜像 ====================
build_image() {
# 如果镜像已存在,询问是否重建
# ==================== 加载镜像 ====================
load_image() {
if docker image inspect "$IMAGE_NAME" &> /dev/null; then
log_warn "镜像 $IMAGE_NAME 已存在"
read -p "是否重新构建?[y/N]: " rebuild
if [ "$rebuild" != "y" ] && [ "$rebuild" != "Y" ]; then
log_info "跳过构建,使用已有镜像"
read -p "是否重新加载?[y/N]: " reload
if [ "$reload" != "y" ] && [ "$reload" != "Y" ]; then
log_info "跳过加载,使用已有镜像"
return 0
fi
docker rmi "$IMAGE_NAME" 2>/dev/null || true
fi
log_step "准备构建目录..."
# 清理并创建构建目录
rm -rf "$BUILD_DIR"
mkdir -p "$BUILD_DIR"
cp "$DOCKERFILE_SRC" "$BUILD_DIR/Dockerfile"
cp "$TENGINE_TAR" "$BUILD_DIR/"
# 创建 .dockerignore
cat > "$BUILD_DIR/.dockerignore" << 'DOCKERIGNORE'
*
!Dockerfile
!tengine-3.1.0.tar.gz
DOCKERIGNORE
log_step "开始构建镜像(预计 5-10 分钟)..."
cd "$BUILD_DIR"
if docker build -t "$IMAGE_NAME" . ; then
log_info "镜像构建成功: $IMAGE_NAME"
else
log_error "镜像构建失败"
exit 1
fi
log_step "加载镜像..."
docker load -i "$IMAGE_FILE"
log_info "镜像加载完成"
}
# ==================== 停止旧容器 ====================
stop_old_container() {
log_step "停止旧容器..."
# 停止 utengine(如果正在运行)
if docker ps --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
log_info "停止现有 ${CONTAINER_NAME} 容器..."
docker stop "$CONTAINER_NAME" 2>/dev/null || true
......@@ -168,11 +125,10 @@ stop_old_container() {
docker rm "$CONTAINER_NAME" 2>/dev/null || true
fi
# 停止旧 unginx(如果正在运行)
if docker ps --format '{{.Names}}' | grep -q "^${OLD_CONTAINER}$"; then
log_info "停止旧 ${OLD_CONTAINER} 容器..."
docker stop "$OLD_CONTAINER"
log_info "${OLD_CONTAINER} 已停止(保留容器,可回滚用 docker start ${OLD_CONTAINER})"
log_info "${OLD_CONTAINER} 已停止(保留容器,回滚: docker start ${OLD_CONTAINER})"
fi
}
......@@ -180,7 +136,6 @@ stop_old_container() {
start_tengine() {
log_step "启动 Tengine 容器..."
# 构建 docker run 命令
local run_cmd="docker run -d --name ${CONTAINER_NAME}"
run_cmd+=" --restart always"
run_cmd+=" --network bridge"
......@@ -204,7 +159,6 @@ start_tengine() {
sleep 2
# 检查容器是否启动
if docker ps --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
log_info "容器已启动"
else
......@@ -218,14 +172,10 @@ start_tengine() {
configure_tengine() {
log_step "配置 Tengine 主配置文件..."
# 写入主配置文件到临时文件
echo "$TENGINE_MAIN_CONF" > /tmp/tengine_main.conf
# 拷入容器
docker cp /tmp/tengine_main.conf "${CONTAINER_NAME}:/etc/tengine/tengine.conf"
rm -f /tmp/tengine_main.conf
# 测试配置
if docker exec "$CONTAINER_NAME" nginx -t 2>&1; then
log_info "配置文件语法检查通过"
else
......@@ -233,7 +183,6 @@ configure_tengine() {
exit 1
fi
# 重载配置
docker exec "$CONTAINER_NAME" nginx -s reload 2>&1
log_info "配置已重载"
}
......@@ -242,17 +191,14 @@ configure_tengine() {
verify_deployment() {
log_step "验证部署..."
# 1. 容器状态
echo ""
echo "=== 容器状态 ==="
docker ps --filter "name=${CONTAINER_NAME}" --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
# 2. Tengine 版本
echo ""
echo "=== Tengine 版本 ==="
docker exec "$CONTAINER_NAME" nginx -v 2>&1
# 3. HTTPS 连通性测试
echo ""
echo "=== HTTPS 连通性测试 ==="
if curl -skI --connect-timeout 5 https://127.0.0.1/ 2>&1 | head -5; then
......@@ -261,7 +207,6 @@ verify_deployment() {
log_warn "HTTPS 测试异常,请检查"
fi
# 4. Server 头验证
echo ""
SERVER_HEADER=$(curl -skI --connect-timeout 5 https://127.0.0.1/ 2>&1 | grep -i "Server:" || echo "")
if echo "$SERVER_HEADER" | grep -qi "Tengine"; then
......@@ -270,7 +215,6 @@ verify_deployment() {
log_warn "Server 头未确认为 Tengine: $SERVER_HEADER"
fi
# 5. 编译模块
echo ""
echo "=== 编译的模块 ==="
docker exec "$CONTAINER_NAME" nginx -V 2>&1
......@@ -278,7 +222,7 @@ verify_deployment() {
echo ""
log_info "======== 部署完成 ========"
echo ""
echo " 访问地址: https://192.168.5.70"
echo " 访问地址: https://$(hostname -I 2>/dev/null | awk '{print $1}' || echo 'YOUR_IP')"
echo " 容器名称: ${CONTAINER_NAME}"
echo " 查看日志: docker logs -f ${CONTAINER_NAME}"
echo " 配置目录: /data/middleware/nginx/config/"
......@@ -291,19 +235,19 @@ verify_deployment() {
main() {
echo ""
echo "============================================"
echo " Tengine 容器一键部署脚本"
echo " Tengine 容器一键部署脚本 (X86)"
echo " 版本: 2.0 (docker load 模式)"
echo " 目标服务器: $(hostname)"
echo " 时间: $(date '+%Y-%m-%d %H:%M:%S')"
echo "============================================"
echo ""
preflight_check
build_image
load_image
stop_old_container
start_tengine
configure_tengine
verify_deployment
}
# 执行
main "$@"
#==============================================================#
# 函数名: docker_x86
# 功能: 检查并安装 Docker(x86_64 离线安装)
# 说明: 用于在无网络或受限环境中自动部署 Docker 引擎
# 若 Docker 已安装则跳过;否则从本地 tar 包离线安装
# 安装内容包括:
# - 解压 docker 二进制文件到 /usr/bin
# - 配置 systemd 服务文件
# - 启动并设置开机自启
# 作者: [ubains]
# 日期: $(date +%Y-%m-%d)
#--------------------------------------------------------------#
# 参数: 无
# 返回: 0: 成功(已安装或跳过)
# 1: 安装失败
#--------------------------------------------------------------#
# 依赖: tar, systemctl, sudo(通过 $sudoset)
# 注意: 请确保以下资源已提前上传:
# - /data/temp/docker-29.1.3.tgz
# - /data/temp/docker.service
#==============================================================#
function docker_x86() {
log "INFO" "=================================================================="
log "INFO" "开始检查并安装 Docker (x86_64 离线模式)"
log "INFO" "=================================================================="
# ------------------- 定义变量 -------------------
local docker_version="29.1.3"
local temp_dir="/data/temp"
local tar_file="${temp_dir}/docker-${docker_version}.tgz"
local service_file="${temp_dir}/docker.service"
local docker_bin="/usr/bin/docker"
# ------------------- 检查 Docker 是否已安装 -------------------
log "INFO" "🔍 正在检查 Docker 是否已安装..."
if command -v docker >/dev/null 2>&1; then
local version=$(docker --version 2>&1)
log "INFO" "✅ Docker 已安装: $version"
log "INFO" "💡 若需重装,请先手动卸载。"
return 0
else
log "WARN" "❌ Docker 未安装,准备从离线包安装..."
fi
# ------------------- 检查依赖和文件是否存在 -------------------
log "INFO" "🔧 检查安装依赖和文件..."
if [[ ! -f "$tar_file" ]]; then
log "ERROR" "⛔ Docker 离线包不存在: $tar_file"
log "ERROR" "请将 docker-${docker_version}.tgz 上传至 $temp_dir 目录"
return 1
fi
if [[ ! -f "$service_file" ]]; then
log "ERROR" "⛔ Docker systemd 服务文件不存在: $service_file"
log "ERROR" "请将 docker.service 配置文件上传至 $temp_dir 目录"
return 1
fi
# ------------------- 开始安装 Docker -------------------
log "INFO" "📥 开始解压 Docker ${docker_version} ..."
if $sudoset tar -xzf "$tar_file" -C "$temp_dir"; then
log "INFO" "✅ 解压成功"
else
log "ERROR" "⛔ 解压失败,请检查压缩包完整性"
return 1
fi
log "INFO" "📦 安装 Docker 二进制文件到 /usr/bin/ ..."
if $sudoset cp "$temp_dir/docker"/* /usr/bin/ && $sudoset chmod +x /usr/bin/docker*; then
log "INFO" "✅ Docker 核心命令安装完成"
else
log "ERROR" "⛔ Docker 二进制文件复制失败"
return 1
fi
# ------------------- 配置 systemd 服务 -------------------
log "INFO" "⚙️ 配置 Docker systemd 服务 ..."
$sudoset rm -f /etc/systemd/system/docker.service
if $sudoset cp "$service_file" /etc/systemd/system/docker.service; then
$sudoset chmod 644 /etc/systemd/system/docker.service
log "INFO" "✅ 服务文件已部署"
else
log "ERROR" "⛔ 服务文件复制失败"
return 1
fi
# ------------------- 启动 Docker 服务 -------------------
log "INFO" "🚀 正在启动 Docker 服务 ..."
$sudoset systemctl daemon-reload
if $sudoset systemctl start docker; then
log "INFO" "✅ Docker 服务启动成功"
else
log "ERROR" "⛔ Docker 启动失败,请检查日志: journalctl -u docker"
return 1
fi
if $sudoset systemctl enable docker.service; then
log "INFO" "✅ Docker 已设置为开机自启"
else
log "WARN" "⚠️ 设置开机自启失败,可能影响后续使用"
fi
# ------------------- 验证安装 -------------------
log "INFO" "🔍 验证 Docker 安装结果..."
if command -v docker >/dev/null 2>&1 && docker info >/dev/null 2>&1; then
log "INFO" "🎉 Docker 安装并启动成功!版本信息:"
docker --version
return 0
else
log "ERROR" "⛔ Docker 安装后验证失败,请手动排查"
return 1
fi
}
#==============================================================#
# 函数名: mysql_x86
# 功能: 部署基于 Docker 的 MySQL 服务(x86 架构)
# 说明: 1. 检查本地是否已运行 umysql 容器
# 2. 若无,则从离线 tar 加载镜像并启动容器
# 3. 初始化数据库:创建用户、数据库、授权
# 4. 配置定时备份脚本(每天 13:00)
# 作者: [ubains]
# 日期: $(date +%Y-%m-%d)
#--------------------------------------------------------------#
# 参数: 无
# 返回: 0: 成功
# 1: 失败
#--------------------------------------------------------------#
# 依赖: docker, crond (或 cronie), sudo
# 注意: 请确保以下资源已上传:
# - /data/temp/umysql.tar.gz
# - $PWD/UbainsmysqlBakUp.sh
# 并确保宿主机 /data/middleware/mysql/ 目录存在
#==============================================================#
function mysql_x86() {
# --- 配置参数 ---
local container_name="umysql"
local image_tar="/data/temp/mysql-8.0.46.tar.gz"
local image_name="mysql:8.0"
local image_id="4c5574ba4b04"
local mysql_root_password="dNrprU&2S"
local mysql_port="8306"
local host_data_dir="/data/middleware/mysql"
local backup_script_src="$PWD/UbainsmysqlBakUp.sh"
local backup_script_dst="/usr/local/docker/UbainsmysqlBakUp.sh"
local cron_user="root"
log "INFO" "=================================================================="
log "INFO" "开始部署 MySQL 服务 (Docker 版, x86)"
log "INFO" "=================================================================="
# 自动判断是否需要 sudo
local SUDO=""
if [[ $(id -u) -ne 0 ]]; then
if command -v sudo >/dev/null; then
SUDO="sudo"
else
log "ERROR" "⛔ 当前不是 root 用户,且系统未安装 sudo,无法执行操作"
return 1
fi
fi
# ------------------- 检查容器是否已运行 -------------------
log "INFO" "🔍 检查容器 '$container_name' 是否已运行..."
if $SUDO docker ps --format '{{.Names}}' | grep -qw "$container_name"; then
log "INFO" "✅ 容器 '$container_name' 已在运行"
return 0
fi
# ------------------- 检查镜像是否存在 -------------------
log "INFO" "🔍 检查镜像 $image_name 是否存在..."
if $SUDO docker images --format '{{.Repository}}:{{.Tag}}' | grep -qw "$image_name"; then
log "INFO" "✅ 镜像 $image_name 已存在"
else
log "WARN" "❌ 镜像 $image_name 不存在,开始加载离线包..."
if [[ ! -f "$image_tar" ]]; then
log "ERROR" "⛔ 镜像文件不存在: $image_tar"
return 1
fi
if $SUDO docker load -i "$image_tar"; then
log "INFO" "🎉 镜像加载成功"
else
log "ERROR" "⛔ 镜像加载失败,请检查文件完整性"
return 1
fi
fi
# ------------------- 启动容器 -------------------
log "INFO" "🚀 正在启动 MySQL 容器: $container_name"
$SUDO docker run -d \
--name "$container_name" \
--mac-address="02:42:ac:11:00:05" \
-p "${mysql_port}:3306" \
-v "${host_data_dir}/conf/my.cnf:/etc/mysql/my.cnf" \
-v "${host_data_dir}/conf.d:/etc/mysql/conf.d" \
-v "${host_data_dir}/log:/var/log/mysql" \
-v "${host_data_dir}/data:/var/lib/mysql" \
-v "/etc/localtime:/etc/localtime:ro" \
--restart=always \
-e "MYSQL_ROOT_PASSWORD=$mysql_root_password" \
"$image_name"
if [[ $? -ne 0 ]]; then
log "ERROR" "⛔ 容器启动失败,请检查端口占用或磁盘权限"
log "INFO" "📄 查看最近容器日志以排查问题..."
$SUDO docker logs "$container_name" 2>/dev/null || true
return 1
fi
sleep 120
log "INFO" "✅ 容器启动成功,等待 MySQL 服务就绪..."
# ------------------- 初始化数据库:创建用户、数据库、授权、导入数据 -------------------
log "INFO" "🔧 初始化数据库:创建用户、数据库、授权..."
# 定义要执行的 SQL 命令序列(注意顺序)
local init_sql=(
"CREATE USER IF NOT EXISTS 'nacos'@'%' IDENTIFIED BY 'nacos2025';"
"CREATE USER IF NOT EXISTS 'mysqluser'@'%' IDENTIFIED BY 'dNrprU&2S';"
"CREATE DATABASE IF NOT EXISTS nacos_mysql CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
"CREATE DATABASE IF NOT EXISTS devops CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
"CREATE DATABASE IF NOT EXISTS devops_voice CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
"CREATE DATABASE IF NOT EXISTS offline CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
"CREATE DATABASE IF NOT EXISTS huazhao2 CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
"GRANT ALL PRIVILEGES ON nacos_mysql.* TO 'nacos'@'%';"
"GRANT ALL PRIVILEGES ON devops.* TO 'mysqluser'@'%';"
"FLUSH PRIVILEGES;"
)
# 执行前半部分 SQL
for sql in "${init_sql[@]}"; do
$SUDO docker exec "$container_name" mysql -uroot -p"$mysql_root_password" -e "$sql"
if [[ $? -ne 0 ]]; then
log "ERROR" "⛔ 执行SQL语句失败: $sql"
log "INFO" "📄 输出容器最近日志..."
$SUDO docker logs "$container_name" | tail -30
return 1
fi
done
# 在导入数据后执行 IP 替换
log "INFO" "🔄 正在更新nacos_mysql配置中的 IP 地址..."
$SUDO docker exec "$container_name" mysql -uroot -p"$mysql_root_password" -D nacos_mysql -e \
"UPDATE config_info SET content = REPLACE(content, '192.168.9.84', '"$server_ip"')
WHERE data_id IN ('auth-sso-auth-dev.yml','auth-sso-gateway-dev.yml','auth-sso-system-dev.yml');"
# 修改system.yml连接mysql的地址
$SUDO docker exec "$container_name" mysql -uroot -p"$mysql_root_password" -D nacos_mysql -e \
"UPDATE config_info SET content = REPLACE(content, '"$server_ip"', '172.17.0.1')
WHERE data_id IN ('auth-sso-system-dev.yml');"
log "INFO" "🔄 正在保存配置..."
$SUDO docker exec "$container_name" mysql -uroot -p"$mysql_root_password" -D nacos_mysql -e \
"FLUSH PRIVILEGES;"
if [[ $? -eq 0 ]]; then
log "INFO" "✅ 配置保存成功"
else
log "ERROR" "⛔ 配置保存失败"
return 1
fi
# ------------------- 提升用户权限 -------------------
for user in "root" "mysqluser"; do
$SUDO docker exec "$container_name" mysql -u"root" -p"$mysql_root_password" -e \
"UPDATE mysql.user SET Grant_priv='Y', Super_priv='Y' WHERE User='$user' AND Host='%'; FLUSH PRIVILEGES;" 2>/dev/null
done
log "INFO" "✅ 用户权限提升完成"
# ------------------- 部署备份脚本 -------------------
log "INFO" "📦 部署备份脚本到容器..."
$SUDO mkdir -p "$(dirname "$backup_script_dst")"
if $SUDO cp -f "$backup_script_src" "$backup_script_dst"; then
$SUDO chmod +x "$backup_script_dst"
log "INFO" "✅ 备份脚本已复制到: $backup_script_dst"
else
log "ERROR" "⛔ 备份脚本复制失败,请检查源文件是否存在"
return 1
fi
# ------------------- 配置定时任务 -------------------
log "INFO" "⏰ 配置定时备份任务 (每天 13:00)"
local cron_job="0 13 * * * bash $backup_script_dst"
if $SUDO crontab -u "$cron_user" -l 2>/dev/null | grep -Fq "$backup_script_dst"; then
log "INFO" "✅ 定时任务已存在"
else
( $SUDO crontab -u "$cron_user" -l 2>/dev/null; echo "$cron_job" ) | $SUDO crontab -u "$cron_user" -
if [[ $? -eq 0 ]]; then
log "INFO" "✅ 定时任务添加成功"
else
log "ERROR" "⛔ 定时任务添加失败"
return 1
fi
fi
# ------------------- 重启 crond -------------------
log "INFO" "🔄 重启 crond 服务..."
if command -v systemctl >/dev/null; then
$SUDO systemctl restart crond || $SUDO systemctl restart cron
else
$SUDO service crond restart || $SUDO service cron restart
fi
log "INFO" "✅ crond 服务已重启"
# ------------------- 最终状态输出 -------------------
log "INFO" "🎉 MySQL 部署完成!"
$SUDO docker ps --filter "name=$container_name" --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
return 0
}
#x86架构安装mqtt
function emqx_x86()
{
# ------------------- 定义变量 -------------------
local container_name="uemqx"
local image_tar="/data/temp/uemqx-6.0.0.tar.gz"
local image_name="emqx/emqx:6.0.0"
local host_config_dir="/data/middleware/emqx/config"
local host_dir="/data/middleware/emqx"
log "INFO" "=================================================================="
log "INFO" "开始部署 EMQX 服务 (Docker 版, x86)"
log "INFO" "=================================================================="
# ------------------- 检查容器是否已运行 -------------------
log "INFO" "🔍 检查 EMQX 容器是否已运行..."
if $sudoset docker ps --format '{{.Names}}' | grep -wq "$container_name"; then
log "INFO" "✅ 容器 '$container_name' 已在运行。"
return 0
fi
# ------------------- 检查镜像是否存在 -------------------
log "INFO" "🔍 检查 EMQX 镜像是否存在..."
if $sudoset docker images --format '{{.Repository}}:{{.Tag}}' | grep -wq "$image_name"; then
log "INFO" "✅ 镜像 $image_name 已存在。"
else
log "WARN" "❌ 镜像 $image_name 不存在,开始加载离线包..."
if [[ ! -f "$image_tar" ]]; then
log "ERROR" "⛔ 镜像文件不存在: $image_tar"
return 1
fi
if $sudoset docker load -i "$image_tar"; then
log "INFO" "🎉 镜像加载成功"
else
log "ERROR" "⛔ 镜像加载失败,请检查文件完整性"
return 1
fi
fi
# EMQX 容器使用用户 1000:1000
$sudoset chown -R 1000:1000 "$host_dir"/{data,log}
log "INFO" "✅ 目录创建完成,权限已设置"
# ------------------- 启动 EMQX 容器 -------------------
log "INFO" "🚀 正在启动 EMQX 容器: $container_name ..."
$sudoset docker run -d \
--name "$container_name" \
--mac-address="02:42:ac:12:00:06" \
--privileged \
--restart=always \
-p 1883:1883 \
-p 8083:8083 \
-p 8883:8883 \
-v "$host_config_dir/emqx.conf:/opt/emqx/etc/emqx.conf:ro" \
-v "$host_config_dir/auth-built-in-db-bootstrap.csv:/opt/emqx/etc/auth-built-in-db-bootstrap.csv:ro" \
-v "$host_config_dir/acl.conf:/opt/emqx/etc/acl.conf:ro" \
-v "$host_dir/data:/opt/emqx/data" \
-v "$host_dir/log:/opt/emqx/log" \
"$image_name"
if [ $? -ne 0 ]; then
log "ERROR" "⛔ 容器启动失败"
return 1
fi
log "INFO" "✅ EMQX 容器启动成功,等待初始化..."
sleep 5
# ------------------- 验证容器状态 -------------------
if $sudoset docker ps --format '{{.Names}}' | grep -wq "$container_name"; then
log "INFO" "🎉 EMQX 部署完成!"
$sudoset docker ps --filter "name=$container_name" --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
else
log "ERROR" "⛔ 容器启动后未运行,请检查日志: docker logs $container_name"
return 1
fi
return 0
}
function redis_x86()
{
# ------------------- 定义变量 -------------------
local container_name="uredis"
local image_tar="/data/temp/redis-8.8.0.tar.gz"
local image_name="redis:8"
local image_id="3bd8c109f88b"
local redis_conf_host="/data/middleware/redis/config/redis.conf"
local redis_data_host="/data/middleware/redis/data"
local redis_port="6379"
log "INFO" "=================================================================="
log "INFO" "开始部署 Redis 服务 (Docker 版, x86)"
log "INFO" "=================================================================="
# ------------------- 检查容器是否已运行 -------------------
log "INFO" "🔍 检查 Redis 容器是否已运行..."
if $sudoset docker ps --format '{{.Names}}' | grep -wq "$container_name"; then
log "INFO" "✅ 容器 '$container_name' 已在运行。"
return 0
fi
# ------------------- 自动配置 sysctl -------------------
log "INFO" "🔧 配置系统参数: /etc/sysctl.conf"
local sysctl_config="
#新增
net.core.somaxconn = 511
vm.overcommit_memory = 1
"
# 检查是否已存在配置,避免重复添加
if ! grep -Fq "#新增" /etc/sysctl.conf; then
echo "$sysctl_config" | $sudoset tee -a /etc/sysctl.conf > /dev/null
if [ $? -eq 0 ]; then
log "INFO" "✅ sysctl 配置已追加"
else
log "ERROR" "⛔ 写入 /etc/sysctl.conf 失败,请检查权限"
return 1
fi
else
log "INFO" "✅ sysctl 配置已存在,跳过添加"
fi
# 应用配置
$sudoset sysctl -p > /dev/null 2>&1
if [ $? -eq 0 ]; then
log "INFO" "✅ sysctl 参数已生效"
else
log "WARN" "⚠️ sysctl -p 执行可能有警告,继续执行"
fi
# ------------------- 检查镜像是否存在 -------------------
log "INFO" "🔍 检查 Redis 镜像是否存在..."
if $sudoset docker images --format '{{.Repository}}:{{.Tag}}' | grep -wq "$image_name"; then
log "INFO" "✅ 镜像 $image_name 已存在。"
else
log "WARN" "❌ 镜像 $image_name 不存在,开始加载离线包..."
if [[ ! -f "$image_tar" ]]; then
log "ERROR" "⛔ 镜像文件不存在: $image_tar"
return 1
fi
if $sudoset docker load -i "$image_tar"; then
log "INFO" "🎉 镜像加载成功"
else
log "ERROR" "⛔ 镜像加载失败,请检查文件完整性"
return 1
fi
fi
# ------------------- 启动 Redis 容器 -------------------
log "INFO" "🚀 正在启动 Redis 容器: $container_name ..."
$sudoset docker run -d \
--name "$container_name" \
--security-opt seccomp=unconfined \
--network host \
-v "$redis_conf_host:/etc/redis/redis.conf" \
-v "$redis_data_host:/data" \
-v "/etc/localtime:/etc/localtime:ro" \
--restart=always \
"$image_name" \
redis-server /etc/redis/redis.conf --appendonly yes
if [ $? -ne 0 ]; then
log "ERROR" "⛔ 容器启动失败"
return 1
fi
log "INFO" "✅ Redis 容器启动成功,等待初始化..."
sleep 5
# ------------------- 验证状态 -------------------
if $sudoset docker ps --format '{{.Names}}' | grep -wq "$container_name"; then
log "INFO" "🎉 Redis 部署完成!"
$sudoset docker ps --filter "name=$container_name" --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
else
log "ERROR" "⛔ 容器启动后未运行,请检查日志: docker logs $container_name"
return 1
fi
return 0
}
#安装fastfds
function fastfds_x86()
{
# ------------------- 定义变量 -------------------
local image_tar="/data/temp/ufastdfs-v2.tar.gz"
local image_name="ufastdfs:v2"
local tracker_container="utracker"
local storage_container="ustorage"
local tracker_host_dir="/data/storage/tracker"
local storage_host_dir="/data/storage/storage"
log "INFO" "=================================================================="
log "INFO" "开始部署 FastDFS 服务 (Docker 版, x86)"
log "INFO" "=================================================================="
# 自动获取本机 IP(优先使用非 loopback 的 IPv4)
local host_ip
host_ip=$(ip -4 addr show scope global | grep -oP '(?<=inet\s)\d+(\.\d+){3}' | head -n1)
if [[ -z "$host_ip" ]]; then
host_ip=$(hostname -I | awk '{print $1}')
fi
if [[ -z "$host_ip" ]]; then
log "ERROR" "⛔ 无法获取本机 IP 地址"
return 1
fi
log "INFO" "🌐 检测到本机 IP: $host_ip"
# ------------------- 检查两个容器是否都已运行 -------------------
log "INFO" "🔍 检查 FastDFS 容器是否已运行..."
local tracker_running=false
local storage_running=false
if $sudoset docker ps --format '{{.Names}}' | grep -wq "^$tracker_container$"; then
tracker_running=true
log "INFO" "✅ 容器 '$tracker_container' 已在运行。"
fi
if $sudoset docker ps --format '{{.Names}}' | grep -wq "^$storage_container$"; then
storage_running=true
log "INFO" "✅ 容器 '$storage_container' 已在运行。"
fi
if [[ "$tracker_running" == true && "$storage_running" == true ]]; then
log "INFO" "🎉 FastDFS 服务已全部运行,跳过安装。"
return 0
fi
# ------------------- 检查镜像是否存在 -------------------
log "INFO" "🔍 检查 FastDFS 镜像是否存在..."
if $sudoset docker images --format '{{.Repository}}:{{.Tag}}' | grep -wq "$image_name"; then
log "INFO" "✅ 镜像 $image_name 已存在。"
else
log "WARN" "❌ 镜像 $image_name 不存在,开始加载离线包..."
if [[ ! -f "$image_tar" ]]; then
log "ERROR" "⛔ 镜像文件不存在: $image_tar"
return 1
fi
if $sudoset docker load -i "$image_tar"; then
log "INFO" "🎉 镜像加载成功"
else
log "ERROR" "⛔ 镜像加载失败,请检查文件完整性"
return 1
fi
fi
# ------------------- 启动 Tracker 容器 -------------------
if [[ "$tracker_running" == false ]]; then
log "INFO" "🚀 正在启动 Tracker 服务: $tracker_container ..."
$sudoset docker run -d \
--network=host \
--name "$tracker_container" \
--restart=always \
-v "$tracker_host_dir:/var/fdfs" \
-v "/etc/localtime:/etc/localtime:ro" \
"$image_name" \
tracker
if [ $? -ne 0 ]; then
log "ERROR" "⛔ Tracker 容器启动失败"
return 1
fi
log "INFO" "✅ Tracker 启动成功"
fi
# ------------------- 启动 Storage 容器 -------------------
if [[ "$storage_running" == false ]]; then
log "INFO" "🚀 正在启动 Storage 服务: $storage_container ..."
$sudoset docker run -d \
--network=host \
--name "$storage_container" \
--restart=always \
-e TRACKER_SERVER="192.168.5.51:22122,192.168.5.52:22122,192.168.5.53:22122" \
-v "$storage_host_dir:/var/fdfs" \
-v "/etc/localtime:/etc/localtime:ro" \
"$image_name" \
storage
if [ $? -ne 0 ]; then
log "ERROR" "⛔ Storage 容器启动失败"
return 1
fi
log "INFO" "✅ Storage 启动成功"
fi
# ------------------- 等待并验证 -------------------
log "INFO" "⏳ 等待服务初始化..."
sleep 8
local all_running=true
for container in "$tracker_container" "$storage_container"; do
if ! $sudoset docker ps --format '{{.Names}}' | grep -wq "^$container$"; then
log "ERROR" "⛔ 容器 '$container' 启动后未运行"
all_running=false
fi
done
if [[ "$all_running" == true ]]; then
log "INFO" "🎉 FastDFS 部署完成!"
$sudoset docker ps --filter "name=utracker" --filter "name=ustorage" --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
else
log "ERROR" "⛔ 部分容器启动失败,请检查日志: docker logs utracker / ustorage"
return 1
fi
return 0
}
#安装ngrok
function ngrok_x86()
{
# ------------------- 定义变量 -------------------
local container_name="ungrok"
local image_tar="/data/temp/ungrok2.tar.gz"
local image_name="ngrok:v1"
local image_id="493b3f514dfd"
local ngrok_script_host="/data/middleware/ngrok/ngrok.sh"
local ngrok_script_container="/home/ngrok.sh"
log "INFO" "=================================================================="
log "INFO" "开始部署 ngrok 服务 (Docker 版, x86)"
log "INFO" "=================================================================="
# ------------------- 检查容器是否已运行 -------------------
log "INFO" "🔍 检查 ngrok 容器是否已运行..."
if $sudoset docker ps --format '{{.Names}}' | grep -wq "^$container_name$"; then
log "INFO" "✅ 容器 '$container_name' 已在运行。"
return 0
fi
# ------------------- 检查镜像是否存在 -------------------
log "INFO" "🔍 检查 ngrok 镜像是否存在..."
if $sudoset docker images --format '{{.Repository}}:{{.Tag}}' | grep -wq "^$image_name$"; then
log "INFO" "✅ 镜像 $image_name 已存在。"
else
log "WARN" "❌ 镜像 $image_name 不存在,开始加载离线包..."
if [[ ! -f "$image_tar" ]]; then
log "ERROR" "⛔ 镜像文件不存在: $image_tar"
return 1
fi
if $sudoset docker load -i "$image_tar"; then
log "INFO" "🎉 镜像加载成功"
else
log "ERROR" "⛔ 镜像加载失败,请检查文件完整性"
return 1
fi
# 打标签
$sudoset docker tag "$image_id" "$image_name" 2>/dev/null || true
log "INFO" "🏷️ 镜像已标记为 $image_name"
fi
# ------------------- 检查 ngrok 启动脚本 -------------------
if [[ ! -f "$ngrok_script_host" ]]; then
log "ERROR" "⛔ ngrok 启动脚本不存在: $ngrok_script_host"
return 1
fi
if [[ ! -x "$ngrok_script_host" ]]; then
log "WARN" "🔧 ngrok 脚本无执行权限,正在添加..."
$sudoset chmod +x "$ngrok_script_host"
if [ $? -ne 0 ]; then
log "ERROR" "⛔ 无法为 $ngrok_script_host 添加执行权限"
return 1
fi
fi
log "INFO" "✅ ngrok 启动脚本检查通过"
# ------------------- 启动 ngrok 容器 -------------------
log "INFO" "🚀 正在启动 ngrok 容器: $container_name ..."
$SUDO docker run -d \
--name "$container_name" \
--restart=always \
--network=host \
-v /etc/localtime:/etc/localtime \
-v "$ngrok_script_host":/home/ngrok.sh \
"$image_name"
if [ $? -ne 0 ]; then
log "ERROR" "⛔ 容器启动失败"
return 1
fi
log "INFO" "✅ ngrok 容器已启动,等待初始化..."
sleep 5
# ------------------- 验证容器状态 -------------------
if $sudoset docker ps --format '{{.Names}}' | grep -wq "^$container_name$"; then
log "INFO" "🎉 ngrok 服务部署完成!"
$sudoset docker ps --filter "name=$container_name" --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
else
log "ERROR" "⛔ 容器启动后未运行,请检查日志: docker logs $container_name"
return 1
fi
return 0
}
function nacos_x86() {
# --- 配置变量 ---
local container_name="unacos"
local image_tag="nacos-server:v2.5.2"
local tar_image="/data/temp/nacos-server-v2.5.2.tar.gz"
local host_data_dir="/data/middleware/nacos"
# 🔐 新增认证配置
local nacos_username="nacos" # 用户名
local nacos_password="dNrprU&2S" # 密码
log "INFO" "=================================================================="
log "INFO" "开始部署 Nacos Server (Standalone) - x86"
log "INFO" "=================================================================="
# 自动判断 sudo
local SUDO=""
if [[ $(id -u) -ne 0 ]]; then
if command -v sudo >/dev/null; then
SUDO="sudo"
else
log "ERROR" "⛔ 当前不是 root 用户且无 sudo 权限"
return 1
fi
fi
# --- 1. 检查容器是否已在运行 ---
if $SUDO docker ps --format '{{.Names}}' | grep -wq "^$container_name$"; then
log "INFO" "✅ 容器 '$container_name' 已在运行,跳过部署。"
log "INFO" "🎉 访问地址: http://\$IP:8848/nacos (默认账号密码: nacos/nacos)"
return 0
fi
# --- 2. 检查镜像是否存在 ---
if $SUDO docker images --format '{{.Repository}}:{{.Tag}}' | grep -wq "^$image_tag$"; then
log "INFO" "✅ 镜像 '$image_tag' 已存在,跳过加载。"
else
log "INFO" "📦 开始加载离线镜像包: $tar_image"
# 检查离线包是否存在
if [[ ! -f "$tar_image" ]]; then
log "ERROR" "⛔ 镜像文件不存在: $tar_image"
log "INFO" "请确保已上传 nacos-server-v2.5.1.tar.gz 到 /data/temp/"
return 1
fi
# 加载镜像
if ! $SUDO docker load -i "$tar_image"; then
log "ERROR" "⛔ 镜像加载失败,请检查文件是否完整或已损坏"
return 1
fi
log "INFO" "✅ 镜像加载成功"
fi
# --- 3. 启动 Nacos 容器 ---
log "INFO" "🚀 正在启动 Nacos 容器..."
$SUDO docker run -d \
--name "$container_name" \
--restart=always \
-p 8848:8848 \
-p 9848:9848 \
-e MODE=standalone \
-e NACOS_AUTH_ENABLE=true \
-e NACOS_AUTH_USERNAME="$nacos_username" \
-e NACOS_AUTH_PASSWORD="$nacos_password" \
-e NACOS_AUTH_IDENTITY_KEY="nacos" \
-e NACOS_AUTH_IDENTITY_VALUE="nacos" \
-v "$host_data_dir:/home/nacos" \
--mac-address="02:42:ac:11:00:10" \
"$image_tag"
if [[ $? -ne 0 ]]; then
log "ERROR" "⛔ Nacos 容器启动失败"
return 1
fi
log "INFO" "✅ Nacos 容器已启动,名称: $container_name"
# --- 4. 状态确认(容器是否仍在运行)---
sleep 5
if ! $SUDO docker ps --format '{{.Names}}' | grep -wq "^$container_name$"; then
log "ERROR" "⛔ 容器启动后退出,请检查日志: $SUDO docker logs $container_name"
return 1
fi
# --- 5. 获取本机 IP 地址 ---
local server_ip=$(ip addr show | grep -E 'inet\s+(192\.168|172\.1[6789]\.|172\.2[0-9]\.|172\.3[01]\.|10\.)' | awk '{print $2}' | cut -d/ -f1 | head -n1)
if [[ -z "$server_ip" ]]; then
# 回退到 hostname -I
server_ip=$(hostname -I | awk '{print $1}')
fi
# --- 6. 输出访问信息 ---
if [[ -n "$server_ip" ]]; then
log "INFO" "✅ Nacos 部署完成!"
log "🎉 可通过浏览器访问: http://$server_ip:8848/nacos"
log "💡 默认账号密码: nacos / nacos"
else
log "INFO" "🎉 Nacos 部署完成。"
log "💡 默认账号密码: nacos / nacos"
log "📌 无法获取服务器 IP,请手动确认访问地址: http://<your-ip>:8848/nacos"
fi
return 0
}
function nginx_x86() {
# ------------------- 定义变量 -------------------
local temp_dir="/data/temp"
local nginx_version="1.30.2"
local nginx_image="nginx:${nginx_version}"
local nginx_container_name="unginx"
local nginx_image_tar="${temp_dir}/nginx-${nginx_version}.tar.gz"
local required_dirs=(
"/data/middleware/nginx/log"
"/data/middleware/nginx/data/cache"
"/data/middleware/nginx/data/html"
"/data/middleware/nginx/config"
"/data/services/web"
"/data/security/nginx_cert"
)
log "INFO" "=================================================================="
log "INFO" "开始部署 Nginx (离线编译安装) - x86"
log "INFO" "=================================================================="
# 目录预检查,缺失则创建
for dir in "${required_dirs[@]}"; do
if [ ! -d "$dir" ]; then
log "WARN" "目录 $dir 不存在,自动创建"
mkdir -p "$dir" || {
log "ERROR" "目录 $dir 创建失败"
return 1
}
fi
done
#创建nginx用户
groupadd -r nginx
useradd -r -g nginx -s /sbin/nologin -d /var/cache/nginx nginx
#检查是否创建成功
id nginx
#赋予权限
chown -R nginx:nginx /data/middleware/nginx/data/cache
chmod -R 755 /data/middleware/nginx/data/cache
# 赋予权限
chown -R 1000:1000 /data/middleware/nginx/log
chown -R 1000:1000 /data/middleware/nginx/data/cache
chmod -R 700 /data/middleware/nginx/data/cache
# 校验镜像包
if [ ! -s "$nginx_image_tar" ]; then
log "ERROR" "离线包 $nginx_image_tar 不存在或为空"
return 1
fi
# 加载镜像文件
if ! docker load -i "$nginx_image_tar"; then
log "ERROR" "镜像加载失败"
return 1
fi
log "INFO" "镜像加载成功"
# 检查容器是否存在
if docker ps -a --format '{{.Names}}' | grep -qw "$nginx_container_name"; then
log "WARN" "容器 $nginx_container_name 已存在,自动退出部署操作!!!"
return 0
fi
# 生成容器
if ! docker run -d \
--name "$nginx_container_name" \
--restart=always \
--mac-address "02:42:ac:11:00:25" \
-v /etc/localtime:/etc/localtime:ro \
-p 443:443 \
-v /data/middleware/nginx/config:/etc/nginx/conf.d \
-v /data/middleware/nginx/data/html:/usr/share/nginx/html \
-v /data/middleware/nginx/log:/var/log/nginx \
-v /data/middleware/nginx/data/cache:/var/cache/nginx \
-v /data/services/web:/data/services/web:rw \
-v /data/security/nginx_cert:/data/security/nginx_cert:ro \
"$nginx_image"; then
log "ERROR" "容器 $nginx_container_name 启动失败"
return 1
fi
# 拷贝/data/temp/nginx.conf到容器内/etc/nginx/目录下
docker cp /data/temp/nginx.conf $nginx_container_name:/etc/nginx/
log "INFO 已将nginx.conf复制到容器内/etc/nginx/目录下"
# 重启unginx容器
docker restart $nginx_container_name
log "INFO" "容器 $nginx_container_name 启动成功"
return 0
}
#===================================================================================
# 函数名称:install_middleware
# 功能说明:中间件部署主入口函数,解析参数并调用对应的中间件部署函数
# 参数说明:通过环境变量 middleware_type 传入中间件类型,多个用空格分隔
# 支持的中间件:redis、mysql、emqx、fdfs、ngrok、nacos、nginx
# 返回值:0-部署成功, 1-部署失败
#===================================================================================
install_middleware() {
log "INFO" "=================================================================="
log "INFO" "开始部署中间件服务"
log "INFO" "=================================================================="
# ------------------- 初始化变量 -------------------
# 初始化sudo相关变量
if [[ $(id -u) -ne 0 ]]; then
sudoset="sudo"
SUDO="sudo"
else
sudoset=""
SUDO=""
fi
# server_ip由主脚本传入
if [[ -z "$server_ip" ]]; then
log "WARN" "未传入服务器IP地址"
else
log "INFO" "服务器IP地址: $server_ip"
fi
# ------------------- 优先部署Docker环境 -------------------
# Docker是所有中间件的基础,必须无条件优先部署
log "INFO" "----------------------------------------"
log "INFO" "优先部署Docker环境"
if docker_x86; then
log "INFO" "✅ Docker环境部署成功"
else
log "ERROR" "❌ Docker环境部署失败,停止中间件部署"
return 1
fi
# ------------------- 解析参数 -------------------
local middlewares="${middleware_type:-}"
if [[ -z "$middlewares" ]]; then
log "ERROR" "未指定中间件类型,请通过middleware_type环境变量指定"
return 1
fi
log "INFO" "待部署的中间件: $middlewares"
# ------------------- 中间件函数映射 -------------------
declare -A middleware_map=(
["mysql"]="mysql_x86"
["emqx"]="emqx_x86"
["redis"]="redis_x86"
["fdfs"]="fastfds_x86"
["ngrok"]="ngrok_x86"
["nacos"]="nacos_x86"
["nginx"]="nginx_x86"
)
# ------------------- 遍历部署中间件 -------------------
local deploy_failed=0
local deploy_order=()
# 按照建议顺序排序部署(mysql优先)
for middleware in mysql redis emqx nacos fdfs ngrok nginx; do
if [[ "$middlewares" =~ $middleware ]]; then
deploy_order+=("$middleware")
fi
done
# 执行部署
for middleware in "${deploy_order[@]}"; do
local func_name="${middleware_map[$middleware]}"
if [[ -z "$func_name" ]]; then
log "ERROR" "未找到中间件 '$middleware' 对应的部署函数"
deploy_failed=1
continue
fi
log "INFO" "----------------------------------------"
log "INFO" "开始部署: $middleware"
# 调用对应的部署函数
if $func_name; then
log "INFO" "✅ $middleware 部署成功"
else
log "ERROR" "❌ $middleware 部署失败"
deploy_failed=1
fi
done
# ------------------- 返回结果 -------------------
log "INFO" "=================================================================="
if [[ $deploy_failed -eq 0 ]]; then
log "INFO" "所有中间件部署完成"
return 0
else
log "ERROR" "部分中间件部署失败,请检查日志"
return 1
fi
}
......@@ -68,7 +68,7 @@ sudo DM_PWD='MyComplexPwd@2026' DM_PORT=5237 DM_INSTANCE=DMSERVER2 bash auto_dep
| 容器名 | `udm` |
| 端口 | `5236` |
| 账号 | `SYSDBA` |
| 密码 | `Dameng@2026`(可通过 `DM_PWD` 环境变量修改) |
| 密码 | `dNrprU&2S!`(可通过 `DM_PWD` 环境变量修改) |
| 实例名 | `DMSERVER` |
| 页大小 | 16K |
| 字符集 | UNICODE (UTF-8) |
......@@ -81,7 +81,7 @@ sudo DM_PWD='MyComplexPwd@2026' DM_PORT=5237 DM_INSTANCE=DMSERVER2 bash auto_dep
```bash
# 容器内连接
docker exec -it udm /opt/dmdbms/bin/disql SYSDBA/Dameng@2026
docker exec -it udm /opt/dmdbms/bin/disql SYSDBA/dNrprU\&2S!
# 外部 JDBC 连接
jdbc:dm://192.168.5.46:5236
......
......@@ -43,7 +43,7 @@ function log() {
# ------------------- 可配置参数 -------------------
CONTAINER_NAME="${DM_CONTAINER_NAME:-udm}" # 容器名(遵循仓库 u 前缀规则)
DM_PORT="${DM_PORT:-5236}" # 达梦默认端口
SYSDBA_PWD="${DM_PWD:-Dameng@2026}" # SYSDBA 密码(须满足复杂度:长度≥9、大小写+数字+特殊符号)
SYSDBA_PWD="${DM_PWD:-dNrprU&2S!}" # SYSDBA 密码(须满足复杂度:长度≥9、大小写+数字+特殊符号)
INSTANCE_NAME="${DM_INSTANCE:-DMSERVER}" # 实例名
PAGE_SIZE="${DM_PAGE_SIZE:-16}" # 页大小
EXTENT_SIZE="${DM_EXTENT_SIZE:-16}" # 簇大小
......@@ -310,6 +310,33 @@ setup_backup() {
return 0
}
#==============================================================#
# 函数: import_databases
# 功能: 如果 databases/ 目录下有 DDL SQL 文件,则导入业务表结构
#==============================================================#
IMPORT_SCRIPT_SRC="$DEPLOY_DIR/import_dm8_databases.sh"
import_databases() {
if [[ ! -d "$DEPLOY_DIR/databases" ]]; then
log "INFO" "⏩ databases/ 目录不存在,跳过业务表导入"
return 0
fi
# 检查是否有 DDL SQL 文件
local ddl_count=$(ls "$DEPLOY_DIR/databases"/*_ddl.sql 2>/dev/null | wc -l)
if [[ $ddl_count -eq 0 ]]; then
log "INFO" "⏩ databases/ 下无 DDL SQL 文件,跳过业务表导入"
return 0
fi
if [[ ! -f "$IMPORT_SCRIPT_SRC" ]]; then
log "WARN" "⚠️ 导入脚本不存在: $IMPORT_SCRIPT_SRC,跳过业务表导入"
return 0
fi
log "INFO" "📦 检测到 $ddl_count 个 DDL SQL 文件,开始导入业务表..."
# 调用导入脚本,传入容器名和密码
bash "$IMPORT_SCRIPT_SRC"
log "INFO" "✅ 业务表导入完成"
return 0
}
#==============================================================#
# 函数: print_summary
# 功能: 输出连接信息与后续操作
......@@ -355,6 +382,7 @@ main() {
run_container || exit 1
wait_dm_ready || log "WARN" "⚠️ 自动登录验证未通过,请按提示手动验证(不阻断部署)"
setup_backup
import_databases
print_summary
$SUDO docker ps --filter "name=$CONTAINER_NAME" --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论