0

我正在开发一个 Java 程序,它结合了 Process 和 Runtime 来运行多个 shell 脚本以进行自动化测试。除了其中一个脚本之外的所有脚本都运行良好,这会导致脚本调用出现问题。前任:

process = runtime.exec("A.sh");
process = runtime.exec("B.sh");
process = runtime.exec("C.sh");

A.sh 运行良好,只需几秒钟即可运行。然而,B.sh 需要几分钟才能运行,我认为这会导致运行 C.sh 出现问题,因为它们都与同一个 MySQL 表进行交互,并且重叠会导致通信链接失败。

在不给您带来不必要的信息的情况下,我的问题是,在继续下一个 exec() 调用之前,我该如何等待以确保运行 shell 脚本已运行到完成/终止?

我试过的:

process.waitFor()

这不起作用,我认为它不会等到脚本完全完成

process.wait(long time_period)

这不起作用,因为它会导致当前线程等待,从而导致剩余的 shell 脚本调用被跳过并且下一个测试用例过早开始。

我调用的导致问题的shell脚本不是一个简单的脚本,而是我自己没有写,对它在幕后做了什么了解很少。我所拥有的唯一相关信息是它直接连接到有问题的 MySQL 数据库,而我的程序使用 java.sql.* 来(我相信)远程连接(尽管它是远程机器上的本地数据库)。

编辑:

遵循建议后,我查看了 Apache Commons Exec 并尝试了一种新策略,但未成功。

ExecuteWatchdog watchdog = new ExecuteWatchdog(300000); //For five minutes
CommandLine cmdline = CommandLine.parse("./directory/shell.sh");
DefaultExecutor executor = setExitValue(0);
executor.setWatchdog(watchdog);
int exitVal = executor.execute(cmdLine);
//A line to log the exit val in another file

我的日志没有暗示 shell 脚本实际上已经运行,因为记录的语句“shell.sh 开始”和“测试 2 开始”之间的时间基本上是同一时刻,这意味着 shell.sh 大约需要 2 分钟的过程跑步永远不会发生。我哪里做错了?

4

1 回答 1

2

我使用Apache Commons Exec。具有同步和异步执行支持。可以设置执行超时。

他们教程页面的第一段:

在这一点上,我们可以放心地假设您希望从 Java 应用程序中启动一些子进程,并且您在这里花了一些时间来正确地完成它。您查看 Commons Exec 并认为“哇 - 调用 Runtime.exec() 很容易,而 Apache 人员正在用大量代码浪费他们和我的时间”。好吧,我们很难(在我的例子中不止一次)了解到使用普通的 Runtime.exec() 可能是一种痛苦的经历。因此,我们邀请您深入研究 commons-exec 并以简单的方式查看艰难的课程......

高级用法示例(缺少一些代码,例如 BusinessException 和“StreamUtil.closeQuietly”,但可以轻松替换):

    ExecuteWatchdog watchdog = new ExecuteWatchdog(EXECUTION_TIMEOUT_IN_MS);
    DefaultExecutor executor = new DefaultExecutor();

    executor.setWatchdog(watchdog);
    executor.setExitValue(0);

    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
    ByteArrayOutputStream errorStream = new ByteArrayOutputStream();

    executor.setStreamHandler(new PumpStreamHandler(outputStream, errorStream));

    try {
        log.info(commandLine.toString());

        int exitCode = executor.execute(commandLine, (Map<?, ?>) null);

        if (exitCode != 0)
            throw new BusinessException("Process exited with non-zero exit code.");

        return outputStream.toString();
    } catch (ExecuteException e) {
        String errorStreamStr = null;

        if (errorStream.size() != 0)
            errorStreamStr = errorStream.toString();

        StringBuilder errorMessageBuilder = new StringBuilder();

        errorMessageBuilder.append("main.error").append(":\n").append(
                e.getMessage()).append("\n\n");

        if (errorStreamStr != null) {
            errorMessageBuilder.append("additional.error").append(":\n").append(errorStreamStr).append("\n\n");
        }

        errorMessageBuilder.append("command.line").append(":\n").append(commandLine.toString());

        if (log.isDebugEnabled())
            log.debug(errorMessageBuilder.toString());

        throw new BusinessException(errorMessageBuilder.toString());
    } catch (IOException e) {
        throw new IllegalStateException(e);
    } finally {
        StreamUtil.closeQuietly(outputStream, errorStream);
    }
于 2012-04-13T13:45:48.510 回答