java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > SpringBoot集成JSch

Spring Boot集成JSch的示例代码

作者:HBLOG

本文主要介绍了Spring Boot集成JSch的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

1.JSch介绍

JSch是SSH2的纯Java实现。
JSch允许您连接到sshd服务器并使用端口转发,X11转发,文件传输等,并且可以将其功能集成到您自己的Java程序中。

2.实现原理

根据远程主机的IP地址,用户名和端口,建立会话(Session)
设置用户信息(包括密码和Userinfo),然后连接session,getSession()只是创建一个session,需要设置必要的认证信息之后,调用connect()才能建立连接。
设置channel上需要远程执行的Shell脚本,连接channel,就可以远程执行该Shell脚本,调用openChannel(String type) 可以在session上打开指定类型的channel。该channel只是被初始化,使用前需要先调用connect()进行连接。
可以读取远程执行Shell脚本的输出,然后依次断开channel和session的连接

3.代码工程

实验目标:实现文件上传到服务,服务器下载文件以及执行服务器命令

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<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">
    <parent>
        <artifactId>springboot-demo</artifactId>
        <groupId>com.et</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>JSch</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>
    <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.jcraft/jsch -->
        <dependency>
            <groupId>com.jcraft</groupId>
            <artifactId>jsch</artifactId>
            <version>0.1.55</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.78</version>
        </dependency>
    </dependencies>
</project>

remote.java

package com.et.jsch.model;

import lombok.Data;

@Data
public class Remote {
  private String host;
  private final int port = 22;
  private String user;
  private String password;
  private final String identity = "~/.ssh/id_rsa";
  private String passphrase;
}

JSchUtil.java

package com.et.jsch.util;

import com.et.jsch.model.Remote;
import com.jcraft.jsch.*;
import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;

/**
 * ssh tools
 */
@Slf4j
public class JSchUtil {

    public static final int SESSION_TIMEOUT = 30000;
    public static final int CONNECT_TIMEOUT = 3000;

    /**
     * get session
     *
     * @param remote ssh server info
     * @return session
     * @throws JSchException /
     */
    public static Session getSession(Remote remote) throws JSchException {
        JSch jSch = new JSch();
        if (Files.exists(Paths.get(remote.getIdentity()))) {
            jSch.addIdentity(remote.getIdentity(), remote.getPassphrase());
        }
        Session session = jSch.getSession(remote.getUser(), remote.getHost(), remote.getPort());
        session.setPassword(remote.getPassword());
        session.setConfig("StrictHostKeyChecking", "no");
        return session;
    }

    /**
     * excute remote command
     *
     * @param session session
     * @param command command
     * @return /
     * @throws JSchException /
     */
    public static List<String> remoteExecute(Session session, String command) throws JSchException {
        log.debug(">> {}", command);
        List<String> resultLines = new ArrayList<>();
        ChannelExec channel = null;
        try {
            channel = openExecChannel(session);
            channel.setCommand(command);
            InputStream input = channel.getInputStream();
            channel.connect(CONNECT_TIMEOUT);
            try {
                BufferedReader inputReader = new BufferedReader(new InputStreamReader(input));
                String inputLine;
                while ((inputLine = inputReader.readLine()) != null) {
                    log.debug("   {}", inputLine);
                    resultLines.add(inputLine);
                }
            } finally {
                if (input != null) {
                    try {
                        input.close();
                    } catch (Exception e) {
                        log.error("JSch inputStream close error:", e);
                    }
                }
            }
        } catch (IOException e) {
            log.error("IOException:", e);
        } finally {
            disconnect(channel);
        }
        return resultLines;
    }

    /**
     * scp file to remote server
     *
     * @param session     session
     * @param source      local file
     * @param destination remote target file
     * @return file size
     */
    public static long scpTo(Session session, String source, String destination) {
        FileInputStream fileInputStream = null;
        ChannelExec channel = null;
        try {
            channel = openExecChannel(session);
            OutputStream out = channel.getOutputStream();
            InputStream in = channel.getInputStream();
            boolean ptimestamp = false;
            String command = "scp";
            if (ptimestamp) {
                command += " -p";
            }
            command += " -t " + destination;
            channel.setCommand(command);
            channel.connect(CONNECT_TIMEOUT);
            if (checkAck(in) != 0) {
                return -1;
            }
            File _lfile = new File(source);
            if (ptimestamp) {
                command = "T " + (_lfile.lastModified() / 1000) + " 0";
                // The access time should be sent here,
                // but it is not accessible with JavaAPI ;-<
                command += (" " + (_lfile.lastModified() / 1000) + " 0\n");
                out.write(command.getBytes());
                out.flush();
                if (checkAck(in) != 0) {
                    return -1;
                }
            }
            //send "C0644 filesize filename", where filename should not include '/'
            long fileSize = _lfile.length();
            command = "C0644 " + fileSize + " ";
            if (source.lastIndexOf('/') > 0) {
                command += source.substring(source.lastIndexOf('/') + 1);
            } else {
                command += source;
            }
            command += "\n";
            out.write(command.getBytes());
            out.flush();
            if (checkAck(in) != 0) {
                return -1;
            }
            //send content of file
            fileInputStream = new FileInputStream(source);
            byte[] buf = new byte[1024];
            long sum = 0;
            while (true) {
                int len = fileInputStream.read(buf, 0, buf.length);
                if (len <= 0) {
                    break;
                }
                out.write(buf, 0, len);
                sum += len;
            }
            //send '\0'
            buf[0] = 0;
            out.write(buf, 0, 1);
            out.flush();
            if (checkAck(in) != 0) {
                return -1;
            }
            return sum;
        } catch (JSchException e) {
            log.error("scp to caught jsch exception, ", e);
        } catch (IOException e) {
            log.error("scp to caught io exception, ", e);
        } catch (Exception e) {
            log.error("scp to error, ", e);
        } finally {
            closeInputStream(fileInputStream);
            disconnect(channel);
        }
        return -1;
    }

    /**
     * scp remote file to local
     *
     * @param session     session
     * @param source      remote file
     * @param destination local file
     * @return file size
     */
    public static long scpFrom(Session session, String source, String destination) {
        FileOutputStream fileOutputStream = null;
        ChannelExec channel = null;
        try {
            channel = openExecChannel(session);
            channel.setCommand("scp -f " + source);
            OutputStream out = channel.getOutputStream();
            InputStream in = channel.getInputStream();
            channel.connect();
            byte[] buf = new byte[1024];
            //send '\0'
            buf[0] = 0;
            out.write(buf, 0, 1);
            out.flush();
            while (true) {
                if (checkAck(in) != 'C') {
                    break;
                }
            }
            //read '644 '
            in.read(buf, 0, 4);
            long fileSize = 0;
            while (true) {
                if (in.read(buf, 0, 1) < 0) {
                    break;
                }
                if (buf[0] == ' ') {
                    break;
                }
                fileSize = fileSize * 10L + (long) (buf[0] - '0');
            }
            String file = null;
            for (int i = 0; ; i++) {
                in.read(buf, i, 1);
                if (buf[i] == (byte) 0x0a) {
                    file = new String(buf, 0, i);
                    break;
                }
            }
            // send '\0'
            buf[0] = 0;
            out.write(buf, 0, 1);
            out.flush();
            // read a content of lfile
            if (Files.isDirectory(Paths.get(destination))) {
                fileOutputStream = new FileOutputStream(destination + File.separator + file);
            } else {
                fileOutputStream = new FileOutputStream(destination);
            }
            long sum = 0;
            while (true) {
                int len = in.read(buf, 0, buf.length);
                if (len <= 0) {
                    break;
                }
                sum += len;
                if (len >= fileSize) {
                    fileOutputStream.write(buf, 0, (int) fileSize);
                    break;
                }
                fileOutputStream.write(buf, 0, len);
                fileSize -= len;
            }
            return sum;
        } catch (JSchException e) {
            log.error("scp to caught jsch exception, ", e);
        } catch (IOException e) {
            log.error("scp to caught io exception, ", e);
        } catch (Exception e) {
            log.error("scp to error, ", e);
        } finally {
            closeOutputStream(fileOutputStream);
            disconnect(channel);
        }
        return -1;
    }

    /**
     * remote edit
     *
     * @param session session
     * @param source  target file
     * @param process edit command collect
     * @return isSuccess
     */
    private static boolean remoteEdit(Session session, String source, Function<List<String>, List<String>> process) {
        InputStream in = null;
        OutputStream out = null;
        try {
            String fileName = source;
            int index = source.lastIndexOf('/');
            if (index >= 0) {
                fileName = source.substring(index + 1);
            }
            //backup source
            remoteExecute(session, String.format("cp %s %s", source, source + ".bak." + System.currentTimeMillis()));
            //scp from remote
            String tmpSource = System.getProperty("java.io.tmpdir") + session.getHost() + "-" + fileName;
            scpFrom(session, source, tmpSource);
            in = new FileInputStream(tmpSource);
            //edit file according function process
            String tmpDestination = tmpSource + ".des";
            out = new FileOutputStream(tmpDestination);
            List<String> inputLines = new ArrayList<>();
            BufferedReader reader = new BufferedReader(new InputStreamReader(in));
            String inputLine = null;
            while ((inputLine = reader.readLine()) != null) {
                inputLines.add(inputLine);
            }
            List<String> outputLines = process.apply(inputLines);
            for (String outputLine : outputLines) {
                out.write((outputLine + "\n").getBytes());
                out.flush();
            }
            //scp to remote
            scpTo(session, tmpDestination, source);
            return true;
        } catch (Exception e) {
            log.error("remote edit error, ", e);
            return false;
        } finally {
            closeInputStream(in);
            closeOutputStream(out);
        }
    }

    /**
     * update file
     *
     * @param session   session
     * @param in        file stream
     * @param directory local dir
     * @param fileName  FTP server file name:xxx.txt ||xxx.txt.zip
     */
    public static boolean uploadFile(Session session, InputStream in, String directory, String fileName) {
        log.info(">>>>>>>>uploadFile--ftp start>>>>>>>>>>>>>");
        ChannelSftp channel = null;
        try {
            channel = openSftpChannel(session);
            channel.connect(CONNECT_TIMEOUT);
            String[] folders = directory.split("/");
            try {
                for (int i = 0; i < folders.length; i++) {
                    if (i == 0 && folders[i].length() == 0) {
                        channel.cd("/");
                    } else if (folders[i].length() > 0) {
                        try {
                            channel.cd(folders[i]);
                        } catch (SftpException e) {
                            channel.mkdir(folders[i]);
                            channel.cd(folders[i]);
                        }
                    }
                }
            } catch (SftpException e) {
                log.error("ftp create file fail" + directory, e);
                return false;
            }

            try {
                channel.put(in, fileName);
            } catch (SftpException e) {
                log.error("sftp error-->" + e.getMessage(), e);
                return false;
            }

            log.info(">>>>>>>>uploadFile--ftp upload end>>>>>>>>>>>>>");
            log.info(">>>>>>>>ftp upload dir:{},filename:{}>>>>>>>>>>>>>", directory, fileName);

            return true;
        } catch (JSchException e) {
            log.error("JSch error-->" + e.getMessage(), e);
            return false;
        } finally {
            closeInputStream(in);
            disconnect(channel);
        }
    }


    /**
     *
     *
     * @param channel   sftp connect
     * @param directory
     * @param fileName
     * @return
     */
    public static InputStream stream(ChannelSftp channel, String directory, String fileName) {
        try {
            channel.connect(CONNECT_TIMEOUT);
            InputStream inputStream = channel.get(directory + "/" + fileName);
            log.info(">>>>>>>>ftp file directory:{},filename:{}>>>>>>>>>>>>>", directory, fileName);
            return inputStream;
        } catch (SftpException e) {
            log.error("sftp error-->" + e.getMessage());
            return null;
        } catch (JSchException e) {
            log.error("JSch error-->" + e.getMessage());
            return null;
        }
    }


    /**
     * ftp delete remote file
     *
     * @param session   session
     * @param directory directory
     * @param fileName  filename
     * @return is Success
     */
    public static boolean deleteFile(Session session, String directory, String fileName) {
        log.info(">>>>>>>>deleteFile--ftp delete file end>>>>>>>>>>>>>");
        ChannelSftp channel = null;
        try {
            channel = openSftpChannel(session);
            channel.connect(CONNECT_TIMEOUT);
            channel.rm(directory + "/" + fileName);

            log.info(">>>>>>>>deleteFile--deletefile end>>>>>>>>>>>>>");
            log.info(">>>>>>>>ftp delete file directory:{},filename:{}>>>>>>>>>>>>>", directory, fileName);
        } catch (SftpException e) {
            log.error("ftp create directory fail" + directory);
            return false;
        } catch (JSchException e) {
            log.error("JSch error-->" + e.getMessage());
            return false;
        } finally {
            disconnect(channel);
        }

        return true;
    }

    public static Channel openChannel(Session session, String type) throws JSchException {
        if (!session.isConnected()) {
            session.connect(SESSION_TIMEOUT);
        }
        return session.openChannel(type);
    }

    public static ChannelSftp openSftpChannel(Session session) throws JSchException {
        return (ChannelSftp) openChannel(session, "sftp");
    }

    public static ChannelExec openExecChannel(Session session) throws JSchException {
        return (ChannelExec) openChannel(session, "exec");
    }

    /**
     * disconnect
     *
     * @param session
     */
    public static void disconnect(Session session) {
        if (session != null) {
            if (session.isConnected()) {
                try {
                    session.disconnect();
                    log.info("session disconnect successfully");
                } catch (Exception e) {
                    log.error("JSch session disconnect error:", e);
                }
            }
        }
    }

    /**
     * close connection
     *
     * @param channel channel connection
     */
    public static void disconnect(Channel channel) {
        if (channel != null) {
            if (channel.isConnected()) {
                try {
                    channel.disconnect();
                    log.info("channel is closed already");
                } catch (Exception e) {
                    log.error("JSch channel disconnect error:", e);
                }
            }
        }
    }

    public static int checkAck(InputStream in) throws IOException {
        int b = in.read();
        // b may be 0 for success,
        //          1 for error,
        //          2 for fatal error,
        //          -1
        if (b == 0) {
            return b;
        }
        if (b == -1) {
            return b;
        }
        if (b == 1 || b == 2) {
            StringBuilder sb = new StringBuilder();
            int c;
            do {
                c = in.read();
                sb.append((char) c);
            }
            while (c != '\n');
            if (b == 1) { // error
                log.debug(sb.toString());
            }
            if (b == 2) { // fatal error
                log.debug(sb.toString());
            }
        }
        return b;
    }

    public static void closeInputStream(InputStream in) {
        if (in != null) {
            try {
                in.close();
            } catch (IOException e) {
                log.error("Close input stream error." + e.getMessage());
            }
        }
    }

    public static void closeOutputStream(OutputStream out) {
        if (out != null) {
            try {
                out.close();
            } catch (IOException e) {
                log.error("Close output stream error." + e.getMessage());
            }
        }
    }

}

DemoApplication.java

package com.et.jsch;

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

@SpringBootApplication
public class DemoApplication {

   public static void main(String[] args) {
      SpringApplication.run(DemoApplication.class, args);
   }
}

代码仓库

https://github.com/Harries/springboot-demo

4.测试

import com.alibaba.fastjson.JSONObject;
import com.et.jsch.DemoApplication;
import com.et.jsch.model.Remote;
import com.et.jsch.util.JSchUtil;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.List;


@RunWith(SpringRunner.class)
@SpringBootTest(classes = DemoApplication.class)
public class JSchUtilTests {
    private Logger log = LoggerFactory.getLogger(getClass());

    Session session;
    @Before
    public void before() throws JSchException {
        Remote remote= new Remote();
        remote.setHost("xxx.xxx.xxx.xxx");
        remote.setUser("root");
        remote.setPassword("xxxx");
        session= JSchUtil.getSession(remote);
    }
    @After
    public void after(){
        JSchUtil.disconnect(session);
    }
    @Test
    public void remoteExecute() throws JSchException {
        List<String>  list= JSchUtil.remoteExecute(session,"ls");
        System.out.println(JSONObject.toJSON(list));
    }
    @Test
    public void uploadFile() throws JSchException, FileNotFoundException {
        String filestr ="D:\\tmp\\test\\file_utils\\file1.txt";
        File file = new File(filestr);
        InputStream in = new FileInputStream(file);

        String directory="/root/test";
        String fileName="test.txt";
       boolean flag= JSchUtil.uploadFile(session,in,directory,fileName);
        System.out.println(flag);
    }
    @Test
    public void deleteFile() throws JSchException, FileNotFoundException {
        String directory="/root/test";
        String fileName="test.txt";
        boolean flag= JSchUtil.deleteFile(session,directory,fileName);
        System.out.println(flag);
    }
    @Test
    public void scpFrom() throws JSchException, FileNotFoundException {

        String source="/root/test/file1.txt";
        String destination ="D:\\tmp\\scfFrom.txt";
        long  filesize= JSchUtil.scpFrom(session,source,destination);
        System.out.println(filesize);
    }
    @Test
    public void scpTo() throws JSchException, FileNotFoundException {

        String filestr ="D:\\tmp\\test\\file_utils\\file1.txt";
        String destination="/root/test/file1.txt";
        long  filesize= JSchUtil.scpTo(session,filestr,destination);
        System.out.println(filesize);
    }

}

自己尝试一下吧,非常好的一个工具,更多功能可以去官网看例子

5.引用

http://www.jcraft.com/jsch/examples/

http://www.liuhaihua.cn/archives/710346.html

到此这篇关于Spring Boot集成JSch的示例代码的文章就介绍到这了,更多相关SpringBoot集成JSch内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文