`
lee79
  • 浏览: 106265 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Java执行Shell脚本超时控制

阅读更多

Java的Runtime可以执行命令行脚本,某些特定场合需要对脚本的执行时间进行控制,防止脚本某些异常情况下,一直未能正确结束,导致Java主进程挂起。本文的程序对这一过程进行了控制

 

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

 

public class CommandUtils {
    private static Logger logger = LoggerFactory.getLogger(CommandUtils.class);

    //default time out, in millseconds
    public static final int DEFAULT_TIMEOUT = 10 * 1000;
    public static final int DEFAULT_INTERVAL = 1000;

    /**
     * Executes the specified command in a separate process. The method then blocks until the process returned.
     * If an error arises during the execution or if the exeecuted process returned an non-null return code,
     * the content of the process' stderr is returned to the caller. If the execution is fine, null is returned.
     *
     * @param command String
     * @return CommandResult
     */
    public static CommandResult exec(String command) {
        long start = System.currentTimeMillis();
        long last;

        CommandResult commandResult = new CommandResult();

        try {
            Process process = Runtime.getRuntime().exec(command);
            process(process, commandResult);

            if (process != null) {
                process.destroy();
            }

            last = (System.currentTimeMillis() - start) / 1000;
            logger.info("Execute command [" + command + "], last [" + last + "] s.");

        } catch (Exception e) {
            last = (System.currentTimeMillis() - start) / 1000;
            String error = "Execute command [" + command + "] last [" + last + "] s, failed [" + e.getMessage() + "]";
            logger.error(error, e);

            commandResult.setExitValue(CommandResult.EXIT_VALUE_UNEXCEPTED);
            commandResult.setErrorOutput(error);
        }

        return commandResult;
    }

    private static void process(Process process, CommandResult commandResult) {
        BufferedReader errorReader = null;
        BufferedReader inputReader = null;

        try {
            errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
            inputReader = new BufferedReader(new InputStreamReader(process.getInputStream()));

            //timeout control
            long start = System.currentTimeMillis();
            boolean processFinished = false;

            while (System.currentTimeMillis() - start < DEFAULT_TIMEOUT && !processFinished) {
                processFinished = true;
                try {
                    process.exitValue();
                } catch (IllegalThreadStateException e) {
                    // process hasn't finished yet
                    processFinished = false;

                    try {
                        Thread.sleep(DEFAULT_INTERVAL);
                    } catch (InterruptedException e1) {
                        logger.error("Process, failed [" + e.getMessage() + "]", e);
                    }
                }
            }

            if (!processFinished) {
                commandResult.setExitValue(CommandResult.EXIT_VALUE_TIMEOUT);
                commandResult.setErrorOutput("Command process timeout");
                return;
            }

            commandResult.setExitValue(process.waitFor());

            StringBuffer sb;
            String line;

            //parse error info
            if (errorReader.ready()) {
                sb = new StringBuffer();
                while ((line = errorReader.readLine()) != null) {
                    sb.append(line);
                }
                commandResult.setErrorOutput(sb.toString());
            }

            //parse info
            if (inputReader.ready()) {
                sb = new StringBuffer();
                while ((line = inputReader.readLine()) != null) {
                    sb.append(line);
                }
                commandResult.setInfoOutput(sb.toString());
            }

        } catch (Exception e) {
            String error = "Command process, failed [" + e.getMessage() + "]";
            logger.error(error, e);

            commandResult.setExitValue(CommandResult.EXIT_VALUE_UNEXCEPTED);
            commandResult.setErrorOutput(error);

        } finally {
            if (errorReader != null) {
                try {
                    errorReader.close();
                } catch (IOException e) {
                    logger.error("Close BufferedReader, failed [" + e.getMessage() + "]", e);
                }
            }

            if (inputReader != null) {
                try {
                    inputReader.close();
                } catch (IOException e) {
                    logger.error("Close BufferedReader, failed [" + e.getMessage() + "]", e);
                }
            }
        }
    }
}

 

分享到:
评论
3 楼 u013246812 2017-06-20  
谢谢博主帮我解决了问题,就是那个process.exitValue()方法是解决问题的关键,我一直没注意点这个方法的执行时抛异常表示子进程还没有执行完。
2 楼 lee79 2009-11-13  
呵呵,讲的很对
1 楼 fangwei 2009-08-17  
非常感谢!!!

btw 你虽然用到了slf4j,却没有用到它的强项
logger.info("Execute command [{}], last [{}] s.",command,last);
如果是遗留问题,可以当我废话

相关推荐

    java运行shell脚本方法示例

    在Java编程中,有时我们需要在程序中执行操作系统级别的任务,比如运行Linux的Shell脚本。这时,我们可以利用Java内置的`Runtime`类的`execute`方法来实现这一目标。本文将详细讲解如何在Java中使用`Runtime.execute...

    java调用shell脚本完美封装

    在Java编程中,有时我们需要与操作系统进行交互,执行一些系统级别的任务,比如自动化运维、文件管理等,这时就可能需要用到调用Shell脚本。本文将详细介绍如何在Java中完美封装shell脚本的调用方法,并提供相关的...

    java在win下启动bat和在linux下启动shell脚本

    在Windows和Linux环境中,启动批处理脚本(bat)和shell脚本(sh)是常见的任务,特别是在自动化和脚本执行过程中。`RunScript.java`和`StreamGobbler.java`这两个文件可能就是用来实现这个功能的。 `RunScript....

    如何用java程序(JSch)运行远程linux主机上的shell脚本

    在Java编程中,有时我们需要远程执行Linux主机上的shell脚本,这通常涉及到SSH(Secure Shell)协议。JSch(Java Secure Channel)是一个纯Java实现的SSH2库,它允许Java应用程序连接到SSH服务器并执行各种操作,...

    Java 执行本地脚本携带多参数

    首先,Java提供了一个内置的`java.lang.Runtime`类,它可以让我们与运行Java虚拟机的同一操作系统进行交互,包括执行系统命令。我们可以使用`Runtime.getRuntime().exec()`方法来执行外部命令或脚本。例如,如果你有...

    利用Python+Java调用Shell脚本时的死锁陷阱详解

    在IT领域,尤其是在系统自动化和任务调度中,经常需要通过编程语言调用Shell脚本来执行特定的任务,例如在本例中触发Spark作业。本文将详细探讨如何使用Python和Java调用Shell脚本,并着重讲解在调用过程中可能出现...

    linux shell的java操作实现

    除了基础的命令执行,还可以实现更复杂的Shell脚本执行,例如通过`channel.setCommand("bash your_script.sh")`来执行存储在远程服务器上的Shell脚本。同时,还可以使用JSch的SCP或SFTP功能进行文件的上传和下载。 ...

    shell 管理SpringBoot 生产环境服务-转载

    标题中的“shell管理SpringBoot生产环境服务”表明我们要探讨的是如何使用Linux Shell脚本来启动、停止和管理在生产环境中运行的Spring Boot应用。Spring Boot是一个轻量级的Java框架,它简化了创建独立的、生产级别...

    JavaShellCommand:用于在 windows 和 linux 上执行 shell 命令的 Java 实用程序

    在Windows上,它可能会使用批处理命令,而在Linux上则使用bash或其他shell脚本。 2. **API设计**:项目可能提供了一个简洁的API,例如`executeCommand(String command)`方法,开发者只需要传入要执行的命令字符串,...

    fastdfs一键安装脚本

    - **Shell**:这里提到的脚本是用Shell语言编写,Shell是Unix/Linux系统中的命令解释器,可以用来编写自动化任务脚本。 【总结】 FastDFS的一键安装脚本极大地简化了部署流程,使得开发者能够快速搭建文件存储系统...

    jdbc-avail-wait:简单的Java命令行应用程序(将在shell脚本中使用),等待指定的JDBC URL(用户名和密码)可用

    一个非常简单的命令行实用程序,它可以等待直到指定的JDBC连接可以访问或等待时间超时。 动机 假设您要使用数据库(oracle)启动docker容器,同时您要使用tomcat启动另一个容器,该容器的数据源正在使用oracle容器...

    tomcat健康检查脚本文件异常发送邮件通知.rar

    在这个场景中,脚本会定期执行一系列检查,例如通过查看Tomcat的日志文件、检查进程状态或者监听端口是否正常来判断Tomcat是否运行正常。如果检测到任何异常,比如Tomcat服务挂起或者响应超时,脚本会触发邮件通知...

    某银行用了10多年的Java-jar启停脚本(超详细).zip

    某银行用了10多年的Java启动脚本,包括运行状态检查,如果程序正在运行则杀死,杀死期间循环检查,直到杀死或者杀死超时,然后重新启动,如果程序没有运行则直接启动,启动期间每间隔一定时间检测一次,直到启动成功或者超时...

    一个java tcp服务器的基础框架

    在Unix系统上,这可能是一个Shell脚本;在Windows上,可能是批处理文件。这个脚本通常会设置环境变量,然后调用Java虚拟机(JVM)启动服务器主类。 总结,这个“Java TCP服务器的基础框架”是一个利用Java NIO构建...

    Kettle简单参数化配置连接数据库

    2. **运行Shell脚本**:通过命令行运行此脚本,传递参数值: ``` sh sh执行kettle文件.sh mydatabase.example.com admin secret ``` 3. **调度任务**:为了定期执行,可以将这个脚本添加到cron定时任务中,根据...

    shell连接不上linux虚拟机解决方案

    有时,环境变量配置不当也会导致Shell脚本或程序运行异常,影响SSH连接。 **解决方案:** 确保关键环境变量如`PATH`, `LD_LIBRARY_PATH`, `TCL_LIBRARY`等设置正确。编辑用户主目录下的`.bashrc`文件,添加或修改...

    java开发常见错误

    在编写Shell脚本时,可能会遇到语法错误、命令执行错误、变量使用不当等问题。比如,未正确使用引号导致命令解析错误,忘记在命令行末尾添加分号或换行符,或者在使用变量时未正确引用。为了避免这些错误,开发者...

    java开源包4

    MyBatchFramework 是一个开源的轻量级的用以创建可靠的易管理的批量作业的Java包,主要特点是多线程、调度、JMX管理和批量执行报表,执行历史等。 SIP协议包 jSIP.tar jSIP这个Java包目标是用Java实现SIP(SIP:...

    java开源包101

    MyBatchFramework 是一个开源的轻量级的用以创建可靠的易管理的批量作业的Java包,主要特点是多线程、调度、JMX管理和批量执行报表,执行历史等。 SIP协议包 jSIP.tar jSIP这个Java包目标是用Java实现SIP(SIP:...

Global site tag (gtag.js) - Google Analytics