0

自動テスト用にいくつかのシェル スクリプトを実行するために、Process と Runtime を組み込んだ Java プログラムに取り組んでいます。これらのスクリプトは 1 つを除いてすべて正常に実行されるため、それに続くスクリプト呼び出しで問題が発生します。元:

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

A.sh は正常に実行され、実行に数秒しかかかりません。ただし、B.sh の実行には数分かかります。これが C.sh の実行に問題を引き起こしていると思います。これは、両方が同じ MySQL テーブルと対話し、重複によって通信リンク障害が発生するためです。

不必要な情報であなたを過負荷にすることなく、私の質問は、次の exec() 呼び出しに移る前に、実行シェルスクリプトが完了/終了まで実行されたことを確認するにはどうすればよいですか?

私が試したこと:

process.waitFor()

これは機能しません。スクリプトが完全に完了するまで待たないと思います

process.wait(long time_period)

現在のスレッドが待機し、残りのシェル スクリプト呼び出しがスキップされ、次のテスト ケースが時期尚早に開始されるため、これは機能しません。

問題の原因となるシェル スクリプトは単純なスクリプトではありませんが、自分で書いたわけではなく、その背後で何をしているのかほとんど理解していません。私が持っている唯一の関連情報は、問題の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.sh 開始」と「テスト 2 開始」というログに記録されたステートメントの間の時間は本質的に同じ瞬間であるため、私のログは、シェル スクリプトが実際に実行されたことを示唆するものではありません。実行は決して起こりません。どこで私は間違えましたか?

4

1 に答える 1

2

私はApache Commons Execを使用しています。同期および非同期の実行をサポートします。実行タイムアウトを設定できます。

チュートリアルページの最初の段落:

この時点で、Java アプリケーション内からいくつかのサブプロセスを開始したいと考えており、適切に実行するためにここで時間を費やしたと想定できます。Commons Exec を見て、「うわー、Runtime.exec() を呼び出すのは簡単なのに、Apache 関係者は大量のコードで時間を無駄にしている」と思います。まあ、私たちは、プレーンな Runtime.exec() を使用するのが苦痛な経験になる可能性があることを難しい方法で (私の場合は 2 回以上) 学びました。したがって、あなたは 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 に答える