【无标题】

1. 背景

最近安装consul加配置很费劲,所以就写了个一键安装的脚本。

1.1. 使用环境

感觉对环境要求不大,此处列出我的使用环境:

  1. 操作系统:ubuntu20.04
  2. consul版本:v1.15.3

1.2. 安装准备

需要先下载好consul文件,将正文中的两个脚本内容保存至setupConsul.sh与testConsul.sh文件中,然后与consul放置在同一目录下。如图所示,放置路径随意。
备注:如果觉得单独下载麻烦也可以在脚本中增加下载命令。
在这里插入图片描述

1.3. 运行步骤

打开命令行,执行如下命令

# 赋予执行权限并运行
sudo chmod +x setupConsul.sh
./setupConsul.sh

2. 正文

2.1. 安装脚本

setupConsul.sh

#!/bin/bash
# 离线安装 Consul 

# ---------- 配置变量 ----------
readonly BIN_DIR="/usr/local/bin"
readonly DATA_DIR="/opt/consul"
readonly CONF_PATH="/etc/consul.d"
readonly CONF_FILE="$CONF_PATH/consul.json"
readonly ADMIN_PASSWORD="1" # 电脑密码需要修改
readonly SERVICE_PATH="/etc/systemd/system"
readonly SERVICE_FILE="$SERVICE_PATH/consul.service"

set -euo pipefail  # 启用严格错误处理

# ---------- 函数定义 ----------

# 提权执行函数
run_as_root() {
    if [ "$(id -u)" -ne 0 ]; then
        echo "$ADMIN_PASSWORD" | sudo -S "$@" 2>/dev/null
    else
        "$@"
    fi
}

# 获取网络IP地址
get_network_ips() {
    ip addr | grep 'inet ' | grep -v '127.0.0.1' | awk '{print $2}' | cut -d'/' -f1
}

# 选择网卡IP地址
select_ip() {
    local ips=($(get_network_ips))
    local count=${#ips[@]}
    
    if [[ $count -eq 0 ]]; then
        echo "❌ 未找到可用网卡" >&2
        exit 1
    elif [[ $count -eq 1 ]]; then
        echo -e "ℹ️  \033[36m检测为单网卡,自动设置IP。\033[0m"
        selected_ip="${ips[0]}"
    else
        echo "🔍 检测到多个网卡,请选择:"
        for i in "${!ips[@]}"; do
            echo "$((i+1)). ${ips[$i]}"
        done
        
        while true; do
            read -p "➡️ 请输入选择序号 (1-$count): " choice
            if [[ $choice =~ ^[0-9]+$ ]] && ((choice >= 1 && choice <= count)); then
                selected_ip="${ips[$((choice-1))]}"
                break
            else
                echo "❌ 无效选择,请重新输入"
            fi
        done
    fi
    echo "✅ IP设置为: $selected_ip"
}

# 卸载Consul
uninstall_consul() {
    if command -v consul &>/dev/null; then
        # 用户确认
        echo -e "检测到已安装Consul。按回车继续卸载(Ctrl+C取消)..."
        echo -e "\033[33m⚠️  警告: 若当前节点属于Consul集群!强制卸载可能导致数据不一致。\033[0m"
        read -r

        # 停止服务
        echo "1. 卸载:"
        echo "1.1. 停止进程"
        if systemctl is-active --quiet consul 2>/dev/null || pgrep -x consul >/dev/null; then
            echo "1)停止Consul服务"
            run_as_root systemctl stop consul 2>/dev/null || {
                echo "2)强制终止残留进程"
                run_as_root pkill -9 consul 2>/dev/null
            }
            sleep 2
        fi

        # 执行卸载
        echo "1.2. 执行卸载"
        echo "1)删除二进制文件"
        run_as_root rm -f "$BIN_DIR/consul" 2>/dev/null || true
        echo "2)删除配置和数据"
        run_as_root rm -rf "$CONF_PATH" "$DATA_DIR" 2>/dev/null || true
        echo "3)清理系统服务"
        run_as_root rm -f "$SERVICE_FILE" 2>/dev/null || true
        run_as_root systemctl daemon-reload 2>/dev/null || true
        echo "4)删除专用用户"
        run_as_root userdel consul 2>/dev/null || true

        echo -e "✅ \033[32m卸载完成!\033[0m\n"
    else
        echo -e "❌ \033[32m系统未安装Consul,跳过卸载\033[0m\n"
    fi
}

# 安装二进制文件
install_binary() {
    echo "2.1. 安装 Consul 二进制文件"
    run_as_root cp "consul" "$BIN_DIR/"
    run_as_root chmod +x "$BIN_DIR/consul"
}

# 创建用户和目录
setup_dirs_and_user() {
    echo "2.2. 创建系统用户和目录"
    id -u consul &>/dev/null || run_as_root useradd --system --home "$CONF_PATH" --shell /bin/false consul
    run_as_root mkdir -p "$DATA_DIR" "$CONF_PATH" "$SERVICE_PATH"
    run_as_root chmod 777 -R "$DATA_DIR" "$CONF_PATH" "$SERVICE_PATH"
    echo -e "✅ \033[32m安装完成!\033[0m\n"
}

# 生成配置文件
generate_config() {
    echo "2.3. 生成 JSON 配置文件"
    cat > "$CONF_FILE" << EOF
{
  "data_dir": "$DATA_DIR",
  "node_name": "node1",   
  "server": true,
  "bind_addr": "$selected_ip",
  "client_addr": "0.0.0.0",
  "bootstrap_expect": 3,  
  "log_level": "INFO",
  "retry_join":["$selected_ip","192.168.187.133","192.168.187.134"],
  "ui_config": {
    "enabled": true
  }
}
EOF
    
    # 验证配置文件
    if ! consul validate /etc/consul.d/; then
        echo "❌ 配置验证失败"
    fi
}

# 配置系统服务
setup_systemd_service() {
    echo "配置 Systemd 服务"
    cat > "$SERVICE_FILE" << EOF
[Unit]
Description=Consul Service Discovery Agent
After=network.target

[Service]
Type=simple
User=root
ExecStart=/usr/local/bin/consul agent -config-dir=/etc/consul.d
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF
}

# 启动服务
start_consul_service() {
    echo "启动 Consul 服务"
    run_as_root systemctl daemon-reload
    run_as_root systemctl enable consul
    run_as_root systemctl start consul
}

# 验证安装
verify_installation() {
    echo -e "4.验证:可以点击ctrl+左键,访问Web UI:\033[34mhttp://$selected_ip:8500/ui\033[0m"
    local consul_version_output=$(consul --version 2>&1)
    local exit_code=$?

    if [[ $exit_code -eq 0 ]]; then
        if [[ $consul_version_output =~ [Cc]onsul[[:space:]]+v?[0-9]+\.[0-9]+\.[0-9]+ ]]; then
            echo -e "✅ \033[32m安装成功!\033[0m\n"
            echo -e "ℹ️  \033[36m版本信息:\033[0m\n$consul_version_output\n"
        else
            echo "❌ 输出异常:未识别到版本号" >&2
            echo "输出内容:$consul_version_output" >&2
        fi
    else
        case $exit_code in
            127) echo "❌ Consul 未安装:命令不存在" >&2 ;;
            *)   echo "❌ Consul 执行失败(错误码 $exit_code)" >&2
                 echo "输出内容:$consul_version_output" >&2 ;;
        esac
    fi
}

# 验证运行状态
verify_running_status() {

    echo -en "5. 运行:等待服务初始化(约3秒)"
    gnome-terminal --tab -t "单节点启动consul" -- bash -c \
     "echo '单节点启动consul...';
      consul agent -dev -config-dir=/etc/consul.d -bootstrap-expect=1
      exec bash;"

    # 健康检查等待
    for i in {1..3}; do
      echo -n "."
      sleep 1
    done
    echo

    ./testConsul.sh
}

# ---------- 主执行流程 ----------
main() {
    # 卸载检测
    uninstall_consul
    
    # 安装步骤
    echo "2. 安装:"
    install_binary
    setup_dirs_and_user
    
    echo "3. 设置:"
    select_ip
    generate_config
    
    # 以下服务配置可根据需要取消注释
    # setup_systemd_service
    # start_consul_service
    
    echo -e "✅ \033[32m设置完成!\033[0m\n"
    
    # 验证安装
    verify_installation
    
    # 验证运行状态
    verify_running_status
}

# 执行主函数
main

2.2.测试脚本

#!/bin/bash


# 运行 consul members 并捕获输出及状态码
members_output=$(consul members 2>&1)
exit_code=$?

# 判断基础状态./
if [[ $exit_code -ne 0 ]]; then
    echo -e "\033[31m❌ Consul 未运行或命令执行失败 (错误码: $exit_code)\033[0m"
    echo "错误详情:$members_output"
fi

# 解析节点状态
alive_nodes=0
failed_nodes=0
server_nodes=0
leader_found=0

while read -r line; do

    # 跳过标题行
    [[ $line == Node* ]] && continue
    
    # 提取关键字段
    status=$(echo "$line" | awk '{print $3}')
    type=$(echo "$line" | awk '{print $4}')
    
    # 统计节点状态
    case "$status" in
        alive) 
            ((alive_nodes++))
            [[ $type == server ]] && ((server_nodes++))
            ;;
        failed) 
            ((failed_nodes++))
            ;;
    esac
    
    # 检查 Leader 状态
    if [[ $line == *leader* ]]; then
        leader_found=1
    fi
done <<< "$members_output"

# 输出集群状态报告
echo -e "\033[36mℹ️  集群状态:\033[0m"
echo "存活节点: $alive_nodes  故障节点: $failed_nodes"
echo "Server 节点: $server_nodes  Leader 存在: $([ $leader_found -eq 1 ] && echo "是" || echo "否")"

# 健康状态判断
if (( failed_nodes > 0 )); then
    echo -e "\n\033[31m■ 严重: 存在故障节点!需立即处理。\033[0m"
    consul members | grep failed
elif (( server_nodes == 0 )); then
    echo -e "\n\033[33m⚠️  警告: 无 Server 节点,集群功能受限。\033[0m"
elif [[ $leader_found -eq 0 ]]; then
    echo -e "\n\033[33m⚠️  警告: 未检测到 Leader,可能影响写操作。\033[0m"
    consul operator raft list-peers
else
    echo -e "\n\033[32m● 健康: 集群运行正常。\033[0m"
fi

结语

如果有帮到您,请点个免费的赞,感谢!如果有别的需求,可以留言或发送邮件到200919854@qq.com。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值