使用net/ssh Ruby脚本连接AWS主机失败:认证及密钥不匹配问题
让我们一步步拆解你遇到的这两个问题,帮你搞定net-ssh脚本的连接故障:
一、初始脚本的Net::SSH::AuthenticationFailed认证失败问题
你的初始代码没有显式指定远程主机的登录用户名,net-ssh默认会使用本地运行脚本的系统用户名——如果这个用户名和远程AWS主机允许的登录用户不一致,直接就会触发认证失败。
另外你设置了:non_interactive => true,这个参数会强制禁用所有交互式提示,哪怕你填了正确的passphrase,如果认证过程需要额外验证(比如密钥权限问题导致的二次确认),脚本也不会弹出提示,直接报错。哪怕你后来改成false,但核心的用户名问题没解决,自然还是失败。
二、修改后脚本的Net::SSH::HostKeyMismatch主机密钥不匹配问题
这个错误是因为net-ssh读取的主机密钥记录,和远程主机实际返回的密钥不一致。虽然你用系统ssh命令能正常连接,但要注意:
- 系统
ssh默认读取~/.ssh/known_hosts,但net-ssh可能因为运行环境(比如不同用户权限、自定义配置)读取的是其他路径的known_hosts文件; - 也可能是远程AWS主机的密钥近期更新过,系统
ssh已经自动信任了新密钥,但net-ssh还在读取旧的记录。
针对性解决方案
1. 先修正认证失败的核心问题
- 必须显式指定远程主机的登录用户名:就像你修改后代码里的
USER = 'markhorrocks',这是最关键的一步,确保和你用ssh命令连接时的用户名完全一致; - 检查密钥文件权限:本地
~/.ssh/id_rsa权限必须设为600,~/.ssh目录权限设为700——权限太宽会被ssh协议拒绝,哪怕密钥本身是对的; - 合理设置
non_interactive:如果需要脚本提示输入密码短语(比如不想硬编码passphrase),就设为false;如果要完全自动化,确保passphrase绝对正确,再设为true。
2. 解决主机密钥不匹配问题
- 强制指定known_hosts路径:在脚本里添加
:known_hosts => '/home/markhorrocks/.ssh/known_hosts',确保net-ssh和系统ssh用的是同一个密钥记录文件; - 验证远程主机密钥类型:用
ssh myhost -p 1234 -Q key查看远程主机支持的密钥类型,如果不是ssh-rsa,就把脚本里的:host_key改成对应的值(比如ecdsa-sha2-nistp256); - 测试阶段临时跳过验证(仅限测试):如果只是临时调试,可以添加
:verify_host_key => :never参数跳过密钥检查,但生产环境绝对不能用,会有安全风险。
简化后的修正示例脚本
#!/usr/bin/env ruby require 'rubygems' require 'net/ssh' HOST = 'myhost' USER = 'markhorrocks' PORT = 1234 KEY_PATH = '/home/markhorrocks/.ssh/id_rsa' KNOWN_HOSTS = '/home/markhorrocks/.ssh/known_hosts' Net::SSH.start(HOST, USER, port: PORT, auth_methods: ['publickey'], passphrase: 'mypassphrase', non_interactive: false, # 允许交互式提示,调试阶段更友好 keys: [KEY_PATH], known_hosts: KNOWN_HOSTS, host_key: 'ssh-rsa' # 确保和远程主机密钥类型一致 ) do |session| output = session.exec!('ls') puts output end
建议你先去掉修改后代码里的:encryption、:compression这类非必需参数,先保证基础连接正常,再逐步添加你需要的额外配置。
内容的提问来源于stack exchange,提问作者markhorrocks
相关产品推荐
相关产品推荐

