java连接linux服务器执行shell命令(框架分析+推荐)

java连接linux服务器执行shell命令(框架分析+推荐)

一、分类+连接方式

  1. 程序打成jar包,在本地服务器上执行shell命令。这种使用MyRuntimeUtil工具类
  2. java程序远程linux服务器有两个框架分别是:jsch与ganymed-ssh2框架推荐使用jsch框架因为ganymed-ssh2框架不支持麒麟服务器的连接原因是openssl版本过高,ganymed-ssh框架不维护了所以不支持。

二、执行本地的shell命令

    <dependency>
      <groupId>cn.hutool</groupId>
      <artifactId>hutool-all</artifactId>
      <version>5.7.21</version>
    </dependency>

工具类

package com.dameng.util;
import cn.hutool.core.exceptions.UtilException;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.text.StrBuilder;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.CharUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.log.StaticLog;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.management.ManagementFactory;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
/**
 * @author xgt(小光头)
 * @version 1.0
 * @date 2022-3-3 22:40
 */
public class MyRuntimeUtil {

    /**
     * 执行系统命令,使用系统默认编码
     *
     * @param cmds 命令列表,每个元素代表一条命令
     * @return 执行结果
     * @throws IORuntimeException IO异常
     */
    public static String execForStr(String... cmds) throws IORuntimeException {
        return execForStr(CharsetUtil.systemCharset(), cmds);
    }

    /**
     * 执行系统命令,使用系统默认编码
     *
     * @param charset 编码
     * @param cmds    命令列表,每个元素代表一条命令
     * @return 执行结果
     * @throws IORuntimeException IO异常
     * @since 3.1.2
     */
    public static String execForStr(Charset charset, String... cmds) throws IORuntimeException {
        return getResult(exec(cmds), charset);
    }
    public static String execForErrStr(Charset charset,String cmd) throws IORuntimeException {
        return getResultErr(exec(cmd), charset);
    }


    /**
     * 执行系统命令,使用系统默认编码
     *

     */
    public static String execForStr(Charset charset, String cmds) throws IORuntimeException {
        return getResult(exec(cmds), charset);
    }

    /**
     * 执行系统命令,使用系统默认编码
     *
     * @param cmds 命令列表,每个元素代表一条命令
     * @return 执行结果,按行区分
     * @throws IORuntimeException IO异常
     */
    public static List<String> execForLines(String... cmds) throws IORuntimeException {
        return execForLines(CharsetUtil.systemCharset(), cmds);
    }

    /**
     * 执行系统命令,使用系统默认编码
     *
     * @param charset 编码
     * @param cmds    命令列表,每个元素代表一条命令
     * @return 执行结果,按行区分
     * @throws IORuntimeException IO异常
     * @since 3.1.2
     */
    public static List<String> execForLines(Charset charset, String... cmds) throws IORuntimeException {
        return getResultLines(exec(cmds), charset);
    }

    /**
     * 执行命令<br>
     * 命令带参数时参数可作为其中一个参数,也可以将命令和参数组合为一个字符串传入
     *
     * @param cmds 命令
     * @return {@link Process}
     */
    public static Process exec(String... cmds) {
        Process process;
        try {


            process = new ProcessBuilder(handleCmds(cmds)).redirectErrorStream(true).start();
        } catch (IOException e) {
            throw new IORuntimeException(e);
        }
        return process;
    }

    /**
     * 执行命令<br>
     * 命令带参数时参数可作为其中一个参数,也可以将命令和参数组合为一个字符串传入
     *
     * @param cmd 命令
     * @return {@link Process}
     */
    public static Process exec(String cmd) {
        Process process;
        try {
            // 得到Java进程的相关Runtime运行对象
            Runtime runtime = Runtime.getRuntime();
            if(cmd.indexOf("|")>0){
                String[] cmdArr = {"sh","-c",cmd};
                process = runtime.exec(cmdArr);
            }else{
                process = runtime.exec(cmd);
            }



        } catch (IOException e) {
            throw new IORuntimeException(e);
        }
        return process;
    }


    /**
     * 执行命令<br>
     * 命令带参数时参数可作为其中一个参数,也可以将命令和参数组合为一个字符串传入
     *
     * @param envp 环境变量参数,传入形式为key=value,null表示继承系统环境变量
     * @param cmds 命令
     * @return {@link Process}
     * @since 4.1.6
     */
    public static Process exec(String[] envp, String... cmds) {
        return exec(envp, null, cmds);
    }

    /**
     * 执行命令<br>
     * 命令带参数时参数可作为其中一个参数,也可以将命令和参数组合为一个字符串传入
     *
     * @param envp 环境变量参数,传入形式为key=value,null表示继承系统环境变量
     * @param dir  执行命令所在目录(用于相对路径命令执行),null表示使用当前进程执行的目录
     * @param cmds 命令
     * @return {@link Process}
     * @since 4.1.6
     */
    public static Process exec(String[] envp, File dir, String... cmds) {
        try {
            return Runtime.getRuntime().exec(handleCmds(cmds), envp, dir);
        } catch (IOException e) {
            throw new IORuntimeException(e);
        }
    }

    // -------------------------------------------------------------------------------------------------- result

    /**
     * 获取命令执行结果,使用系统默认编码,获取后销毁进程
     *
     * @param process {@link Process} 进程
     * @return 命令执行结果列表
     */
    public static List<String> getResultLines(Process process) {
        return getResultLines(process, CharsetUtil.systemCharset());
    }

    /**
     * 获取命令执行结果,使用系统默认编码,获取后销毁进程
     *
     * @param process {@link Process} 进程
     * @param charset 编码
     * @return 命令执行结果列表
     * @since 3.1.2
     */
    public static List<String> getResultLines(Process process, Charset charset) {
        InputStream in = null;
        try {
            in = process.getInputStream();
            return IoUtil.readLines(in, charset, new ArrayList<>());
        } finally {
            IoUtil.close(in);
            destroy(process);
        }
    }

    /**
     * 获取命令执行结果,使用系统默认编码,,获取后销毁进程
     *
     * @param process {@link Process} 进程
     * @return 命令执行结果列表
     * @since 3.1.2
     */
    public static String getResult(Process process) {
        return getResult(process, CharsetUtil.systemCharset());
    }

    /**
     * 获取命令执行结果,获取后销毁进程
     *
     * @param process {@link Process} 进程
     * @param charset 编码
     * @return 命令执行结果列表
     * @since 3.1.2
     */
    public static String getResult(Process process, Charset charset) {
        InputStream in = null;
        InputStream errorStream = null;
        try {
            in = process.getInputStream();
            errorStream = process.getErrorStream();
            String errorResult = IoUtil.read(errorStream, charset);
            if(StrUtil.isNotBlank(errorResult)){
                StaticLog.warn("Shell command execution error, because {}",errorResult);
            }
            return IoUtil.read(in, charset);
        } finally {
            IoUtil.close(in);
            IoUtil.close(errorStream);
            destroy(process);
        }
    }

    /**
     * 获取错误的执行结果,获取后销毁进程
     *
     * @param process {@link Process} 进程
     * @param charset 编码
     * @return 命令执行结果列表
     * @since 3.1.2
     */
    public static String getResultErr(Process process, Charset charset) {
        InputStream in = null;
        InputStream errorStream = null;
        try {
            in = process.getInputStream();

            errorStream = process.getErrorStream();
           // System.out.println("252"+IoUtil.read(errorStream, charset));
            return IoUtil.read(errorStream, charset);
        } finally {
            IoUtil.close(in);
            IoUtil.close(errorStream);
            destroy(process);
        }
    }


    /**
     * 获取命令执行异常结果,使用系统默认编码,,获取后销毁进程
     *
     * @param process {@link Process} 进程
     * @return 命令执行结果列表
     * @since 4.1.21
     */
    public static String getErrorResult(Process process) {
        return getErrorResult(process, CharsetUtil.systemCharset());
    }

    /**
     * 获取命令执行异常结果,获取后销毁进程
     *
     * @param process {@link Process} 进程
     * @param charset 编码
     * @return 命令执行结果列表
     * @since 4.1.21
     */
    public static String getErrorResult(Process process, Charset charset) {
        InputStream in = null;
        try {
            in = process.getErrorStream();
            return IoUtil.read(in, charset);
        } finally {
            IoUtil.close(in);
            destroy(process);
        }
    }

    /**
     * 销毁进程
     *
     * @param process 进程
     * @since 3.1.2
     */
    public static void destroy(Process process) {
        if (null != process) {
            process.destroy();
        }
    }

    /**
     * 增加一个JVM关闭后的钩子,用于在JVM关闭时执行某些操作
     *
     * @param hook 钩子
     * @since 4.0.5
     */
    public static void addShutdownHook(Runnable hook) {
        Runtime.getRuntime().addShutdownHook((hook instanceof Thread) ? (Thread) hook : new Thread(hook));
    }

    /**
     * 获得JVM可用的处理器数量(一般为CPU核心数)
     *
     * @return 可用的处理器数量
     * @since 5.3.0
     */
    public static int getProcessorCount() {
        return Runtime.getRuntime().availableProcessors();
    }

    /**
     * 获得JVM中剩余的内存数,单位byte
     *
     * @return JVM中剩余的内存数,单位byte
     * @since 5.3.0
     */
    public static long getFreeMemory() {
        return Runtime.getRuntime().freeMemory();
    }

    /**
     * 获得JVM已经从系统中获取到的总共的内存数,单位byte
     *
     * @return JVM中剩余的内存数,单位byte
     * @since 5.3.0
     */
    public static long getTotalMemory() {
        return Runtime.getRuntime().totalMemory();
    }

    /**
     * 获得JVM中可以从系统中获取的最大的内存数,单位byte,以-Xmx参数为准
     *
     * @return JVM中剩余的内存数,单位byte
     * @since 5.3.0
     */
    public static long getMaxMemory() {
        return Runtime.getRuntime().maxMemory();
    }

    /**
     * 获得JVM最大可用内存,计算方法为:<br>
     * 最大内存-总内存+剩余内存
     *
     * @return 最大可用内存
     */
    public static long getUsableMemory() {
        return getMaxMemory() - getTotalMemory() + getFreeMemory();
    }

    /**
     * 获取当前进程ID,首先获取进程名称,读取@前的ID值,如果不存在,则读取进程名的hash值
     *
     * @return 进程ID
     * @throws UtilException 进程名称为空
     * @since 5.7.3
     */
    public static int getPid() throws UtilException {
        final String processName = ManagementFactory.getRuntimeMXBean().getName();
        if (StrUtil.isBlank(processName)) {
            throw new UtilException("Process name is blank!");
        }
        final int atIndex = processName.indexOf('@');
        if (atIndex > 0) {
            return Integer.parseInt(processName.substring(0, atIndex));
        } else {
            return processName.hashCode();
        }
    }

    /**
     * 处理命令,多行命令原样返回,单行命令拆分处理
     *
     * @param cmds 命令
     * @return 处理后的命令
     */
    private static String[] handleCmds(String... cmds) {
        if (ArrayUtil.isEmpty(cmds)) {
            throw new NullPointerException("Command is empty !");
        }

        // 单条命令的情况
        if (1 == cmds.length) {
            final String cmd = cmds[0];
            if (StrUtil.isBlank(cmd)) {
                throw new NullPointerException("Command is blank !");
            }
            cmds = cmdSplit(cmd);
        }
        return cmds;
    }

    /**
     * 命令分割,使用空格分割,考虑双引号和单引号的情况
     *
     * @param cmd 命令,如 git commit -m 'test commit'
     * @return 分割后的命令
     */
    private static String[] cmdSplit(String cmd) {
        final List<String> cmds = new ArrayList<>();

        final int length = cmd.length();
        final Stack<Character> stack = new Stack<>();
        boolean inWrap = false;
        final StrBuilder cache = StrUtil.strBuilder();

        char c;
        for (int i = 0; i < length; i++) {
            c = cmd.charAt(i);
            switch (c) {
                case CharUtil.SINGLE_QUOTE:
                case CharUtil.DOUBLE_QUOTES:
                    if (inWrap) {
                        if (c == stack.peek()) {
                            //结束包装
                            stack.pop();
                            inWrap = false;
                        }
                        cache.append(c);
                    } else {
                        stack.push(c);
                        cache.append(c);
                        inWrap = true;
                    }
                    break;
                case CharUtil.SPACE:
                    if (inWrap) {
                        // 处于包装内
                        cache.append(c);
                    } else {
                        cmds.add(cache.toString());
                        cache.reset();
                    }
                    break;
                default:
                    cache.append(c);
                    break;
            }
        }

        if (cache.hasContent()) {
            cmds.add(cache.toString());
        }

        return cmds.toArray(new String[0]);
    }
}

使用方法

package java.nio.charset;

Charset charset = Charset.forName("UTF-8");
MyRuntimeUtil.execForStr(charset,"ls");

三、Jsch远程连接执行

      <dependency>
      <groupId>cn.hutool</groupId>
      <artifactId>hutool-all</artifactId>
      <version>5.7.21</version>
    </dependency>
 <!-- jsch的方式 远程连接的包-->
    <dependency>
      <groupId>com.jcraft</groupId>
      <artifactId>jsch</artifactId>
      <version>0.1.55</version>
    </dependency>

工具类

package com.dameng.util;

import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.ssh.JschUtil;
import com.jcraft.jsch.*;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.Properties;
 
/**
 * 执行Shell工具类
 *
 * @author JustryDeng
 * @date 2019/4/29 16:29
 */
public class ExecuteShellUtil {
 

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

 
    private ExecuteShellUtil() {
    }
 
    /**
     * 获取ExecuteShellUtil类实例对象
     *
     * @return 实例
     * @date 2019/4/29 16:58
     */
    public static ExecuteShellUtil getInstance() {
        return new ExecuteShellUtil();
    }
 
    /**
     * 初始化
     *
     * @param ip
     *         远程Linux地址
     * @param port
     *         端口
     * @param username
     *         用户名
     * @param password
     *         密码
     * @throws JSchException
     *         JSch异常
     * @date 2019/3/15 12:41
     */
    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(1200 * 1000);


    }
 
    /**
     * 执行一条命令,探活使用
     */
    public static String execCmd(Session session,String command) throws Exception {
//        if (session == null || channel == null || channelExec == null) {
//            throw new Exception(DONOT_INIT_ERROR_MSG);
//        }
        // 打开执行shell指令的通道
        Channel channel = session.openChannel("exec");
        ChannelExec channelExec = (ChannelExec) channel;
        channelExec.setCommand("source /etc/profile && source ~/.bash_profile && source ~/.bashrc &&  adb devices && locale charmap");
        channelExec.setCommand(command);
        channel.setInputStream(null);
        channelExec.setErrStream(System.err);
       // channel.setXForwarding();
        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);
            }


         //2023-02-21 关闭流
            IoUtil.close(reader);
            IoUtil.close(isr);
            IoUtil.close(in);



            return sb.toString();
        }finally {
            if (channelExec.isConnected()) {
                channelExec.disconnect();
            }
            if (channel.isConnected()) {
                channel.disconnect();
            }
        }
    }


    /**
     * 执行一条命令
     */
    public String execCmd(String command) throws Exception {
//        if (session == null || channel == null || channelExec == null) {
//            throw new Exception(DONOT_INIT_ERROR_MSG);
//        }
        // 打开执行shell指令的通道
        Channel channel = session.openChannel("exec");
        ChannelExec channelExec = (ChannelExec) channel;
        channelExec.setCommand("source /etc/profile && source ~/.bash_profile && source ~/.bashrc &&  adb devices && locale charmap");
        channelExec.setCommand(command);
        channel.setInputStream(null);
        channelExec.setErrStream(System.err);
        // channel.setXForwarding();
        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);
            }


            //2023-02-21 关闭流
            IoUtil.close(reader);
            IoUtil.close(isr);
            IoUtil.close(in);





            return sb.toString();
        }finally {
            if (channelExec != null && channelExec.isConnected()) {
                channelExec.disconnect();
            }
            if ( channel != null && channel.isConnected()) {
                channel.disconnect();
            }
        }
    }





    /**
     * 执行一条命令 获取错误流中的内容
     */
    public String execCmdErrContent(String command) throws Exception {
//        if (session == null || channel == null || channelExec == null) {
//            throw new Exception(DONOT_INIT_ERROR_MSG);
//        }
        // 打开执行shell指令的通道
        Channel channel = session.openChannel("exec");
        ChannelExec channelExec = (ChannelExec) channel;
        channelExec.setCommand(command);
        channel.setInputStream(null);
        ByteArrayOutputStream err  = new ByteArrayOutputStream();
        channelExec.setErrStream(err);
        channel.connect();
        StringBuilder sb = new StringBuilder(16);
        try (InputStream in = channelExec.getErrStream();
             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);
            }



            //2023-02-21 关闭流
            IoUtil.close(reader);
            IoUtil.close(isr);
            IoUtil.close(in);
            IoUtil.close(err);



            if(StrUtil.contains(sb.toString(), "没有那个文件或目录")){
                return "";
            }else{
                return sb.toString();
            }

        }finally {
            if (channelExec != null && channelExec.isConnected()) {
                channelExec.disconnect();
            }
            if ( channel != null && channel.isConnected()) {
                channel.disconnect();
            }
        }
    }


    public static void closeConnect() {
        if (session != null && session.isConnected()) {
            session.disconnect();
        }
    }
}

使用方法

package com.dameng;

import cn.hutool.core.text.StrSplitter;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.ssh.JschUtil;
import com.dameng.util.ExecuteShellUtil;
import com.dameng.util.ShellCmdUtil;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import org.junit.Test;

import java.math.BigDecimal;
import java.util.List;

/**
 * Unit test for simple App.
 */
public class JschUtilTest
{
    /**
     * Jsch方式4830
     */
    @Test
    public void shouldAnswerWithTrue() {
        long currentTimeMillis = System.currentTimeMillis();
        ExecuteShellUtil instance = ExecuteShellUtil.getInstance();
        try {
            //instance.init("192.168.60.179", 22, "root","password123.1");
          //  String ls = instance.execCmd("top -p 21475 -n 1 -b");
            String ls = instance.execCmd("cat /opt/dmdbms/log/dm_DW1_01B_202203.log | grep -v 'INFO'");
            List<String> lineFreedList = StrSplitter.splitByRegex(StrUtil.trimToEmpty(ls), "\n", -1, true, true);
            for (String s : lineFreedList) {
                List<String> stringList = StrSplitter.split(StrUtil.trimToEmpty(s), "=", -1, true, true);
                System.out.println(stringList);


            }

            System.out.println(ls);

//
//            // 计算内存使用率(已使用内存/总内存)
//            String freeStr = instance.execCmd("free | sed -n '2p'");
//            List<String> freeInfoList = StrSplitter.splitByRegex(StrUtil.trimToEmpty(freeStr), "\\s+", -1, true, true);
//            String allMemory = freeInfoList.get(1);
//            String usedMemory = freeInfoList.get(2);
//            double f1 = new BigDecimal(Float.valueOf(usedMemory) / Float.valueOf(allMemory)).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue() * 100;
//
//
//
//
//            System.out.println(ls);
//            long currentTimeMillis1 = System.currentTimeMillis();
//            System.out.println("Jsch方式"+(currentTimeMillis1-currentTimeMillis));
        } catch (Exception e) {
            System.out.println("error info");
            e.printStackTrace();
        }


    }
}

四、ganymed-ssh2远程连接执行

    <dependency>
      <groupId>cn.hutool</groupId>
      <artifactId>hutool-all</artifactId>
      <version>5.7.21</version>
    </dependency>
     <!-- GanymedUtil的方式 远程连接的包-->
    <dependency>
      <groupId>ch.ethz.ganymed</groupId>
      <artifactId>ganymed-ssh2</artifactId>
      <version>262</version>
    </dependency>

工具类

package com.dameng.util;

import ch.ethz.ssh2.Connection;
import ch.ethz.ssh2.ConnectionInfo;
import ch.ethz.ssh2.Session;
import ch.ethz.ssh2.StreamGobbler;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.log.StaticLog;
import com.dameng.core.exception.MyGanymedException;
import com.dameng.core.exception.MyHostConnectException;
import com.dameng.core.exception.MyResolutionException;
import com.dameng.domain.OsInfo;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.List;

/**
 * @author xgt(小光头)
 * @version 1.0
 * @date 2022-2-26 15:36
 */
public class MyGanymedSingleUtil {

    private MyGanymedSingleUtil() {
    }


    private static Connection connect;
    private static  MyGanymedSingleUtil myGanymedSingleUtil;

    public static MyGanymedSingleUtil getInstance() {

        if(myGanymedSingleUtil == null){
            myGanymedSingleUtil =new MyGanymedSingleUtil();
        }

        return myGanymedSingleUtil;
    }


    /**
     * 连接到服务器
     * @param sshHost 主机
     * @param sshPort 端口
     * @return {@link Connection}
     */
    public  Connection connect(String sshHost, int sshPort) {
        connect = new Connection(sshHost, sshPort);
        try {
            connect.connect();
        } catch (IOException e) {
            throw new IORuntimeException(e);
        }
        return connect;
    }

    /**
     * 打开远程会话
     *
     * @param sshHost 主机
     * @param sshPort 端口
     * @param sshUser 用户名,如果为null,默认root
     * @param sshPass 密码
     * @return {@link Session}
     */
    public void openConnect(String sshHost, int sshPort, String sshUser, String sshPass) throws MyHostConnectException {
        // 默认root用户
        if (StrUtil.isEmpty(sshUser)) {
            sshUser = "root";
        }

        connect = connect(sshHost, sshPort);
        try {
            connect.authenticateWithPassword(sshUser, sshPass);

            ConnectionInfo connectionInfo = connect.getConnectionInfo();
           // session = connect.openSession();
        } catch (IOException e) {
            throw new MyHostConnectException(e);
        }
    }



    /**
     * 执行Shell命令(使用EXEC方式)
     * <p>
     * 此方法单次发送一个命令到服务端,不读取环境变量,执行结束后自动关闭Session,不会产生阻塞。
     * </p>
     *
     * @param cmd       命令
     * @param charset   发送和读取内容的编码
     * @return 执行返回结果
     */
    public  String exec(String cmd, String charset) throws Exception {


        final String result;
        final String stderrStr;
        ByteArrayOutputStream errStream = new ByteArrayOutputStream();
        Session session = null;
        try {
            session = connect.openSession();
            Charset charset1 = Charset.forName(charset);
            session.execCommand(cmd, charset1.name());
            result = IoUtil.read(new StreamGobbler(session.getStdout()), charset1);
            //打印错误的流输出
            IoUtil.copy(new StreamGobbler(session.getStderr()), errStream);
            stderrStr = new String(errStream.toByteArray(),charset);
        } finally {
            session.close();
        }
        if(!StrUtil.isEmpty(stderrStr)){
            throw new MyGanymedException(stderrStr);
        }

        return result;
    }




    /**
     * 执行Shell命令
     * <p>
     * 此方法单次发送一个命令到服务端,自动读取环境变量,执行结束后自动关闭Session,不会产生阻塞。
     * </p>
     *
     * @param cmd       命令
     * @param charset   发送和读取内容的编码
     * @param errStream 错误信息输出到的位置
     * @return 执行返回结果
     */
    public  String execByShell(String cmd, Charset charset, OutputStream errStream) {
        final String result;
        Session session = null;
        try {
            //这个方法有问题
            session.requestDumbPTY();
            IoUtil.write(session.getStdin(), charset, true, cmd);

            result = IoUtil.read(new StreamGobbler(session.getStdout()), charset);
            if(null != errStream){
                // 错误输出
                IoUtil.copy(new StreamGobbler(session.getStdout()), errStream);
            }
        } catch (IOException e) {
            throw new IORuntimeException(e);
        } finally {
            close(session);
        }
        return result;
    }

    /**
     * 关闭会话
     *
     */
    public  void close(Session session) {

        if(session!=null){
            session.close();
        }
    }

    /**
     * 关闭会话
     *
     */
    public  void closeConnect() {

        if(connect!=null){
            connect.close();
        }
    }


}

使用方式

package com.dameng;

import ch.ethz.ssh2.Session;
import cn.hutool.extra.ssh.GanymedUtil;
import cn.hutool.extra.ssh.JschUtil;
import com.dameng.util.ExecuteShellUtil;
import com.dameng.util.MyGanymedUtil;
import org.junit.Test;

import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.nio.charset.Charset;

/**
 * Unit test for simple App.
 */
public class GanymedUtilTest
{
    private static String DEFAULTCHART = "UTF-8";
    /**
     * Rigorous Test :-)
     */
    @Test
    public void shouldAnswerWithTrue()  {
        long currentTimeMillis = System.currentTimeMillis();
      //  Session session = JschUtil.getSession("192.168.60.177", 22, "root", "root");

        Session session = MyGanymedUtil.openSession("192.168.60.177", 22, "root", "root");
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        Charset charset = Charset.forName("UTF-8");
        String ls = MyGanymedUtil.exec(session, "awk -F: '/model name/ {name=$2} END {print name}' /proc/cpuinfo | sed 's/^[ \\t]*//;s/[ \\t]*$//'", charset, byteArrayOutputStream);


        String str = new String(byteArrayOutputStream.toByteArray(),charset);
        System.out.println(ls);

        System.out.println("error="+str);
        long currentTimeMillis1 = System.currentTimeMillis();
        System.out.println("Ganymed方式"+(currentTimeMillis1-currentTimeMillis));
    }
}

问题总结

1. dd命令进行磁盘测速方法获取不到值

经过分析发现执行结果都在工具类的错误流中,并非在正常流中,自己打印一下错误流就发现了。

  1. 本地的shell命令的话参考一下工具类的MyRuntimeUtil.execForErrStr(charset,cmd)这个方法。
  2. jsch框架的话参考一下工具类的jschInstance.execCmdErrContent(cmd)这个方法。

2. 执行ll命令报错

采用框架中的方法调用,是不带用户的环境变量的所以ll命令会报错,ll命令是ls -l命令封装后的结果。所以需要使用ls -l命令。

3.执行top命令报错

不支持top这种不断刷新交互式的命令。加参数获取一次性结果。

top -b -n 1 |head -n 4 | grep 'sy' | grep 'us' | awk '{print $2}'
  • 22
    点赞
  • 83
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
要通过Java 1.8连接Linux服务器执行shell脚本,可以使用Java的SSH库,如JSch。下面是一种可能的实现方式: 首先,你需要在你的Java项目中导入JSch库。你可以在Maven中添加以下依赖项: ```xml <dependency> <groupId>com.jcraft</groupId> <artifactId>jsch</artifactId> <version>0.1.55</version> </dependency> ``` 然后,你需要使用JSch创建一个SSH会话并连接到远程服务器。以下是一个简单的示例代码: ```java import com.jcraft.jsch.*; public class SSHExample { public static void main(String[] args) { String host = "your_host"; int port = 22; String username = "your_username"; String password = "your_password"; try { JSch jsch = new JSch(); Session session = jsch.getSession(username, host, port); session.setConfig("StrictHostKeyChecking", "no"); session.setPassword(password); session.connect(); Channel channel = session.openChannel("exec"); ((ChannelExec) channel).setCommand("your_shell_command"); channel.setInputStream(null); ((ChannelExec) channel).setErrStream(System.err); InputStream in = channel.getInputStream(); channel.connect(); // 读取命令输出 byte[] tmp = new byte[1024]; while (true) { while (in.available() > 0) { int i = in.read(tmp, 0, 1024); if (i < 0) break; System.out.print(new String(tmp, 0, i)); } if (channel.isClosed()) { if (in.available() > 0) continue; System.out.println("exit-status: " + channel.getExitStatus()); break; } } channel.disconnect(); session.disconnect(); } catch (JSchException | IOException e) { e.printStackTrace(); } } } ``` 在上述代码中,你需要将"your_host"替换为远程服务器的IP地址或域名,"your_username"和"your_password"替换为你的用户名和密码。然后,将"your_shell_command"替换为你想要在远程服务器执行shell命令。 此代码将连接到远程服务器执行shell命令并打印输出流中的结果。你还可以根据需要进行进一步的修改和扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值