文章目录

  • 说明
  • 分享
  • 记录
    • 导包
    • 代码
  • 总结

说明

  • 本博客每周五更新一次。
  • 日常使用ssh连接工具是jsch实现,但该库从2018年开始停止更新,项目开发中使用免密登录功能时,因为ssh加密算法版本过低失败,最后不得不使用账号密码连接。那次后,萌生了寻找替代方案的想法,并找到了sshd库。

分享

  • 大数据博客列表
  • 开发记录汇总
  • 个人java工具库 项目https://gitee.com/wangzonghui/object-tool
    • 包含json、string、集合、excel、zip压缩、pdf、bytes、http等多种工具,欢迎使用。

记录

导包

maven导包如下:

<dependency><groupId>org.apache.sshd</groupId><artifactId>sshd-scp</artifactId><version>2.8.0</version>
</dependency>

代码

实例代码实现了远程命令执行、scp文件上传和下载,基于sftp的未实现。


import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;import org.apache.sshd.client.SshClient;
import org.apache.sshd.client.channel.ChannelExec;
import org.apache.sshd.client.session.ClientSession;
import org.apache.sshd.scp.client.DefaultScpClientCreator;
import org.apache.sshd.scp.client.ScpClient;
import org.apache.sshd.scp.client.ScpClientCreator;
import org.apache.sshd.sftp.client.SftpClient;
import org.apache.sshd.sftp.client.impl.DefaultSftpClientFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import com.tool.cn.model.SshModel;/*** * @author wangzonghui* @date 2022年2月7日 上午9:55:58 * @Description ssh工具类测试*/
public final class SshSshdUtil {private  final static Logger log = LoggerFactory.getLogger(SshSshdUtil.class);private String host;private String user;private String password;private int port;private ClientSession session;private  SshClient client;/*** 创建一个连接* * @param host     地址* @param user     用户名* @param port     ssh端口* @param password 密码*/public SshSshdUtil(String host,String user,int port,String password) {this.host = host;this.user = user;this.port=port;this.password=password;}/*** 登录* @return* @throws Exception*/public boolean initialSession() {if (session == null) {try {// 创建 SSH客户端client = SshClient.setUpDefaultClient();// 启动 SSH客户端client.start();// 通过主机IP、端口和用户名,连接主机,获取Sessionsession = client.connect(user, host, port).verify().getSession();// 给Session添加密码session.addPasswordIdentity(password);// 校验用户名和密码的有效性return session.auth().verify().isSuccess();} catch (Exception e) {log.info("Login Host:"+host+" Error",e);return false;}}return true;}/*** 关闭连接* @throws Exception*/public void close() throws Exception  {//关闭sessionif (session != null && session.isOpen()) {session.close();}// 关闭 SSH客户端if (client != null && client.isOpen()) {client.stop();client.close();}}/*** 下载文件 基于sftp* * @param localFile  本地文件名,若为空或是*,表示目前下全部文件* @param remotePath 远程路径,若为空,表示当前路径,若服务器上无此目录,则会自动创建* @throws Exception*/public boolean sftpGetFile(String localFile, String remoteFile) {SftpClient sftp=null;InputStream is=null;try {if(this.initialSession()) {DefaultSftpClientFactory sftpFactory=new DefaultSftpClientFactory();sftp=sftpFactory.createSftpClient(session);is=sftp.read(remoteFile);Path dst=Paths.get(localFile);Files.deleteIfExists(dst);Files.copy(is, dst);}} catch (Exception e) {log.error(host+"Local File "+localFile+" Sftp Get File:"+remoteFile+" Error",e);return false;}finally {try {if(is!=null) {is.close();}if(sftp!=null) {sftp.close();}} catch (Exception e) {log.error("Close Error",e);}}return true;}/*** 下载文件 基于sftp* * @param localFile  本地文件名,若为空或是*,表示目前下全部文件* @param remotePath 远程路径,若为空,表示当前路径,若服务器上无此目录,则会自动创建* @param outTime 超时时间 单位毫秒* @throws Exception*/public boolean sftpGetFile(String localFile, String remoteFile,int timeOut) {ProcessWithTimeout process=new ProcessWithTimeout(localFile,remoteFile,1);int exitCode=process.waitForProcess(timeOut);if(exitCode==-1) {log.error("{} put Local File {} To Sftp Path:{} Time Out",host,localFile,remoteFile);}return exitCode==0?true:false;}/*** 上传文件 基于sftp* * @param localFile  本地文件名,若为空或是*,表示目前下全部文件* @param remotePath 远程路径,若为空,表示当前路径,若服务器上无此目录,则会自动创建* @param outTime 超时时间 单位毫秒* @throws Exception*/public boolean sftpPutFile(String localFile, String remoteFile,int timeOut) {ProcessWithTimeout process=new ProcessWithTimeout(localFile,remoteFile,0);int exitCode=process.waitForProcess(timeOut);if(exitCode==-1) {log.error("{} put Local File {} To Sftp Path:{} Time Out",host,localFile,remoteFile);}return exitCode==0?true:false;}/*** * @author wangzonghui* @date 2022年4月13日 下午2:15:17 * @Description 任务执行线程,判断操作超时使用*/class ProcessWithTimeout extends Thread{private String localFile;private String remoteFile;private int type;private int exitCode =-1;/*** * @param localFile 本地文件* @param remoteFile  sftp服务器文件* @param type 0 上传  1 下载*/public ProcessWithTimeout(String localFile, String remoteFile,int type) {this.localFile=localFile;this.remoteFile=remoteFile;this.type=type;}public int waitForProcess(int outtime){this.start();try{this.join(outtime);}catch (InterruptedException e){log.error("Wait Is Error",e);}return exitCode;}@Overridepublic void run() {super.run();boolean state;if(type==0) {state=sftpPutFile(localFile, remoteFile);}else {state=sftpGetFile(localFile, remoteFile);}exitCode= state==true?0:1;}}/*** 上传文件 基于sftp* * @param localFile  本地文件名,若为空或是*,表示目前下全部文件* @param remotePath 远程路径,若为空,表示当前路径,若服务器上无此目录,则会自动创建* @throws Exception*/public boolean sftpPutFile(String localFile, String remoteFile) {SftpClient sftp=null;OutputStream os=null;try {if(this.initialSession()) {DefaultSftpClientFactory sftpFactory=new DefaultSftpClientFactory();sftp=sftpFactory.createSftpClient(session);os=sftp.write(remoteFile,1024);Files.copy(Paths.get(localFile), os);}} catch (Exception e) {log.error(host+"Local File "+localFile+" Sftp Upload File:"+remoteFile+" Error",e);return false;}finally {try {if(os!=null) {os.close();}if(sftp!=null) {sftp.close();}} catch (Exception e) {log.error("Close Error",e);}}return true;}/*** 上传文件 基于scp* * @param localFile  本地文件名,若为空或是*,表示目前下全部文件* @param remotePath 远程路径,若为空,表示当前路径,若服务器上无此目录,则会自动创建* @throws Exception*/public boolean scpPutFile( String localFile, String remoteFile) {ScpClient scpClient=null;try {if(this.initialSession()) {ScpClientCreator creator = new DefaultScpClientCreator();// 创建 SCP 客户端scpClient = creator.createScpClient(session);// ScpClient.Option.Recursive:递归copy,可以将子文件夹和子文件遍历copyscpClient.upload(localFile, remoteFile, ScpClient.Option.Recursive);}else {log.error("Host:{} User:{} Upload Local File:{} Error",host,user,localFile);return false;}} catch (Exception e) {log.error(e.toString(), e);return false;}finally {// 释放 SCP客户端if (scpClient != null) {scpClient = null;}}return true;}/*** 下载文件 基于scp* * @param localPath  本地路径,若为空,表示当前路径* @param localFile  本地文件名,若为空或是*,表示目前下全部文件* @param remotePath 远程路径,若为空,表示当前路径,若服务器上无此目录,则会自动创建* @throws Exception*/public boolean scpGetFile( String localFile, String remoteFile) {ScpClient scpClient=null;try {if(this.initialSession()) {ScpClientCreator creator = new DefaultScpClientCreator();// 创建 SCP 客户端scpClient = creator.createScpClient(session);scpClient.download(remoteFile, localFile);  //下载文件}else {log.error("Host:{} User:{} Get File:{} Error",host,user,remoteFile);return false;}} catch (Exception e) {log.error(e.toString(), e);return false;}finally {// 释放 SCP客户端if (scpClient != null) {scpClient = null;}}return true;}/*** 执行远程命令 * @param command 执行的命令* @return 0成功 1异常* @throws Exception*/public int runCommand(String command)  {ChannelExec channel=null;try {if(this.initialSession()) {channel=session.createExecChannel(command);int time = 0;boolean run = false;channel.open();ByteArrayOutputStream err = new ByteArrayOutputStream();channel.setErr(err);while (true) {if (channel.isClosed() || run) {break;}try {Thread.sleep(100);} catch (Exception e) {}if (time > 1800) {break;}time++;}int status=channel.getExitStatus();if(status>0) {log.info("{}  host:{} user:{} Run Is code:{} Message:{}",command,host,user,status,err.toString());}return status;}else {log.error("Host:{} User:{} Login Error",host,user);return 1;}} catch (Exception e) {log.error("Host "+host+" Run Command Error:"+command+" " +e.toString(),e);return 1;}finally {if(channel!=null) {try {channel.close();} catch (Exception e) {log.error("Close Connection Error");}}}}/*** 执行远程命令 * @param command 执行的命令* @return 0成功 其他 异常* @throws Exception*/public SshModel run(String command)  {SshModel sshModel=new SshModel();ChannelExec channel=null;try {if(this.initialSession()) {channel=session.createExecChannel(command);int time = 0;boolean run = false;channel.open();ByteArrayOutputStream info = new ByteArrayOutputStream();channel.setOut(info);ByteArrayOutputStream err = new ByteArrayOutputStream();channel.setErr(err);while (true) {if (channel.isClosed() || run) {break;}try {Thread.sleep(100);} catch (Exception ee) {}if (time > 180) {break;}time++;}int status=channel.getExitStatus();sshModel.setCode(status);sshModel.setInfo(info.toString());sshModel.setError(err.toString());}else {log.error("Host:{} User:{} Login Error",host,user);sshModel.setCode(1);sshModel.setError("Loging Error");}} catch (Exception e) {log.error("Host "+host+"Run Command Error:"+command+" " +e.toString(),e);sshModel.setCode(1);}finally {if(channel!=null) {try {channel.close();} catch (IOException e) {log.error("Close Connection Error");}}}return sshModel;}
}
  • 引用数据模型类SshModel
package ssh.model.cn;/*** * @author wangzonghui* @date 2020年8月14日 下午3:09:24 * @Description:ssh模型类*/
public class SshModel {/*** 状态码*/private int code;/*** 信息*/private String info;/*** 错误信息*/private String error;public int getCode() {return code;}public void setCode(int code) {this.code = code;}public String getInfo() {return info;}public void setInfo(String info) {this.info = info;}public String getError() {return error;}public void setError(String error) {this.error = error;}@Overridepublic String toString() {return "SshModel [code=" + code + ", info=" + info + ", error=" + error + "]";}}

总结

  • 学习技术是个漫长有趣的过程,同样功能的更好方式实现,更高效执行,功能的快速开发,都是自我的价值体现。
  • 本文为2022年第一篇博客,新开始,新征程,小步慢跑,加油努力,做任何事都不会容易。

java sshd实现连接ssh操作相关推荐

  1. JAVA通过JDBC连接并操作MySQL数据库

    JAVA通过JDBC连接并操作MySQL数据库 JDBC(Java Data Base Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提 ...

  2. 使用Spring JDBC框架连接并操作数据库

    在前一篇博文JAVA通过JDBC连接并操作MySQL数据库中,我们知道如何通过JDBC连接并操作数据库,但是请看程序,整个程序连接数据库和关闭数据库占了很大一部分代码量,而且每次我们执行一下数据库操作 ...

  3. java 连接SSH工具操作服务器 (构建者模式+Util类) 分享

    需求 因为需要以java 远程操作服务器, 比如进行文件下载/上传操作, 或者执行一些服务器常用命令ls cat grep 等等. 调研发现比较好用的SSH 工具有: ganymed-ssh2 jsc ...

  4. ssh长时间不操作便断开_连接SSH长时间不操作断开解决办法

    经常连接ssh长时间不操作就断开,实在忍无可忍,每次都想解决这个问题,但是就是懒得搞,这次必须得一刀解决. 解决方法一:服务器配置 1. 连接SSH ssh root@192.168.0.1 复制代码 ...

  5. idea如何给oracle添加数据_intelij idea下使用java和JDBC连接oracle数据库及简单的SQL操作...

    intelij idea下使用java和JDBC连接oracle数据库及简单的SQL操作 发布时间:2018-07-04 10:09, 浏览次数:2532 , 标签: intelij idea jav ...

  6. Java打造一款SSH客户端,而且已开源

    点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 来源:https://blog.csdn.net/NoCo ...

  7. 修改密码后服务器断开连接,SSH无需密码登录服务器且保持连接不断开的方法

    SSH无需密码登录服务器 Mac 无密码 SSH 登录服务器,只需要简单三步,不再需要记住账号密码,快速进入服务器 测试H1 dfsdfsf 测试H2 dfsdfsf 测试H3 dfsdfsf 测试H ...

  8. java使用Jsch实现远程操作linux服务器进行文件上传、下载,删除和显示目录信息...

    1.java使用Jsch实现远程操作linux服务器进行文件上传.下载,删除和显示目录信息. 参考链接:https://www.cnblogs.com/longyg/archive/2012/06/2 ...

  9. 第五十四篇 Linux相关——远程连接SSH

    No.1. SSH(Secure Shell)安全外壳协议 建立在应用层基础上的安全协议 可靠,专为远程登录会话和其他网络服务提供安全性的协议 有效防止远程管理过程中的信息泄漏问题 SSH客户端适用于 ...

最新文章

  1. PARAMETERS 指令
  2. excel如何分类汇总_Excel教程:一个排序后分类汇总他弄了一天 Excel神技能!
  3. 高并发编程-通过volatile重新认识CPU缓存 和 Java内存模型(JMM)
  4. opeansea, nft, trend
  5. python语言通过字典实现映射关系_mpython3丨字典的使用介绍
  6. 热图绘制一个快乐五一
  7. IAR for AVR delay函数
  8. 老李分享:HTTP协议之协议头
  9. 为什么别人一周搞定Linux,而你却做不到
  10. 多语言可视化编辑webControl 2.0版
  11. 2021-11-1-无法在此设备上激活WINDOWS因为无法连接到你的组织的激活服务器
  12. appcan使用心得体会
  13. 前端开发和后端开发的区别
  14. 漫画 | Code Review快把我逼疯了!
  15. Numpy库的下载及安装(吐血总结)
  16. 验证wireshark追踪qq图片
  17. 计算机打开共享网络连接打印机共享打印机,两台电脑如何共享打印机 多台电脑共享一台打印机设置方法【详细教程】...
  18. mysql maven 依赖关系_Maven依赖总结
  19. 数学思想方法之抽象与概括(2)概括
  20. julia的plot

热门文章

  1. Excel数据透视表排序
  2. html文本框背景text怎么变透明,css怎么设置背景图片透明文字不透明?
  3. 在线PS把图片背景变成透明(灰白格子)
  4. CAPL基础篇-----CAPL中的循环
  5. 程序员必备的16个实用的网站
  6. 112家IT公司薪水一览表
  7. 语义分割网络-BiSenet
  8. “云”上就诊,泽塔云超融合助力医院数字化转型
  9. numpy库函数:reshape用法
  10. 微信公众号开发——关键词自动回复