使用JSCH与服务器交互工具类

本文介绍了一个基于JSch库实现的SSH连接工具类,该工具类支持密码和密钥认证方式,并提供了连接服务器、执行命令、上传文件等功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

package com.tiger.queue.framework.utils;

import com.jcraft.jsch.*;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.util.HashMap;
import java.util.Map;

public class JschConnectionUtils {
    private static final Logger LOGGER= LoggerFactory.getLogger(JschConnectionUtils.class);
    //ip
    private final String hostname;
    //端口
    private final int port;
    //登录名称
    private final String username;
    //密码【和密钥二选一】
    private final String password;
    //密钥【和密码二选一】,这个密钥是文件的地址,不是密钥的里面的内容
    private final String privateKey;

    public JschConnectionUtils(String hostname, int port, String username, String password, String privateKey) {
        this.hostname = hostname;
        this.port = port;
        this.username = username;
        this.password = password;
        this.privateKey = privateKey;
    }

    /**
     * 连接服务器
     * @return Session 连接会话
     */
    public Session connect(){
        Session session = null;
        try {
            JSch jSch=new JSch();
            if (StringUtils.isNotBlank(privateKey) && StringUtils.isBlank(password)){
                jSch.addIdentity(privateKey);
            }
            session = jSch.getSession(username, hostname, port);
            if (StringUtils.isNotBlank(password) && StringUtils.isBlank(privateKey)){
                session.setPassword(password);
            }
            if (StringUtils.isNotBlank(password) && StringUtils.isNotBlank(privateKey)){
                throw new RuntimeException("param error!");
            }
            session.setConfig("StrictHostKeyChecking", "no");
            session.connect(30000);
            LOGGER.info("ip:{},port:{}connect success",hostname,port);
        } catch (JSchException e) {
            if (session!=null){
                session.disconnect();
            }
        }
        return session;
    }

    /**
     * exce模式命令交互
     * @param session 当前会话,也就是窗口
     * @param command 命令,可以单个命令,也可以多个命令,使用分隔符隔开
     *                ;【各命令的执行给果,不会影响其它命令的执行。换句话说,各个命令都会执行,但不保证每个命令都执行成功】
     *                &&【若前面的命令执行成功,才会去执行后面的命令。这样可以保证所有的命令执行完毕后,执行过程都是成功的】
     *                ||【只有前面的命令执行失败后才去执行下一条命令,直到执行成功一条命令为止】
     *
     * @return Map<String,String>
     *     INFO【正常消息】
     *     ERROR【异常消息】
     */
    public Map<String,String> channelExec(Session session, String command){
        ChannelExec exec = null;
        BufferedReader errorReader=null;
        BufferedReader infoReader=null;
        Map<String,String> resultBody=new HashMap<>(2);
        try {
            exec= (ChannelExec) session.openChannel("exec");
            exec.setCommand(command);
            exec.connect(15000);
            //正常消息
            infoReader=new BufferedReader(new InputStreamReader(exec.getInputStream()));
            //异常消息
            errorReader=new BufferedReader(new InputStreamReader(exec.getErrStream()));
            //获取正常消息
            StringBuilder infoResultBody = new StringBuilder();
            String infoMsg;
            while ((infoMsg=infoReader.readLine())!=null){
                infoResultBody.append(infoMsg).append("\n");
            }
            resultBody.put("INFO",infoResultBody.toString());
            //获取异常消息
            StringBuilder errorResultBody = new StringBuilder();
            String errorMsg;
            while ((errorMsg=errorReader.readLine())!=null){
                errorResultBody.append(errorMsg).append("\n");
            }
            resultBody.put("ERROR",errorResultBody.toString());
        } catch (JSchException | IOException e) {
           e.printStackTrace();
        } finally {
            if (infoReader!=null){
                try {
                    infoReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (errorReader!=null){
                try {
                    errorReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (exec!=null){
                exec.disconnect();
            }
        }
        return resultBody;
    }

    /**
     * 执行多条命令方法
     * @param session 当前会话
     * @param command 命令组
     */
    public String channelShell(Session session, String[] command){
        ChannelShell shell=null;
        BufferedReader reader=null;
        BufferedWriter writer=null;
        StringBuilder resultBody = new StringBuilder();
        try {
            shell = (ChannelShell) session.openChannel("shell");
            shell.connect(15000);
            writer=new BufferedWriter(new OutputStreamWriter(shell.getOutputStream()));
            reader=new BufferedReader(new InputStreamReader(shell.getInputStream()));
            //输入
            for (String cmd : command) {
                writer.write(cmd+"\n");
                writer.flush();
            }
            //命令执行完毕加上exit,结束本次交互
            writer.write("exit\n");
            writer.flush();
            //输出
            String line;
            while ((line=reader.readLine())!=null){
                resultBody.append(line).append("\n");
            }
        }catch (JSchException | IOException e){
            e.printStackTrace();
        }finally {
            if (reader!=null){
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (writer!=null){
                try {
                    writer.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (shell!=null){
                shell.disconnect();
            }
        }
        return resultBody.toString();
    }

    /**
     * 上传文件...
     * @param session 当前的会话
     * @param directory 上传文件夹
     * @param fileName 文件名称
     * @param inputStream 文件流
     * @throws SftpException 执行异常
     */
    public void channelSftp(Session session,String directory,String fileName,InputStream inputStream) throws SftpException {
        ChannelSftp sftp=null;
        try {
            sftp= (ChannelSftp) session.openChannel("sftp");
            if (sftp.ls(directory)==null){
                sftp.mkdir(directory);
            }
            //切换到指定的目录
            sftp.cd(directory);
            //上传文件
            sftp.put(inputStream,fileName);
        }catch (JSchException | SftpException e) {
            if (sftp!=null){
                sftp.mkdir(directory);
                sftp.cd(directory);
                sftp.put(inputStream,fileName);
            }
        }finally {
            if (sftp!=null){
                sftp.disconnect();
            }
        }
    }

    /**
     * 关闭连接
     * @param session 当前会话
     */
    public void disconnect(Session session){
        if (session.isConnected()){
            session.disconnect();
        }
    }

    public static void main(String[] args) {
        JschConnectionUtils connectionUtils=
                new JschConnectionUtils("********",22,"root",null,"********.pem");
        Session root = connectionUtils.connect();
        if (root!=null){
            String s = connectionUtils.channelShell(root, new String[]{"cd ..", "cd /usr/local", "ls -a"});
            System.out.println(s);
            connectionUtils.disconnect(root);
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值