java在linux上执行本地命令、ssh方式执行本地命令、ssh方式执行ssh命令,并获取结果

使用 ProcessBuilder 执行本机命令,适用于有限时间内返回结果,且返回结果内容不大(不会撑爆缓冲区),获取标准输出、错误输出:

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.springframework.util.CollectionUtils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
public class ProcessUtil {

    public enum StreamType {
        OUTPUT,
        INPUT,
        ERROR
    }

    // 获得命令的执行输出流
    public static List<String> bashResultSyn(String command) {
        return bashFullSyn(command).get(StreamType.INPUT);
    }

    // 获得命令的执行错误流
    public static List<String> bashErrorSyn(String command) {
        return bashFullSyn(command).get(StreamType.ERROR);
    }

    public static Map<StreamType, List<String>> bashFullSyn(String command) {
        Map<StreamType, List<String>> map = new HashMap<>();

        try {
            Process process = new ProcessBuilder("bash", "-c", command).start();

            List<String> result = getProcessResult(process);
            List<String> error = getProcessError(process);

            int exitCode = process.waitFor();
            map.put(StreamType.INPUT, result);
            map.put(StreamType.ERROR, error);
            exitCodeLog(exitCode, command, result, error);
        } catch (IOException | InterruptedException e) {
            log("command", command);
            log.error(ExceptionUtils.getFullStackTrace(e));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return map;
    }

    private static void log(String key, Object value) {
        log.info("{}:{}", key, value);
    }

    private static void exitCodeLog(int exitCode, String command, List<String> result, List<String> error) {
        log("command", command);
        if (result.size() < 100) {
            for (String s : result) {
                log.info(s);
            }
        } else {
            log("result size", result.size());
        }
        if (!CollectionUtils.isEmpty(error)) {
            log("exitCode", exitCode);
            log("error", error);
        }
    }

    private static List<String> getProcessResult(Process process) throws IOException {
        return readStream(process.getInputStream());
    }

    private static List<String> getProcessError(Process process) throws IOException {
        return readStream(process.getErrorStream());
    }

    private static List<String> readStream(InputStream inputStream) throws IOException {
        List<String> lines = new ArrayList<>();
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
            String line;
            while ((line = reader.readLine()) != null) {
                lines.add(line);
            }
        }
        return lines;
    }

}

ssh执行远程主机命令,适用场景同上

import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

@Slf4j
public class LinuxUtil {

    public static List<String> execCmd(String command, String host, String user, String password) {
        log.info("host:{}, cmd:{}", host, command);

        Session session = null;
        ChannelExec channelExec = null;

        try {
            session = createSession(host, user, password);
            channelExec = (ChannelExec) session.openChannel("exec");
            channelExec.setCommand(command);
            channelExec.setInputStream(null);
            channelExec.setErrStream(System.err);
            InputStream inputStream = channelExec.getInputStream();
            InputStream errStream = channelExec.getErrStream();
            channelExec.connect();
            return getResult(inputStream, errStream);
        } catch (JSchException | IOException e) {
            List<String> errList = new ArrayList<>();
            errList.add(e.getMessage());
            return errList;
        } finally {
            if (channelExec != null) {
                channelExec.disconnect();
            }
            if (session != null) {
                session.disconnect();
            }
        }
    }

    private static Session createSession(String host, String user, String password) throws JSchException {
        JSch jsch = new JSch();
        //获取sshSession
        Session session = jsch.getSession(user, host, 22);
        //添加密码
        session.setPassword(password);
        //严格主机密钥检查
        session.setConfig("StrictHostKeyChecking", "no");
        //开启sshSession连接
        session.setTimeout(999999999);
        session.connect();
        return session;
    }

    // 合并输出流结果和错误流结果
    private static List<String> getResult(InputStream inputStream, InputStream errStream) throws IOException {
        List<String> result = readStream(inputStream);
        List<String> error = readStream(errStream);

        if (result.size() < 100) {
            for (String s : result) {
                log.info(s);
            }
        } else {
            log.info("result size:{}", result.size());
        }
        if (!CollectionUtils.isEmpty(error)) {
            log.error("error:{}", error);
        }
        result.addAll(error);
        return result;
    }

    private static List<String> readStream(InputStream inputStream) throws IOException {
        List<String> lines = new ArrayList<>();
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
            String line;
            while ((line = reader.readLine()) != null) {
                lines.add(line);
            }
        }
        return lines;
    }

}

jsch依赖

<dependency>
    <groupId>com.github.mwiede</groupId>
    <artifactId>jsch</artifactId>
    <version>0.2.17</version>
</dependency>

检查远程主机是否可连接

boolean checkCoonServer(String host) {
    try {
        InetAddress coon = InetAddress.getByName(host);
        return coon.isReachable(200);
    } catch (IOException e) {
        log.error("coonServer find IOException " + e.getMessage());
        return false;
    }
}

ssh到别的主机上执行ssh命令(交互式)

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;

import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

public class InteractiveCommandUtil {

    public static final int SESSION_TIMEOUT = 60000;

    public static final int CHANNEL_TIMEOUT = 60 * 20 * 1000;

    public static void main(String[] args) throws Exception {
        String host = "***";
        String user = "***";
        String password = "***";

        try {
            JSch jsch = new JSch();
            Session session = jsch.getSession(user, host, 22);
            session.setTimeout(SESSION_TIMEOUT);
            session.setPassword(password);

            java.util.Properties config = new java.util.Properties();
            config.put("StrictHostKeyChecking", "no");
            session.setConfig(config);

            session.connect();

            Channel channel = session.openChannel("shell");
            channel.connect(CHANNEL_TIMEOUT);

            InputStream inputStream = channel.getInputStream();
            OutputStream outputStream = channel.getOutputStream();

            sendCommand(outputStream, "ssh ***@*** date -R");

            // Read the output
            List<String> result1 = readOutput(inputStream);
            if (linesContains(result1, "yes/no")) {
                sendCommand(outputStream, "yes");
                result1 = readOutput(inputStream);
            }
            if (linesContains(result1, "password")) {
                sendCommand(outputStream, "***");
                result1 = readOutput(inputStream);
            }

            readOutput(inputStream);

            channel.disconnect();
            session.disconnect();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void sendCommand(OutputStream outputStream, String command) throws Exception {
        outputStream.write((command + "\n").getBytes());
        outputStream.flush();
        Thread.sleep(1000); // Wait for command to execute (adjust as needed)
    }

    private static List<String> readOutput(InputStream inputStream) throws Exception {
        byte[] buffer = new byte[1024];
        int bytesRead;

        List<String> result = new ArrayList<>();
        while (inputStream.available() > 0 && (bytesRead = inputStream.read(buffer)) > 0) {
            String s = new String(buffer, 0, bytesRead);
            result.add(s);
            System.out.print(s);
        }

        return result;
    }

    public static boolean linesContains(List<String> lines, String keyword) {
        return lines.stream().anyMatch(t -> t.contains(keyword));
    }

}

这一段参考的代码原型:

jsch 交互式执行命令示例-CSDN博客

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值