Display Sh script output in browser - java

I have a webappliaction(developed in Jsp & Severlet) that execute the sh script and displays the output in browser only after executing the script but i want to print the output like how its executing in teriminal (one by one for eg ping command).So that user will have the experience like working in unix terminal. My script will run almost one minute(Script to start stop my WAS servers) so the user should not wait till one minute to see the final output . They should see the script started output once they start the process .please find my sample code below.
pb = new ProcessBuilder("/bin/sh",script);
pb.directory(new File(filePath));
p = pb.start();
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = null;
while ((line = reader.readLine()) != null){
System.out.println(line);
out.println(line);
}
p.waitFor();
System.out.println ("exit: " + p.exitValue());
out.println("exit: " + p.exitValue());
p.destroy();
out.println("Script Executed");
Please anyone guide me.

Finally i got a solution for my problem, I just added out.flush() after out.println(line);So its flushing output to browser each time in while loop and its looks like unix terminal . Below code did the magic.
pb = new ProcessBuilder("/bin/sh",script);
pb.directory(new File(filePath));
p = pb.start();
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = null;
while ((line = reader.readLine()) != null){
System.out.println(line);
out.println(line);
out.flush();
}
p.waitFor();
System.out.println ("exit: " + p.exitValue());
out.println("exit: " + p.exitValue());
p.destroy();
out.println("Script Executed");

Your problem is invisible here in the code example because it works just fine locally (e.g. for System.out). So logic implies that the problem must be somewhere in networking between client and server. Neither do you show how out is created (I guess it is some kind of socket-connected PrintStream) nor how the JSP reads it. What you want is some AJAX approach (XmlHttpRequest or similar) and probably you do not use it, but some "naïve", old-fashioned way. I am not a web developer, but your favourite search engine or some other people here might be able to help you with that part.

Related

Java Process Builder runs ffmpeg commands very slowly

I'm trying to run ffmpeg in Java using ProcessBuilder. I'm on Windows. It works fine. But not sure why it's much slower than when I just run the same command in command prompt or PowerShell.
Why is it? Is there any ways to increase the speed?
processBuilder.command("C:\\Windows\\System32\\cmd.exe", "/c","ffmpeg.exe", "-y", "-i", video,"-vf","scale=720:-1","out.mp4");
processBuilder.redirectErrorStream(true);
try {
process = processBuilder.start();
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line="";
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (Exception e) {
System.err.println("Error in processBuilder. ");
}
You have two starts, delete the first or the redirect will not work:
process = processBuilder.start();
If your sub-process is quite verbose the problem may simply be System.out.println() as multiple line output to some Windows cmd / terminals can be exceptionally slow. You can verify if this is the case by commenting out the print, or capture to File based output before start:
processBuilder.redirectOutput(new File("stdout.log"));
Don't forget to add status check at the end and cross check rc with ffmpeg documentation:
int rc = process.waitFor();

Grab CloudCompare Command Line Output with Java ProcessBuilder

I'm playing a bit around with a small JAVA gui for the command line mode of cloudcompare.
Therefore I'm using a short snippet like these:
var processBuilder = new ProcessBuilder();
try {
var process = processBuilder
.command("open", "-a", "CloudCompare.app", "-n",
"--args", "-NO_TIMESTAMP", "-C_EXPORT_FMT", "LAS",
"-O", "/Users/se/pcl_1.las",
"-O", "/Users/se/pcl_2.las",
"-MERGE_CLOUDS")
.start();
String error, line;
BufferedReader inputStream = new BufferedReader(new InputStreamReader(process.getInputStream()));
while ((line = inputStream.readLine()) != null) {
System.out.println("line = " + line);
}
BufferedReader errorStream = new BufferedReader(new InputStreamReader(process.getErrorStream()));
while ((error = errorStream.readLine()) != null) {
System.out.println("error = " + error);
}
var ret = process.waitFor();
System.out.printf("Program exited with code: %d", ret);
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
But if I run it on macOS the command line window opens, the process runs normal, but I can't grab any of the informations in it. There is an option to write log files from cloudcompare. That works - the log file shows that all cloud processing steps are done.
Does anybody knows, how to grab the command line output?
As mentioned here, the /usr/bin/open command is not an option to grab the stdinput stream.
I change the command to /Applications/CloudCompare.app/Contents/MacOS/CloudCompare and it works.
The next question is, how to grab the InputStream with a thread. I tried some stack overflow topics, but it doesn't work at the moment, to get the output stream in realtime. It is flushed at the end of the CloudCompare process.

Sending input to stdin and getting the full output in Java - Festival TTS

I'm trying to use the Java Runtime.getRuntime().exec(String) command to run Festival, then use OutputStreamWriter to write some commands to the outpustream of the process.
This works great, and I'm able to do something like this:
Process p = Runtime.getRuntime().exec("festival");
Writer w = new OutputStreamWriter(p.getOutputStream());
w.append("(SayText \"Hello World\")");
w.flush();
Obviously the way I can tell this works is that it speaks the text through the speakers.
What I am having a real hard time doing is getting the text output from what I would see in the terminal. I'm trying to run some other commands (such as (voice.list)) which output text, presumably to stdout.
For example, I've tried using a BufferedReader in the following way:
BufferedReader reader = new BufferedReader (new InputStreamReader(p.getInputStream()));
w.append("(voice.list)");
w.flush();
String output = "";
String line = reader.readLine();
System.out.println(line);
while ((line = reader.readLine()) != null)
{
System.out.println("Reading: " + line);
output += line;
}
(The System.out.println's is just for debugging, I would do the entire thing in a cleaner way if I was able to get it to work.)
No matter what code I try, I'm never able to get any output from Festival. I can get output from other commands. E.G. I have tried this code as well http://en.allexperts.com/q/Java-1046/2008/2/Runtime-getRuntime-exec-cmd.htm and it works with many other commands (like ls) but not Festival.
Does anything have any idea how I would be able to get this to work?
Thanks.
Festival may output it's text on stderr instead of stdout. Try replacing
p.getInputStream()
with
p.getErrorStream()

How to detect java process exit?

In a java program, I am generating an sh script for use on a centOS machine, which will use sox and lame to decode an MP3 audio file, then apply some gain to the file respectively. Im having some issues getting the Process.waitFor() method to do anything other than hang indefinitely. Here is the code:
try
{
// TODO code application logic here
String reviewPath = "/SomeDirectory/";
String fileName = "FileName";
String extension = ".mp3";
StringBuilder sb = new StringBuilder();
sb.append("#!/bin/bash\n");
sb.append("cd " + reviewPath + "\n");
sb.append("lame --decode " + fileName + extension + "\n");
File script = new File(reviewPath + fileName + ".sh");
script.createNewFile();
script.setExecutable(true);
FileWriter writer = new FileWriter(script);
writer.write(sb.toString());
writer.close();
Process p = Runtime.getRuntime().exec(script.getAbsolutePath());
String line;
BufferedReader bri = new BufferedReader
(new InputStreamReader(p.getInputStream()));
BufferedReader bre = new BufferedReader
(new InputStreamReader(p.getErrorStream()));
while ((line = bri.readLine()) != null) {
System.out.println(line);
}
bri.close();
while ((line = bre.readLine()) != null) {
System.out.println(line);
}
bre.close();
p.waitFor();
System.out.println("Done.");
}
catch (Exception e)
{
System.out.println(e.getMessage());
}
The odd part is that when I run the .sh file it generates by hand, it runs and exits nicely, but when I execute it from a process object in java, it never exits. The exitValue of the process is always "Process has not exited". Ive tried adding set -e to the script, and exit to the end of the script. Short of using the kill command (which I dont really think I can do here) Im at a loss as to what is going on here. Any suggestions?
Add something like while(p.getInputStream().read() != -1); after starting the process. The buffer will get filled and the process will stop waiting for something (in this case, your program) to read from it to free up space.
I figured it out! The problem here was indeed that the output streams needed to be flushed for the application to exit, but simply reading from the streams is not enough. I used Suresh Koya's suggestion and used the processBuilder api, and redirected the error stream on the process before starting it, and read from the streams. This fixed the issues I was having :D

Using java to get the current process owner

I want to know the owner of current process in Unix using Java. I want to find the current server's owner name. I tried with running "who am i" command in Runtime.getRuntime().exec(), but its not returning me any results.
String line = "";
Process p = Runtime.getRuntime().exec("who am i");
InputStream iStream = p.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(iStream);
BufferedReader bufReader = new BufferedReader(inputStreamReader);
while ((line = bufReader.readLine()) != null) {
System.out.println("Input "+line);
}
Is there anything wrong with this code or any idea how can I find the owner of current process using Java?
First thing, I think System.getProperty("user.name") should work for that
Second thing, the reason your code is not returning anything is because the command is whoami with NO SPACES so your exec line should be (assuming you are running on windows through cygwin or on a **nix based system)
Process p = Runtime.getRuntime().exec("whoami");

Categories