如何在Bash中读取过滤标准输出,自动处理SSH主机密钥错误?
自动处理RSYNC中的SSH主机密钥变更问题
当服务器IP变更或更换新服务器时,rsync会因SSH主机密钥不匹配抛出错误,比如:
Warning: the ECDSA host key for 'example.com' differs from the key for the IP address 'x.x.x.x.'
Offending key for IP in /home//.ssh/known_hosts:5
Matching host key in /home//.ssh/known_hosts:6
或者:
WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!
以下是可以自动捕获这类错误、删除旧密钥并重新执行同步的Bash脚本:
#!/bin/bash # 替换为你的实际rsync同步命令 RSYNC_CMD="rsync -avz your_user@target_host:/remote/source/ /local/destination/" # 捕获rsync的所有输出(包括stderr) rsync_output=$($RSYNC_CMD 2>&1) # 检查输出中是否包含主机密钥变更的错误关键词 if echo "$rsync_output" | grep -qE "Warning: the ECDSA host key for|WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!"; then # 从错误输出中提取有问题的主机名或IP地址 offending_hosts=$(echo "$rsync_output" | grep -oP "(?<=for ')[^']+|(?<=IP address ')[^']+") # 去重并逐个删除旧密钥 echo "$offending_hosts" | sort -u | while read -r host; do echo "清理 $host 的旧SSH密钥..." ssh-keygen -R "$host" done # 清理完成后重新执行同步 echo "重新启动rsync同步..." $RSYNC_CMD else echo "同步完成,无SSH密钥问题!" fi
关键细节说明
- 捕获错误输出:通过
2>&1将stderr重定向到stdout,确保所有rsync输出都被捕获到变量中。 - 错误匹配:使用
grep -qE静默匹配两种错误模式,-q只返回匹配状态,不输出内容;-E支持多关键词的正则匹配。 - 提取目标地址:借助Perl正则
(?<=for ')[^']+和(?<=IP address ')[^']+,精准提取错误信息中的主机名或IP。 - 去重处理:用
sort -u避免重复处理同一主机,确保每个地址只清理一次。 - 自动重试:清理旧密钥后自动重新执行rsync,无需手动干预。
使用注意
- 务必将脚本中的
RSYNC_CMD替换为你实际的同步命令,包含正确的用户、主机和路径。 - 由于脚本会修改
~/.ssh/known_hosts,确保你信任该操作(如你所述,脚本为动态下载后自动删除,安全性有保障)。 - 可以通过批量部署工具(如Ansible、PDsh)将脚本推送到30台客户端机器执行,避免手动操作。
内容的提问来源于stack exchange,提问作者Chiwda
相关产品推荐
相关产品推荐

