java执行linux和windows脚本工具类

我们有时候会

在java代码中,去执行一个linux shell脚本或者windows触发执行一个.bat脚本

本文章,会写一个通用的脚本工具类,通过这个工具类,可以在java代码中,调用linux shell脚本,或者window .bat脚本。

 

比如我们数据平台,有一个数据分析工具,当数据分析工程师,通过我们的工具,配置了某一个数据分析任务,后台的injector进程会监测到这个job,然后会调用shell脚本,去集群上执行我们的MapReduce程序。

本工具类就是实现如何java中调用linux  shell脚本的, 当然windows 也是支持的。

 

首先定义一下结果类:

public class CommandResult {
    public static final int EXIT_VALUE_TIMEOUT=-1;
    int exitValue;
    private String output;
    private String error;


    public int getExitValue() {
        return exitValue;
    }

    public void setExitValue(int exitValue) {
        this.exitValue = exitValue;
    }

    public String getOutput() {
        return output;
    }

    public void setOutput(String output) {
        this.output = output;
    }

    public String getError() {
        return error;
    }

    public void setError(String error) {
        this.error = error;
    }
}

接下来 ,写我们 核心的CommandUtils工具类

public class CommandUtils {
    public static Logger logger = LoggerFactory.getLogger(CommandUtils.class);
    public static int DEFAULT_TIMEOUT=1000;
    public static final int DEFAULT_INTERVAL=100;
    public static long startTime ;
    public static CommandResult exec(String command){
        startTime = System.nanoTime();
        Process process=null;
        CommandResult commandResult =null;
        try {
            if (null == command || "".equals(command = command.trim())) {
                commandResult = new CommandResult() ;
                commandResult.setExitValue(1);
                commandResult.setError("command is not empty");
            }
            String[] cmd;
            String osName = System.getProperty("os.name");
            if (osName.startsWith("Windows")) {
                cmd = new String[3];
                if (osName.equals("Windows 95")) { // windows 95 only
                    cmd[0] = "command.com";
                } else {
                    cmd[0] = "cmd.exe";
                }
                cmd[1] = "/C";
                cmd[2] = command;
            } else if (osName.equals("Linux")) {  //linux
                cmd = new String[3];
                cmd[0] = "/bin/sh";
                cmd[1] = "-c";
                cmd[2] = command;
            } else {
                cmd = new String[1];
                cmd[0] = command;
            }
             process= Runtime.getRuntime().exec(cmd);
             commandResult = wait(process);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }finally {
            if (process!=null){
                process.destroy();
            }
            return commandResult;
        }
    }
//判断是否超时
    public static  boolean isOverTime(){
        return  (TimeUnit.MILLISECONDS.toNanos(DEFAULT_TIMEOUT) - (System.nanoTime() - startTime)) < 0;
    }

    public static CommandResult wait(Process process) throws InterruptedException, IOException {
        BufferedReader errorStreamReader = null;
        BufferedReader inputStreamReader = null;
        try {
            errorStreamReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
            inputStreamReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
            boolean isFinished = false;
            while (true) {  //这是一个死循环,直到超时,或者command 执行完成
                if (isOverTime()) {  //如果超时 ,直接返回
                    CommandResult result = new CommandResult();
                    result.setExitValue(CommandResult.EXIT_VALUE_TIMEOUT);
                    result.setOutput("Command process timeout");
                    return result;
                }
                if (isFinished) {
                    CommandResult result = new CommandResult();
                    result.setExitValue(process.waitFor());
                    //  error info 
                    if (errorStreamReader.ready()) {  
                        StringBuilder buffer = new StringBuilder();
                        String line;
                        while ((line = errorStreamReader.readLine()) != null) {
                            buffer.append(line);
                        }
                        result.setError(buffer.toString());
                    }
                    //  info
                    if (inputStreamReader.ready()) {
                        StringBuilder buffer = new StringBuilder();
                        String line;
                        while ((line = inputStreamReader.readLine()) != null) {
                            buffer.append(line);
                        }
                        result.setOutput(buffer.toString());
                    }
                    return result;
                }
                try {
                    isFinished = true;     //很乐观的认为command 已经执行完成了 ,将isFinished 赋值为true
                    process.exitValue();   //这个方法,command 没有执行完成的时候会抛出异常IllegalThreadStateException被catch捕获,如果执行完成 则isFinished =true
                } catch (IllegalThreadStateException e) {
                    //  hasn't finished yet
                    isFinished = false;  //执行到这里,说明command 没有执行完成,那么将isFinished 重新设置为false;
                    Thread.sleep(DEFAULT_INTERVAL);  //如果command 没有执行完成,可以睡眠 DEFAULT_INTERVAL 
                }
            }
        } finally {
            if (errorStreamReader != null) {
                try {
                    errorStreamReader.close();
                } catch (IOException e) {
                }
            }
            if (inputStreamReader != null) {
                try {
                    inputStreamReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

最后是我们的命令执行调用类:

public class InvokeCommand {

    public static void main(String[] args) {
        String win = "C:\\Users\\zhang\\xxx.bat";
        String lin = "/user/run.sh";

        int timeout = Integer.parseInt("5000");
        CommandUtils.DEFAULT_TIMEOUT = timeout;
        CommandResult result = CommandUtils.exec(win);
        if (result != null)
        {
            if (result.getError()!=null) {
                System.out.println("Error:" + result.getError());
            }
            if (result.getOutput()!=null) {
                System.out.println("Output:" + result.getOutput());
            }
        }

    }
}

上面测试了一下,win平台下的效果,结果发现.bat文件可以正常调用,并返回结果。

 

xxx.bat文件内容为: @echo hello boy!

 

下面为测试返回结果:

java执行linux和windows脚本工具类_第1张图片

你可能感兴趣的:(linux/shell基础,java基础)