SBT发布未使用SSH密钥却要求输入密码的问题排查
Scala库发布到本地SSH仓库的SBT认证问题
此前成功将Scala库发布到本地托管仓库,现在遇到异常:SBT未按配置使用指定SSH密钥登录仓库主机,反而弹出带Ivy标识的密码对话框。
配置的publishTo设置
publishTo := Some( Resolver .ssh("Degree Audit", "REPO_HOST_MACHINE", "/u1/HOST_ACCOUNT/public_html/maven") .as("HOST_ACCOUNT", file(sys.env("HOME") + "/.ssh/oat_rsa"), None) .withPublishPermissions("0644") ),
异常现象
- 将SSH密钥文件名改为不存在的
.ssh/oat_rsaXXX也无报错,但执行show publishTo显示SBT已读取密钥配置 - 直接执行
ssh HOST_ACCOUNT@REPO_HOST_MACHINE -i .ssh/oat_rsa可正常连接服务器 - 取消密码对话框会触发NullPointerException;输入错误密码则出现
SSH_MSG_DISCONNECT: 2 Too many authentication failures错误栈
疑问
- 将
.ssh/oat_rsa改为不存在的文件名是否应该抛出错误? - 能否追踪SBT与服务器间的SSH调用,或验证SBT是否确实在尝试使用我的SSH密钥?
- 若SBT无法通过SSH连接,是否会自动 fallback 到密码认证?
- SBT文档中关于Credentials匹配的说明是否与我的场景相关?若相关请解释。
- 还有其他排查该问题的方法吗?
问题解答
不存在的密钥文件是否应该报错?
应该报错,但SBT的Resolver.ssh采用延迟加载机制——仅在实际发起SSH连接时才检查密钥文件的存在性,而非加载配置阶段。因此修改为不存在的文件名时,show publishTo仅解析配置字符串,不会触发检查;直到发布执行时,若SBT fallback到密码认证,就会跳过密钥文件错误的抛出。如何追踪SSH调用/验证密钥使用情况?
- 开启SBT调试日志:执行
sbt -Dssh.debug=true publish,日志会输出SSH连接的完整流程,包括密钥加载尝试、认证步骤等细节 - 查看服务器端SSH日志(通常位于
/var/log/auth.log或/var/log/secure),日志会记录每个认证请求的类型(公钥/密码),可直接确认SBT是否尝试了公钥认证
SBT是否会自动 fallback 到密码认证?
是的。当指定密钥认证失败(包括密钥文件不存在、密钥无效等情况),SBT会自动触发密码认证流程,这是Ivy SSH resolver的默认行为,也是弹出密码对话框的原因。Credentials匹配是否相关?
不相关。Credentials配置针对的是用户名/密码形式的仓库认证(如HTTP仓库),而你的场景使用SSH密钥认证,Resolver.ssh的.as方法已直接指定用户名和密钥,无需额外配置Credentials。其他排查方法
- 检查密钥文件权限:确保
.ssh/oat_rsa的权限为0600(仅所有者可读可写),权限过宽会被SSH客户端拒绝使用 - 验证密钥有效性:执行
ssh-keygen -y -f ~/.ssh/oat_rsa,若能输出公钥则密钥有效,否则密钥已损坏 - 清除SBT缓存:删除
~/.ivy2/cache和~/.sbt下的缓存文件,避免旧配置干扰 - 替换密钥路径写法:尝试直接写死密钥文件绝对路径(如
file("/home/your-user/.ssh/oat_rsa")),排除sys.env("HOME")解析错误的可能 - 切换SBT版本:尝试回退到之前成功发布时的版本,或升级到最新稳定版,排查版本兼容性问题
内容的提问来源于stack exchange,提问作者bwbecker
相关产品推荐
相关产品推荐

