java實(shí)現(xiàn)遠(yuǎn)程連接執(zhí)行命令行與上傳下載文件
遇到一個(gè)需要通過java代碼對(duì)遠(yuǎn)程Linux系統(tǒng)進(jìn)行遠(yuǎn)程操作的場(chǎng)景,其中包括遠(yuǎn)程執(zhí)行命令、上傳文件、下載文件。
一、maven依賴
<dependency> <groupId>com.jcraft</groupId> <artifactId>jsch</artifactId> <version>0.1.53</version> </dependency>
二、yml配置
desensitization: server: ip: xxx #IP地址 user: root #登錄用戶名 password: xxx #登錄密碼 port: 22 #遠(yuǎn)程連接端口 path: /root/test_data/ #對(duì)應(yīng)處理的目錄
三、配置類編寫
import com.xxx.fileupload.exception.BizException; import com.xxx.fileupload.exception.CommonUtilEnum; import com.jcraft.jsch.JSch; import com.jcraft.jsch.JSchException; import com.jcraft.jsch.Session; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * @description: ssh遠(yuǎn)程連接配置類 * @author ZXS * @date 2022/11/8 9:57 * @version 1.0 */ @Configuration public class JSchSessionConfig { //指定的服務(wù)器地址 @Value("${desensitization.server.ip}") private String ip; //用戶名 @Value("${desensitization.server.user}") private String user; //密碼 @Value("${desensitization.server.password}") private String password; //服務(wù)器端口 默認(rèn)22 @Value("${desensitization.server.port}") private String port; /** * @description: 注入一個(gè)bean,jsch.Session * @param: * @return: com.jcraft.jsch.Session * @author ZXS * @date: 2022/11/8 9:58 */ @Bean public Session registSession(){ Session session; try { JSch jSch = new JSch(); //設(shè)置session相關(guān)配置信息 session = jSch.getSession(user, ip, Integer.valueOf(port)); session.setPassword(password); //設(shè)置第一次登陸的時(shí)候提示,可選值:(ask | yes | no) session.setConfig("StrictHostKeyChecking", "no"); } catch (JSchException e) { throw new BizException(CommonUtilEnum.FILE_DOWNLOAD_FAIL); } return session; } }
四、組件工具類的編寫
import com.xxx.fileupload.exception.BizException; import com.xxx.fileupload.exception.CommonUtilEnum; import com.jcraft.jsch.*; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import javax.annotation.Resource; import java.io.*; /** * @description: ssh遠(yuǎn)程連接工具類 * @author ZXS * @date 2022/9/28 17:11 * @version 1.0 */ @Component @Slf4j public class SshRemoteComponent { private ThreadLocal<Session> connContainer = new ThreadLocal<>(); @Resource private Session session; //上傳文件到脫敏服務(wù)器的指定目錄 自行修改 @Value("${desensitization.server.path}") private String path; /** * @description: 根據(jù)端口號(hào)創(chuàng)建ssh遠(yuǎn)程連接 * @param: port 端口號(hào) * @return: com.jcraft.jsch.Session * @author ZXS * @date: 2022/9/28 15:57 */ public Session createConnection(){ try { session.connect(30000); connContainer.set(session); } catch (JSchException e) { throw new BizException(CommonUtilEnum.CONN_FAIL); } return connContainer.get(); } /** * @description: 關(guān)閉ssh遠(yuǎn)程連接 * @param: * @return: void * @author ZXS * @date: 2022/9/28 15:58 */ public void closeConnection(){ Session session=connContainer.get(); try { if(session != null){ session.disconnect(); } } catch (Exception e) { throw new BizException(CommonUtilEnum.CONN_CLOSE_FAIL); }finally { connContainer.remove(); } } /** * @description: ssh通過sftp上傳文件 * @param: session,bytes文件字節(jié)流,fileName文件名,resultEncoding 返回結(jié)果的字符集編碼 * @return: java.lang.String 執(zhí)行返回結(jié)果 * @author ZXS * @date: 2022/9/30 10:02 */ public Boolean sshSftpUpload(Session session, byte[] bytes,String fileName) throws Exception{ //上傳文件到指定服務(wù)器的指定目錄 自行修改 //String path = "/root/test_data/"; Channel channel = null; OutputStream outstream = null; Boolean flag = true; try { //創(chuàng)建sftp通信通道 channel = session.openChannel("sftp"); channel.connect(1000); ChannelSftp sftp = (ChannelSftp) channel; //進(jìn)入服務(wù)器指定的文件夾 sftp.cd(path); //列出服務(wù)器指定的文件列表 /*Vector v = sftp.ls("*"); for(int i=0;i<v.size();i++){ System.out.println(v.get(i)); }*/ outstream = sftp.put(fileName); outstream.write(bytes); } catch (Exception e) { e.printStackTrace(); flag = false; } finally { if(outstream != null){ outstream.flush(); outstream.close(); } if(session != null){ closeConnection(); } if(channel != null){ channel.disconnect(); } } return flag; } /** * @description: ssh通過sftp下載文件 * @param: session,fileName文件名,filePath 文件下載保存路徑 * @return: java.lang.String 執(zhí)行返回結(jié)果 * @author ZXS * @date: 2022/9/30 10:03 */ public Boolean sshSftpDownload(Session session, String fileName, String filePath) throws Exception{ Channel channel = null; InputStream inputStream = null; FileOutputStream fileOutputStream; Boolean flag = true; try { //創(chuàng)建sftp通信通道 channel = session.openChannel("sftp"); channel.connect(1000); ChannelSftp sftp = (ChannelSftp) channel; //進(jìn)入服務(wù)器指定的文件夾 sftp.cd(path); inputStream = sftp.get(fileName); BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream); fileOutputStream = new FileOutputStream(filePath+"/"+fileName); BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream); byte[] buf = new byte[4096]; int length = bufferedInputStream.read(buf); while (-1 != length){ bufferedOutputStream.write(buf,0,length); length = bufferedInputStream.read(buf); } bufferedInputStream.close(); bufferedOutputStream.close(); } catch (Exception e) { e.printStackTrace(); flag = false; } finally { if(inputStream != null){ inputStream.close(); } if(session != null){ closeConnection(); } if(channel != null){ channel.disconnect(); } } return flag; } /** * @description: 遠(yuǎn)程執(zhí)行單條Linux命令 * @param: session,command命令字符串 * @return: java.lang.String * @author ZXS * @date: 2022/9/28 16:34 */ public Boolean execCommand(Session session, String command){ //默認(rèn)方式,執(zhí)行單句命令 ChannelExec channelExec; Boolean flag = true; try { channelExec = (ChannelExec) session.openChannel("exec"); channelExec.setCommand(command); channelExec.setErrStream(System.err); channelExec.connect(); /** 判斷執(zhí)行結(jié)果 **/ InputStream in = channelExec.getInputStream(); byte[] tmp = new byte[1024]; while(true){ while(in.available() > 0){ int i = in.read(tmp,0,1024); if(i < 0) break; log.info("腳本執(zhí)行過程:"+new String(tmp,0,i)); } //獲取執(zhí)行結(jié)果 if(channelExec.isClosed()){ if(in.available() > 0) continue; if(channelExec.getExitStatus() != 0){ //腳本非正常結(jié)束,退出嗎非零 flag = false; log.info("腳本執(zhí)行出錯(cuò)"); } break; } try{ Thread.sleep(1000); }catch (Exception e){ log.info(e.getMessage()); } } channelExec.disconnect(); } catch (Exception e) { e.printStackTrace(); flag = false; } return flag; } }
五、使用測(cè)試
@SpringBootTest @Slf4j public class TestCase { @Resource private SshRemoteComponent component; @Test public void test(){ Session session = component.createConnection(); component.execCommand(session, "pwd"); component.closeConnection(); } }
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
springboot2.0以上調(diào)度器配置線程池的實(shí)現(xiàn)
這篇文章主要介紹了springboot2.0以上調(diào)度器配置線程池的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-12-12SSH框架網(wǎng)上商城項(xiàng)目第11戰(zhàn)之查詢和刪除商品功能實(shí)現(xiàn)
這篇文章主要為大家詳細(xì)介紹了SSH框架網(wǎng)上商城項(xiàng)目第11戰(zhàn)之查詢和刪除商品功能實(shí)現(xiàn)的相關(guān)資料,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-06-06Servlet和Filter之間的區(qū)別與聯(lián)系
這篇文章主要介紹了Servlet和Filter之間的區(qū)別與聯(lián)系的相關(guān)資料,需要的朋友可以參考下2016-05-05java實(shí)現(xiàn)簡(jiǎn)易外賣訂餐系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)簡(jiǎn)易外賣訂餐系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-10-10maven如何打包動(dòng)態(tài)環(huán)境變量(包括啟動(dòng)腳本)
這篇文章主要介紹了maven如何打包動(dòng)態(tài)環(huán)境變量(包括啟動(dòng)腳本)問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-04-04Spring Kafka中@KafkaListener注解的參數(shù)與使用小結(jié)
@KafkaListener注解為開發(fā)者提供了一種聲明式的方式來(lái)定義消息監(jiān)聽器,本文主要介紹了Spring Kafka中@KafkaListener注解的參數(shù)與使用小結(jié),具有一定的參考價(jià)值,感興趣的可以了解一下2024-06-06Java 8中Stream API的這些奇技淫巧!你Get了嗎?
這篇文章主要介紹了Java 8中Stream API的這些奇技淫巧!你Get了嗎?文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08