Getting output from executing a terminal command in a java code running inside Cubieboard Platform
Question
The code that I am using for running a terminal command in Linux Debian and getting the output inside a java program is this:
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();
}
Now the problem is, it works for normal commands like ls /
and gives back the appropriate result. But my goal is to run commands like:
echo 23 > /sys/class/gpio/export
which is, for example, for activating the gpio pin in the CubieBoard platform. (Cubieboard is a mini-pc board like Raspberry Pi).
Now running this command in the terminal of the system itself, works fine and gives me the proper result. But when i am running it from this java code, i cannot get any results back.
The point is that, it works and the command executes well, but just that i cannot get the output message of the command!
For example if the pin was active from the past, then normally it should give me back the result like:
bash: echo: write error: Device or resource busy
But when i run this command through java code above, i do not get any response back. (again it takes effect but just the response of the terminal i cannot get!)
When i run the code, both stdInput
and stdError
variables in the code are having the value null
. :(
Please help me so that i can finish my project. this is the only part that is remaining :(
Thank you.
Solution 2
the code is right, just in the second line, I changed
"/bin/sh" to "/bin/bash"
And everything works!
sh == bash?
For a long time, /bin/sh used to point to /bin/bash on most GNU/Linux systems. As a result, it had almost become safe to ignore the difference between the two. But that started to change recently.
Some popular examples of systems where /bin/sh does not point to /bin/bash (and on some of which /bin/bash may not even exist) are:
Modern Debian and Ubuntu systems, which symlink sh to dash by default;
Busybox, which is usually run during the Linux system boot time as part of initramfs. It uses the ash shell implementation.
BSDs. OpenBSD uses pdksh, a descendant of the Korn shell. FreeBSD's sh is a descendant of the original UNIX Bourne shell.
For more information on this please refer to : Difference between sh and bash
OTHER TIPS
There maybe the childProcess doesn't run to end
Please to try:
proc.waitFor()
and run read stdInput and stdError in other Thread before proc.waitFor().
Example:
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();
}
}