2
try {

        String str;
        Process process = Runtime.getRuntime().exec("bash /home/abhishek/workspace/Pro/run");
        InputStream isout = process.getInputStream();
        InputStreamReader isoutr = new InputStreamReader(isout);
        BufferedReader brout = new BufferedReader(isoutr);
        while ((str = brout.readLine()) != null) {
            System.out.println(str);
        }

} catch (IOException e) {
        e.printStackTrace();
}

代码在从进程中获取 InputStream 时存在问题,因为如果我从终端运行 Shell 脚本,它运行得非常好,但是如果我像这样运行脚本,则 str 始终为空,

我正在使用此代码将 Shell 脚本的输出直接转换为 Java,而不是将脚本输出写入文件中

有没有其他方法可以实现这一点,或者如何使用当前方法解决问题

4

6 回答 6

6

我认为通过错误流返回了一些东西,所以你可以尝试从Process.getErrorStream()中检查一些东西。

您还应该等待创建的进程以防止您的主程序在它之前完成。使用Process.waitFor();

public class TestMain {
   private static final String BASH_CMD = "bash";

   private static final String PROG = "/home/abhishek/workspace/Pro/run";

   private static final String[] CMD_ARRAY = { BASH_CMD , PROG };

   public static void main(String[] args) {
      new Thread(new Runnable() {
         public void run() {
            BufferedReader reader = new BufferedReader(new InputStreamReader(
                  System.in));
            String command = null;
            try {
               while ((command = reader.readLine()) != null) {
                  System.out.println("Command Received:" + command);
               }
            } catch (Exception ex) {
               ex.printStackTrace();
               // failed to listening command
            }

         }
      }).start();
      Process process = null;
      try {
         ProcessBuilder processBuilder = new ProcessBuilder(CMD_ARRAY);
         process = processBuilder.start();
         InputStream inputStream = process.getInputStream();
         setUpStreamGobbler(inputStream, System.out);

         InputStream errorStream = process.getErrorStream();
         setUpStreamGobbler(errorStream, System.err);

         System.out.println("never returns");
         process.waitFor();
      } catch (IOException e) {
         throw new RuntimeException(e);
      } catch (InterruptedException e) {
         throw new RuntimeException(e);
      }
   }

   public static void setUpStreamGobbler(final InputStream is, final PrintStream ps) {
      final InputStreamReader streamReader = new InputStreamReader(is);
      new Thread(new Runnable() {
         public void run() {
            BufferedReader br = new BufferedReader(streamReader);
            String line = null;
            try {
               while ((line = br.readLine()) != null) {
                  ps.println("process stream: " + line);
               }
            } catch (IOException e) {
               e.printStackTrace();
            } finally {
               try {
                  br.close();
               } catch (IOException e) {
                  e.printStackTrace();
               }
            }
         }
      }).start();
   }
}
于 2013-02-07T06:47:55.040 回答
0

可能的问题是当您获得 inputSram 时,子流程还没有准备好

尝试

Process process = Runtime.getRuntime().exec("bash /home/abhishek/workspace/Pro/run");
InputStream isout = process.getInputStream();    
process.waitFor()
于 2013-02-06T11:20:59.690 回答
0

/home/abhishek/workspace/Pro/run如果它是外壳,请编辑您并在顶部添加以下行。

#!/usr/bin/bash

并赋予/home/abhishek/workspace/Pro/run.

然后使用以下行

Process process = Runtime.getRuntime().exec("/home/abhishek/workspace/Pro/run");

现在,如果运行程序打印任何内容,您应该在输出中看到它。

于 2013-02-06T11:21:32.950 回答
0

你的代码看起来不错。因此,我认为问题出在您正在使用的命令行中 ( bash /home/abhishek/workspace/Pro/run) 或您的脚本本身。

我建议您执行以下步骤:

  1. 尝试运行一些众所周知的命令而不是您的脚本。例如pwd. 检查从输入流中读取的代码是否正常工作。
  2. 现在尝试简化您的脚本。run1创建运行相同的脚本pwd。现在从 java 运行这个脚本,看看它是否正常工作。顺便说一句,您不必将其作为bash yourscript. 可以不带bash前缀直接运行
  3. 如果所有这些工作开始逐步从简单到您的真实脚本。我相信你会发现你的错误。可能您的脚本因某些与环境相关的问题而无法启动。
于 2013-02-06T11:24:07.087 回答
0

尝试这样的事情:

String[] runCommand = new String[3];

runCommand[0] = "sh";
runCommand[1] = "-c";
runCommand[2] = "bash /home/abhishek/workspace/Pro/run";

Process process = runtime.exec(runCommand);
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line = reader.readLine();
reader.close();
于 2013-02-06T11:43:30.603 回答
0

在多次阅读https://github.com/AdoptOpenJDK/openjdk-jdk11/blob/master/src/java.base/unix/classes/java/lang/ProcessImpl.java的unix实现的源代码Process之后标准重定向将始终吞入 a :ProcessBuilder.NullInputStream

    if (redirects[1] == Redirect.PIPE) {
        std_fds[1] = -1;
    }...

    stdout = (fds[1] == -1 || forceNullOutputStream) ?
            ProcessBuilder.NullInputStream.INSTANCE :
            new ProcessPipeInputStream(fds[1]);

(对于 stdIn、stdOut 和 stdErr 流重复相同的代码)

我发现的唯一一种感觉很笨拙的解决方法是使用临时文件:

    File stdOutTmp;  // create and destroy however you see fit
    ProcessBuilder pb = ...;
    pb.redirectOutput(ProcessBuilder.Redirect.to(stdOutTmp));
    ...

还有其他静态工厂方法(Redirect.appendTo(File)附加到现有文件而不是覆盖现有文件,以及Redirect.from(File)用于 stdIn)

于 2021-11-09T18:32:21.070 回答