Java 没有得到 shell 启动程序的输出
Java not getting output of shell-launched program
我有一个用 Java 编写的小型 HTTP 服务器。当它收到“localhost:port/something”形式的 HTTP 请求时,它会调用一个 shell 脚本,该脚本只接受 arg“something”。
然后 shell 脚本自己调用另一个 .jar Java 程序,该程序简单地将“某物”作为 arg,反转字符串,然后将其打印出来。 shell 脚本获取 JAR 程序的输出并将其写出,以便服务器可以接收回该输出(“gnihtemos”)并将其发送到浏览器。
问题是一切正常,但前提是我在 shell 脚本中直接使用“echo”命令。例如,如果我的 shell 脚本是:
#!/bin/bash
echo printthisout
服务器接收“printthisout”作为脚本的输出,然后毫无问题地将其发送回浏览器。
但是如果我将脚本更改为:
#!/bin/bash
java -jar MyJarProgram.jar | xargs echo
没有输出到达服务器。 但是如果我 运行 来自终端的脚本,它工作正常。这意味着 JAR 程序也在运行。更新:相反,如果我直接从 Web 服务器调用 JAR 程序(跳过 shell 脚本),它都不起作用。输出似乎是空的。所以问题似乎是让网络服务器从 JAR 程序中捕获标准输出。
我尝试了所有方法:睡眠、等待、waitFor() 方法、使用 exec() 调用子进程等,但似乎没有任何效果。我很确定我错过了一些非常基本的东西,但真的不知道是什么。
这是调用脚本并取回输出的服务器部分:
String result = "";
try {
Runtime r = Runtime.getRuntime();
String cmd="/path/to/script/script.sh " + req; //req is the request token, "something" in the example above
System.out.println("Command: " + cmd);
ProcessBuilder builder = new ProcessBuilder("bash", cmd);
Process p = builder.start();
BufferedReader in =
new BufferedReader(new InputStreamReader(p.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null) {
System.out.println("Input line: " + inputLine);
result += inputLine;
}
in.close();
System.out.println("Result of script: "+ result);
ps.print("HTTP/1.1 200 OK\r\n");
ps.print("Content-Type: text/html\r\n");
ps.print("\r\n\r\n");
ps.print("<link rel=\"icon\" href=\"data:,\">\r\n");
ps.print(result + "\r\n");
} catch (IOException e) {
System.out.println(e);
}
问题是“inputLine”仍然是空的。
这是脚本调用的 JAR Java 程序:
public static void main(String[] args) {
if(args.length>0) {
StringBuilder sb =new StringBuilder(args[0]);
System.out.println(sb.reverse().toString());
}
}
}
如果你的 MyJarProgram.jar
将它的输出打印到 stderr,它会出现在你的屏幕上,但不会被 xargs 的管道捕获(并且正在被丢弃,因为你正在阅读 p.getInputStream()
,专门读取标准输出)。要么更改您的程序以打印到标准输出;或像这样将其 stderr 重定向到 stdout:
#!/bin/bash
java -jar MyJarProgram.jar "" 2>&1 | xargs echo
我还会删除 | xargs echo
,因为输出会以任何一种方式发回——不需要额外级别的 echo
处理:
#!/bin/bash
java -jar MyJarProgram.jar "" 2>&1
我自己解决了这个问题!
首先我错过了我可以将 ProcessBuilder 的错误重定向到标准输出:
builder.redirectErrorStream(true);
这给了我一个基本的调试解决方案。从那里我发现隐藏的错误是 Java Web 服务器以错误的方式启动脚本。据报道:
"bash: /path/of/script.sh something: File or directory not found"
问题是在实例化 ProcessBuilder 时必须将脚本作为主命令调用,然后将 arg 字符串作为字符串传递,始终在构造函数中:
ProcessBuilder builder = new ProcessBuilder("/path/of/script.sh", req); //Where req is the String thas has to be reversed
我还在启动进程后添加了Process.waitFor()
调用:
Process p = builder.start();
p.waitFor();
这样一切都很好。
我有一个用 Java 编写的小型 HTTP 服务器。当它收到“localhost:port/something”形式的 HTTP 请求时,它会调用一个 shell 脚本,该脚本只接受 arg“something”。
然后 shell 脚本自己调用另一个 .jar Java 程序,该程序简单地将“某物”作为 arg,反转字符串,然后将其打印出来。 shell 脚本获取 JAR 程序的输出并将其写出,以便服务器可以接收回该输出(“gnihtemos”)并将其发送到浏览器。
问题是一切正常,但前提是我在 shell 脚本中直接使用“echo”命令。例如,如果我的 shell 脚本是:
#!/bin/bash
echo printthisout
服务器接收“printthisout”作为脚本的输出,然后毫无问题地将其发送回浏览器。
但是如果我将脚本更改为:
#!/bin/bash
java -jar MyJarProgram.jar | xargs echo
没有输出到达服务器。 但是如果我 运行 来自终端的脚本,它工作正常。这意味着 JAR 程序也在运行。更新:相反,如果我直接从 Web 服务器调用 JAR 程序(跳过 shell 脚本),它都不起作用。输出似乎是空的。所以问题似乎是让网络服务器从 JAR 程序中捕获标准输出。 我尝试了所有方法:睡眠、等待、waitFor() 方法、使用 exec() 调用子进程等,但似乎没有任何效果。我很确定我错过了一些非常基本的东西,但真的不知道是什么。
这是调用脚本并取回输出的服务器部分:
String result = "";
try {
Runtime r = Runtime.getRuntime();
String cmd="/path/to/script/script.sh " + req; //req is the request token, "something" in the example above
System.out.println("Command: " + cmd);
ProcessBuilder builder = new ProcessBuilder("bash", cmd);
Process p = builder.start();
BufferedReader in =
new BufferedReader(new InputStreamReader(p.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null) {
System.out.println("Input line: " + inputLine);
result += inputLine;
}
in.close();
System.out.println("Result of script: "+ result);
ps.print("HTTP/1.1 200 OK\r\n");
ps.print("Content-Type: text/html\r\n");
ps.print("\r\n\r\n");
ps.print("<link rel=\"icon\" href=\"data:,\">\r\n");
ps.print(result + "\r\n");
} catch (IOException e) {
System.out.println(e);
}
问题是“inputLine”仍然是空的。
这是脚本调用的 JAR Java 程序:
public static void main(String[] args) {
if(args.length>0) {
StringBuilder sb =new StringBuilder(args[0]);
System.out.println(sb.reverse().toString());
}
}
}
如果你的 MyJarProgram.jar
将它的输出打印到 stderr,它会出现在你的屏幕上,但不会被 xargs 的管道捕获(并且正在被丢弃,因为你正在阅读 p.getInputStream()
,专门读取标准输出)。要么更改您的程序以打印到标准输出;或像这样将其 stderr 重定向到 stdout:
#!/bin/bash
java -jar MyJarProgram.jar "" 2>&1 | xargs echo
我还会删除 | xargs echo
,因为输出会以任何一种方式发回——不需要额外级别的 echo
处理:
#!/bin/bash
java -jar MyJarProgram.jar "" 2>&1
我自己解决了这个问题! 首先我错过了我可以将 ProcessBuilder 的错误重定向到标准输出:
builder.redirectErrorStream(true);
这给了我一个基本的调试解决方案。从那里我发现隐藏的错误是 Java Web 服务器以错误的方式启动脚本。据报道:
"bash: /path/of/script.sh something: File or directory not found"
问题是在实例化 ProcessBuilder 时必须将脚本作为主命令调用,然后将 arg 字符串作为字符串传递,始终在构造函数中:
ProcessBuilder builder = new ProcessBuilder("/path/of/script.sh", req); //Where req is the String thas has to be reversed
我还在启动进程后添加了Process.waitFor()
调用:
Process p = builder.start();
p.waitFor();
这样一切都很好。