使用Perl Net::OpenSSH连接需RSA密钥+密码认证的服务器遇阻
解决Net::OpenSSH连接双重认证服务器失败问题
问题根源
当你在Net::OpenSSH->new中显式传入password参数时,模块默认会优先采用密码认证,甚至跳过密钥认证流程——这就是为什么你的RSA密钥没有被发送到服务器,最终触发"Permission denied (publickey)"错误。
修复方案
1. 调整认证顺序,强制优先尝试密钥认证
显式指定SSH客户端的认证顺序,让它先尝试密钥认证,再使用密码。若服务器在密钥认证后仍要求密码,模块会自动处理交互;若需要提前传入密码,也可以保留password参数:
my $ssh = Net::OpenSSH->new( $server, user => $username, timeout => 10, master_opts => [ -o => "UserKnownHostsFile=/dev/null", -o => "PreferredAuthentications=publickey,password" ] ); $ssh->error and die "Unable to connect: " . $ssh->error;
2. 显式指定密钥文件路径
如果sudo运行脚本时HOME环境变量被重置(比如指向root目录),模块可能找不到myuser的密钥文件。可以直接指定密钥路径:
my $ssh = Net::OpenSSH->new( $server, user => $username, password => $passwd, timeout => 10, master_opts => [ -o => "UserKnownHostsFile=/dev/null", -o => "IdentityFile=/home/myuser/.ssh/id_rsa", # 替换为实际密钥路径 -o => "PreferredAuthentications=publickey,password" ] ); $ssh->error and die "Unable to connect: " . $ssh->error;
3. 保留sudo运行时的HOME环境变量
sudo默认会重置HOME变量,导致模块读取不到myuser的.ssh目录。可以在执行脚本时强制保留HOME:
sudo -u myuser HOME=/home/myuser perl your_script.pl
调试技巧
添加-v参数开启SSH调试模式,查看详细的认证流程,定位具体问题:
master_opts => [ -v, -o => "UserKnownHostsFile=/dev/null", -o => "PreferredAuthentications=publickey,password" ]
内容的提问来源于stack exchange,提问作者Jason M
相关产品推荐
相关产品推荐

