java execute external program and read its output - java

I want to read output from ADB logcat (https://developer.android.com/studio/command-line/adb). I have such code (test):
try {
Process p = Runtime.getRuntime().exec("sh -c adb logcat");
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(p.getInputStream()));
while(true) {
String s = bufferedReader.readLine();
if(s == null) {
continue;
}
System.out.println("From process: " + s);
}
} catch (IOException e) {
e.printStackTrace();
}
But this prints nothing. If I execute this:
Process p = Runtime.getRuntime().exec("sh -c ls");
It works.

Okay, I too fast asked the question on SO.
I read error stream instead of inputstream and I find out that cannot find program ADB. Need to provide full path:
ProcessBuilder processBuilder = new ProcessBuilder("/home/UserName/Soft/Android/Sdk/platform-tools/adb", "logcat");
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(p.getInputStream()));
But on another computer path is different. Also you can on every computer make symbolic link and in code use as path simply "adb":
sudo ln -s /home/UserName/Soft/Android/Sdk/platform-tools/adb /bin/adb
ProcessBuilder processBuilder = new ProcessBuilder("adb", "logcat");
This is not the best solution, partially resolves problem. Would be great without making symbolic link, using simply "adb" in instantiating ProcessBuilder object. Because in every disk location on my computer I can use ADB in terminal, it is visible but in this code no. In Windows I know that this is in System Environments > PATH. In linux I wrote command "printenv" but I don't see anything with android & adb.

Related

Run shell script with Angular CLI commands from Java

I'm trying to run a shell script from Java (using Runtime.getRuntime().exec(cmd)). All commands in the script file seem to be running normally except the angular-cli (ng) commands.
My Java File:
System.out.println("Executing Script...");
final String[] cmd = new String[]{"/bin/bash", "test.sh"};
final Process process = Runtime.getRuntime().exec(cmd);
process.waitFor();
final BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String s;
while ((s = reader.readLine()) != null) {
System.out.println("Script output: " + s);
}
process.destroy();
System.out.println("Script Executed.");
test.sh:
#!/bin/bash
cd ~/ &&
ng new newAngularProject &&
Outout:
Executing Script...
Script Executed.
No errors are thrown. All other commands work but for some reason, I'm unable to run ng commands. Also, I've tested the file w/o running it from Java - When I run the same script directly on the console, it works perfectly and all commands (including ng commands) work neatly. I'm running on MacOS in case you wanted to know.
Also print the error stream. You will get the error message, if it is there.
final BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
while ((s = errorReader.readLine()) != null) {
System.out.println("error: " + s);
}
Also you can try to use absolute path of ng in your test.sh e.g. /home/my/install/node-vxxx/ng, since the process spawn by java to run your command might not get the environment variable you set in your .bashrc /.bash_aliases

Run exec file using Java on Mac

I need to start a server using bash, so I had created an UNIX shell , but I am not able to execute it with Java from Eclipse.
I tried the following code which doesn't work :
Process proc = Runtime.getRuntime().exec(./startServer);
Here is content of the startServer file :
#!/bin/bash
cd /Users/sujitsoni/Documents/bet/client
npm start
You can try the following two options.
Option 1
Process proc = Runtime.getRuntime().exec("/bin/bash", "-c", "<Abosulte Path>/startServer");
Option 2
ProcessBuilder pb = new ProcessBuilder("/bin/bash", "-c", "<Absolute Path>/startServer");
pb.directory(new File("<Absolute Path>"));
Process proc = pb.start();
A couple Of things can go wrong:
The path to the file you have given might be wrong for eclipse it can take relative path but from the command line, it will take the absolute path.
error=13, Permission denied - If the script file doesn't have required permissions. In your scenario, that might not the case as you are not getting any error.
At last, you are executing the script by java program so the output of your script will not be printed out. In your scenario, this might be the case. You need to capture the output of script from BufferedReade and print it. ( In your case server might have started but you are not seeing the logs/output of the script.
See the code sample below for printing output.
public static void main(String[] args) throws IOException, InterruptedException {
Process proc = Runtime.getRuntime().exec("./startServer");
proc.waitFor();
StringBuffer output = new StringBuffer();
BufferedReader reader = new BufferedReader(new InputStreamReader(proc.getInputStream()));
String line = "";
while ((line = reader.readLine()) != null) {
output.append(line + "\n");
}
System.out.println(output);
}

Calling sccmap using Java

I am trying to call the sccmap command from GraphViz using Java.
String command = "/usr/bin/sccmap -S /home/paperclip/Desktop/graph.dot > /home/paperclip/Desktop/scc.dot";
try {
Runtime rt = Runtime.getRuntime();
Process p = rt.exec(command);
System.out.println("Process exited with code = " + p.waitFor());
java.io.InputStream is = p.getInputStream();
java.io.BufferedReader reader = new java.io.BufferedReader(new InputStreamReader(is));
String s = null;
while ((s = reader.readLine()) != null) {
System.out.println(s);
}
is.close();
} catch (Exception e) {
e.printStackTrace();
}
The output for this snippet of code is:
Process exited with code = 0
The sccmap function is supposed to output a dot file in the location that I have specified. However, it doesn't work like I expected. Even though the exitValue was given as 0, the dot file was not created.
I tried using the command manually in Terminal and it works perfectly. I also tried using other commands such as "ls" and it works too. Why does this code not work for "sccmap"?
I also searched for some Java APIs for GraphViz such as the jGraphViz (http://jgraphviz.sourceforge.net/) and graphviz-java-api at (http://www.loria.fr/~szathmar/off/projects/java/GraphVizAPI/index.php), but they don't seem to work for me.
FYI I am on Ubuntu 11.10 and GraphViz is already installed.
Thanks!
> is interpreted by the shell (it's a stream redirect), it's not an argument to the application. There is no shell in this situation.
Try /usr/bin/sccmap -S -o /home/paperclip/Desktop/scc.dot /home/paperclip/Desktop/graph.dot instead.

How can I execute unix sort command (/usr/bin/sort) from Java?

I am hoping to leverage the unix sort command to sort a large text file in Java. I've tried executing sort with the process builder, but with no luck. However when I print the exact command it is going to execute and copy and paste it into the terminal, it works fine.
So far I've tried executing with /bin/sh -c "", making sure the directory the input file is and where the output file will be is fully permissioned (chmod 777) but with no luck.
Here is the code (if it looks funny, note is using some functions found in Guava)
File inputFile = new File(inputFileName);
//build the command (optional number of sort columns)
List<String> command = new LinkedList<String>();
command.addAll(ImmutableList.<String>of("sort","-t"+delimiter));
for (int i : sortFieldPositions) {
command.add("-k"+i+","+i);
}
command.addAll(ImmutableList.<String>of(inputFileName,">",outputFileName));
//for debugging: output the command that will be executed
System.out.println("Executing: "+Joiner.on(" ").join(command));
//construct and start the process
Process process = new ProcessBuilder(command).redirectErrorStream(true).directory(inputFile.getParentFile()).start();
//for debugging: save process output
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
StringBuilder outputStringBuilder = new StringBuilder();
for (String line; (line = bufferedReader.readLine()) != null; /*reading taking place in check */) {
System.out.println("FROM PROCESS: "+line);
outputStringBuilder.append(line);
}
bufferedReader.close();
if (process.exitValue() != 0) {
//something went wrong
throw new RuntimeException("Error code "+process.exitValue()+" executing command: "+Joiner.on(" ").join(command)+"\n"+outputStringBuilder.toString());
}
Unfortunately this does not work, with the following output:
Executing: sort -t, -k2,2 -k1,1 /tmp/java/TestDataSorterImporterInput.txt /tmp/java/TestDataSorterImporterOutput.txt
FROM PROCESS: sort: stat failed: >: No such file or directory
Edit: It may be helpful to note that if I remove saving the output (> outputfile) from the command, then the command executes without complaint and the sorted version appears in the output from the Processes' input stream)
It is the shell that knows how to perform output redirection. The sort program cannot do it on its own. So if you want redirection, you need to do /bin/sh -c ... to let she shell into the loop.
(You write that you have tried this, but something else must have gone wrong with that).
Try this:
String whatever = "filename";
Process p = Runtime.getRuntime().exec("sort -t -k2 2 -k1 1 " + whatever);
See this site.
Process process = new ProcessBuilder("/bin/bash", "-c", "sort -t'|' -k2").start();

Run CMD equivalent in OSX?

I'm using this code to make my Java program open a (visible) CMD window:
try {
String line;
Process p = Runtime.getRuntime().exec("cmd /C start \"Render\" \"" + myPath + "\\punchRender.cmd\"");
BufferedReader input =
new BufferedReader(new InputStreamReader(p.getInputStream()));
while ((line = input.readLine()) != null) {
System.out.println(line);
jLabel7.setText(line);
}
input.close();
} catch (Exception err) {
err.printStackTrace();
}
and I've been trying to do the same thing with the OSX terminal, this is where I'm at right now:
try {
String line;
Process p = Runtime.getRuntime().exec("sh " + myPath + "/punchRender.sh");
BufferedReader input =
new BufferedReader(new InputStreamReader(p.getInputStream()));
while ((line = input.readLine()) != null) {
System.out.println(line);
jLabel7.setText(line);
}
input.close();
} catch (Exception err) {
err.printStackTrace();
}
So far, no luck :( Any suggestions? The .sh file isn't even running...
I would just make sure your shell script has the execute bits on and just pass in the shell script file name.
Process p = Runtime.getRuntime().exec(myPath + "/punchRender.sh")
Edit:
I don't know Java specifically if there is anyway to set file permissions for Unix/Linux with it to set the eXecute bit or how to escape quotes. But It would be something like this:
Process chmod = Runtime.getRuntime().exec("chmod u+x \"" + myPath + "/punchRenderer.sh\"")
This should work. Not only running the script, but opening a terminal also:
Process p = Runtime.getRuntime().exec("open -a /Applications/Utilities/Terminal.app \"" + myPath + " /punchRender.sh\"");
If you want a new visible Terminal window, you can't run the shell directly. You need to start Terminal and then run a .command file, not a shell script. I'm not sure how hard it would be to connect the stdout of that command to your Java process. You might have to figure out some other way of getting the output into the terminal.
By the way, I tried your code in a class on my own Mac at home, and it ran a .sh file just fine. I was running the java class from the command line. Maybe sh just isn't in your PATH.
I assume you've checked that the .sh file is executable, haven't you?
Can I suggest you capture the standard error as well as the standard output, and dump that. That should give you some idea as to what's going on (it's good practise generally).
You may need to gather standard output and standard error in different threads to avoid blocking issues. See here for a StreamGobbler

Categories

Resources