ansible-devops/scripts/ssh.sh

196 lines
6.0 KiB
Bash
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/bash
# 多节点互相同步SSH密钥脚本支持从文件读取IP、指定用户和密码
# ==================== 颜色与样式定义 ====================
GREEN="\033[32m" # 成功/完成
YELLOW="\033[33m" # 进行中/提示
RED="\033[31m" # 错误/失败
BLUE="\033[34m" # 标题/分隔线
CYAN="\033[36m" # 信息/说明
NC="\033[0m" # 重置颜色
# 打印分隔线
print_sep() {
echo -e "${BLUE}------------------------------------------------${NC}"
}
# ==================== 参数解析与校验 ====================
# 解析命令行参数
while [[ $# -gt 0 ]]; do
case "$1" in
--file=*)
IP_FILE="${1#*=}"
shift
;;
--user=*)
SSH_USER="${1#*=}"
shift
;;
--passwd=*)
SSH_PASSWD="${1#*=}"
shift
;;
*)
echo -e "${RED}未知参数: $1${NC}"
exit 1
;;
esac
done
# 检查必要参数
if [ -z "$IP_FILE" ] || [ -z "$SSH_USER" ] || [ -z "$SSH_PASSWD" ]; then
echo -e "\n${YELLOW}用法:${NC} --file=IP文件路径 --user=用户名 --passwd=密码"
exit 1
fi
# 检查IP文件是否存在
if [ ! -f "$IP_FILE" ]; then
echo -e "${RED}错误IP文件 $IP_FILE 不存在${NC}"
exit 1
fi
# 从文件读取IP列表去重、过滤空行
NODES=()
while IFS= read -r ip; do
if [ -n "$ip" ] && ! [[ " ${NODES[@]} " =~ " $ip " ]]; then
NODES+=("$ip")
fi
done < "$IP_FILE"
if [ ${#NODES[@]} -eq 0 ]; then
echo -e "${RED}错误IP文件 $IP_FILE 中未找到有效IP${NC}"
exit 1
fi
# ==================== 核心功能函数 ====================
# 安装sshpass处理自动输入密码
install_sshpass() {
echo -e "\n${YELLOW}【步骤1/3】检查并安装sshpass工具...${NC}"
if ! command -v sshpass &> /dev/null; then
echo -e " ${YELLOW}→ sshpass未安装正在安装...${NC}"
if command -v apt &> /dev/null; then
apt update -y >/dev/null && apt install -y sshpass >/dev/null
elif command -v yum &> /dev/null; then
yum install -y sshpass >/dev/null
else
echo -e " ${RED}✗ 未找到apt或yum无法安装sshpass${NC}"
exit 1
fi
# 验证安装结果
if command -v sshpass &> /dev/null; then
echo -e " ${GREEN}✓ sshpass安装成功${NC}"
else
echo -e " ${RED}✗ sshpass安装失败请手动安装后重试${NC}"
exit 1
fi
else
echo -e " ${GREEN}✓ sshpass已安装${NC}"
fi
}
# 在目标节点生成SSH密钥若不存在
generate_key() {
local node=$1
echo -e " ${YELLOW}→ 处理节点 $node...${NC}"
# 远程生成密钥(静默模式)
sshpass -p "$SSH_PASSWD" ssh -o StrictHostKeyChecking=no ${SSH_USER}@$node << EOF >/dev/null 2>&1
if [ ! -f ~/.ssh/id_rsa ]; then
ssh-keygen -t rsa -N "" -f ~/.ssh/id_rsa
fi
EOF
# 检查执行结果
if [ $? -eq 0 ]; then
echo -e " ${GREEN}✓ 密钥生成完成(已存在则跳过)${NC}"
else
echo -e " ${RED}✗ 生成失败(可能密码错误或节点不可达)${NC}"
exit 1
fi
}
# 获取目标节点的公钥
get_public_key() {
local node=$1
# 静默获取公钥,忽略错误输出
sshpass -p "$SSH_PASSWD" ssh -o StrictHostKeyChecking=no ${SSH_USER}@$node "cat ~/.ssh/id_rsa.pub" 2>/dev/null
}
# 将公钥追加到目标节点的authorized_keys
append_public_key() {
local pub_key="$1"
local target_node=$2
# 远程执行追加公钥操作
sshpass -p "$SSH_PASSWD" ssh -o StrictHostKeyChecking=no ${SSH_USER}@$target_node << EOF >/dev/null 2>&1
mkdir -p ~/.ssh
chmod 700 ~/.ssh
if ! grep -q "$pub_key" ~/.ssh/authorized_keys 2>/dev/null; then
echo "$pub_key" >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
fi
EOF
# 反馈结果
if [ $? -eq 0 ]; then
echo -e " ${GREEN}→ 同步成功${NC}"
else
echo -e " ${RED}→ 同步失败${NC}"
exit 1
fi
}
# ==================== 主流程 ====================
main() {
# 欢迎信息
clear
print_sep
echo -e "${BLUE} 多节点SSH密钥互相同步工具 ${NC}"
print_sep
echo -e " ${CYAN}节点列表:${NC} ${NODES[*]}"
echo -e " ${CYAN}操作用户:${NC} $SSH_USER"
echo -e " ${CYAN}开始时间:${NC} $(date +'%Y-%m-%d %H:%M:%S')"
print_sep
# 1. 安装依赖工具
install_sshpass
print_sep
# 2. 为所有节点生成密钥
node_count=${#NODES[@]}
echo -e "\n${YELLOW}【步骤2/3】为所有节点生成SSH密钥$node_count 个节点)...${NC}"
for i in "${!NODES[@]}"; do
echo -e "\n 节点 ${i+1}/$node_count: ${NODES[$i]}"
generate_key ${NODES[$i]}
done
print_sep
# 3. 收集公钥并互相同步
echo -e "\n${YELLOW}【步骤3/3】公钥互相同步$node_count 个节点)...${NC}"
for i in "${!NODES[@]}"; do
current_node=${NODES[$i]}
echo -e "\n 处理第 ${i+1}/$node_count 个节点: $current_node"
# 获取当前节点公钥
echo -e " ${YELLOW}→ 获取公钥...${NC}"
pub_key=$(get_public_key $current_node)
if [ -z "$pub_key" ]; then
echo -e " ${RED}✗ 无法获取 $current_node 的公钥${NC}"
exit 1
fi
# 同步到所有节点
echo -e " ${YELLOW}→ 同步到所有节点...${NC}"
for target in "${NODES[@]}"; do
echo -e " 目标节点: $target"
append_public_key "$pub_key" $target
done
done
# 完成提示
print_sep
echo -e "\n${GREEN}=== 所有操作完成!===${NC}"
echo -e " ${CYAN}验证方法:${NC} 在任意节点执行 'ssh ${NODES[1]}' 测试免密登录"
echo -e " ${CYAN}结束时间:${NC} $(date +'%Y-%m-%d %H:%M:%S')"
print_sep
}
# 执行主流程
main