我下面有以下代码示例。你可以在其中输入bash shell的命令,即echo test回显结果。但是,先读后。其他输出流不起作用?
bash shell
echo test
为什么会这样或我做错了什么?我的最终目标是创建一个线程计划任务,该任务定期执行对/ bash的命令,因此OutputStreamand InputStream必须一前一后工作,而不能停止工作。我也一直在经历错误的java.io.IOException: Broken pipe任何想法?
OutputStreamand InputStream
java.io.IOException: Broken pipe
谢谢。
String line; Scanner scan = new Scanner(System.in); Process process = Runtime.getRuntime ().exec ("/bin/bash"); OutputStream stdin = process.getOutputStream (); InputStream stderr = process.getErrorStream (); InputStream stdout = process.getInputStream (); BufferedReader reader = new BufferedReader (new InputStreamReader(stdout)); BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(stdin)); String input = scan.nextLine(); input += "\n"; writer.write(input); writer.flush(); input = scan.nextLine(); input += "\n"; writer.write(input); writer.flush(); while ((line = reader.readLine ()) != null) { System.out.println ("Stdout: " + line); } input = scan.nextLine(); input += "\n"; writer.write(input); writer.close(); while ((line = reader.readLine ()) != null) { System.out.println ("Stdout: " + line); }
首先,我建议更换生产线
Process process = Runtime.getRuntime ().exec ("/bin/bash");
与线
ProcessBuilder builder = new ProcessBuilder("/bin/bash"); builder.redirectErrorStream(true); Process process = builder.start();
ProcessBuilder是Java 5中的新增功能,它使运行外部进程更加容易。在我看来,它最大的改进Runtime.getRuntime().exec()是它允许你将子进程的标准错误重定向到其标准输出中。这意味着你只有一个人InputStream可以阅读。在此之前,你需要有两个单独的线程,一个从中stdout读取,另一个从中读取stderr,以避免在标准输出缓冲区为空(导致子进程挂起)时填充标准错误缓冲区,反之亦然。
Runtime.getRuntime().exec()
InputStream
stderr
接下来,循环(其中有两个循环)
while ((line = reader.readLine ()) != null) { System.out.println ("Stdout: " + line); }
仅当reader从流程的标准输出读取的,返回文件末尾时退出。这仅在bash进程退出时发生。如果当前碰巧不再有该过程的输出,它将不会返回文件结尾。相反,它将等待流程的下一行输出,直到有下一行才返回。
由于你要在到达此循环之前向流程发送两行输入,因此,如果在这两行输入之后流程尚未退出,则这两个循环中的第一个将挂起。它会坐在那里等待另一行被读取,但是永远不会再有另一行可以读取。
我编译了你的源代码(目前我在Windows上,所以我将其替换/bin/bash为cmd.exe,但是原理应该相同),我发现:
exit
cmd.exe
IOException
我获取了你的代码,并writer使用以下循环替换了分配给该行的所有内容:
writer
while (scan.hasNext()) { String input = scan.nextLine(); if (input.trim().equals("exit")) { // Putting 'exit' amongst the echo --EOF--s below doesn't work. writer.write("exit\n"); } else { writer.write("((" + input + ") && echo --EOF--) || echo --EOF--\n"); } writer.flush(); line = reader.readLine(); while (line != null && ! line.trim().equals("--EOF--")) { System.out.println ("Stdout: " + line); line = reader.readLine(); } if (line == null) { break; } }
完成此操作后,我可以可靠地运行一些命令,并将每个命令的输出分别返回给我。
echo --EOF--发送到shell的那一行中的两个命令可以确保–EOF–即使在命令出错的情况下也可以终止命令的输出。
echo --EOF--
当然,这种方法有其局限性。这些限制包括:
--EOF--
bash
如果你要考虑的是计划任务中要执行的任务,那么这些要点可能对你而言并不重要,因为这些任务将仅限于一个命令或一小部分命令,这些命令或行为永远不会以这种病理方式表现。
编辑:在Linux上运行此命令后,改善退出处理和其他较小更改。