本文目录导读:

我来介绍几种批量推送SSH公钥的方法:
方法1:使用 ssh-copy-id 命令(推荐)
创建批量推送脚本 batch-ssh-copy.sh:
#!/bin/bash
# 主机列表文件格式: user@host:port
HOSTS_FILE="hosts.txt"
SSH_KEY="${HOME}/.ssh/id_rsa.pub"
SSH_PASSWORD="your_password_here"
# 检查必要文件
if [ ! -f "$HOSTS_FILE" ]; then
echo "错误:主机列表文件 $HOSTS_FILE 不存在"
echo "格式:user@host:port 或 user@host"
exit 1
fi
if [ ! -f "$SSH_KEY" ]; then
echo "错误:SSH公钥文件 $SSH_KEY 不存在"
exit 1
fi
# 安装 sshpass(如果需要密码认证)
if ! command -v sshpass &> /dev/null; then
echo "正在安装 sshpass..."
if [[ "$OSTYPE" == "darwin"* ]]; then
brew install hudochenkov/sshpass/sshpass
else
apt-get install -y sshpass || yum install -y sshpass
fi
fi
# 读取主机列表并批量推送
while IFS= read -r line; do
# 跳过注释和空行
[[ "$line" =~ ^#.*$ || -z "$line" ]] && continue
# 解析主机信息
if [[ "$line" == *":"* ]]; then
user_host="${line%:*}"
port="${line##*:}"
else
user_host="$line"
port="22"
fi
echo "正在推送公钥到: $user_host (端口: $port)"
# 推送公钥
sshpass -p "$SSH_PASSWORD" ssh-copy-id \
-i "$SSH_KEY" \
-p "$port" \
-o StrictHostKeyChecking=no \
"$user_host" 2>&1
if [ $? -eq 0 ]; then
echo "✓ 成功: $user_host"
else
echo "✗ 失败: $user_host"
fi
echo "---"
done < "$HOSTS_FILE"
echo "批量推送完成!"
hosts.txt 文件格式示例:
# 格式:user@host:port 或 user@host
root@192.168.1.10:2222
admin@192.168.1.11
deploy@192.168.1.12:2222
方法2:使用 expect 实现交互式推送
安装 expect:
# Ubuntu/Debian apt-get install expect # CentOS/RHEL yum install expect
创建脚本 ssh-copy-expect.sh:
#!/bin/bash
HOSTS_FILE="hosts.txt"
SSH_KEY="${HOME}/.ssh/id_rsa.pub"
PASSWORD="your_password"
if [ ! -f "$HOSTS_FILE" ]; then
echo "错误:主机列表文件不存在"
exit 1
fi
# 读取主机列表
while IFS= read -r host; do
[[ "$host" =~ ^#.*$ || -z "$host" ]] && continue
echo "处理主机: $host"
# 使用 expect 自动交互
expect << EOF
set timeout 10
spawn ssh-copy-id -i $SSH_KEY $host
expect {
"yes/no" { send "yes\r"; exp_continue }
"password:" { send "$PASSWORD\r" }
"Permission denied" { exit 2 }
eof
}
expect eof
catch wait result
exit [lindex \$result 3]
EOF
if [ $? -eq 0 ]; then
echo "✓ 成功: $host"
else
echo "✗ 失败: $host"
fi
done < "$HOSTS_FILE"
echo "完成!"
方法3:使用循环 + ssh 命令手动创建
#!/bin/bash
# 服务器列表
HOSTS=(
"root@192.168.1.10:2222"
"admin@192.168.1.11"
"deploy@192.168.1.12"
)
PUBLIC_KEY=$(cat ~/.ssh/id_rsa.pub)
PASSWORD="your_password"
for host_info in "${HOSTS[@]}"; do
# 解析主机信息
IFS=':' read -r host port <<< "$host_info"
port=${port:-22}
echo "推送到: $host (端口: $port)"
# 创建 .ssh 目录并设置权限
sshpass -p "$PASSWORD" ssh -p "$port" -o StrictHostKeyChecking=no "$host" \
"mkdir -p ~/.ssh && chmod 700 ~/.ssh" 2>&1
# 添加公钥
sshpass -p "$PASSWORD" ssh -p "$port" "$host" \
"echo '$PUBLIC_KEY' >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys" 2>&1
if [ $? -eq 0 ]; then
echo "✓ 成功: $host"
else
echo "✗ 失败: $host"
fi
done
方法4:使用 Ansible(生产环境推荐)
创建 inventory.ini:
[servers] server1 ansible_host=192.168.1.10 ansible_user=root ansible_port=2222 server2 ansible_host=192.168.1.11 ansible_user=admin server3 ansible_host=192.168.1.12 ansible_user=deploy [servers:vars] ansible_ssh_pass=your_password ansible_ssh_common_args='-o StrictHostKeyChecking=no'
创建 push-keys.yml:
---
- name: 批量推送SSH公钥
hosts: servers
gather_facts: no
tasks:
- name: 确保 .ssh 目录存在
file:
path: ~/.ssh
state: directory
mode: '0700'
- name: 添加公钥到 authorized_keys
authorized_key:
user: "{{ ansible_user }}"
state: present
key: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}"
运行:
ansible-playbook -i inventory.ini push-keys.yml
安全建议
-
使用密钥认证:尽量避免明文密码
-
限制权限:
chmod 600 ~/.ssh/authorized_keys chmod 700 ~/.ssh chmod 600 script.sh # 如果脚本包含密码
-
使用配置文件:考虑使用
~/.ssh/configHost server1 HostName 192.168.1.10 Port 2222 User root IdentityFile ~/.ssh/id_rsa -
日志记录:添加操作日志
LOG_FILE="ssh_push_$(date +%Y%m%d_%H%M%S).log" # 在脚本中使用 tee 记录日志 echo "信息" | tee -a "$LOG_FILE"
选择最适合你场景的方法,推荐优先使用方法1或方法4(生产环境)。