当前位置 : 主页 > 编程语言 > c++ >

Shell.java

来源:互联网 收集:自由互联 发布时间:2021-06-30
Shell.java package com.hy.toolsimport org.apache.commons.io.IOUtils;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import java.io.*;import java.lang.reflect.Field;import java.util.concurrent.CountDownLatch;import java.util.concurren
Shell.java
package com.hy.tools

import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.lang.reflect.Field;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * author: houying
 * date  : 17-6-30
 * desc  :
 */
public class Shell {
    private static final Logger logger = LoggerFactory.getLogger(Shell.class);
    private String cmd;
    private String dir;
    private String output;
    private Process process;
    private int processId;
    private int exitCode;
    private CountDownLatch completeLatch;
    private CountDownLatch startLatch;
    private OutputMonitorCallback callback;

    public Shell(String cmd, String dir, String output, OutputMonitorCallback callback) {
        this.cmd = cmd;
        this.dir = dir;
        this.output = output;
        this.callback = callback;
        this.exitCode = -1;
        this.completeLatch = new CountDownLatch(1);
        this.startLatch = new CountDownLatch(1);
    }

    public Shell(String cmd, String dir) {
        this(cmd, dir, null, null);
    }

    public void run(ExecutorService poolExecutor) {
        poolExecutor.execute(shellRunnable());
        poolExecutor.execute(logRunnable());
    }

    public void run() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                logInternal();
            }
        }).start();
        executeInternal();
    }

    public void kill() {
        if (process != null && processId != 0) {
            try {
                Runtime.getRuntime().exec(String.format("kill -15 %s", processId));
                logger.info("kill -15 {}", processId);
            } catch (IOException e) {
                logger.error("Kill attempt failed.", e);
                e.printStackTrace();
            }
            process.destroy();
        }
    }

    public boolean awaitCompletion(long timeout) throws InterruptedException {
        return completeLatch.await(timeout, TimeUnit.MILLISECONDS);
    }

    public void awaitCompletion() throws InterruptedException {
        completeLatch.await();
    }

    public int getExitCode() {
        return exitCode;
    }

    private int processId(final java.lang.Process process) {
        int processId = 0;
        try {
            Field f = process.getClass().getDeclaredField("pid");
            f.setAccessible(true);
            processId = f.getInt(process);
        } catch (Throwable e) {
            e.printStackTrace();
        }
        return processId;
    }

    private void executeInternal() {
        ProcessBuilder builder = new ProcessBuilder(cmd.split(" ")).redirectErrorStream(true)
                .directory(new File(dir));
        try {
            process = builder.start();
            processId = processId(process);
            logger.info("process {} start", processId);
            startLatch.countDown();
            exitCode = process.waitFor();
            logger.info("process {} end, exit code: {}", processId, exitCode);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            logger.warn("process was interrupted");
        } finally {
            if (process != null) {
                IOUtils.closeQuietly(process.getInputStream());
                IOUtils.closeQuietly(process.getOutputStream());
                IOUtils.closeQuietly(process.getErrorStream());
            }
            completeLatch.countDown();
            logger.info("shell exit");
        }
    }

    private void logInternal() {
        BufferedReader reader = null;
        try {
            startLatch.await();
            reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
            if (output != null) {
                writeLog(reader);
            } else {
                printLog(reader);
            }
        } catch (InterruptedException e) {
            logger.error("log thread interrupted");
        } finally {
            IOUtils.closeQuietly(reader);
            logger.info("log thread exit");
        }
    }

    private void printLog(BufferedReader reader) {
        String line;
        try {
            while( (line = reader.readLine()) != null) {
                logger.info("[shell log]: {}", line);
                if (callback != null) {
                    if (!callback.callback(line, Shell.this)) {
                        break;
                    }
                }
            }
        } catch (IOException e) {
            logger.error("日志异常退出", e);
        }
    }

    private void writeLog(BufferedReader reader) {
        BufferedWriter writer = null;
        try {
            writer = new BufferedWriter(new FileWriter(output));
            String line;
            while( (line = reader.readLine()) != null) {
                writer.write(line);
                writer.newLine();
                if (callback != null) {
                    if (!callback.callback(line, Shell.this)) {
                        break;
                    }
                }
            }
        } catch (IOException e) {
            logger.error("写日志异常退出", e.getMessage());
        } finally {
            IOUtils.closeQuietly(writer);
        }
    }

    private Runnable shellRunnable() {
        return new Runnable() {
            public void run() {
                executeInternal();
            }
        };
    }

    private Runnable logRunnable() {
        return new Runnable() {
            public void run() {
                logInternal();
            }
        };
    }
}
网友评论