package cn.reghao.autodop.common.util.shell;

import java.io.*;
import java.util.UUID;

/**
 * @author reghao
 * @date 2019-08-20 23:45:06
 */
public class ShellExecutor {
    private ProcessBuilder pb;

    public ShellExecutor() {
        this.pb = new ProcessBuilder();
    }

    /**
     * 执行 shell 命令/脚本
     *
     * @param cmd shell 命令或脚本
     * @param dir 工作目录
     * @return
     * @date 2020-11-09 下午11:22
     */
    public ShellResult exec(String cmd, String dir) {
        String[] cmdarray = cmd.split("\\s+");
        String output = System.getProperty("java.io.tmpdir") + "/" + UUID.randomUUID().toString() + ".out";
        File ofile = new File(output);

        ShellResult shellResult;
        try {
            ofile.createNewFile();
            pb.command(cmdarray)
                    // 将标准错误合并到标准输出
                    .redirectErrorStream(true)
                    // 将所有输出重定向到文件
                    .redirectOutput(ofile);
            if (dir != null) {
                pb.directory(new File(dir));
            }

            shellResult = exec(pb, ofile);
            ofile.delete();
        } catch (IOException | InterruptedException e) {
            shellResult = new ShellResult(1);
            shellResult.setOutput(e.getMessage());
        }

        return shellResult;
    }

    private ShellResult exec(ProcessBuilder pb, File ofile) throws IOException, InterruptedException {
        Process newProcess = pb.start();
        ProcessHandle handle = newProcess.toHandle();
        // 子进程 PID
        long pid = handle.pid();

        // 父进程等待子进程结束
        int exitCode = newProcess.waitFor();
        ShellResult shellResult = new ShellResult(exitCode);
        shellResult.setExitCode(exitCode);
        shellResult.setOutput(output(ofile));
        return shellResult;
    }

    private String output(File ofile) throws IOException {
        StringBuilder sb = new StringBuilder();
        BufferedReader in =  new BufferedReader(new InputStreamReader(new FileInputStream(ofile)));
        String line;
        while ((line = in.readLine()) != null) {
            sb.append(line).append(System.lineSeparator());
        }
        in.close();
        return sb.toString();
    }
}
