踩坑记录:java连接ssh的问题

目录

  • 概述
  • 一、第一个
    • 问题
    • 解决
  • 二、第二个
    • 问题
    • 分析
    • 解决
  • 三、第三个
    • 问题
    • 分析
    • 解决
  • 第四个
    • 问题
    • 解决

概述

手里有个CS架构的老系统,服务端要用SSH的方式传文件。没想到写了两天!遇到一堆问题,于是记录下。(老系统真恶心啊!)

一、第一个

问题

一开始使用原有的jsch包,但是ssh连不上,查资料后发现,服务器的ssh版本升级了,而且中央仓库的jsch包十几年不更新了,缺少很多密钥算法。

解决

改为使用apache的sshd包,我看一直有更新,因为线上服务器的ssh更高,于是用了比较新的版本。而且需要三个包,详细代码后面有。
sshd-core
sshd-sftp
sshd-common (这里和第二个坑有关!)

二、第二个

问题

使用sshd后,本地测试没问题,而放到测试服务器,服务端就一直报找不到sshd下面的ClientSession。

分析

因为是ClassLoader报的,原以为是二次代理,导致的ClassLoader无法获取第二次代理的外部jar(老架构的service全是用代理模式获取的,之前遇到过因二次代理导致service中无法获取hutool的问题)。后来想想这里不存在二次代理的问题,应该就只是ClassLoader获取外部jar包,于是找了下这个类,谁知。。(这里是idea用maven看的,netbean看起来实在麻烦)
在这里插入图片描述
core和common都有org.apache.sshd.client包!ClientSession在core里(不理解为啥不都装到core里!)
ClassLoader会先去找上面的common包找org.apache.sshd.client.ClientSession,找不到就不接着找了。

解决

用URLClassLoader去指定加载core里的ClientSession,但是想想太麻烦算了,于是准备把ssh传文件写成脚本,service去调用脚本的方式。

三、第三个

问题

开始写脚本,因为服务器没有go环境,python也有各种问题不想用,就用java写了个脚本。

import org.apache.sshd.client.SshClient;
import org.apache.sshd.client.kex.DHGClient;
import org.apache.sshd.client.kex.DHGEXClient;
import org.apache.sshd.client.session.ClientSession;
import org.apache.sshd.common.kex.BuiltinDHFactories;
import org.apache.sshd.common.kex.KeyExchangeFactory;
import org.apache.sshd.scp.client.ScpClient;
import org.apache.sshd.scp.client.ScpClientCreator;import java.util.Arrays;/*** ssh执行器* * @author zilong* @date 2023/12/14**/
public class SshExcute {public static void main(String args[]) {String username = null;String password = null;String ip = null;String sourcePath = null;String targetPath = null;String fileName = null;if (args[0] != null) {username = args[0];}if (args[1] != null) {password = args[1];}if (args[2] != null) {ip = args[2];}if (args[3] != null) {sourcePath = args[3];}if (args[4] != null) {targetPath = args[4];}if (args[5] != null) {fileName = args[5];}sendFile(username,password,ip,sourcePath,targetPath,fileName);}public static boolean sendFile (String username, String password, String ip, String sourcePath,String targetPath, String fileName) {Security.addProvider(new BouncyCastleProvider());int port = 22;try {sourcePath = sourcePath + "/";String osName = System.getProperty("os.name");if (osName.toUpperCase().contains("WINDOWS")) {sourcePath = sourcePath.replaceAll("/", "\\\\");}String source = sourcePath + fileName;String target = targetPath + "/" + fileName;SshClient client = SshClient.setUpDefaultClient();client.start();ClientSession session = client.connect(username, ip, port).verify().getSession();session.addPasswordIdentity(password);boolean isSuccess = session.auth().verify().isSuccess();if (isSuccess) {ScpClientCreator creator = ScpClientCreator.instance();ScpClient scpClient = creator.createScpClient(session);System.out.println("Scp beginning...");scpClient.upload(source, target, ScpClient.Option.Recursive);System.out.println("Scp finished...");if (scpClient != null) {scpClient = null;}if (session != null && session.isOpen()) {session.close();}if (client != null && client.isOpen()) {client.stop();client.close();}}} catch (Exception e) {e.printStackTrace();}return true;}
}
java.lang.IllegalArgumentException: KeyExchangeFactories not setat org.apache.sshd.common.util.ValidateUtils.createFormattedException(ValidateUtils.java:213)at org.apache.sshd.common.util.ValidateUtils.throwIllegalArgumentException(ValidateUtils.java:179)at org.apache.sshd.common.util.ValidateUtils.checkTrue(ValidateUtils.java:174)at org.apache.sshd.common.util.ValidateUtils.checkNotNullAndNotEmpty(ValidateUtils.java:80)at org.apache.sshd.common.helpers.AbstractFactoryManager.checkConfig(AbstractFactoryManager.java:513)at org.apache.sshd.client.SshClient.checkConfig(SshClient.java:389)at org.apache.sshd.client.SshClient.start(SshClient.java:450)at Ss.sendFile(Ss.java:81)at Ss.main(Ss.java:46)

分析

debug看源码
在这里插入图片描述本地测试是有这些密钥算法的,但是服务器上没有,不知道从哪获取的,手动加上试试

在这里插入图片描述又报错
java.security.NoSuchAlgorithmException: Algorithm ECDH not avaliable
感觉还是得从源头下手,应该是服务器缺少相关环境,于是百度,发现是jre缺少加密算法相关的包导致的,那么手动加下就好了。
The Bouncy Castle Crypto package

解决

import org.apache.sshd.client.SshClient;
import org.apache.sshd.client.kex.DHGClient;
import org.apache.sshd.client.kex.DHGEXClient;
import org.apache.sshd.client.session.ClientSession;
import org.apache.sshd.common.kex.BuiltinDHFactories;
import org.apache.sshd.common.kex.KeyExchangeFactory;
import org.apache.sshd.scp.client.ScpClient;
import org.apache.sshd.scp.client.ScpClientCreator;
import org.bouncycastle.jce.provider.BouncyCastleProvider;import java.security.Security;
import java.util.Arrays;/*** ssh执行器* * @author zilong* @date 2023/12/14**/
public class SshExcute {public static void main(String args[]) {String username = null;String password = null;String ip = null;String sourcePath = null;String targetPath = null;String fileName = null;if (args[0] != null) {username = args[0];}if (args[1] != null) {password = args[1];}if (args[2] != null) {ip = args[2];}if (args[3] != null) {sourcePath = args[3];}if (args[4] != null) {targetPath = args[4];}if (args[5] != null) {fileName = args[5];}sendFile(username,password,ip,sourcePath,targetPath,fileName);}public static boolean sendFile (String username, String password, String ip, String sourcePath,String targetPath, String fileName) {Security.addProvider(new BouncyCastleProvider());int port = 22;try {sourcePath = sourcePath + "/";String osName = System.getProperty("os.name");if (osName.toUpperCase().contains("WINDOWS")) {sourcePath = sourcePath.replaceAll("/", "\\\\");}String source = sourcePath + fileName;String target = targetPath + "/" + fileName;SshClient client = SshClient.setUpDefaultClient();client.setKeyExchangeFactories(Arrays.<KeyExchangeFactory>asList(DHGClient.newFactory(BuiltinDHFactories.ecdhp521),DHGClient.newFactory(BuiltinDHFactories.ecdhp384),DHGClient.newFactory(BuiltinDHFactories.ecdhp256),DHGEXClient.newFactory(BuiltinDHFactories.dhgex256),DHGClient.newFactory(BuiltinDHFactories.dhg18_512),DHGClient.newFactory(BuiltinDHFactories.dhg17_512),DHGClient.newFactory(BuiltinDHFactories.dhg16_512),DHGClient.newFactory((BuiltinDHFactories.dhg15_512)),DHGClient.newFactory(BuiltinDHFactories.dhg14_256)));client.start();ClientSession session = client.connect(username, ip, port).verify().getSession();session.addPasswordIdentity(password);boolean isSuccess = session.auth().verify().isSuccess();if (isSuccess) {ScpClientCreator creator = ScpClientCreator.instance();ScpClient scpClient = creator.createScpClient(session);System.out.println("Scp beginning...");scpClient.upload(source, target, ScpClient.Option.Recursive);System.out.println("Scp finished...");if (scpClient != null) {scpClient = null;}if (session != null && session.isOpen()) {session.close();}if (client != null && client.isOpen()) {client.stop();client.close();}}} catch (Exception e) {e.printStackTrace();}return true;}
}

第四个

问题

java运行shell命令

Process p = Runtime.getRuntime().exec("nohup java -Djava.ext.dirs=nosignlib SshExcute " +"root root 192.168.1.15 /file /file a.txt >ssh.out &");
int rc = p.waitFor();
if (rc != 0) {InputStream errorStream = p.getErrorStream();BufferedReader reader = new BufferedReader(new InputStreamReader(errorStream));String line;while ((line = reader.readLine()) != null) {System.out.println(line);}
}

遇到了各种问题,有rc是0,但是没执行的,还有其他错误。

解决

java里执行nohup命令,会卡到那无法退出,并且很多问题可以通过sh运行脚本来解决,于是封装个脚本

# ssh_excute.sh
nohup java -Djava.ext.dirs=nosignlib SshExcute $1 $2 $3 $4 $5 $6 >ssh.out &
echo "excute completed..."
exit 0

对应java代码
1、必须用绝对路径,不然会找不到脚本。
2、必须用数组的构造器。字符串的构造器,底层会因特殊字符,将命令转换错误。
3、必须带 -c,要不然底层会把后面命令按空格截断。

String c = "/xxx/ssh_excute.sh root root 192.168.1.15 /file /file a.txt"
String[] command = {"/bin/sh", "-c", c};
ProcessBuilder pb = new ProcessBuilder(command);
p = pb.start();

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/229086.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

浮点数float类型不能用“==” 否知if语句不起作用

浮点数float类型不能用“” 否知if语句不起作用 简介演练 简介 在许多编程语言中&#xff0c;包括Python&#xff0c;浮点数类型&#xff08;float&#xff09;的比较是有问题的。浮点数是近似表示的&#xff0c;因此在比较两个浮点数是否相等时可能会遇到精度问题。 比如&am…

Linux(23):Linux 核心编译与管理

编译前的任务&#xff1a;认识核心与取得核心原始码 Linux 其实指的是核心。这个【核心(kernel)】是整个操作系统的最底层&#xff0c;他负责了整个硬件的驱动&#xff0c;以及提供各种系统所需的核心功能&#xff0c;包括防火墙机制、是否支持 LVM 或 Quota 等文件系统等等&a…

CMA、CNAS软件检测公司分享:压力测试应关注的指标和面临的问题

软件压力测试是容易被传统企业忽视的测试点&#xff0c;用户人数一旦超过预期&#xff0c;极易造成软件产品卡顿、崩溃的情况&#xff0c;不利于用户正常使用&#xff0c;严重影响企业公信力和盈利水平。今天卓码软件测评小编来聊聊压力测试过程中应该关注的指标和会面临的问题…

PLC、RS485、变频器通讯接线图详解

plc与变频器两者是一种包含与被包含的关系&#xff0c;PLC与变频器都可以完成一些特定的指令&#xff0c;用来控制电机马达&#xff0c;PLC是一种程序输入执行硬件&#xff0c;变频器则是其中之一。 但是PLC的涵盖范围又比变频器大&#xff0c;还可以用来控制更多的东西&#x…

【ProcessOn】流程图咏道图Axure自定义元件使用----含流程图案例

目录 一&#xff0c;ProcessOn 1.1 ProcessOn是什么 1.2 ProcessOn应用场景 1.3 流程图 1.4 泳道图简介 1.5 Process网址与界面简介 二&#xff0c;流程图案例 2.1 门诊流程图 2.2 住院流程图 2.3 药房药库流程图 2.4 会议OA流程图 三&#xff0c;Axure自定义元件 …

WEB渗透—PHP反序列化(三)

Web渗透—PHP反序列化 课程学习分享&#xff08;课程非本人制作&#xff0c;仅提供学习分享&#xff09; 靶场下载地址&#xff1a;GitHub - mcc0624/php_ser_Class: php反序列化靶场课程&#xff0c;基于课程制作的靶场 课程地址&#xff1a;PHP反序列化漏洞学习_哔哩…

嵌入式培训-数据结构-day23-线性表

线性表 线性表是包含若干数据元素的一个线性序列 记为&#xff1a; L(a0, ...... ai-1, ai, ai1 ...... an-1) L为表名&#xff0c;ai (0≤i≤n-1)为数据元素&#xff1b; n为表长,n>0 时&#xff0c;线性表L为非空表&#xff0c;否则为空表。 线性表L可用二元组形式描述…

diffuser为pipeline设置不用的scheduler

查看默认的schedulers&#xff1a; 使用默认的schedulers生成数据 查看默认scheduler的默认配置&#xff0c;定义了采样器中的相关参数&#xff0c;网上关于DDPM和DDIM的文章较多&#xff0c;可以先去看看这两种schedulers&#xff1a; 修改scheduler&#xff0c;可以用于…

【总结】THUPC2024

队名&#xff1a;消灭智哥 队友&#xff1a;zbh&#xff0c;hrl 比赛前一天组的队。队名源于及其智慧的对面楼的宿管。 复赛就不用想了&#xff0c;就体验一下 ACM 的队伍赛制。 去年一题没切&#xff0c;被队友 szt 单人切 3 带飞。现在 szt 已经是高贵的华附哥了。 今年我…

Linux——进程地址空间与进程控制

进程地址空间与进程控制 文章目录 进程地址空间与进程控制1. 进程地址空间1.1 进程地址空间的引入1.1 进程地址空间的特点1.2 页表1.3 C/C的地址1.4 进程地址空间 页表的优势 2. 进程控制2.1 进程创建2.1.1 写时拷贝 2.2 进程终止2.2.1 进程退出码2.2.2 异常信号码2.2.3 errno…

前端对接 —— 周末

1.点击校验 点击校验 宇哥 记得过滤 不能校验的数据&#xff08;我后端还要检验吗&#xff1f;&#xff09; 2.前端数据对接 这个可以吗&#xff1f; 这种的可以吗&#xff1f;

go原生http开发简易blog(一)项目简介与搭建

文章目录 一、项目简介二、项目搭建前置知识三、首页- - -前端文件与后端结构体定义四、配置文件加载五、构造假数据- - -显示首页内容 代码地址&#xff1a;https://gitee.com/lymgoforIT/goblog 一、项目简介 使用Go原生http开发一个简易的博客系统&#xff0c;包含一下功能…

使用堆排序算法

使用堆排序算法&#xff08;升序&#xff0c;建大堆顶&#xff09;完善此程序。&#xff08;注&#xff1a;截图为堆排序初始化后的大堆顶结果&#xff0c;详见源代码&#xff09; #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #define N 10void input(int a[], …

【react.js + hooks】基于事件机制的跨组件数据共享

跨组件通信和数据共享不是一件容易的事&#xff0c;如果通过 prop 一层层传递&#xff0c;太繁琐&#xff0c;而且仅适用于从上到下的数据传递&#xff1b;建立一个全局的状态 Store&#xff0c;每个数据可能两三个组件间需要使用&#xff0c;其他地方用不着&#xff0c;挂那么…

MySQL日志管理,备份与恢复

备份的主要目的是灾难恢复&#xff0c;备份还可以测试应用、回滚数据修改、查询历史数据、审计等。 而备份、恢复中&#xff0c;日志起到了很重要的作用 MySQL日志管理是数据库管理中的一个重要方面&#xff0c;它可以用于诊断问题、监控性能、进行故障恢复等。MySQL主要有几种…

【合成数字】合成类游戏-uniapp项目开发流程详解

以前玩过2048游戏&#xff0c;从中发现规律&#xff0c;想到跟合成类游戏相似&#xff0c;知道为什么很相似吗&#xff0c;在这里&#xff0c;做一个数字合成游戏玩玩吧&#xff0c;感兴趣的话可以看看&#xff0c;这里给大家讲一讲数字合成游戏的开发过程。 文章目录 创建项目…

Pandas-DataFtame的索引与切片(第3讲)

Pandas-DataFtame的索引与切片(第3讲)         🍹博主 侯小啾 感谢您的支持与信赖。☀️ 🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ�…

【动态读取配置文件】ParameterTool读取带环境的配置信息

不同环境Flink配置信息是不同的&#xff0c;为了区分不同环境的配置文件&#xff0c;使用ParameterTool工具读取带有环境的配置文件信息 区分环境的配置文件 三个配置文件&#xff1a; flink.properties&#xff1a;决定那个配置文件生效 flink-dev.properties&#xff1a;测…

主持知识竞赛类节目的一般流程是什么

竞争性的团队活动&#xff0c;更适合青年的特点&#xff0c;更容易得到青年的支持&#xff0c;也是"离教于乐"的好方式。 这类活动可从内容和特点上分为知识性竞赛&#xff0c;技能性竞赛&#xff0c;文娱性竞赛&#xff0c;体育竞技性竞赛等形式。 知识性竞赛&…

【VMware安装及虚拟机配置】

1. 下载VMware 进入 VMware Workstation 17 Pro下载链接 下拉到如下位置&#xff0c;点击DOWNLOAD 2. 安装VMware 参考&#xff1a;虚拟机VMware下载与安装教程 本次安装是vmware 17&#xff0c;安装步骤差不多&#xff0c;只参考第二部分即可。 3. 激活VMware 密钥&…