Springboot 封装ssh 服务

2023-11-18

前提条件:Linux 已经启动SSH 服务或Windows 启动SSH 服务。

整体项目结构:

第一步:BuleSky 的pom.xml 文件

<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">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.zzg</groupId>
	<artifactId>BuleSky</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>pom</packaging>

	<!--springboot 父类 -->
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.1.0.RELEASE</version>
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<!--springboot 依赖web -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<!--springboot 依赖test -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
		</dependency>
		<!--springboot 依赖devtool -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
		</dependency>
		<!--lombak 集成 -->
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<version>1.18.0</version>
		</dependency>
		<!--apache common 工具包 -->
		<dependency>
			<groupId>commons-net</groupId>
			<artifactId>commons-net</artifactId>
			<version>3.6</version>
		</dependency>
		 <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.8.1</version>
        </dependency>
	</dependencies>
	<modules>
		<module>common-ssh</module>
		<module>common-ftp</module>
		<module>common-fastdfs</module>
		<module>common-monitor-windows</module>
		<module>common-monitor_linux</module>
		<module>common-elasticsearch</module>
	</modules>
</project>

common-ssh 项目结构:

common-ssh 的pom.xml文件

<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">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>com.zzg</groupId>
    <artifactId>BuleSky</artifactId>
    <version>0.0.1-SNAPSHOT</version>
  </parent>
  <artifactId>common-ssh</artifactId>
  
  <!--依赖远程ssh 框架 -->
  <dependencies>
  		<dependency>
    		<groupId>com.jcraft</groupId>
    		<artifactId>jsch</artifactId>
    		<version>0.1.55</version>
		</dependency>
  </dependencies>
</project>

Application.java

package com.zzg.common;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		SpringApplication.run(Application.class, args);
	}

}

SSHConfig.java

package com.zzg.common.config;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import lombok.Data;

/**
 * 远程服务器ssh 配置对象
 * @author zzg
 *
 */
@Configuration
@PropertySource(value = "classpath:ssh.properties")
@ConfigurationProperties(prefix = "ssh.remote")
@Data
public class SSHConfig {
	private String ip;
	private String username;
	private String password;
	private int port;
	private boolean isCheck;
}

SSHConstant.java

package com.zzg.common.constant;

public class SSHConstant {
	// Linux 系统
	public static final String SHELL = "shell";
	// Windows 系统
	public static final String EXEC = "exec";
	
}

SSHEntity.java

package com.zzg.common.entity;

import lombok.Data;

@Data
public class SSHEntity {
	private String ip;
	private String username;
	private String password;
	private int port;
	private boolean isCheck;
}

CustomerUser.java

package com.zzg.common.user;

import com.jcraft.jsch.UserInfo;

public class CustomerUser implements UserInfo {

	@Override
	public String getPassphrase() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public String getPassword() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public boolean promptPassphrase(String arg0) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean promptPassword(String arg0) {
		// TODO Auto-generated method stub
		return false;
	}

	// 消息通知
	@Override
	public boolean promptYesNo(String arg0) {
		// TODO Auto-generated method stub
		return true;
	}

	@Override
	public void showMessage(String arg0) {
		// TODO Auto-generated method stub

	}

}

SSHActuator.java

package com.zzg.common.util;

import com.jcraft.jsch.*;

import java.io.*;
import java.util.concurrent.TimeUnit;

import static java.lang.String.format;

import com.zzg.common.config.SSHConfig;
import com.zzg.common.constant.SSHConstant;
import com.zzg.common.entity.SSHEntity;
import com.zzg.common.user.CustomerUser;

import lombok.extern.slf4j.Slf4j;

/**
 * ssh 远程连接服务器
 * @author zzg
 *
 */
@Slf4j
public class SSHActuator {
	private static int SESSION_TIMEOUT = 30000;
	private static int CHANNEL_TIMEOUT = 3000;
	private static int INTERVAL = 100;
	
	private JSch jsch = null;
	private Session session = null;
	
	//私有构造函数
	private SSHActuator(SSHEntity entity){
		try{
			jsch =new JSch();
	        session = jsch.getSession(entity.getUsername(),entity.getIp(),entity.getPort());
	        session.setPassword(entity.getPassword());
	        session.setUserInfo(new CustomerUser());
	        session.connect(SESSION_TIMEOUT);
		}catch(JSchException e){
			log.error(e.getMessage());
			System.out.println(e.getMessage());
		}
		
	}
	
	// 单列模式
	public static SSHActuator getInstance(SSHEntity entity) throws JSchException {
		return new SSHActuator(entity);
	}
	
	// 获取连接会话
	public Session getSession(){
        return session;
    }

	// 关闭连接会话
    public void close(){
        getSession().disconnect();
    }
    
    // 执行shell 脚本
    public long shell(String cmd, String outputFileName) throws JSchException, IOException, InterruptedException {
        long start = System.currentTimeMillis();
        Channel channel = session.openChannel(SSHConstant.SHELL);
        PipedInputStream pipeIn = new PipedInputStream();
        PipedOutputStream pipeOut = new PipedOutputStream( pipeIn );
        FileOutputStream fileOut = new FileOutputStream( outputFileName, true);
        channel.setInputStream(pipeIn);
        channel.setOutputStream(fileOut);
        channel.connect(CHANNEL_TIMEOUT);

        pipeOut.write(cmd.getBytes());
        Thread.sleep( INTERVAL );
        pipeOut.close();
        pipeIn.close();
        fileOut.close();
        channel.disconnect();
        return System.currentTimeMillis() - start;
    }
    
    // 执行exec 脚本
    public int exec(String cmd) throws IOException, JSchException, InterruptedException {
        ChannelExec channelExec = (ChannelExec)session.openChannel(SSHConstant.EXEC);
        channelExec.setCommand( cmd );
        channelExec.setInputStream( null );
        channelExec.setErrStream( System.err );
        InputStream in = channelExec.getInputStream();
        channelExec.connect();

        int res = -1;
        StringBuffer buf = new StringBuffer( 1024 );
        byte[] tmp = new byte[ 1024 ];
        while ( true ) {
            while ( in.available() > 0 ) {
                int i = in.read( tmp, 0, 1024 );
                if ( i < 0 ) break;
                buf.append( new String( tmp, 0, i ) );
            }
            if ( channelExec.isClosed() ) {
                res = channelExec.getExitStatus();
                System.out.println( format( "Exit-status: %d", res ) );
                break;
            }
            TimeUnit.MILLISECONDS.sleep(INTERVAL);
        }
        System.out.println( buf.toString() );
        channelExec.disconnect();
        return res;
    }
}

ssh.properties(ssh 配置参数)

#linux setting
# ssh.remote.ip:192.168.60.178
#windows setting
ssh.remote.ip:192.168.1.74
ssh.remote.username:root
ssh.remote.password:123456
ssh.remote.port:22
ssh.remote.isCheck:false

SSHTest.java(ssh 功能测试)

package com.zzg.common.ssh.test;

import java.io.IOException;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import com.jcraft.jsch.JSchException;
import com.zzg.common.config.SSHConfig;
import com.zzg.common.entity.SSHEntity;
import com.zzg.common.util.SSHActuator;

@RunWith(SpringRunner.class)
@SpringBootTest
public class SSHTest {
	@Autowired
	private SSHConfig config;
	
	@Test
	public void ssh(){
		SSHEntity entity = new SSHEntity();
		entity.setIp(config.getIp());
		entity.setUsername(config.getUsername());
		entity.setPassword(config.getPassword());
		entity.setPort(config.getPort());
		try {
			SSHActuator ssh = SSHActuator.getInstance(entity);
			System.out.println("================");
	        long shell1 = ssh.shell("ls\n","C:\\Users\\zzg\\Desktop\\shell.txt");
	        long shell2 = ssh.shell("pwd\n","C:\\Users\\zzg\\Desktop\\shell.txt");
	        System.out.println("shell 1 执行了"+shell1+"ms");
	        System.out.println("shell 2 执行了"+shell2+"ms");
	        System.out.println("================");
	        ssh.close();
		} catch (JSchException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	@Test
	public void cmd(){
		SSHEntity entity = new SSHEntity();
		entity.setIp(config.getIp());
		entity.setUsername(config.getUsername());
		entity.setPassword(config.getPassword());
		entity.setPort(config.getPort());
		try {
			SSHActuator ssh = SSHActuator.getInstance(entity);
			System.out.println("================");
	        long shell1 = ssh.shell("ipconfig\n","C:\\Users\\zzg\\Desktop\\shell.txt");
	        long shell2 = ssh.shell("ipconfig\n","C:\\Users\\zzg\\Desktop\\shell.txt");
	        System.out.println("shell 1 执行了"+shell1+"ms");
	        System.out.println("shell 2 执行了"+shell2+"ms");
	        System.out.println("================");
	        ssh.close();
		} catch (JSchException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	
}

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Springboot 封装ssh 服务 的相关文章

随机推荐

  • Pycharm通过ssh远程连接服务器

    目录 一 概述 二 步骤 1 连接服务器 2 设置Python解释器 3 建立Mapping 4 实现代码自动上传 一 概述 笔记本没有英伟达独显 需要跑深度学习的代码 可以使用pycharm远程连接服务器 将本机代码同步到实验室服务器中运
  • Vue 动态连接线

    尝试了两个连线库 jsplumb 和 leadline 其实两个库都很强大 但是基于个人使用的习惯 决定还是用 leadline 在Vue 下我使用它的一个包装库 leader line vue 下面是上图的连接线示例代码 连接线很轻松的就
  • 刷脸支付服务于人就是制胜关键

    在过去 一句 我出门都不用带钱 刷脸就行了 道出的是四海之内皆兄弟的 面子 市场 而如今 不需要兄弟给 面子 任何人露一下脸便可完成交易 方便快捷是支付技术革新的最终目的 成功的互联网企业 或者说互联网企业想要成功 都要解决一个共同问题 服
  • angularjs $http调用接口的方式

    angularjs http调用接口的方式 http get merchantmall merchant json success function data status headers config console log argume
  • 【LEDE】树莓派上玩LEDE终极指南-75-获取CPU温度

    先来说说获取CPU温度的方法 1 通过hwmon获取 2 通过thermal获取 而树莓派就比较蛋疼了 没有额外的传感器 所以sensor detect这些东西完全不起作用 唯独CPU封装内的VideoCore具有温度传感功能 而想要与Vi
  • airpods pro动画不显示_airpodspro为什么没有弹窗

    大家好 我是时间财富网智能客服时间君 上述问题将由我为大家进行解答 airpodspro没有弹窗的原因是 1 耳机离手机太远 2 手机有bug 重启手机试试 3 可能是系统没有升级 更新系统试试 4 也有可能手机没有打开蓝牙功能 5 有可能
  • 总听大佬说起数字化转型,但你真正理解什么是数字化吗?( 2017-02-14 大愚若智 译 )

    作者 Reda Hmeid 译者 大愚若智 充分理解数字化 明确数字化是什么以及不是什么 对于一个架构师来说非常重要 毕竟我们需要向董事长 CEO CTO 分析师 开发者 以及其他所有相关人员解释这些概念 同样重要的是明确数字化转型成功的标
  • Java 压缩多个文件为zip包(中间不生成临时文件,直接压缩为zip二进制流),以及解压zip包二进制流为文件

    Java 压缩多个文件为zip包及解压zip包以及压缩多文件为zip文件流解压zip二进制流 中间不生成临时文件 直接压缩为zip二进制流 并验证解压 1 效果图 2 源码 这篇博客将提供俩种方法 提前生成要压缩的多个文件 然后读取文件夹多
  • 大数据技术之Kafka——Kafka入门

    目录 一 概述 1 1 为什么要有Kafka 1 2 定义 1 3 消息队列 1 消息队列的应用场景 2 消息队列的两种模式 1 4 基础架构 二 Producer生产者 2 1 生产者消息发送流程 2 1 1 发送原理 2 2 异步发送A
  • Python中常见文件操作,纯干货

    Python文件操作 一 关于文件 二 读写文件简单操作 三 文件权限 四 文件高级操作 五 大文件的读取 基本方法 常用函数 六 大文件的读取其他方式 一 关于文件 文件的作用 把一些数据储存起来 使用文件流程 打开文件 读写文件 关闭文
  • 什么是JIT

    一些其他解释的网站 http www sohu com a 169704040 464084 1 动态编译 dynamic compilation 指的是 在运行时进行编译 与之相对的是事前编译 ahead of time compilat
  • 用Google浏览器下载网页视频(包括优酷,土豆等网站视频)

    用Google浏览器下载网页视频 包括优酷 土豆等网站视频 一 准备工具 Google浏览器 Video download helper Chrome插件 二 步骤 1 安装Video download helper插件 1 下载网址 ht
  • 设计模式的 C++ 实现---原型模式

    前文回顾 单例模式 一 单例模式 二 观察者模式 简单工厂模式 工厂方法模式 一 工厂方法模式 二 抽象工厂模式 一 抽象工厂模式 二 前言 原型模式指直接用一个已经存在的对象来创建一个新的对象 然后对新对象进行稍微修改即可 类似复制的操作
  • 动手学CV-目标检测入门教程4:模型结构

    3 4 模型结构 本文来自开源组织 DataWhale CV小组创作的目标检测入门教程 对应开源项目 动手学CV Pytorch 的第3章的内容 教程中涉及的代码也可以在项目中找到 后续会持续更新更多的优质内容 欢迎 如果使用我们教程的内容
  • 在单链表中删除指定值的节点

    在单链表中删除指定值的节点 题目 给定一个单链表和一个数val 删除链表中所有值为val的节点 例如 1 gt 2 gt 3 gt 4 删除3 结果为 1 gt 2 gt 4 思路1 用栈 def remove node with val1
  • Java中如何设置注释模板呢?

    转自 Java中如何设置注释模板呢 下文笔者讲述在日常开发IDE工具中设置注释模板的方法分享 如下所示 Eclipse中设置Java注释模板 Eclipse设置注释模板的菜单 Window gt Preference gt Java gt
  • 实时音频编解码之八 频带扩展

    本文谢绝任何形式转载 谢谢 1 4 8 频带扩展 在线性预测应用中 由于极点过于靠近单位圆 合成滤波器可能处于临界稳定的状态 在定点实现中这一问题更加严重 定点的量化和计算中的精度损失可能使得临界稳定的滤波器变得不稳定 极点位于单位圆外 这
  • maven 配置篇 之 settings.xml 整理中...

    maven 配置 settings xml maven2比起maven1 来说 需要配置的文件少多了 主要集中在pom xml和settings xml中 先来说说settings xml settings xml对于maven 来说相 当
  • 【JS】jsx/tsx是什么?为什么 Vue3 的组件库都在使用 jsx/tsx?如何在Vue3中使用 jsx/tsx?

    前几天得到一个疑问 为什么 React 要用 JSX 语法 这样显得代码好像 很耦合 按照传统应推荐 html js css 模版分离 这样设计的优越性到底在哪里 一 jsx是什么 JSX 即 javascript Xml的缩写 是Face
  • Springboot 封装ssh 服务

    前提条件 Linux 已经启动SSH 服务或Windows 启动SSH 服务 整体项目结构 第一步 BuleSky 的pom xml 文件