背景

Java外调程序,比如frp、进行服务监听,然后保活,如果挂掉,不断拉起等操作

Show Code

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class ExecCmdResult {
    private boolean status;
    private int exitCode;
    private String execCommand;
    private String execContent;
    private Long cost;
}

import com.boommanpro.marriott.helper.model.ExecCmdResult;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.io.InputStreamReader;
import java.util.concurrent.TimeUnit;

@Slf4j
public class ExecCmdUtils {

    private final static int BUFFER_SIZE = 1024;

    private final static String DEFAULT_ENCODING = "gbk";

    private static class ProcessWorker extends Thread {
        private final Process process;
        private volatile int exitCode = -99;
        private volatile boolean completed = false;
        private volatile String output = "";

        private ProcessWorker(Process process) {
            this.process = process;
        }

        @Override
        public void run() {
            try (InputStreamReader reader = new InputStreamReader(
                    process.getInputStream(), DEFAULT_ENCODING)) {

                StringBuilder log = new StringBuilder();
                char[] buffer = new char[BUFFER_SIZE];
                int length;
                while ((length = reader.read(buffer)) != -1) {
                    log.append(buffer, 0, length);
                }
                output = log.toString();
                exitCode = process.waitFor();
                completed = true;
            } catch (InterruptedException | IOException e) {
                Thread.currentThread().interrupt();
            }
        }

        public int getExitCode() {
            return exitCode;
        }

        public String getOutput() {
            return output;
        }

        public boolean isCompleted() {
            return completed;
        }
    }


    public static ExecCmdResult execCmd(String command) {
        return execCmd(command, 15);
    }


    public static void execDaemonCmd(String command) {
        ProcessBuilder processBuilder = new ProcessBuilder(command.split(" "));
        // 合并错误输出流
        processBuilder.redirectErrorStream(true);

        try {
            Process process = processBuilder.start();
            InputStreamReader reader = new InputStreamReader(process.getInputStream(), DEFAULT_ENCODING);

            char[] buffer = new char[BUFFER_SIZE];
            int length;
            while ((length = reader.read(buffer)) != -1) {
                log.info("command:{},rowOutput:\n{}", command, new String(buffer, 0, length));
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        throw new RuntimeException("run error");

    }

    public static ExecCmdResult execCmd(String command, int timeoutSecond) {
        long start = System.currentTimeMillis();
        StringBuilder content = new StringBuilder();
        ProcessBuilder processBuilder = new ProcessBuilder(command.split(" "));
        // 合并错误输出流
        processBuilder.redirectErrorStream(true);
        Process process;
        try {
            process = processBuilder.start();
        } catch (IOException e) {
            log.error("execCmd error, execCmd:{}.e:", command, e);
            return new ExecCmdResult(false, -1, command, e.getMessage(), System.currentTimeMillis() - start);
        }

        ProcessWorker processWorker = new ProcessWorker(process);
        int exitCode = processWorker.getExitCode();
        processWorker.start();
        try {
            processWorker.join(TimeUnit.SECONDS.toMillis(timeoutSecond));
            if (processWorker.isCompleted()) {
                content.append(processWorker.getOutput());
                exitCode = processWorker.getExitCode();
            } else {
                process.destroy();
                processWorker.interrupt();
                return new ExecCmdResult(false, processWorker.exitCode, "thread exec timeout", processWorker.getOutput(), System.currentTimeMillis() - start);
            }
        } catch (InterruptedException e) {
            processWorker.interrupt();
        }
        return new ExecCmdResult(exitCode == 0, exitCode, command, content.toString(), System.currentTimeMillis() - start);
    }
}