java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Java远程执行Shell指令

Java实现远程执行Shell指令

作者:Jeremy_Lee123

文章介绍使用JSch在SpringBoot项目中实现远程Shell操作,涵盖环境配置、依赖引入及工具类编写,详解分号和双与号执行多指令的区别

JSch(Java Secure Channel)是SSH2的一个纯Java实现。

它允许你连接到一个sshd 服务器,进而使用端口转发,X11转发,文件传输等等功能。

本文这里主要介绍如何利用JSch进行远程Shell操作。

软硬件环境说明

在pom.xml中引入JSch依赖

<!-- https://mvnrepository.com/artifact/com.jcraft/jsch -->
<dependency>
    <groupId>com.jcraft</groupId>
    <artifactId>jsch</artifactId>
    <version>0.1.55</version>
</dependency>

编写执行Shell指令的工具类

package com.lxk.aisware.util;

import com.jcraft.jsch.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.Properties;

/**
 * 执行Shell工具类
 *
 */
public class ExecuteShellUtil {

    private static final Logger LOGGER = LoggerFactory.getLogger(ExecuteShellUtil.class);

    /** 未调用初始化方法 错误提示信息 */
    private static final String DONOT_INIT_ERROR_MSG = "please invoke init(...) first!";

    private Session session;

    private Channel channel;

    private ChannelExec channelExec;

    private ExecuteShellUtil() {
    }

    /**
     * 获取ExecuteShellUtil类实例对象
     *
     */
    public static ExecuteShellUtil getInstance() {
        return new ExecuteShellUtil();
    }

    /**
     * 初始化
     *
     * @param ip
     *         远程Linux地址
     * @param port
     *         端口
     * @param username
     *         用户名
     * @param password
     *         密码
     * @throws JSchException
     *         JSch异常
     */
    public void init(String ip, Integer port, String username, String password) throws JSchException {
        JSch jsch = new JSch();
        jsch.getSession(username, ip, port);
        session = jsch.getSession(username, ip, port);
        session.setPassword(password);
        Properties sshConfig = new Properties();
        sshConfig.put("StrictHostKeyChecking", "no");
        session.setConfig(sshConfig);
        session.connect(60 * 1000);
        LOGGER.info("Session connected!");
        // 打开执行shell指令的通道
        channel = session.openChannel("exec");
        channelExec = (ChannelExec) channel;
    }

    /**
     * 执行一条命令
     */
    public String execCmd(String command) throws Exception {
        if (session == null || channel == null || channelExec == null) {
            throw new Exception(DONOT_INIT_ERROR_MSG);
        }
        LOGGER.info("execCmd command - > {}", command);
        channelExec.setCommand(command);
        channel.setInputStream(null);
        channelExec.setErrStream(System.err);
        channel.connect();
        StringBuilder sb = new StringBuilder(16);
        try (InputStream in = channelExec.getInputStream();
             InputStreamReader isr = new InputStreamReader(in, StandardCharsets.UTF_8);
             BufferedReader reader = new BufferedReader(isr)) {
            String buffer;
            while ((buffer = reader.readLine()) != null) {
                sb.append("\n").append(buffer);
            }
        }catch (Exception  e){
            LOGGER.info("execCmd result failed- > {}",e.toString());
        }finally {
            // 释放资源
            close();
        }

        LOGGER.info("execCmd result succeed- > {}", sb.toString());
        return sb.toString();
    }

    /**
     * 释放资源
     *
     * @date 2019/3/15 12:47
     */
    private void close() {
        if (channelExec != null && channelExec.isConnected()) {
            channelExec.disconnect();
        }
        if (channel != null && channel.isConnected()) {
            channel.disconnect();
        }
        if (session != null && session.isConnected()) {
            session.disconnect();
        }
    }
}

注:

如果要执行多个指令,可以多次调用工具类,也可以像使用多指令shell一样,使用【;】或【&&】等符号将多个指令隔开。     

追注:

1、【;】隔开的多个shell命令,会按照顺序执行下来,但是不能保证每条命令都执行成功。   

2、【&&】隔开的多个shell命令,前面的命令执行成功,才会执行后面的命令,否则后面的命令不执行。       

3、将多指令隔开的符号,上面给出的只是最常用的两种,更多功能的符号可自行查阅相关资料。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

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