我正在使用在Linux Debian中运行terminal命令并在java程序中获取输出的代码是这样的:
public static String execute(String command) { StringBuilder sb = new StringBuilder(); String[] commands = new String[]{"/bin/sh", "-c", command}; try { Process proc = new ProcessBuilder(commands).start(); BufferedReader stdInput = new BufferedReader(new InputStreamReader(proc.getInputStream())); BufferedReader stdError = new BufferedReader(new InputStreamReader(proc.getErrorStream())); String s = null; while ((s = stdInput.readLine()) != null) { sb.append(s); sb.append("\n"); } while ((s = stdError.readLine()) != null) { sb.append(s); sb.append("\n"); } } catch (IOException e) { return e.getMessage(); } return sb.toString(); }
现在的问题是,它适用于正常的命令,如ls /
并给出适当的结果。 但我的目标是运行如下命令:
echo 23 > /sys/class/gpio/export
例如,用于激活CubieBoard平台上的gpio引脚。 (Cubieboard是像Raspberry Pi这样的迷你pc板)。
现在在系统本身的terminal上运行这个命令,工作正常,给了我正确的结果。 但是,当我从这个Java代码运行它,我不能得到任何结果。
重点是,它的工作和命令执行得很好,但只是我不能得到命令的输出消息!
例如,如果引脚是从过去的活跃,那么通常它应该给我回来的结果,如:
bash: echo: write error: Device or resource busy
但是,当我通过上面的Java代码运行这个命令,我没有得到任何回应。 (再次生效,但只是terminal的反应,我不能得到!)
当我运行代码时,代码中的stdInput
和stdError
variables的值都为null
。 🙁
请帮助我,以便我可以完成我的项目。 这是剩下的唯一部分:(
谢谢。
有可能childProcess不会运行结束
请尝试:
proc.waitFor()
并在proc.waitFor()之前的其他线程中运行读取stdInput和stdError。
public static String execute(String command) { String[] commands = new String[] { "/bin/sh", "-c", command }; ExecutorService executor = Executors.newCachedThreadPool(); try { ProcessBuilder builder = new ProcessBuilder(commands); /*- Process proc = builder.start(); CollectOutput collectStdOut = new CollectOutput( proc.getInputStream()); executor.execute(collectStdOut); CollectOutput collectStdErr = new CollectOutput( proc.getErrorStream()); executor.execute(collectStdErr); // */ // /*- // merges standard error and standard output builder.redirectErrorStream(); Process proc = builder.start(); CollectOutput out = new CollectOutput(proc.getInputStream()); executor.execute(out); // */ // child proc exit code int waitFor = proc.waitFor(); return out.get(); } catch (IOException e) { return e.getMessage(); } catch (InterruptedException e) { // proc maybe interrupted e.printStackTrace(); } return null; } public static class CollectOutput implements Runnable { private final StringBuffer buffer = new StringBuffer(); private final InputStream inputStream; public CollectOutput(InputStream inputStream) { super(); this.inputStream = inputStream; } /* * (non-Javadoc) * * @see java.lang.Runnable#run() */ @Override public void run() { BufferedReader reader = null; String line; try { reader = new BufferedReader(new InputStreamReader(inputStream)); while ((line = reader.readLine()) != null) { buffer.append(line).append('\n'); } } catch (Exception e) { System.err.println(e); } finally { try { reader.close(); } catch (IOException e) { } } } public String get() { return buffer.toString(); } }
代码是正确的,就在第二行,我改变了
"/bin/sh" to "/bin/bash"
一切正常!
sh == bash?
很长一段时间,/ bin / sh用于在大多数GNU / Linux系统上指向/ bin / bash。 结果,忽略两者之间的差异几乎变得安全了。 但最近开始发生变化。
/ bin / sh不指向/ bin / bash(甚至有些/ bin / bash甚至可能不存在)的一些流行的系统示例如下:
现代Debian和Ubuntu系统,默认符号链接到破折号;
Busybox,通常在Linux系统启动时运行,作为initramfs的一部分。 它使用灰壳实现。
BSD系统。 OpenBSD使用pdksh,它是Korn shell的后代。 FreeBSD的sh是原来的UNIX Bourne shell的后代。
有关这方面的更多信息,请参阅: sh和bash之间的区别