java通過ssh連接執(zhí)行shell命令,文件傳輸方式
java通過ssh連接執(zhí)行shell命令,文件傳輸
JSch 是SSH2的純 Java 實現(xiàn) 。
JSch 允許您連接到 sshd 服務(wù)器并使用端口轉(zhuǎn)發(fā)、X11 轉(zhuǎn)發(fā)、文件傳輸?shù)?,可以將其功能集成到您自己?Java 程序中。
JSch 是在BSD 風(fēng)格許可下獲得許可的。
JSCH 官網(wǎng):http://www.jcraft.com/jsch/
zip文件中有很多demo.
jar為依賴jar
maven 依賴
<dependency> <groupId>com.jcraft</groupId> <artifactId>jsch</artifactId> <version>0.1.55</version> </dependency>
測試代碼
import com.jcraft.jsch.*; import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import java.io.*; import java.util.Properties; @Slf4j public class SshTest { private String charset = "UTF-8"; // 設(shè)置編碼格式 private static String userName = "kevin"; // 用戶名 private static String passWord= "1"; // 登錄密碼 private static String host = "192.168.10.101"; // 主機IP private static int port = 22; //默認端口 private static JSch jsch; private static Session session; private static ChannelSftp channelSftp; @BeforeAll public static void createConn() throws JSchException { JSch.setLogger(new Log4JSch()); // detail log for JSch. jsch = new JSch(); // jsch = new KeyGen().keyGenTest(); // 密鑰方式 jsch.setKnownHosts("C:\\Users\\Admin\\.ssh\\known_hosts"); // jsch.addIdentity("~/.ssh/id_rsa", "~/.ssh/id_rsa.pub", null); // jsch.addIdentity("C:\\Users\\Admin\\.ssh\\id_rsa", "C:\\Users\\Admin\\.ssh\\id_rsa.pub", null); String privKeyPath = "C:\\Users\\Admin\\.ssh\\id_rsa"; jsch.addIdentity(privKeyPath); session = jsch.getSession(userName, host, port); // 密碼方式 // session.setPassword(passWord); Properties config = new Properties(); /* * 在代碼里需要跳過檢測。否則會報錯找不到主機 * Test ignored. * com.jcraft.jsch.JSchException: UnknownHostKey: 192.168.10.101. RSA key fingerprint is 10:92:98:45:d2:ea:6b:8f:c1:43:e5:df:86:e5:ae:3c */ config.put("StrictHostKeyChecking", "no"); session.setConfig(config); // 為Session對象設(shè)置properties int timeout = 30000; session.setTimeout(timeout); // 設(shè)置timeout時間 session.connect(); // 通過Session建立與遠程服務(wù)器的連接回話 log.info("connect server host: " + host); } /** * 關(guān)閉連接 */ @AfterAll public static void disconnect(){ log.info("disconnect..."); if (channelSftp != null && channelSftp.isConnected()) { channelSftp.disconnect(); } if(session != null && session.isConnected()){ session.disconnect(); } } @Test public void downloadFile() throws JSchException, FileNotFoundException, SftpException { channelSftp = (ChannelSftp) session.openChannel("sftp"); channelSftp.connect(); log.info("start download channel file!"); String directory = "/tmp"; channelSftp.cd(directory); String saveDir = "D:\\desktop\\"+System.currentTimeMillis()+".txt"; File file = new File(saveDir); String downloadFile = "Test.java"; channelSftp.get(downloadFile, new FileOutputStream(file)); log.info("Download Success!"); channelSftp.disconnect(); log.info("end execute channel sftp!"); } @Test public void uploadFile() throws JSchException, SftpException, FileNotFoundException { channelSftp = (ChannelSftp) session.openChannel("sftp"); channelSftp.connect(); log.info("start upload channel file!"); String directory = "/tmp"; channelSftp.cd(directory); File file = new File("D:\\desktop\\Test.java"); channelSftp.put(new FileInputStream(file), file.getName().replace(".", System.currentTimeMillis()+".")); log.info("Upload Success!"); channelSftp.disconnect(); log.info("end execute channel sftp!"); } @Test public void execShell() throws JSchException, IOException { ChannelExec channelExec = (ChannelExec) session.openChannel("exec"); String cmd = "pwd"; channelExec.setCommand(cmd); //添加傳入進來的shell命令 channelExec.setErrStream(System.err);//通道連接錯誤信息提示 channelExec.connect(); log.info("start execute channel command!"); try(BufferedReader in = new BufferedReader(new InputStreamReader(channelExec.getInputStream()))) { String msg; log.info("start read!"); while ((msg = in.readLine()) != null) { log.info("命令返回信息:{}", msg); } } catch (IOException e) { e.printStackTrace(); } channelExec.disconnect(); log.info("end execute channel command!"); } }
JSch 詳細日志實現(xiàn)。
JSch.setLogger(new Log4JSch());
import com.jcraft.jsch.Logger; import java.util.HashMap; public class Log4JSch implements Logger { private static HashMap<String, String> name = new HashMap(); static { name.put(String.valueOf(DEBUG), "DEBUG"); name.put(String.valueOf(INFO), "INFO"); name.put(String.valueOf(WARN), "WARN"); name.put(String.valueOf(ERROR), "ERROR"); name.put(String.valueOf(FATAL), "FATAL"); } @Override public boolean isEnabled(int i) { return true; } @Override public void log(int level, String message) { System.err.println(name.get(String.valueOf(level)) + ": " + message); } }
問題1
com.jcraft.jsch.JSchException: invalid privatekey: [B@17f7cd29
查看id_rsa文件,內(nèi)容如下
-----BEGIN OPENSSH PRIVATE KEY----- b3BlbnNzaC... ... ... ...MAECAwQF -----END OPENSSH PRIVATE KEY-----
解決方案
Jsch好像不支持上面的私鑰格式,要解決這個問題,我們可以使用ssh-keygen將私鑰格式轉(zhuǎn)換為RSAorpem模式,再次運行上面的程序。
$ ssh-keygen -p -f ~/.ssh/id_rsa -m pem
重新檢查私鑰內(nèi)容,它應(yīng)該以BEGIN RSA.
-----BEGIN RSA PRIVATE KEY----- MIIG4wIBAAK... ... ... ...E428GBDI4 -----END RSA PRIVATE KEY-----
再次嘗試連接正常。
Admin@DESKTOP-91JEC09 MINGW64 ~ $ ssh kevin@hadoop101 Last login: Wed Oct 20 14:28:41 2021 from 192.168.10.1 [kevin@hadoop101 ~]$ client_loop: send disconnect: Connection reset by peer Admin@DESKTOP-91JEC09 MINGW64 ~ $ ssh-keygen -p -f C:\\Users\\Admin\\.ssh\\id_rsa -m pem Key has comment 'Admin@DESKTOP-91JEC09' Enter new passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved with the new passphrase. Admin@DESKTOP-91JEC09 MINGW64 ~ $ ssh kevin@hadoop101 Last login: Wed Oct 20 15:43:57 2021 from 192.168.10.1
參考文檔:https://mkyong.com/java/jsch-invalid-privatekey-exception/http://www.jcraft.com/jsch/
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Spring Boot 2結(jié)合Spring security + JWT實現(xiàn)微信小程序登錄
這篇文章主要介紹了Spring Boot 2結(jié)合Spring security + JWT實現(xiàn)微信小程序登錄,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-01-01使用Java和WebSocket實現(xiàn)網(wǎng)頁聊天室實例代碼
WebSocket是HTML5一種新的協(xié)議,它實現(xiàn)了瀏覽器與服務(wù)器全雙工通信,這里就將使用WebSocket來開發(fā)網(wǎng)頁聊天室,對Java和WebSocket實現(xiàn)網(wǎng)頁聊天室的實例代碼感興趣的朋友一起學(xué)習(xí)吧2016-06-06MapStruct實體轉(zhuǎn)換及List轉(zhuǎn)換的方法講解
今天小編就為大家分享一篇關(guān)于MapStruct實體轉(zhuǎn)換及List轉(zhuǎn)換的方法講解,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2019-03-03java多線程編程之從線程返回數(shù)據(jù)的兩種方法
從線程中返回數(shù)據(jù)和向線程傳遞數(shù)據(jù)類似。也可以通過類成員以及回調(diào)函數(shù)來返回數(shù)據(jù)。但類成員在返回數(shù)據(jù)和傳遞數(shù)據(jù)時有一些區(qū)別,下面讓我們來看看它們區(qū)別在哪2014-01-01SpringBoot?整合?ElasticSearch操作各種高級查詢搜索
這篇文章主要介紹了SpringBoot?整合?ES?進行各種高級查詢搜索的實踐記錄,本文主要圍繞?SpringBoot?整合?ElasticSearch?進行各種高級查詢的介紹,需要的朋友可以參考下2022-06-06java基于ConcurrentHashMap設(shè)計細粒度實現(xiàn)代碼
這篇文章主要介紹了java基于ConcurrentHashMap設(shè)計細粒度實現(xiàn)代碼,通過ConcurrentHashMap實現(xiàn)細粒度,具有一定參考價值,需要的朋友可以了解。2017-10-10一不小心就讓Java開發(fā)踩坑的fail-fast是個什么鬼?(推薦)
這篇文章主要介紹了Java fail-fast,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04