Spring Boot集成JSch的示例代碼
1.JSch介紹
JSch是SSH2的純Java實(shí)現(xiàn)。
JSch允許您連接到sshd服務(wù)器并使用端口轉(zhuǎn)發(fā),X11轉(zhuǎn)發(fā),文件傳輸?shù)?,并且可以將其功能集成到您自己的Java程序中。
2.實(shí)現(xiàn)原理
根據(jù)遠(yuǎn)程主機(jī)的IP地址,用戶名和端口,建立會(huì)話(Session)
設(shè)置用戶信息(包括密碼和Userinfo),然后連接session,getSession()只是創(chuàng)建一個(gè)session,需要設(shè)置必要的認(rèn)證信息之后,調(diào)用connect()才能建立連接。
設(shè)置channel上需要遠(yuǎn)程執(zhí)行的Shell腳本,連接channel,就可以遠(yuǎn)程執(zhí)行該Shell腳本,調(diào)用openChannel(String type) 可以在session上打開指定類型的channel。該channel只是被初始化,使用前需要先調(diào)用connect()進(jìn)行連接。
可以讀取遠(yuǎn)程執(zhí)行Shell腳本的輸出,然后依次斷開channel和session的連接
3.代碼工程
實(shí)驗(yàn)?zāi)繕?biāo):實(shí)現(xiàn)文件上傳到服務(wù),服務(wù)器下載文件以及執(zhí)行服務(wù)器命令
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); } }
代碼倉(cāng)庫(kù)
https://github.com/Harries/springboot-demo
4.測(cè)試
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); } }
自己嘗試一下吧,非常好的一個(gè)工具,更多功能可以去官網(wǎng)看例子
5.引用
http://www.jcraft.com/jsch/examples/
http://www.liuhaihua.cn/archives/710346.html
到此這篇關(guān)于Spring Boot集成JSch的示例代碼的文章就介紹到這了,更多相關(guān)SpringBoot集成JSch內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot統(tǒng)計(jì)接口請(qǐng)求耗時(shí)的方法詳解
接口請(qǐng)求時(shí)間的快慢就代表著獲取到對(duì)應(yīng)的數(shù)據(jù)的快慢,也代表著用戶請(qǐng)求頁(yè)面數(shù)據(jù)的快慢,常??梢越柚涌谡?qǐng)求快慢進(jìn)行相應(yīng)的優(yōu)化,本文給大家介紹了SpringBoot統(tǒng)計(jì)接口請(qǐng)求耗時(shí)的方法,需要的朋友可以參考下2024-12-12SpringBoot使用JDBC獲取相關(guān)的數(shù)據(jù)方法
這篇文章主要介紹了SpringBoot使用JDBC獲取相關(guān)的數(shù)據(jù)方法,JDBC與數(shù)據(jù)庫(kù)建立連接、發(fā)送 操作數(shù)據(jù)庫(kù)的語(yǔ)句并處理結(jié)果,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-03-03java讀取excel文件并復(fù)制(copy)文件到指定目錄示例
這篇文章主要介紹了java讀取excel文件并復(fù)制文件到指定目錄示例,需要的朋友可以參考下2014-02-02關(guān)于Java實(shí)現(xiàn)word(docx、doc)轉(zhuǎn)html的完美解決方案
文章介紹了多種將Word文檔轉(zhuǎn)換為HTML的方法,包括使用Microsoft Word自帶的導(dǎo)出功能、第三方工具和編程實(shí)現(xiàn),展示了如何實(shí)現(xiàn)將.docx文件轉(zhuǎn)換為HTML文件,并自動(dòng)生成目錄、處理分頁(yè)符和增強(qiáng)表格樣式等功能,感興趣的朋友一起看看吧2025-01-01springboot實(shí)現(xiàn)獲取當(dāng)前服務(wù)器IP及當(dāng)前項(xiàng)目使用的端口號(hào)Port
這篇文章主要介紹了springboot實(shí)現(xiàn)獲取當(dāng)前服務(wù)器IP及當(dāng)前項(xiàng)目使用的端口號(hào)Port方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-12-12SpringCloud 服務(wù)網(wǎng)關(guān)路由規(guī)則的坑及解決
這篇文章主要介紹了SpringCloud 服務(wù)網(wǎng)關(guān)路由規(guī)則的坑及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-07-07Java將word文件轉(zhuǎn)成pdf文件的操作方法
這篇文章主要介紹了Java將word文件轉(zhuǎn)成pdf文件的操作方法,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-09-09