如何将groovy作为一个单独的进程从Java运行?
我试图在java程序中作为一个单独的进程运行groovy脚本(以避免jar冲突问题) 这就是我到目前为止所做的:如何将groovy作为一个单独的进程从Java运行?,java,groovy,process,Java,Groovy,Process,我试图在java程序中作为一个单独的进程运行groovy脚本(以避免jar冲突问题) 这就是我到目前为止所做的: public static void runGroovyScript(Path scriptPath, String... args) { try { List<String> argsList = newArrayList(); argsList.add("groovy"); argsList.add(script
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);
}
}
publicstaticvoid runGroovyScript(路径scriptPath,字符串…args){
试一试{
List argsList=newArrayList();
argsList.add(“groovy”);
argsList.add(scriptPath.toabsolutionPath().toString());
Collections.addAll(argsList,args);
Process Process=Runtime.getRuntime().exec(argsList.toArray(新字符串[argsList.size()]);
//注:输出输入是过程的输出
字符串输入=Streams.asString(process.getInputStream());
字符串错误=Streams.asString(process.getErrorStream());
logger.info(“Groovy输出用于“+数组.toString(args)+”\r\n“+输入);
logger.info(“Groovy错误用于“+数组.toString(args)+”\r\n“+错误);
int returnValue=process.waitFor();
如果(返回值!=0){
抛出新的RuntimeException(“Groovy进程返回”+returnValue);
}
}捕获(可丢弃的e){
抛出新的RuntimeException(“运行构建脚本失败:“+scriptPath+”+Joiner.on(“”).join(args),e);
}
}
当然,问题是
groovy
不是一个可识别的命令。由于环境变量PATH
以及cmd.exe的解析功能,它可以从命令行工作。在linux上,有一种不同的解析机制。为了将groovy可执行文件传递给Runtime.exec()
,查找groovy可执行文件的平台无关方法是什么?一种干净的方法是将可执行文件的绝对路径作为某种配置参数传递给应用程序
您也可以解析PATH
环境变量并自行搜索,但是:
- 不同的平台可以有不同的机制来搜索可执行文件。例如,他们使用不同的,你需要处理
- 这是一种安全问题。攻击者可以向您的程序传递指向名为
的恶意程序的groovy
环境变量PATH
我建议采取不同的方法。您可以使用单独的类加载器来加载groovy脚本。优点:
您还可以将其与Java脚本API结合使用。这也许是最健壮、最灵活的解决方案。有关此信息,请参见
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);
}
}
}
import com.google.common.base.Joiner;
导入org.apache.commons.lang.SystemUtils;
导入org.apache.log4j.Logger;
导入java.nio.file.Path;
导入java.util.array;
导入java.util.Collections;
导入java.util.List;
导入静态com.google.common.collect.Lists.newArrayList;
导入静态org.apache.ivy.util.Checks.checkNotNull;
公共类GroovyRunner{
私有最终静态记录器Logger=LoggerHelper.getLogger();
公共静态void runGroovyScript(路径scriptPath,字符串…args){
试一试{
List argsList=newArrayList();
字符串groovyPath=System.getenv(“PLAY_GROOVY_PATH”);
if(SystemUtils.IS\u OS\u WINDOWS){
//窗口,没有简单的PLAY\u GROOVY\u路径默认值
checkNotNull(groovyPath,“缺少环境变量‘PLAY_GROOVY_PATH’”);
argsList.add(“cmd”);
argsList.add(“/c”);
argsList.add(groovyPath);
}否则{
if(groovyPath==null){
//为linux提供合理的默认值
groovyPath=“/usr/bin/groovy”;
}
argsList.add(groovyPath);
}
argsList.add(scriptPath.toabsolutionPath().toString());
Collections.addAll(argsList,args);
字符串join=Collections3.join(argsList,“”);
ExecCommand process=新的ExecCommand(join);
//注:输出输入是过程的输出
字符串输出=process.getOutput();
字符串错误=process.getError();
logger.info(“Groovy输出用于“+数组.toString(args)+”\r\n“+输出);
logger.info(“Groovy错误用于“+数组.toString(args)+”\r\n“+错误);
if(process.getReturnValue()!=0){
抛出新的RuntimeException(“Groovy进程返回”+process.getReturnValue());
}
}捕获(可丢弃的e){
抛出新的RuntimeException(“运行groovy脚本失败:“+scriptPath+”+Joiner.on(“”).join(args),e);
}
}
}
允许远程执行沙盒代码。看看。我想这应该能回答你的问题:@SamuelAudet-我不确定它是否有。好吧,也许你不熟悉java.home
系统属性,它包含bin
目录下的java
可执行文件?我们实际上使用了另一个类加载器,但没有雪茄。我们所做的是在系统变量中定义groovy可执行文件的位置,并为Windows添加“cmd/c”。我会把我们的密码贴出来作为答案。