java通過ssh連接執(zhí)行shell命令,文件傳輸方式
java通過ssh連接執(zhí)行shell命令,文件傳輸
JSch 是SSH2的純 Java 實(shí)現(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"; // 主機(jī)IP
private static int port = 22; //默認(rèn)端口
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();
/*
* 在代碼里需要跳過檢測。否則會(huì)報(bào)錯(cuò)找不到主機(jī)
* 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對(duì)象設(shè)置properties
int timeout = 30000;
session.setTimeout(timeout); // 設(shè)置timeout時(shí)間
session.connect(); // 通過Session建立與遠(yuǎn)程服務(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); //添加傳入進(jìn)來的shell命令
channelExec.setErrStream(System.err);//通道連接錯(cuò)誤信息提示
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 詳細(xì)日志實(shí)現(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好像不支持上面的私鑰格式,要解決這個(gè)問題,我們可以使用ssh-keygen將私鑰格式轉(zhuǎn)換為RSAorpem模式,再次運(yùn)行上面的程序。
$ 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é)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Spring Boot 2結(jié)合Spring security + JWT實(shí)現(xiàn)微信小程序登錄
這篇文章主要介紹了Spring Boot 2結(jié)合Spring security + JWT實(shí)現(xiàn)微信小程序登錄,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-01-01
使用Java和WebSocket實(shí)現(xiàn)網(wǎng)頁聊天室實(shí)例代碼
WebSocket是HTML5一種新的協(xié)議,它實(shí)現(xiàn)了瀏覽器與服務(wù)器全雙工通信,這里就將使用WebSocket來開發(fā)網(wǎng)頁聊天室,對(duì)Java和WebSocket實(shí)現(xiàn)網(wǎng)頁聊天室的實(shí)例代碼感興趣的朋友一起學(xué)習(xí)吧2016-06-06
MapStruct實(shí)體轉(zhuǎn)換及List轉(zhuǎn)換的方法講解
今天小編就為大家分享一篇關(guān)于MapStruct實(shí)體轉(zhuǎn)換及List轉(zhuǎn)換的方法講解,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2019-03-03
java多線程編程之從線程返回?cái)?shù)據(jù)的兩種方法
從線程中返回?cái)?shù)據(jù)和向線程傳遞數(shù)據(jù)類似。也可以通過類成員以及回調(diào)函數(shù)來返回?cái)?shù)據(jù)。但類成員在返回?cái)?shù)據(jù)和傳遞數(shù)據(jù)時(shí)有一些區(qū)別,下面讓我們來看看它們區(qū)別在哪2014-01-01
SpringBoot?整合?ElasticSearch操作各種高級(jí)查詢搜索
這篇文章主要介紹了SpringBoot?整合?ES?進(jìn)行各種高級(jí)查詢搜索的實(shí)踐記錄,本文主要圍繞?SpringBoot?整合?ElasticSearch?進(jìn)行各種高級(jí)查詢的介紹,需要的朋友可以參考下2022-06-06
java基于ConcurrentHashMap設(shè)計(jì)細(xì)粒度實(shí)現(xiàn)代碼
這篇文章主要介紹了java基于ConcurrentHashMap設(shè)計(jì)細(xì)粒度實(shí)現(xiàn)代碼,通過ConcurrentHashMap實(shí)現(xiàn)細(xì)粒度,具有一定參考價(jià)值,需要的朋友可以了解。2017-10-10
一不小心就讓Java開發(fā)踩坑的fail-fast是個(gè)什么鬼?(推薦)
這篇文章主要介紹了Java fail-fast,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04

