java - 等待一系列脚本中的单个 Shell 脚本运行完成后再继续(Java、MySQL、JUnit)

标签 java mysql shell junit

我正在开发一个 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 开始”之间的时间本质上是同一时刻,这意味着大约 2 分钟的过程shell.sh 运行永远不会发生。我哪里出错了?

最佳答案

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

教程页面的第一段:

At this point we can safely assume that you would like to start some subprocesses from within your Java application and you spent some time here to do it properly. You look at Commons Exec and think "Wow - calling Runtime.exec() is easy and the Apache folks are wasting their and my time with tons of code". Well, we learned it the hard way (in my case more than once) that using plain Runtime.exec() can be a painful experience. Therefore you are invited to delve into commons-exec and have a look at the hard lessons the easy way ...

高级使用示例(缺少一些代码,例如 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);
    }

关于java - 等待一系列脚本中的单个 Shell 脚本运行完成后再继续(Java、MySQL、JUnit),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10141865/

相关文章:

mysql - 如何在mysql的多数据中心复制中维护时区

python - 不小心在 shell 脚本中使用了 mv 并移动了文件。 shell脚本在mac上默认运行在哪里?

bash - 转换行结尾

java - 邮件或浏览失败 IOException

java - 无法单击网站上的少数链接,其余其他链接可以使用 Selenium 单击

php - 关于查找文本的 mysQL 查询帮助

json - 将 JSON 字符串作为输入传递给 aws 命令

java - Applet 中的 Paint 方法(Java 中的排序算法)

Java/JSP - 永久计数器

mysql - mysql 中的 ActiveRecord DATETIME 列值