如何用 Shell 脚本批量部署 SSH 公钥到多台服务器免密?

文章导读
使用 Shell 脚本批量部署 SSH 公钥最推荐的做法是在循环中调用 ssh-copy-id 命令,适用于 Linux 和 macOS 等类 Unix 系统。操作前需确保本地已生成 SSH 密钥对,且目标服务器开放 22 端口并允许密码认证,主要风险在于文件权限配置错误会导致免密登录失效。
📋 目录
  1. 命令速用版
  2. 为什么会这样
  3. 分步处理
  4. 怎么验证是否生效
  5. 常见坑
  6. 常见问题
  7. 参考来源
A A

使用 Shell 脚本批量部署 SSH 公钥最推荐的做法是在循环中调用 ssh-copy-id 命令,适用于 Linux 和 macOS 等类 Unix 系统。操作前需确保本地已生成 SSH 密钥对,且目标服务器开放 22 端口并允许密码认证,主要风险在于文件权限配置错误会导致免密登录失效。

先说结论:批量部署 SSH 公钥应优先使用原生 ssh-copy-id 配合主机列表循环,避免手动修改配置文件带来的权限风险。

  • 适合:拥有多台 Linux/Unix 服务器且需要统一密钥管理的运维场景
  • 先看:本地是否已生成 SSH 密钥对,目标服务器是否安装 openssh-clients
  • 建议:部署完成后务必使用 BatchMode 模式验证免密是否真正生效

命令速用版

以下脚本假设本地公钥已生成,且目标服务器列表保存在 hosts.txt 中,每行一个 IP 或主机名。

#!/bin/bash
USER="root"
KEY_FILE=~/.ssh/id_rsa.pub
HOSTS_FILE="hosts.txt"

while read -r HOST; do
  echo "Deploying to $HOST..."
  ssh-copy-id -i $KEY_FILE $USER@$HOST
done < $HOSTS_FILE

如果目标服务器没有 ssh-copy-id 命令,可以使用以下替代命令手动追加公钥。

cat ~/.ssh/id_rsa.pub | ssh user@host "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys"

为什么会这样

SSH 免密登录的本质是将本地公钥内容追加到目标服务器的 ~/.ssh/authorized_keys 文件中。

SSH 服务端在验证时会检查该文件权限必须为 600,所属目录 .ssh 权限必须为 700,且所有者必须是登录用户本人。Shell 脚本批量部署的核心难点不在于传输公钥,而在于确保所有目标服务器的目录结构和权限符合 OpenSSH 的安全规范,否则服务端会拒绝使用公钥认证。

分步处理

第一步:生成本地密钥对

在控制机执行 ssh-keygen -t rsa -b 2048,默认路径为 ~/.ssh/id_rsa 和 ~/.ssh/id_rsa.pub。如果已存在可跳过,注意不要覆盖现有密钥。

第二步:准备主机列表

创建 hosts.txt 文件,填入目标服务器 IP,确保控制机能通过密码登录这些服务器。

如何用 Shell 脚本批量部署 SSH 公钥到多台服务器免密?

第三步:执行部署脚本

运行上述速用版脚本,过程中需要输入一次目标服务器的登录密码。脚本会自动创建目录并设置权限。

第四步:处理已知主机检查

如果是全新环境,建议在脚本中加入 -o StrictHostKeyChecking=no 参数,避免首次连接时因指纹确认中断脚本执行。

怎么验证是否生效

使用 -o BatchMode=yes 参数测试 SSH 连接,该参数禁止密码输入提示,如果连接成功则说明免密配置正确。

ssh -o BatchMode=yes -o StrictHostKeyChecking=no user@host "echo success"

如果输出 success 且没有提示输入密码,则部署成功。如果提示 Permission denied (publickey,password),则说明公钥未生效或权限错误。

常见坑

  • 权限错误:目标服务器 ~/.ssh 目录权限不能超过 700,authorized_keys 不能超过 600,否则 SSH 服务端会忽略该文件。
  • SELinux 限制:在 CentOS/RHEL 系统中,如果开启 SELinux,可能需要运行 restorecon -R -v ~/.ssh 修复安全上下文。
  • 根目录权限:部分严格配置下,用户家目录 ~ 的权限不能是 777,否则认证会被拒绝。
  • 公钥追加:多次运行脚本会导致公钥重复追加到 authorized_keys,建议先检查是否存在相同密钥。

常见问题

目标服务器没有 ssh-copy-id 命令怎么办?

使用 cat 管道配合 ssh 手动创建文件和设置权限,参考“命令速用版”中的替代命令。

如何实现完全无人值守输入密码?

可以安装 sshpass 工具配合脚本使用,但明文密码存在安全风险,仅建议在临时内网环境使用。

部署后仍然提示输入密码?

检查目标服务器 /var/log/secure 或 /var/log/auth.log 日志,确认是否因权限问题导致公钥被拒绝。

参考来源

  • OpenSSH Manual: ssh-copy-id
  • Red Hat Documentation: Configuring SSH key-based authentication