一、前置准备¶
1.1 说明文档里给出的基础要求¶
HOSTADDR_PRE:集群网段前缀。USER_PASSWD:待分发公钥账号的初始密码。HOST_LIST:需要做免密认证的 IP 列表。HOSTNAME_LIST:需要设置的主机名列表。- 适用系统:Ubuntu 24.04。
1.2 建议先配置控制节点的 /etc/hosts¶
echo "<node-ip-1> node-1" >> /etc/hosts
echo "<node-ip-2> node-2" >> /etc/hosts
echo "<node-ip-3> node-3" >> /etc/hosts
二、脚本的核心参数¶
2.1 环境变量集中定义¶
USER_NAME='root'
USER_HOME="/${USER_NAME}/.ssh"
SSH_CONFIG_FILE='/etc/ssh/ssh_config'
USER_PASSWD='<your-password>'
HOSTADDR_PRE='<network-prefix>'
HOST_LIST="${HOSTADDR_PRE}.80 ${HOSTADDR_PRE}.81 ${HOSTADDR_PRE}.13"
HOSTNAME_LIST='node-80 node-81 node-13'
HOSTS_FILE='/etc/hosts'
2.2 适合写进正文的参数解释¶
USER_HOME:密钥生成目录。SSH_CONFIG_FILE:用于关闭首次连接确认。HOSTS_FILE:同步到远端主机的 hosts 文件。HOST_LIST与HOSTNAME_LIST:共同驱动远程主机初始化。
三、自动化流程拆解¶
3.1 基础环境准备¶
apt install expect -y
rm -rf "${USER_HOME}"
ssh-keygen -t rsa -P "" -f "${USER_HOME}/id_rsa"
sed -i '/ask/{s/#/ /; s/ask/no/}' "${SSH_CONFIG_FILE}"
3.2 使用 Expect 自动输入密码¶
expect -c "
spawn ssh-copy-id -i ${USER_HOME}/id_rsa.pub $1
expect {
\"*yes/no*\" {send \"yes\r\"; exp_continue}
\"*password*\" {send \"${USER_PASSWD}\r\"; exp_continue}
}
"
3.3 分发公钥并统一主机名¶
for i in ${HOST_LIST} ${HOSTNAME_LIST}; do
expect_auto ${USER_NAME}@$i
scp -rp "${HOSTS_FILE}" "${USER_NAME}@${i}:${HOSTS_FILE}"
done
for i in ${HOSTNAME_LIST}; do
ssh "${USER_NAME}@${i}" "hostnamectl set-hostname $i"
done
四、与 Ansible 的联动整理¶
4.1 说明文档里的后续优化项¶
[defaults]
deprecation_warnings = False
interpreter_python = /usr/bin/python3
module_name = shell
4.2 发布前建议¶
- 建议把密码改成交互输入,不要明文放在脚本里。
- 建议补充
ssh-copy-id的失败重试和异常主机跳过逻辑。 - 如果后续要写成生产文章,可以把“控制节点准备”“免密认证”“Ansible 验证”拆成三篇。
五、完整脚本¶
以下为本文对应的完整脚本,便于直接复制复用。
5.1 集群主机免密认证.sh¶
#!/bin/bash
# 设置环境变量
USER_NAME='root'
USER_HOME="/${USER_NAME}/.ssh"
SSH_CONFIG_FILE='/etc/ssh/ssh_config'
USER_PASSWD='123456'
HOSTADDR_PRE='10.0.0'
HOST_LIST="${HOSTADDR_PRE}.80 ${HOSTADDR_PRE}.81 ${HOSTADDR_PRE}.13"
HOSTNAME_LIST='ubuntu24-80 ubuntu24-81 rocky9-13'
HOSTS_FILE='/etc/hosts'
# 准备基本环境
base_env() {
apt install expect -y
[ -d "${USER_HOME}" ] && rm -rf "${USER_HOME}"
ssh-keygen -t rsa -P "" -f "${USER_HOME}/id_rsa"
sed -i '/ask/{s/#/ /; s/ask/no/}' "${SSH_CONFIG_FILE}"
}
# expect自动化交互过程
expect_auto() {
local remote_host="$1"
expect -c "
spawn ssh-copy-id -i ${USER_HOME}/id_rsa.pub $1
expect {
\"*yes/no*\" {send \"yes\r\"; exp_continue}
\"*password*\" {send \"$USER_PASSWD\r\"; exp_continue}
\"*Password*\" {send \"$USER_PASSWD\r\";}
}
"
}
# 跨主机免认证环境
auth_auto() {
for i in ${HOST_LIST} ${HOSTNAME_LIST}; do
expect_auto ${USER_NAME}@$i
scp -rp "${HOSTS_FILE}" "${USER_NAME}@${i}:${HOSTS_FILE}"
done
}
# 设定主机名
hostname_set() {
for i in ${HOSTNAME_LIST}; do
ssh "${USER_NAME}@${i}" "hostnamectl set-hostname $i"
done
}
# 主函数执行
main() {
# 基本环境准备
base_env
# 跨主机免密认证
auth_auto
# 设定主机名
hostname_set
}
# 执行主函数
main