SSH不同版本使用jsch问题处理
1.问题一
# 1.系统cat /etc/os-release
# 系统信息NAME="openEuler"VERSION="22.03 (LTS-SP1)"ID="openEuler"VERSION_ID="22.03"PRETTY_NAME="openEuler 22.03 (LTS-SP1)"ANSI_COLOR="0;31"# 2.sshssh-V# ssh信息
OpenSSH_8.8p1, OpenSSL 1.1.1m 14 Dec 2021
# 1.Java报错
com.jcraft.jsch.JSchException: Algorithm negotiation fail
# 2.使用 systemctl status sshd 查看状态
Unable to negotiate with xxx.xxx.x.xxx port xxxxx: no matching host key type found.
Their offer: ssh-rsa,ssh-dss,ecdsa-sha2-nistp256,ecdsa-sha>
问题解决:
- 配置文件
sshd_config
的HostKeyAlgorithms
添加算法ssh-rsa
HostKeyAlgorithms ssh-ed25519,[email protected],rsa-sha2-256,rsa-sha2-512,ssh-rsa
2.问题二
2.1 说明
OpenSSH是从原本的
OpenSSH_7.4p1, OpenSSL 1.0.2k-fips 26 Jan 2017
升级到
OpenSSH_9.7p1, OpenSSL 3.2.0 23 Nov 2023
,当前环境如下:
# 1.系统
CentOS Linux release 7.8.2003 (Core)# 2.ssh -V
OpenSSH_9.7p1, OpenSSL 3.2.0 23 Nov 2023
# 1.密码错误时Java报错信息
cn.hutool.extra.ssh.JschRuntimeException: JSchException: Auth fail
# 密码修改正确后 systemctl status sshd 查看状态
Accepted password for root from 123.160.246.239 port 22838 ssh2
# 2.通过sftp上传文件时
cn.hutool.extra.ssh.JschRuntimeException: JSchException: channel is not opened.
# 过一会儿后 systemctl status sshd 查看状态
error: no more sessions
代码进行调试,发现报错的位置:
// 报错行
channelSftp.put(fs, directory,ChannelSftp.OVERWRITE);// 报错信息com.jcraft.jsch.SftpException:No such file
我一度认为是传输模式的问题,在
ChannelSftp.put(InputStream src, String dst, int mode)
方法中,
mode
参数用于指定文件传输模式,其可选值有:
- ChannelSftp.OVERWRITE:这是默认的传输模式,它会完全覆盖目标服务器上的同名文件。如果目标文件不存在,则会创建一个新的文件。
- ChannelSftp.RESUME:这种模式下,如果传输被中断,那么在下次调用
put
方法时,会从上一次中断的地方继续传输,而不是重新开始传输整个文件。 - ChannelSftp.APPEND:此模式允许你将数据追加到目标服务器上的现有文件中,而不是覆盖它。如果目标文件不存在,则会创建一个新的文件。
换用其他模式依然报错。
2.2 解决
最终发现是代码的问题:
// 进行代码调试时发现远程登录耗时较久SshClient.getInstance().sshRemoteCallLoginByTool(sshHost, sshPort, sshUserName, sshPassword);// 导致创建目标目录时未执行SshClient.getInstance().execCommandByTool("mkdir "+ targetPath);
execCommandByTool方法的原始代码:
/**
* 执行命令
*
* @param command 命令
*/publicStringexecCommandByTool(String command){boolean isConnected =checkConnectionStatus();if(isConnected){returnJschUtil.exec(session, command,Charsets.UTF_8);}returnnull;}
可以看出,如果登录较慢,
checkConnectionStatus
的状态是
false
则创建目录的命令未被执行,导致上传时的文件路径不存在,出现报错信息,改进如下:
/**
* 执行命令
*
* @param command 命令
*/publicStringexecCommandByTool(String command){boolean isConnected =checkConnectionStatus();while(!isConnected){
isConnected =checkConnectionStatus();}returnJschUtil.exec(session, command,Charsets.UTF_8);}
3.问题三
# 连接超时异常
com.jcraft.jsch.JSchException: Session.connect: java.net.SocketTimeoutException: Read timed out
# 包损坏
com.jcraft.jsch.JSchException: Packet corrupt
异常出现的位置及处理方案:
privatebooleancreateSessionAndConnected(){if(session ==null){
log.info("SSHClient createSessionAndConnected...");
session =JschUtil.createSession(this.sshHost,this.sshPort,this.sshUser,this.sshPass);Properties config =newProperties();
config.put("StrictHostKeyChecking","no");
session.setConfig(config);try{
session.connect(8000);// com.jcraft.jsch.JSchException: Session.connect: java.net.SocketTimeoutException: Read timed out// 增加超时时间 session.connect(200000);}catch(JSchException e){// com.jcraft.jsch.JSchException: Packet corrupt// 使用同一个session对象再次进行连接时会报错// 重新连接时使用新的session对象
session =null;
e.printStackTrace();
log.info("SSHClient createSessionAndConnected printStackTrace");returnfalse;}
log.info("SSHClient createSessionAndConnected Success!");}returnthis.session.isConnected();}
版权归原作者 シ風箏 所有, 如有侵权,请联系我们删除。