无法从 java 程序执行 R 脚本?
not able to execute R script from java program?
我在字符串变量中有一个 Rscript,我想从 Java 程序中执行它并向它传递一些变量。如果我独立执行该 R 脚本,它工作正常。我通过使用 Python 程序转义所有内容,将 R 脚本转换为一行,如下所示:
import json
jsonstr = json.dumps({"script": """\
#!/usr/bin/Rscript
# read the data file
library('jsonlite')
library('rpart')
args <- as.list(Sys.getenv(c(
"path",
"client_users")))
if (args[["path"]]==""){
args[["path"]] <- "."
}
# other stuff here
# other stuff here
"""})
print jsonstr
我使用输出的字符串并将其存储在 String 变量中,然后我使用以下代码执行,但它根本不起作用。我正在将 path
和 client_users
变量传递给上面的 R 脚本。
public static void main(String[] args) throws IOException, InterruptedException {
// this is your script in a string
// String script = "#!/bin/bash\n\necho \"Hello World\"\n\n readonly PARAM1=$param1\n echo $PARAM1\n\nreadonly PARAM2=$param2\n echo $PARAM2\n\n";
String script = "above R Script here";
List<String> commandList = new ArrayList<>();
commandList.add("/bin/bash");
ProcessBuilder builder = new ProcessBuilder(commandList);
builder.environment().put("path", "/home/david");
builder.environment().put("client_users", "1000");
builder.redirectErrorStream(true);
Process shell = builder.start();
// Send your script to the input of the shell, something
// like doing cat script.sh | bash in the terminal
try(OutputStream commands = shell.getOutputStream()) {
commands.write(script.getBytes());
}
// read the outcome
try(BufferedReader reader = new BufferedReader(new InputStreamReader(shell.getInputStream()))) {
String line;
while((line = reader.readLine()) != null) {
System.out.println(line);
}
}
// check the exit code
int exitCode = shell.waitFor();
System.out.println("EXIT CODE: " + exitCode);
}
以上代码适用于 bash shell 脚本。我需要为 R 脚本做些什么吗?我将为 bash 脚本和 R 脚本使用相同的代码。
这是我得到的错误:
/bin/bash: line 7: -: No such file or directory /bin/bash: line 10: syntax error near unexpected token `'jsonlite'' /bin/bash: line 10: `library('jsonlite')'
如果我删除 commandList.add("/bin/bash");
并添加 commandList.add("/bin/Rscript");
然后我会看到以下错误:
Cannot run program "/bin/Rscript": error=2, No such file or directory
更新:-
我没有使用上面的脚本,而是决定在 r 中使用简单的 print hell 脚本,看看我是否可以通过 Java 执行它。
// this will print hello
String script = "#!/usr/bin/env Rscript\nsayHello <- function(){\n print('hello')\n}\n\nsayHello()\n";
当我使用 commandList.add("/bin/bash");
执行此脚本时,出现此错误:
/bin/bash: line 2: syntax error near unexpected token `('
/bin/bash: line 2: `sayHello <- function(){'
但是如果我用这个 commandList.add("/bin/sh");
执行,我会得到这个错误:
/bin/sh: 2: Syntax error: "(" unexpected
您必须直接 运行 /usr/bin/Rscript
。此外,该程序不会从标准输入中读取脚本(您必须将脚本的路径指定为 Rscript
的参数),因此您必须:
- 创建一个临时文件
- 编写脚本
- 使用 Rscript 执行脚本
- 删除您的临时文件(作为一种良好的编程习惯)
例如,这是一个 POC:
public static void main(String[] args) throws IOException, InterruptedException {
// Your script
String script = "#!/usr/bin/env Rscript\n" +
"\n" +
"sayHello <- function() {\n" +
" print('hello')\n" +
"}\n" +
"\n" +
"sayHello()\n";
// create a temp file and write your script to it
File tempScript = File.createTempFile("test_r_scripts_", "");
try(OutputStream output = new FileOutputStream(tempScript)) {
output.write(script.getBytes());
}
// build the process object and start it
List<String> commandList = new ArrayList<>();
commandList.add("/usr/bin/Rscript");
commandList.add(tempScript.getAbsolutePath());
ProcessBuilder builder = new ProcessBuilder(commandList);
builder.redirectErrorStream(true);
Process shell = builder.start();
// read the output and show it
try(BufferedReader reader = new BufferedReader(
new InputStreamReader(shell.getInputStream()))) {
String line;
while((line = reader.readLine()) != null) {
System.out.println(line);
}
}
// wait for the process to finish
int exitCode = shell.waitFor();
// delete your temp file
tempScript.delete();
// check the exit code (exit code = 0 usually means "executed ok")
System.out.println("EXIT CODE: " + exitCode);
}
作为替代方案,并且如果您的脚本将 "shebang" 作为第一行,您可以进行以下更改:
- 将其可执行属性设置为"true"
- 使用临时文件的路径作为 commandList 中的第一个元素(即删除
commandList.add("/usr/bin/Rscript");
)
要修改的部分代码为:
...
// create a temp file and write your script to it
File tempScript = File.createTempFile("test_r_scripts_", "");
tempScript.setExecutable(true);
try(OutputStream output = new FileOutputStream(tempScript)) {
output.write(script.getBytes());
}
// build the process object and start it
List<String> commandList = new ArrayList<>();
commandList.add(tempScript.getAbsolutePath());
ProcessBuilder builder = new ProcessBuilder(commandList);
...
我在字符串变量中有一个 Rscript,我想从 Java 程序中执行它并向它传递一些变量。如果我独立执行该 R 脚本,它工作正常。我通过使用 Python 程序转义所有内容,将 R 脚本转换为一行,如下所示:
import json
jsonstr = json.dumps({"script": """\
#!/usr/bin/Rscript
# read the data file
library('jsonlite')
library('rpart')
args <- as.list(Sys.getenv(c(
"path",
"client_users")))
if (args[["path"]]==""){
args[["path"]] <- "."
}
# other stuff here
# other stuff here
"""})
print jsonstr
我使用输出的字符串并将其存储在 String 变量中,然后我使用以下代码执行,但它根本不起作用。我正在将 path
和 client_users
变量传递给上面的 R 脚本。
public static void main(String[] args) throws IOException, InterruptedException {
// this is your script in a string
// String script = "#!/bin/bash\n\necho \"Hello World\"\n\n readonly PARAM1=$param1\n echo $PARAM1\n\nreadonly PARAM2=$param2\n echo $PARAM2\n\n";
String script = "above R Script here";
List<String> commandList = new ArrayList<>();
commandList.add("/bin/bash");
ProcessBuilder builder = new ProcessBuilder(commandList);
builder.environment().put("path", "/home/david");
builder.environment().put("client_users", "1000");
builder.redirectErrorStream(true);
Process shell = builder.start();
// Send your script to the input of the shell, something
// like doing cat script.sh | bash in the terminal
try(OutputStream commands = shell.getOutputStream()) {
commands.write(script.getBytes());
}
// read the outcome
try(BufferedReader reader = new BufferedReader(new InputStreamReader(shell.getInputStream()))) {
String line;
while((line = reader.readLine()) != null) {
System.out.println(line);
}
}
// check the exit code
int exitCode = shell.waitFor();
System.out.println("EXIT CODE: " + exitCode);
}
以上代码适用于 bash shell 脚本。我需要为 R 脚本做些什么吗?我将为 bash 脚本和 R 脚本使用相同的代码。
这是我得到的错误:
/bin/bash: line 7: -: No such file or directory /bin/bash: line 10: syntax error near unexpected token `'jsonlite'' /bin/bash: line 10: `library('jsonlite')'
如果我删除 commandList.add("/bin/bash");
并添加 commandList.add("/bin/Rscript");
然后我会看到以下错误:
Cannot run program "/bin/Rscript": error=2, No such file or directory
更新:-
我没有使用上面的脚本,而是决定在 r 中使用简单的 print hell 脚本,看看我是否可以通过 Java 执行它。
// this will print hello
String script = "#!/usr/bin/env Rscript\nsayHello <- function(){\n print('hello')\n}\n\nsayHello()\n";
当我使用 commandList.add("/bin/bash");
执行此脚本时,出现此错误:
/bin/bash: line 2: syntax error near unexpected token `('
/bin/bash: line 2: `sayHello <- function(){'
但是如果我用这个 commandList.add("/bin/sh");
执行,我会得到这个错误:
/bin/sh: 2: Syntax error: "(" unexpected
您必须直接 运行 /usr/bin/Rscript
。此外,该程序不会从标准输入中读取脚本(您必须将脚本的路径指定为 Rscript
的参数),因此您必须:
- 创建一个临时文件
- 编写脚本
- 使用 Rscript 执行脚本
- 删除您的临时文件(作为一种良好的编程习惯)
例如,这是一个 POC:
public static void main(String[] args) throws IOException, InterruptedException {
// Your script
String script = "#!/usr/bin/env Rscript\n" +
"\n" +
"sayHello <- function() {\n" +
" print('hello')\n" +
"}\n" +
"\n" +
"sayHello()\n";
// create a temp file and write your script to it
File tempScript = File.createTempFile("test_r_scripts_", "");
try(OutputStream output = new FileOutputStream(tempScript)) {
output.write(script.getBytes());
}
// build the process object and start it
List<String> commandList = new ArrayList<>();
commandList.add("/usr/bin/Rscript");
commandList.add(tempScript.getAbsolutePath());
ProcessBuilder builder = new ProcessBuilder(commandList);
builder.redirectErrorStream(true);
Process shell = builder.start();
// read the output and show it
try(BufferedReader reader = new BufferedReader(
new InputStreamReader(shell.getInputStream()))) {
String line;
while((line = reader.readLine()) != null) {
System.out.println(line);
}
}
// wait for the process to finish
int exitCode = shell.waitFor();
// delete your temp file
tempScript.delete();
// check the exit code (exit code = 0 usually means "executed ok")
System.out.println("EXIT CODE: " + exitCode);
}
作为替代方案,并且如果您的脚本将 "shebang" 作为第一行,您可以进行以下更改:
- 将其可执行属性设置为"true"
- 使用临时文件的路径作为 commandList 中的第一个元素(即删除
commandList.add("/usr/bin/Rscript");
)
要修改的部分代码为:
...
// create a temp file and write your script to it
File tempScript = File.createTempFile("test_r_scripts_", "");
tempScript.setExecutable(true);
try(OutputStream output = new FileOutputStream(tempScript)) {
output.write(script.getBytes());
}
// build the process object and start it
List<String> commandList = new ArrayList<>();
commandList.add(tempScript.getAbsolutePath());
ProcessBuilder builder = new ProcessBuilder(commandList);
...