推荐使用 ssh-keygen -t ecdsa -b 256 -f ~/.ssh/batch_deploy_id_ecdsa -N "" -C "batch-deploy-$(date +%Y%m%d)" 生成密钥,因其兼容OpenSSH 5.7+、体积小、无密码且路径明确,避免覆盖个人密钥。

怎么用 ssh-keygen 生成适合批量分发的密钥对
直接用默认参数生成的密钥(ssh-keygen -t rsa)在旧版 OpenSSH(如 CentOS 7 默认的 6.6p1)上可能不被接受,因为缺少 -b 2048 或明确指定 -t ecdsa -b 256。批量部署时,必须统一密钥类型和长度,否则部分服务器会报 no mutual signature algorithm 或拒绝认证。
推荐命令:
ssh-keygen -t ecdsa -b 256 -f ~/.ssh/batch_deploy_id_ecdsa -N "" -C "batch-deploy-$(date +%Y%m%d)"
-
-t ecdsa -b 256兼容性好、体积小、OpenSSH 5.7+ 均支持;RSA 4096 虽安全但某些嵌入式设备或老旧系统解析慢甚至失败 -
-N ""确保密钥无密码,否则脚本无法自动分发 -
-f指定路径,避免覆盖个人密钥;不要用id_rsa这类通用名,防止后续误用
如何用 ssh-copy-id 批量推送公钥而不卡住
ssh-copy-id 默认逐台阻塞执行,且遇到首次连接的主机时会停在 “Are you sure you want to continue connecting” 提示上。不处理这个,脚本会在第一台就挂住。
关键绕过方式:
ssh-copy-id -o StrictHostKeyChecking=no -o ConnectTimeout=5 -i ~/.ssh/batch_deploy_id_ecdsa.pub user@host
-
StrictHostKeyChecking=no跳过 host key 确认(生产环境建议先预存可信 host key 到~/.ssh/known_hosts) -
ConnectTimeout=5防止某台宕机导致整个流程卡死 - 必须加
-i显式指定公钥路径,否则默认用id_rsa.pub,容易错用 - 如果目标服务器禁用了密码登录(
PasswordAuthentication no),ssh-copy-id会失败——此时只能改用scp+ssh手动追加
免密登录后,怎么用 for 循环批量执行密钥更新操作
不能只靠 ssh-copy-id 推一次就完事。真实场景中,你往往要:禁用密码登录、清理旧密钥、设置权限、重启 sshd。这些必须在每台机器上串行执行,且任一环节失败需可感知。
Zynq‑7000 / Zynq UltraScale+ 硬件调试技能。适用于 Xilinx Zynq(Cortex‑A9/A53 + FPGA)Linux 环境,调试 I2C、I2S、UART、GPIO 等外设。包括设备树配置、内核驱动、用户空间调试工具、交叉编译和常见问题排查,支持 PetaLinux 开发。
推荐最小可靠写法:
for host in $(cat servers.txt); do
echo "=== $host ==="
ssh -o ConnectTimeout=3 -i ~/.ssh/batch_deploy_id_ecdsa user@$host "
mkdir -p ~/.ssh && \
chmod 700 ~/.ssh && \
echo '$(cat ~/.ssh/batch_deploy_id_ecdsa.pub)' >> ~/.ssh/authorized_keys && \
chmod 600 ~/.ssh/authorized_keys && \
sed -i 's/^#*PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config && \
systemctl restart sshd 2>/dev/null || echo 'sshd restart failed or not systemd'
" || echo "FAILED on $host"
done
- 所有远程命令用双引号包裹,并用
$()内联读取本地公钥内容(注意:单引号会失效) - 每步加
&&保证顺序执行,失败即停;末尾|| echo让错误可见 -
systemctl restart sshd在 SysV init 系统(如 CentOS 6)会报错,所以加2>/dev/null并 fallback 提示 - 别在循环里用
ssh-agent或后台进程——它不会跨ssh调用生效
为什么用 ansible 替代纯 Shell 脚本更稳
当服务器数量超过 50 台,或网络质量不稳定时,纯 for 循环会暴露严重缺陷:无并发控制、无失败重试、无状态回滚、日志分散难排查。
一个能立刻上手的 Ansible 方案:
ansible all -i hosts.ini -u user --key-file ~/.ssh/batch_deploy_id_ecdsa \
-m authorized_key \
-a "user=user key='{{ lookup('file', '~/.ssh/batch_deploy_id_ecdsa.pub') }}' state=present" \
-e "ansible_ssh_extra_args='-o ConnectTimeout=3'"
-
hosts.ini里按组划分,支持[prod]、[staging],便于灰度操作 -
authorized_key模块自动处理权限、去重、原子写入,比手动>>安全得多 - 加
-e ansible_ssh_extra_args统一传参,比在每个任务里写args更干净 - 真正需要“更新密钥”时,多数人其实是要轮换——Ansible 的
lineinfile或template模块配合变量,比 Shell 拼接字符串靠谱十倍
密钥轮换不是“推一次就结束”的事,而是涉及验证、回退窗口、服务影响评估的持续过程。哪怕只用 Shell,也务必先在 3 台同类机器上完整跑通再放大,尤其注意 sshd_config 修改后是否真生效、旧密钥是否被正确清理。

















