Spring Boot集成JSch的示例代码
1.JSch介绍
JSch是SSH2的纯Java实现。
JSch允许您连接到sshd服务器并使用端口转发,X11转发,文件传输等,并且可以将其功能集成到您自己的Java程序中。
2.实现原理
根据远程主机的IP地址,用户名和端口,建立会话(Session)
设置用户信息(包括密码和Userinfo),然后连接session,getSession()只是创建一个session,需要设置必要的认证信息之后,调用connect()才能建立连接。
设置channel上需要远程执行的Shell脚本,连接channel,就可以远程执行该Shell脚本,调用openChannel(String type) 可以在session上打开指定类型的channel。该channel只是被初始化,使用前需要先调用connect()进行连接。
可以读取远程执行Shell脚本的输出,然后依次断开channel和session的连接
3.代码工程
实验目标:实现文件上传到服务,服务器下载文件以及执行服务器命令
pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>springboot-demo</artifactId> <groupId>com.et</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>JSch</artifactId> <properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-autoconfigure</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!-- https://mvnrepository.com/artifact/com.jcraft/jsch --> <dependency> <groupId>com.jcraft</groupId> <artifactId>jsch</artifactId> <version>0.1.55</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.78</version> </dependency> </dependencies> </project>
remote.java
package com.et.jsch.model; import lombok.Data; @Data public class Remote { private String host; private final int port = 22; private String user; private String password; private final String identity = "~/.ssh/id_rsa"; private String passphrase; }
JSchUtil.java
package com.et.jsch.util; import com.et.jsch.model.Remote; import com.jcraft.jsch.*; import lombok.extern.slf4j.Slf4j; import java.io.*; import java.nio.file.Files; import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; import java.util.function.Function; /** * ssh tools */ @Slf4j public class JSchUtil { public static final int SESSION_TIMEOUT = 30000; public static final int CONNECT_TIMEOUT = 3000; /** * get session * * @param remote ssh server info * @return session * @throws JSchException / */ public static Session getSession(Remote remote) throws JSchException { JSch jSch = new JSch(); if (Files.exists(Paths.get(remote.getIdentity()))) { jSch.addIdentity(remote.getIdentity(), remote.getPassphrase()); } Session session = jSch.getSession(remote.getUser(), remote.getHost(), remote.getPort()); session.setPassword(remote.getPassword()); session.setConfig("StrictHostKeyChecking", "no"); return session; } /** * excute remote command * * @param session session * @param command command * @return / * @throws JSchException / */ public static List<String> remoteExecute(Session session, String command) throws JSchException { log.debug(">> {}", command); List<String> resultLines = new ArrayList<>(); ChannelExec channel = null; try { channel = openExecChannel(session); channel.setCommand(command); InputStream input = channel.getInputStream(); channel.connect(CONNECT_TIMEOUT); try { BufferedReader inputReader = new BufferedReader(new InputStreamReader(input)); String inputLine; while ((inputLine = inputReader.readLine()) != null) { log.debug(" {}", inputLine); resultLines.add(inputLine); } } finally { if (input != null) { try { input.close(); } catch (Exception e) { log.error("JSch inputStream close error:", e); } } } } catch (IOException e) { log.error("IOException:", e); } finally { disconnect(channel); } return resultLines; } /** * scp file to remote server * * @param session session * @param source local file * @param destination remote target file * @return file size */ public static long scpTo(Session session, String source, String destination) { FileInputStream fileInputStream = null; ChannelExec channel = null; try { channel = openExecChannel(session); OutputStream out = channel.getOutputStream(); InputStream in = channel.getInputStream(); boolean ptimestamp = false; String command = "scp"; if (ptimestamp) { command += " -p"; } command += " -t " + destination; channel.setCommand(command); channel.connect(CONNECT_TIMEOUT); if (checkAck(in) != 0) { return -1; } File _lfile = new File(source); if (ptimestamp) { command = "T " + (_lfile.lastModified() / 1000) + " 0"; // The access time should be sent here, // but it is not accessible with JavaAPI ;-< command += (" " + (_lfile.lastModified() / 1000) + " 0\n"); out.write(command.getBytes()); out.flush(); if (checkAck(in) != 0) { return -1; } } //send "C0644 filesize filename", where filename should not include '/' long fileSize = _lfile.length(); command = "C0644 " + fileSize + " "; if (source.lastIndexOf('/') > 0) { command += source.substring(source.lastIndexOf('/') + 1); } else { command += source; } command += "\n"; out.write(command.getBytes()); out.flush(); if (checkAck(in) != 0) { return -1; } //send content of file fileInputStream = new FileInputStream(source); byte[] buf = new byte[1024]; long sum = 0; while (true) { int len = fileInputStream.read(buf, 0, buf.length); if (len <= 0) { break; } out.write(buf, 0, len); sum += len; } //send '\0' buf[0] = 0; out.write(buf, 0, 1); out.flush(); if (checkAck(in) != 0) { return -1; } return sum; } catch (JSchException e) { log.error("scp to caught jsch exception, ", e); } catch (IOException e) { log.error("scp to caught io exception, ", e); } catch (Exception e) { log.error("scp to error, ", e); } finally { closeInputStream(fileInputStream); disconnect(channel); } return -1; } /** * scp remote file to local * * @param session session * @param source remote file * @param destination local file * @return file size */ public static long scpFrom(Session session, String source, String destination) { FileOutputStream fileOutputStream = null; ChannelExec channel = null; try { channel = openExecChannel(session); channel.setCommand("scp -f " + source); OutputStream out = channel.getOutputStream(); InputStream in = channel.getInputStream(); channel.connect(); byte[] buf = new byte[1024]; //send '\0' buf[0] = 0; out.write(buf, 0, 1); out.flush(); while (true) { if (checkAck(in) != 'C') { break; } } //read '644 ' in.read(buf, 0, 4); long fileSize = 0; while (true) { if (in.read(buf, 0, 1) < 0) { break; } if (buf[0] == ' ') { break; } fileSize = fileSize * 10L + (long) (buf[0] - '0'); } String file = null; for (int i = 0; ; i++) { in.read(buf, i, 1); if (buf[i] == (byte) 0x0a) { file = new String(buf, 0, i); break; } } // send '\0' buf[0] = 0; out.write(buf, 0, 1); out.flush(); // read a content of lfile if (Files.isDirectory(Paths.get(destination))) { fileOutputStream = new FileOutputStream(destination + File.separator + file); } else { fileOutputStream = new FileOutputStream(destination); } long sum = 0; while (true) { int len = in.read(buf, 0, buf.length); if (len <= 0) { break; } sum += len; if (len >= fileSize) { fileOutputStream.write(buf, 0, (int) fileSize); break; } fileOutputStream.write(buf, 0, len); fileSize -= len; } return sum; } catch (JSchException e) { log.error("scp to caught jsch exception, ", e); } catch (IOException e) { log.error("scp to caught io exception, ", e); } catch (Exception e) { log.error("scp to error, ", e); } finally { closeOutputStream(fileOutputStream); disconnect(channel); } return -1; } /** * remote edit * * @param session session * @param source target file * @param process edit command collect * @return isSuccess */ private static boolean remoteEdit(Session session, String source, Function<List<String>, List<String>> process) { InputStream in = null; OutputStream out = null; try { String fileName = source; int index = source.lastIndexOf('/'); if (index >= 0) { fileName = source.substring(index + 1); } //backup source remoteExecute(session, String.format("cp %s %s", source, source + ".bak." + System.currentTimeMillis())); //scp from remote String tmpSource = System.getProperty("java.io.tmpdir") + session.getHost() + "-" + fileName; scpFrom(session, source, tmpSource); in = new FileInputStream(tmpSource); //edit file according function process String tmpDestination = tmpSource + ".des"; out = new FileOutputStream(tmpDestination); List<String> inputLines = new ArrayList<>(); BufferedReader reader = new BufferedReader(new InputStreamReader(in)); String inputLine = null; while ((inputLine = reader.readLine()) != null) { inputLines.add(inputLine); } List<String> outputLines = process.apply(inputLines); for (String outputLine : outputLines) { out.write((outputLine + "\n").getBytes()); out.flush(); } //scp to remote scpTo(session, tmpDestination, source); return true; } catch (Exception e) { log.error("remote edit error, ", e); return false; } finally { closeInputStream(in); closeOutputStream(out); } } /** * update file * * @param session session * @param in file stream * @param directory local dir * @param fileName FTP server file name:xxx.txt ||xxx.txt.zip */ public static boolean uploadFile(Session session, InputStream in, String directory, String fileName) { log.info(">>>>>>>>uploadFile--ftp start>>>>>>>>>>>>>"); ChannelSftp channel = null; try { channel = openSftpChannel(session); channel.connect(CONNECT_TIMEOUT); String[] folders = directory.split("/"); try { for (int i = 0; i < folders.length; i++) { if (i == 0 && folders[i].length() == 0) { channel.cd("/"); } else if (folders[i].length() > 0) { try { channel.cd(folders[i]); } catch (SftpException e) { channel.mkdir(folders[i]); channel.cd(folders[i]); } } } } catch (SftpException e) { log.error("ftp create file fail" + directory, e); return false; } try { channel.put(in, fileName); } catch (SftpException e) { log.error("sftp error-->" + e.getMessage(), e); return false; } log.info(">>>>>>>>uploadFile--ftp upload end>>>>>>>>>>>>>"); log.info(">>>>>>>>ftp upload dir:{},filename:{}>>>>>>>>>>>>>", directory, fileName); return true; } catch (JSchException e) { log.error("JSch error-->" + e.getMessage(), e); return false; } finally { closeInputStream(in); disconnect(channel); } } /** * * * @param channel sftp connect * @param directory * @param fileName * @return */ public static InputStream stream(ChannelSftp channel, String directory, String fileName) { try { channel.connect(CONNECT_TIMEOUT); InputStream inputStream = channel.get(directory + "/" + fileName); log.info(">>>>>>>>ftp file directory:{},filename:{}>>>>>>>>>>>>>", directory, fileName); return inputStream; } catch (SftpException e) { log.error("sftp error-->" + e.getMessage()); return null; } catch (JSchException e) { log.error("JSch error-->" + e.getMessage()); return null; } } /** * ftp delete remote file * * @param session session * @param directory directory * @param fileName filename * @return is Success */ public static boolean deleteFile(Session session, String directory, String fileName) { log.info(">>>>>>>>deleteFile--ftp delete file end>>>>>>>>>>>>>"); ChannelSftp channel = null; try { channel = openSftpChannel(session); channel.connect(CONNECT_TIMEOUT); channel.rm(directory + "/" + fileName); log.info(">>>>>>>>deleteFile--deletefile end>>>>>>>>>>>>>"); log.info(">>>>>>>>ftp delete file directory:{},filename:{}>>>>>>>>>>>>>", directory, fileName); } catch (SftpException e) { log.error("ftp create directory fail" + directory); return false; } catch (JSchException e) { log.error("JSch error-->" + e.getMessage()); return false; } finally { disconnect(channel); } return true; } public static Channel openChannel(Session session, String type) throws JSchException { if (!session.isConnected()) { session.connect(SESSION_TIMEOUT); } return session.openChannel(type); } public static ChannelSftp openSftpChannel(Session session) throws JSchException { return (ChannelSftp) openChannel(session, "sftp"); } public static ChannelExec openExecChannel(Session session) throws JSchException { return (ChannelExec) openChannel(session, "exec"); } /** * disconnect * * @param session */ public static void disconnect(Session session) { if (session != null) { if (session.isConnected()) { try { session.disconnect(); log.info("session disconnect successfully"); } catch (Exception e) { log.error("JSch session disconnect error:", e); } } } } /** * close connection * * @param channel channel connection */ public static void disconnect(Channel channel) { if (channel != null) { if (channel.isConnected()) { try { channel.disconnect(); log.info("channel is closed already"); } catch (Exception e) { log.error("JSch channel disconnect error:", e); } } } } public static int checkAck(InputStream in) throws IOException { int b = in.read(); // b may be 0 for success, // 1 for error, // 2 for fatal error, // -1 if (b == 0) { return b; } if (b == -1) { return b; } if (b == 1 || b == 2) { StringBuilder sb = new StringBuilder(); int c; do { c = in.read(); sb.append((char) c); } while (c != '\n'); if (b == 1) { // error log.debug(sb.toString()); } if (b == 2) { // fatal error log.debug(sb.toString()); } } return b; } public static void closeInputStream(InputStream in) { if (in != null) { try { in.close(); } catch (IOException e) { log.error("Close input stream error." + e.getMessage()); } } } public static void closeOutputStream(OutputStream out) { if (out != null) { try { out.close(); } catch (IOException e) { log.error("Close output stream error." + e.getMessage()); } } } }
DemoApplication.java
package com.et.jsch; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } }
代码仓库
https://github.com/Harries/springboot-demo
4.测试
import com.alibaba.fastjson.JSONObject; import com.et.jsch.DemoApplication; import com.et.jsch.model.Remote; import com.et.jsch.util.JSchUtil; import com.jcraft.jsch.JSchException; import com.jcraft.jsch.Session; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.InputStream; import java.util.List; @RunWith(SpringRunner.class) @SpringBootTest(classes = DemoApplication.class) public class JSchUtilTests { private Logger log = LoggerFactory.getLogger(getClass()); Session session; @Before public void before() throws JSchException { Remote remote= new Remote(); remote.setHost("xxx.xxx.xxx.xxx"); remote.setUser("root"); remote.setPassword("xxxx"); session= JSchUtil.getSession(remote); } @After public void after(){ JSchUtil.disconnect(session); } @Test public void remoteExecute() throws JSchException { List<String> list= JSchUtil.remoteExecute(session,"ls"); System.out.println(JSONObject.toJSON(list)); } @Test public void uploadFile() throws JSchException, FileNotFoundException { String filestr ="D:\\tmp\\test\\file_utils\\file1.txt"; File file = new File(filestr); InputStream in = new FileInputStream(file); String directory="/root/test"; String fileName="test.txt"; boolean flag= JSchUtil.uploadFile(session,in,directory,fileName); System.out.println(flag); } @Test public void deleteFile() throws JSchException, FileNotFoundException { String directory="/root/test"; String fileName="test.txt"; boolean flag= JSchUtil.deleteFile(session,directory,fileName); System.out.println(flag); } @Test public void scpFrom() throws JSchException, FileNotFoundException { String source="/root/test/file1.txt"; String destination ="D:\\tmp\\scfFrom.txt"; long filesize= JSchUtil.scpFrom(session,source,destination); System.out.println(filesize); } @Test public void scpTo() throws JSchException, FileNotFoundException { String filestr ="D:\\tmp\\test\\file_utils\\file1.txt"; String destination="/root/test/file1.txt"; long filesize= JSchUtil.scpTo(session,filestr,destination); System.out.println(filesize); } }
自己尝试一下吧,非常好的一个工具,更多功能可以去官网看例子
5.引用
http://www.jcraft.com/jsch/examples/
http://www.liuhaihua.cn/archives/710346.html
到此这篇关于Spring Boot集成JSch的示例代码的文章就介绍到这了,更多相关SpringBoot集成JSch内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
java之scan.next()与scan.nextline()函数的使用及区别
这篇文章主要介绍了java之scan.next()与scan.nextline()函数的使用及区别,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教2023-04-04java多态性中的Overload和Override区别详解
这篇文章主要介绍了java多态性中的Overload和Override区别详解,重写(Overriding)是父类与子类之间多态性的一种表现,而重载(Overloading)是一个类中多态性的一种表现,需要的朋友可以参考下2023-07-07如何解决java.util.concurrent.CancellationException问题
这篇文章主要介绍了如何解决java.util.concurrent.CancellationException问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教2024-05-05详解Idea 2019.2 安装lombok插件失效问题解决
这篇文章主要介绍了详解Idea 2019.2 安装lombok插件失效问题解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧2019-10-10
最新评论