简体   繁体   English

Java 没有得到 shell 启动程序的 output

[英]Java not getting output of shell-launched program

I have a small HTTP server written in Java. When it receive a HTTP request in the form "localhost:port/something" it calls a shell script that takes as only arg "something".我有一个用 Java 编写的小型 HTTP 服务器。当它收到“localhost:port/something”形式的 HTTP 请求时,它会调用一个 shell 脚本,该脚本仅作为参数“something”。

Then the shell script inside himself calls another.jar Java program that simply takes "something" as arg, reverse the String and then prints it out.然后他自己内部的 shell 脚本调用 another.jar Java 程序,它只是简单地将“something”作为 arg,反转 String 然后打印出来。 The shell script takes the output of the JAR program and writes it out, so that the server can receive back this output ("gnihtemos") and send it to the browser. shell脚本把JAR程序的output写出来,这样服务器就可以接收回这个output(“gnihtemos”),并发送给浏览器。

The problem is that everything works fine but only if inside the shell script I use directly the "echo" command.问题是一切正常,但前提是在 shell 脚本中我直接使用“echo”命令。 So for example if my shell script is:例如,如果我的 shell 脚本是:

#!/bin/bash
echo printthisout

the server receives "printthisout" as output from the script and then sends it back to the browser without any problem.服务器从脚本接收“printthisout”作为 output,然后毫无问题地将其发送回浏览器。

But if I change the script to:但是,如果我将脚本更改为:

#!/bin/bash
java -jar MyJarProgram.jar $1 | xargs echo

No output arrives to the server.没有 output 到达服务器。 But if I run the script from terminal, it works fine.但是如果我从终端运行脚本,它工作正常。 And it means that also the JAR program is working.这意味着 JAR 程序也在运行。 UPDATE: On the opposite,if I call directly the JAR program from the web server (skipping the shell script) it neither works.更新:相反,如果我直接从 web 服务器调用 JAR 程序(跳过 shell 脚本),它都不起作用。 The output seems to be empty. output 似乎是空的。 So the problem seems to be making the web server catching the stdout from the JAR program.所以问题似乎是使 web 服务器从 JAR 程序捕获标准输出。 I tried everything: sleep, wait, waitFor() method, calling the subprocess using exec(), etc., but nothing seems to work.我尝试了所有方法:睡眠、等待、waitFor() 方法、使用 exec() 调用子进程等,但似乎没有任何效果。 I'm pretty sure I'm missing something of very basic, but really have no idea about what.我很确定我错过了一些非常基本的东西,但真的不知道是什么。

This is the part of the server that calls the script and gets the output back:这是调用脚本并返回 output 的服务器部分:

                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);
                }

The problem is that "inputLine" remains empty.问题是“inputLine”仍然是空的。

This is the JAR Java program called by the script:这是脚本调用的JAR Java程序:

    public static void main(String[] args) {
    if(args.length>0) {
        StringBuilder sb =new StringBuilder(args[0]);
        System.out.println(sb.reverse().toString());
    }
  }
}

If your MyJarProgram.jar prints its output to stderr, it would appear on your screen, but would not be captured by the pipe to xargs (and is being dropped because you're reading with p.getInputStream() , which specifically reads stdout).如果您的 MyJarProgram.jar 将其MyJarProgram.jar打印到 stderr,它会出现在您的屏幕上,但不会被 pipe 捕获到 xargs(并且正在被丢弃,因为您正在使用p.getInputStream()读取,它专门读取 stdout) . Either change your program to print to stdout;要么更改您的程序以打印到标准输出; or redirect its stderr to stdout like this:或像这样将其 stderr 重定向到 stdout:

#!/bin/bash
java -jar MyJarProgram.jar "$1" 2>&1 | xargs echo

I'd also drop the | xargs echo我也会放弃| xargs echo | xargs echo as the output would be sent back either way -- no need for an extra level of echo processing: | xargs echo作为 output 将以任何一种方式发回——不需要额外级别的echo显处理:

#!/bin/bash
java -jar MyJarProgram.jar "$1" 2>&1

I solved the problem myself: First of all I was missing I can redirect errout of the ProcessBuilder to stdout with:我自己解决了这个问题:首先我错过了我可以将 ProcessBuilder 的错误重定向到标准输出:

builder.redirectErrorStream(true);

This gave me a basical debugging solution.这给了我一个基本的调试解决方案。 From there I discovered that the hidden error was that the Java web server was launching the script in a wrong way.从那里我发现隐藏的错误是 Java web 服务器以错误的方式启动脚本。 It reported:据报道:

"bash: /path/of/script.sh something: File or directory not found"

The problem is that the script has to be called as main command when instancing the ProcessBuilder, and then pass the arg String as string, always in the constructor:问题是在实例化 ProcessBuilder 时必须将脚本作为主命令调用,然后始终在构造函数中将 arg 字符串作为字符串传递:

ProcessBuilder builder = new ProcessBuilder("/path/of/script.sh", req); //Where req is the String thas has to be reversed

I also added the Process.waitFor() call after starting the process:我还在启动流程后添加了Process.waitFor()调用:

Process p = builder.start();
p.waitFor();

This way everything works well.这样一切都很好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM