用JSch实现远程传输文件并打包成jar

本文将简单介绍一下 JSch 这个Java的第三方库的一个简单用法,并以此为实例,讲解 IntelliJ 中打包成 jar 包的2种方式。

实现目标

我们的目标是,做出一个jar包,它能够实现类似于 scp 命令的远程传输文件的功能。用法如下:

java -jar UseJsch.jar scp /home/finix/1.txt 192.168.10.21:/home/finix/1.txt 

即,将本地的文件 /home/finix/1.txt 拷贝到远程机器 192.168.10.21 的 /home/finix/1.txt

简介 JSch

JSch 的官网是:http://www.jcraft.com/jsch/
JSch 是SSH2的纯Java实现。 它拥有诸多的和ssh相关的功能,比如 ssh 执行命令、scp等等,并被使用在一些著名的开源软件中。这个库的最新版本似乎就是 0.1.55, 于2018年左右就停止更新了。
本文不打算深入罗列JSch的各种功能,只是使用了其ChannelSftp类的put功能用于远程传输文件。现将ChannelSftp类的一些关键方法罗列如下:

  • put文件上传
  • get文件下载
  • cd进入指定目录
  • ls取得指定目录下的文件列表
  • rename重命名指定的文件或目录
  • mkdir创建目录
  • rmdir删除目录
  • rm删除指定文件

JSch的maven地址

<dependency><groupId>com.jcraft</groupId><artifactId>jsch</artifactId><version>0.1.55</version>
</dependency>

Jsch的gradle写法(build.gradle)

dependencies {  'com.jcraft:jsch:0.1.55'  
}

核心代码

要实现scp文件的功能,可以使用下面的这个类。先看代码,其中具体使用已经写了注释,就不在这里介绍了。

package com.use_jsch;import com.jcraft.jsch.*;import java.io.*;
import java.util.Properties;public class UseJsch {public static void scpFile(int servicePort, String srcFilePath, String dstFilePath, String dstAddress) throws IOException {final String USER = "finix";final String PASSWORD = "123456789";final String PRIVATE_KEY_FILE = "/home/finix/.ssh/id_rsa";final String SESSION_TYPE = "sftp";final int SSH_TIMEOUT = 30000;  // 30 secondsfinal int SSH_COMMAND_ACK_TIMEOUT = 5000;   // 5 secondsfinal int CHANNEL_TIMEOUT = 5000;   // 5 secondsFile file = new File(srcFilePath);if (!file.exists()) {throw new RuntimeException(String.format("%s does not exist", srcFilePath));}Session session = null;Channel channel = null;ChannelSftp sftp = null;FileInputStream fileInputStream = null;try {JSch jsch = new JSch();// jsch.addIdentity(PRIVATE_KEY_FILE);Properties config = new Properties();config.put("StrictHostKeyChecking", "no");config.put("PreferredAuthentications", "publickey,password");session = jsch.getSession(USER, dstAddress, servicePort);session.setPassword(PASSWORD);session.setConfig(config);System.out.println("SCP_FILE: 1. session connecting...");session.connect(SSH_TIMEOUT);session.setTimeout(SSH_COMMAND_ACK_TIMEOUT);System.out.println("SCP_FILE: 2. open channel and connect...");channel = session.openChannel(SESSION_TYPE);channel.connect(CHANNEL_TIMEOUT);sftp = (ChannelSftp) channel;System.out.println("SCP_FILE: 3. scp file...");fileInputStream = new FileInputStream(file);sftp.setInputStream(fileInputStream);sftp.put(fileInputStream, dstFilePath);System.out.println("SCP_FILE: END");} catch (JSchException e) {System.err.println("SCP_FILE: JSchException: " + e);throw new RuntimeException("SCP_FILE: JSchException: " + e);} catch (IOException e) {System.err.println("SCP_FILE: IOException: " + e);throw new RuntimeException("SCP_FILE: IOException: " + e);} catch (Exception e) {System.err.println("SCP_FILE: ERROR: " + e);throw new RuntimeException("SCP_FILE: ERROR: " + e);} finally {if (fileInputStream != null) fileInputStream.close();if (channel != null) channel.disconnect();if (session != null) session.disconnect();}}public static void main(String[] args) {if (args.length != 3 || !args[0].equals("scp")) {System.out.println("Usage: java -jar UseJsch.jar scp <src_file_path> <ip>:<dest_file_path>");System.exit(1);}String srcFilePath = args[1];String[] destFileAndDestAddress = args[2].split(":");String dstFilePath = destFileAndDestAddress[1];String dstAddress = destFileAndDestAddress[0];try {System.out.printf("Start to scp file from %s to %s:%s%n", srcFilePath, dstAddress, dstFilePath);scpFile(22,srcFilePath, dstFilePath, dstAddress);}catch (Exception ex) {System.err.println("SCP FILE ERROR: " + ex);}}
}

这个java文件如果要直接测的话,可以将第一行 “package xxx” 删除,然后运行

java -cp lib/jsch-0.1.55.jar UseJsch.java /home/finix/1.txt 192.168.10.21:/home/cyc/1.txt

运行效果就是:

Start to scp file from /home/finix/1.txt to 192.168.10.21:/home/finix/1.txt
SCP_FILE: 1. session connecting...
SCP_FILE: 2. open channel and connect...
SCP_FILE: 3. scp file...
SCP_FILE: END

值得一提的有2个地方:

  1. config.put("StrictHostKeyChecking", "no");
    这句话相当于 ssh 或 scp 的时候用的命令行参数 -o StrictHostKeyChecking=no, 其作用是,令其不再出现交互式的提问
The authenticity of host '192.168.10.21 (192.168.10.21)' can't be established.
ECDSA key fingerprint is SHA256:lSbwytjbqqvCC2FILkMb+M+yaeUTxEYPAPFTVIjTFOg.
Are you sure you want to continue connecting (yes/no/[fingerprint])?

这是因为这个目标IP没有被加到~/.ssh/known_hosts文件中,所以询问你是否要继续连接。我们用了上面的选项-o StrictHostKeyChecking=no后,就不会再交互式提问,而是默认yes.

  1. config.put("PreferredAuthentications", "publickey,password");
    这一行代表优先使用的认证方式是publickeypassword这两种。
    (据说JSch提供了4种认证方式,但比较常用的应该还是以上提到的这2种)
    这一句的意思是优先使用publickey, 如果不行了再使用password. 如果要使用publickey, 那么其实还要再加一句
final String PRIVATE_KEY_FILE = "/home/finix/.ssh/id_rsa";
...
jsch.addIdentity(PRIVATE_KEY_FILE);

而在本文程序中, jsch.addIdentity(PRIVATE_KEY_FILE);被注释掉了,所以本文程序仍旧使用的是密码的方式。

程序部分就介绍到这里。下面是打包的流程。

打包为jar包

Step 1. 首先,在IntelliJ中新建一个gradle的项目,并加入源代码UseJsch.java, 而build.gradle中依赖包的加法已经在上文中描述过了,就不再重复。这里的目录结构大约是这样的:
在这里插入图片描述

Step 2. File -> Project Structure -> Module, 此处鼠标单击选中 “UseJsch” (不要选中其下面的“main”),此处应该能看到 “Gradle: com.jcraft:jsch:0.1.55”;若看不到,则此处需添加之。
注意:
这一步对于下面的第一种打包方式很重要,是必须的;但对于第二种打包方式则不是必须的。

在这里插入图片描述
Step 3. 还是在上面的界面,鼠标单击选中 “Artifacts”, 再点击“+” 和 “From modules with dependencies”
在这里插入图片描述

Step 4. 在弹出框中填“Module”、“Main class”、“JAR files from libraries”
在这里插入图片描述

注意,这里的 “JAR files from libraries” 有2个选项

  • extract to the target JAR
    这个选项的含义是:将第三方库的jar文件解压成class文件,然后拷贝到和主类相同的目录结构中。
    如果用了这个选项,我们就不用设置classpath来寻找第三方的库了。
  • copy to the output directory and link via manifest
    这个选项的含义是:第三方库将仍以jar包的形式存在,它会被拷贝到指定的地方(如lib目录);主类自己会被打一个jar包;因此需要在给主类打包的时候,指定MANIFEST文件中的classpath怎么写(见下文"打包方式-2")

打包方式-1: extract to the target JAR

Step 5.
上文Step-4中点击OK后,我们可以看到如下的界面:
在这里插入图片描述

注意,这里没有主类 UseJsch, 所以还得点击加号, 以添加主类。添加之后的效果如下:
在这里插入图片描述

注意,此处不用填写Class Path,因为第三方库已经被解压并和主类放置到了相同的目录结构下。
现在点击OK.

Step 6. Build -> Build Artifacts
在这里插入图片描述
此处点击 Build 或 Rebuild.

Build结束之后,我们在 output/artifacts/UseJsch_jar 目录下可以看到 UseJsch.jar 文件了!
在这里插入图片描述

右键选winrar打开,我们可以看到 jcraft 库的代码已经被解压和use_jsch包放到了一起:
在这里插入图片描述
最后,可以运行这个UseJsch.jar了:

$ java -jar UseJsch.jar scp /home/cyc/1.txt 192.168.10.21:/home/cyc/1.txt
Start to scp file from /home/cyc/1.txt to 192.168.10.21:/home/cyc/1.txt
SCP_FILE: 1. session connecting...
SCP_FILE: 2. open channel and connect...
SCP_FILE: 3. scp file...
SCP_FILE: END

打包方式-2: copy to the output directory and link via manifest

在上文Step-4的时候选中 “copy to the output directory and link via manifest”, 点OK
然后可以看到如下的界面。在这里插入图片描述

注意,
这里我们已经可以看到第三方库 jsch-0.1.55.jar了,这是我们在Step-2所作的工作的效果;
(如果没有Step-2的工作,这里将不会显示第三方库,因此就需要手动添加:点击加号“+”,再点击 Library Files)。
但是,此时并没有 主类,所以我们需要手动加主类添加上去:点击加号,再点击“Module Output”,如下:
在这里插入图片描述
最后点击OK, 效果见下一步的图。

Step-5. 点击选中“UseJsch.jar”, 然后在下面出现的框中填写 “Manifest File”、“Main Class”、和“Class Path”
在这里插入图片描述

最后,剩下来的步骤和打包方式-1相同,就是Build -> Build Artifacts.
出来的效果是这样的。
在这里插入图片描述
运行效果也是一样,不再赘述。

(完)

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

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

相关文章

应急响应靶机训练-Linux2题解

前言 接上文&#xff0c;应急响应靶机训练Linux2 靶机地址&#xff1a;应急响应靶机-Linux(2) 题解 登录虚拟机&#xff1a; 修改面板密码 提交攻击者IP 答案&#xff1a;192.168.20.1 查看宝塔日志即可 用的net直接是网关 提交攻击者修改的管理员密码(明文) 答案&…

LeetCode---390周赛

题目列表 3090. 每个字符最多出现两次的最长子字符串 3091. 执行操作使数据元素之和大于等于 K 3092. 最高频率的 ID 3093. 最长公共后缀查询 一、每个字符最多出现两次的最长子字符串 非常经典的滑动窗口问题&#xff0c;即动态维护一段区间&#xff0c;使得这段区间满足…

JUC:park/unpark的用法与原理

park / unpark 用法 // 暂停当前线程 LockSupport.park(); // 恢复某个线程的运行 LockSupport.unpark(暂停线程对象)**先说结论&#xff1a;**无论unpark在park前还是后&#xff0c;都可以解除暂停状态。 先park在unpark可以成功运行&#xff1a; Thread t1 new Thread((…

全局UI方法-弹窗二-列表选择弹窗(ActionSheet)

1、描述 定义列表弹窗 2、接口 ActionSheet.show(value:{ title: string | Resource, message: string | Resource, autoCancel?: boolean, confrim?: {value: string | Resource, action: () > void }, cancel?: () > void, alignment?: DialogAlignment, …

kafka学习笔记02(小滴课堂)

Kafka命令行生产者发送消息和消费者消费消息实战 已存在的kafka不能重复创建。 broker设置的是1&#xff0c;factor大于broker了&#xff0c;所以报错。 生产者发送消息&#xff1a; kafka列表出现了新的kafka。 我们使用这个kafka。 我们启动消费者&#xff1a; 我们现在不从…

【Qt 学习笔记】Day1 | Qt 背景介绍

博客主页&#xff1a;Duck Bro 博客主页系列专栏&#xff1a;Qt 专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ Day1 | Qt 背景介绍 文章编号&#xff1a;Qt 学习笔记 / 01 文章目录…

C/C++语言实现简易通讯录 [含文件操作,循环双链表]

文章目录 C/C语言实现简易通讯录概要基本功能运行截图展示主要代码展示 &#x1f396; 博主的CSDN主页&#xff1a;Ryan.Alaskan Malamute &#x1f4dc; 博主的代码仓库主页 [ Gitee ]&#xff1a;ryanala [GitHub]&#xff1a; Ryan-Ala C/C语言实现简易通讯录 ⚠⚠⚠ …

话题通信的python实现

一、发布者Publisher的python实现 step1&#xff1a;在scripts文件夹中创建py节点 step2&#xff1a;第一行是为了指定解释器&#xff0c;Ubuntu20.04是python3&#xff0c;比他低的版本是python。第二行是为了指定编码方式。第五行中&#xff0c;引用index.ros.org中数据类型…

RVM安装ruby笔记

环境 硬件&#xff1a;Macbook Pro 系统&#xff1a;macOS 14.1 安装公钥 通过gpg安装公钥失败&#xff0c;报错如下&#xff1a; 换了几个公钥地址&#xff08;hkp://subkeys.pgp.net&#xff0c;hkp://keys.gnupg.net&#xff0c;hkp://pgp.mit.edu&#xff09;&#xff0c;…

论文笔记:Retrieval-Augmented Generation forAI-Generated Content: A Survey

北大202402的RAG综述 1 intro 1.1 AICG 近年来&#xff0c;人们对人工智能生成内容&#xff08;AIGC&#xff09;的兴趣激增。各种内容生成工具已经精心设计&#xff0c;用于生产各种模态下的多样化对象 文本&代码&#xff1a;大型语言模型&#xff08;LLM&#xff09;…

Java:链表

一、链表简介 1、链表与顺序表的区别 上一篇博客我介绍了顺序表&#xff0c;这次我们来认识认识链表&#xff01;先来看看二者的区别&#xff1a; 顺序表&#xff1a;由于顺序表实际上是一个数组&#xff0c;因此它在物理上是连续的&#xff0c;逻辑上也是连续的&#xff01; …

【IDEA】使用debug方式去运行java程序

什么是debug工具&#xff1f; 调试工具&#xff08;debug工具&#xff09;是一种用于帮助程序员识别和修复程序中的错误的工具。它们提供了一系列的功能&#xff0c;帮助程序员在代码执行的过程中跟踪和检测问题&#xff0c;例如查看变量的值、检查函数的调用栈、设置断点来停…

Spring学习——什么是循环依赖及其解决方式

文章目录 前言一、什么是循环依赖二、解决思路1、循环依赖分类2、对象初始化步骤及对象分类3、spring是如何解决的4、图解5、三级缓存1、区别2、ObjectFactory是什么 三、源码debug1、spring创建对象过程1、dubug第一步——找到getBean2、dubug第二步——getBean与doGetBean3、…

腾讯 tendis 替代 redis linux安装使用

下载地址 Tendis存储版 点击下载 linux 解压 tar -zxvf 安装包.tgz cd 解压安装包/scripts 启动 ./start.sh 停止 ./stop.sh 详细配置 修改 /scripts tendisplus.conf # tendisplus configuration for testing # 绑定本机IIP bind 192.168.31.112 port 51002 #设…

海格里斯助推实体制造业转型升级 “算法定义硬件”解题AIoT市场

随着自动化的发展&#xff0c;电子商务和智能制造推动了自动化立体仓库的快速发展与创新&#xff0c;产生了“密集仓储”的概念。对于一个实体企业来讲&#xff0c;其数智物流转型正在趋向于“去伪存真”&#xff0c;企业追求高ROI与真实经济价值&#xff0c;具有降本增效的业务…

JavaEE 初阶篇-深入了解多线程安全问题(出现线程不安全的原因与解决线程不安全的方法)

&#x1f525;博客主页&#xff1a; 【小扳_-CSDN博客】 ❤感谢大家点赞&#x1f44d;收藏⭐评论✍ 文章目录 1.0 多线程安全问题概述 1.1 线程不安全的实际例子 2.0 出现线程不安全的原因 2.1 线程在系统中是随机调度且抢占式执行的模式 2.2 多个线程同时修改同一个变量 2.3 线…

游戏行业行业竞争越来越激烈,遇到DDoS攻击遭受严重损失该如何解决

近年来&#xff0c;我们见证了数字化的快速发展&#xff0c;随着这样的发展&#xff0c;网络的威胁也逐渐增多&#xff0c;在网络攻击门槛不断降低&#xff0c;行业竞争越来越激烈&#xff0c;游戏行业的DDoS攻击如雨点般密集&#xff0c;在整个DDoS攻击的份额中&#xff0c;游…

SpringAMQP-Exchange交换机

1、Fanout-Exchange的特点是&#xff1a;和它绑定的消费者都会收到信息 交换机的作用是什么? 接收publisher发送的消息将消息按照规则路由到与之绑定的队列不能缓存消息&#xff0c;路由失败&#xff0c;消息丢失FanoutExchange的会将消息路由到每个绑定的队列 声明队列、交…

【实验报告】--基础VLAN

【VLAN实验报告】 一、项目背景 &#xff08;为 Jan16 公司创建部门 VLAN&#xff09; Jan16 公司现有财务部、技术部和业务部&#xff0c;出于数据安全的考虑&#xff0c;各部门的计算机需进 行隔离&#xff0c;仅允许部门内部相互通信。公司拓扑如图 1 所示&#xff0c; …

http和https的工作原理是什么?

HTTP&#xff08;HyperText Transfer Protocol&#xff09;和HTTPS&#xff08;HyperText Transfer Protocol Secure&#xff09;是两种用于在互联网上传输数据的主要协议&#xff0c;它们均用于在客户端&#xff08;通常是Web浏览器&#xff09;与服务器之间交换信息。尽管它们…