我用于在Linux Debian中运行终端命令并在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板。)
现在在系统终端中运行此命令,工作正常并给我正确的结果。但是当我从这个java代码运行它时,我无法获得任何结果。
重点在于,它可以工作并且命令执行得很好,但只是我无法获得命令的输出消息!
例如,如果引脚过去处于活动状态,那么通常情况下它会给我回复结果:
bash: echo: write error: Device or resource busy
但是当我通过上面的java代码运行此命令时,我没有得到任何回复。 (它再次生效,但只是终端的响应,我无法得到!)
当我运行代码时,代码中的stdInput
和stdError
变量都具有值null
。 :(
请帮助我,以便我可以完成我的项目。这是剩下的唯一部分:(
谢谢。
答案 0 :(得分:2)
可能childProcess没有运行结束
请尝试:
<强> proc.waitFor()强>
并在 proc.waitFor()之前在其他线程中运行read 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();
}
}
答案 1 :(得分:2)
代码是正确的,就在第二行,我改变了
"/bin/sh" to "/bin/bash"
一切正常!
sh == bash?
很长一段时间,/ bin / sh曾经指向大多数GNU / Linux系统上的/ bin / bash。结果,忽略两者之间的差异几乎是安全的。但最近这种情况开始发生变化。
/ bin / sh未指向/ bin / bash(以及其中某些/ bin / bash甚至可能不存在)的系统的一些常见示例是:
现代Debian和Ubuntu系统,默认情况下符号链接为短划线;
Busybox,通常在Linux系统启动时作为initramfs的一部分运行。它使用ash shell实现。
BSD系统。 OpenBSD使用了Korn shell的后代pdksh。 FreeBSD的sh是原始UNIX Bourne shell的后代。
有关详细信息,请参阅: Difference between sh and bash