I am running some .jar programs from a Java code. To do that, I use ProcessBuilder, as follows:
ProcessBuilder pb = new ProcessBuilder("java", "-jar", jarFile, configFile);
Process p = pb.start();
finished = p.waitFor(600, TimeUnit.SECONDS);
// print the error output
if(finished){
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getErrorStream()));
StringBuilder builder = new StringBuilder();
String line = null;
while ( (line = reader.readLine()) != null) {
builder.append(line);
builder.append(System.getProperty("line.separator"));
}
result = builder.toString();
reader.close();
status = p.exitValue();
}
else{
p.destroyForcibly();
result = "Error: maximum time (600 seconds) exceeded.";
}
The above code is within a foor bucle that selects different jar files (using the jarFile variable) at each iteration. Each one of the jar files writes some output files (note that these output files are different from the standard output / standard error of the program, they are other additional output files).
The problem is that, sometimes, some of the jar programs do not create its corresponding files. If I re-run the code several times, the processes that write their output files are different in each execution (which is very rare).
Could someone give me an indication on how to solve this problem? Thanks in advance.
Related
Java code
try {
String command = "/opt/compress.sh param1 param2 param3";
Process ps = Runtime.getRuntime().exec(command);
ps.waitFor(60 * 5, TimeUnit.SECONDS);
br = new BufferedReader(new InputStreamReader(ps.getInputStream()));
StringBuffer sb = new StringBuffer();
String line;
while ((line = br.readLine()) != null) {
sb.append(line).append("\n");
}
result = sb.toString();
log.info("shell logļ¼\n" + result);
}finally {
br.close();
}
shell Code
#Other business codes
zip -m -jP $3 ${zipOutPath} ${fileIputPath}
The workflow engine calls jar packages to execute Java code, and the zip command in the shell often fails. Manually executing the JAR package on the server is normal.Zip compresses only a CSV file,the file size is 2G.Try to enable shell Debug, only get -> addling XXx. CSV (%)
You are not consuming output streams properly so this may lead to freeze, and waitFor must be after reading STDOUT. Try using ProcessBuilder instead and see what errors it reports, it may help you to the next step:
ProcessBuilder pb = new ProcessBuilder(cmd);
// No STDERR => merge to STDOUT (or redirect elsewhere)
pb.redirectErrorStream(true);
Process p = pb.start();
try(var merged = p.getInputStream()) {
merged.transferTo(System.out);
}
// Check the executable worked:
int rc = p.waitFor();
if (rc != 0)
throw new RuntimeException("failed: "+Arrays.toString(cmd));
I have a Java script that starts a new thread to execute a python script using Process builder. The code below currently takes the output from python and displays it in the Java run output and within a JTextArea. BUT, it only does so in bulk, once the py script has finished running. Is there a way to get the output displayed live as it is written out from the py script? Thanks!!!!
public void launchPythonScript() {
try {
ProcessBuilder py = new ProcessBuilder("cmd", "/C", "PythonScriptLocation (C:\\....)",""+Directory(variable needed for py script));
Process launch = py.start();
BufferedReader reader = new BufferedReader(new InputStreamReader(launch.getInputStream()));
String readLine;
StringBuilder JavaOutput = new StringBuilder();
while((readLine = reader.readLine()) != null){
JavaOutput.append(readLine).append(System.lineSeparator());
frame2.consoleOutput.setText(JavaOutput.toString());
System.out.println(readLine);
}
} catch (IOException ex) { Logger.getLogger(Frame1.class.getName()).log(Level.SEVERE, null, ex);}
}
Process InputStream should give you data while the script is running.
You are reading one line at time so if your python script send all data in one single line then you see the output only at the end.
Try to break the output data into multiple lines.
I am calling a bash scrip script from Java.
The script does the following:
cat /home/user/Downloads/bigtextfile.txt | grep 'hello'
This particular command when run command line takes about 1 second to complete on the text file which is 150MB.
When calling the bash script via Java using the following call:
command = "sh /home/user/bashfiletocall"
p = Runtime.getRuntime().exec(command);
The time to complete takes so long I don't wait.
Am I doing something very wrong and if not can you explain the reason for the huge lack in performance?
NOTE: I was running it in Netbeans and this seems to be the problem .. when I ran the file command line it was quick. The performance between execution in netbeans and command line is huge.
Many thanks.
private String executeCommand(String command) {
StringBuilder output = new StringBuilder();
BufferedReader reader = null;
Process p;
try {
p = Runtime.getRuntime().exec(command);
p.waitFor();
reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = "";
while ((line = reader.readLine())!= null) {
output.append(line + "\n");
}
} catch (Exception e) {
e.printStackTrace();
}
return output.toString();
}
After starting your process you need start reading from the input stream. Otherwise the buffers are running full and p.waitFor() waits forever.
Javadoc of the Process class:
Because some native platforms only provide limited buffer size for standard input and output streams, failure to promptly write the input stream or read the output stream of the subprocess may cause the subprocess to block, or even deadlock.
Hy.
I've created a routine that read .tgz files from a directory and unzip each one. I'm using
Process zip01 = Runtime.getRuntime().exec("LINE OF COMMAND");
and
exitVal = zip01.waitFor();
I,m using 7z.exe from its folder to decompress and compress files. The command line is working fine. Now, I what to read the percentage of the decompress and throw it into a textfield or a textarea. The graphics part are ok too, s well all the routine. The only dificult is to get the realtime percentage of the 7z. is there some way to read and show it?
Thanks!
You can get the output of your process like this:
Process zip01 = Runtime.getRuntime().exec("LINE OF COMMAND");
BufferedReader output = new BufferedReader(new InputStreamReader(zip01.getInputStream()));
String line;
while ((line = output.readLine()) != null) {
/* process lines */
}
For some terminal commands, they repeatedly output. For example, for something that's generating a file, it may output the percent that it is complete.
I know how to call terminal commands in Java using
Process p = Runtime.getRuntim().exec("command goes here");
but that doesn't give me a live feed of the current output of the command. How can I do this so that I can do a System.out.println() every 100 milliseconds, for example, to see what the most recent output of the process was.
You need to read InputStream from the process, here is an example:
Edit I modified the code as suggested here to receive the errStream with the stdInput
ProcessBuilder builder = new ProcessBuilder("command goes here");
builder.redirectErrorStream(true);
Process process = builder.start();
InputStream is = process.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
String line = null;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
For debugging purpose, you can read the input as bytes instead of using readLine just in case that the process does not terminate messages with newLine