2

Java プログラム内から別のプロセスとして (jar の衝突の問題を回避するために) グルーヴィーなスクリプトを実行しようとしています。

これは私がこれまでに持っているものです:

public static void runGroovyScript(Path scriptPath, String... args) {
    try {
        List<String> argsList = newArrayList();
        argsList.add("groovy");
        argsList.add(scriptPath.toAbsolutePath().toString());
        Collections.addAll(argsList, args);

        Process process = Runtime.getRuntime().exec(argsList.toArray(new String[argsList.size()]));
        // Note - out input is the process' output
        String input = Streams.asString(process.getInputStream());
        String error = Streams.asString(process.getErrorStream());

        logger.info("Groovy output for " + Arrays.toString(args) + "\r\n" + input);
        logger.info("Groovy error for " + Arrays.toString(args) + "\r\n" + error);

        int returnValue = process.waitFor();
        if (returnValue != 0) {
            throw new RuntimeException("Groovy process returned " + returnValue);
        }
    } catch (Throwable e) {
        throw new RuntimeException("Failure running build script: " + scriptPath + " " + Joiner.on(" ").join(args), e);
    }
}

もちろん、問題はgroovy認識されたコマンドではないことです。PATH環境変数と cmd.exe の解決により、コマンド ラインから動作します。Linux では、別の解決メカニズムがあります。に渡すために、プラットフォームに依存しない Groovy 実行可能ファイルを見つける方法は何Runtime.exec()ですか?

4

3 に答える 3

1

クリーンな方法は、実行可能ファイルの絶対パスを何らかの構成パラメーターとしてアプリケーションに渡すことです。

環境変数を解析PATHして自分で検索することもできますが、次のようになります。

  • プラットフォームが異なれば、実行可能ファイルを検索するメカニズムも異なります。たとえば、それらは異なるパス区切り文字を使用しているため、それに対処する必要があります。
  • これは一種のセキュリティ上の問題です。攻撃者はPATH、悪意のあるプログラムgroovy.

別のアプローチを取ることをお勧めします。Groovy スクリプトをロードするために別の ClassLoader を使用できます。利点:

  1. JAR 衝突の問題も回避できます。
  2. ただし、外部プロセスを生成する必要はありません。
  3. カスタムSecurityManagerを使用して、スクリプトが実行できるアクションを制限することもできます。
  4. 標準入力/出力の代わりにメソッド呼び出しを使用して、スクリプトとの通信を改善できます。

以下も参照してください。


Java Scripting API と組み合わせることもできます。これは、おそらく最も堅牢で柔軟なソリューションです。これについては、を参照してください。

于 2012-08-28T12:38:56.473 に答える
1

java-sandboxを使用すると、サンドボックス化されたコードをリモートで実行できます。http://blog.datenwerke.net/2013/06/sandboxing-groovy-with-java-sandbox.htmlをご覧ください。

于 2013-06-14T13:43:56.003 に答える
0

実際には別のクラスローダーをいじりましたが、葉巻はありませんでした。システム変数で groovy 実行可能ファイルの場所を定義し、Windows 用に「cmd /c」を追加しました。

import com.google.common.base.Joiner;
import org.apache.commons.lang.SystemUtils;
import org.apache.log4j.Logger;

import java.nio.file.Path;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import static com.google.common.collect.Lists.newArrayList;
import static org.apache.ivy.util.Checks.checkNotNull;

public class GroovyRunner {
    private final static Logger logger = LoggerHelper.getLogger();

    public static void runGroovyScript(Path scriptPath, String... args) {
        try {
            List<String> argsList = newArrayList();
            String groovyPath = System.getenv("PLAY_GROOVY_PATH");

            if (SystemUtils.IS_OS_WINDOWS) {
                // Window, no easy default for PLAY_GROOVY_PATH
                checkNotNull(groovyPath, "Missing Env Var 'PLAY_GROOVY_PATH'");

                argsList.add("cmd");
                argsList.add("/c");
                argsList.add(groovyPath);
            } else {
                if (groovyPath == null) {
                    // Provide a reasonable default for linux
                    groovyPath = "/usr/bin/groovy";
                }
                argsList.add(groovyPath);
            }

            argsList.add(scriptPath.toAbsolutePath().toString());
            Collections.addAll(argsList, args);

            String join = Collections3.join(argsList, " ");

            ExecCommand process = new ExecCommand(join);

            // Note - out input is the process' output
            String output = process.getOutput();
            String error = process.getError();

            logger.info("Groovy output for " + Arrays.toString(args) + "\r\n" + output);
            logger.info("Groovy error for " + Arrays.toString(args) + "\r\n" + error);


            if (process.getReturnValue() != 0) {
                throw new RuntimeException("Groovy process returned " + process.getReturnValue());
            }
        } catch (Throwable e) {
            throw new RuntimeException("Failure running groovy script: " + scriptPath + " " + Joiner.on(" ").join(args), e);
        }
    }
}
于 2012-08-29T07:00:38.260 に答える