In my java program I am trying to run a different program through CMD with its output appearing in a command window in the foreground and then analyze the exit code of the child program (foo) in the main java program. Unfortunately, all I seem to be able to access is the exit code of the CMD window, which is always 0.
The following is a snippet of what I'm doing:
ProcessBuilder pb = new ProcessBuilder();
pb.directory(new File(dir));
pb.command("cmd","/c","start","/wait","foo.exe",arg);
process = pb.start();
exitVal = process.waitFor();
but exitVal is always 0 regardless of how foo exits. How can I get just the exit code of foo?
I'm also pretty new to java so if there's a more elegant way of doing this, I'm open to suggestions.
I found a solution by modifying one of the things I had tried before to account for windows batch being finicky. The solution was to send another command to cmd to tell it to exit with the most recent error code. Earlier I had tried this by appending & exit %errorlevel% to the command but cmd variables are only updated at the end of each command line, not at the end of each command.
To force update, I used %^errorlevel% instead.
Related
I have a java restful service method which executes a myscript.sh using processBuilder. My script takes one input (example - myscript.sh /path/to-a/folder).
Inside the script something like this
-> execute a command which is multithreaded i.e parallel processing
-> echo "my message"
Now when call my script from a linux command line it executes fine. First all the threads running finishes and then some text output from threaded command execution shown on terminal and then echo my message is shown.
But when I call the same script from java using processBuilder, the last echo message comes immidiately and execution ends.
Following the way I call my script from java
ProcessBuilder processBuilder = new ProcessBuilder("/bin/bash","/path/to/myscript.sh","/path/to/folder/data");
Process proc = processBuilder.start();
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);
I don't know whats happening, how to debug also.
Can someone enlighten me on how to get the same behaviour from shell script when run from terminal or from java processBuilder?
Use ProcessBuilder.redirectErrorStream(boolean redirectErrorStream) with argument true to merge the errors into output. Alternatively, you could also use the shell command syntax cmd 2>&1 to merge the error with output.
These are some of the cases why you may be immediately getting the output of the last echo statement (instead of the script taking time to run and return proper results):
Missing environment variables
The launched bash needs to source .bashrc or some such recource file
The launched bash may not be running in right directory (you can set this in ProcessBuilder)
The launched bash may not be finding some script/executable in its PATH
The launched bash may not be finding proper libraries in the path for any of the executables
Once you merge error, you would be able to debug and see the errors for yourself.
In your context, separate processes may be spawned in two ways:
1) Bash
/path/to/executables/executable &
This will spawn a new executable executable and you need to wait for it to finish. Here's an answer that will help you.
2) Java
Process exec = Runtime.getRuntime().exec(command);
status = exec.waitFor();
Essentially, you need to wait for the process to end before you start reading its std/err streams.
If I understand the problem correctly, adding just this line to your code should suffice: status = exec.waitFor() (Before you obtain the streams)
Here's the JavaDoc for Process.waitFor() :
Causes the current thread to wait, if necessary, until the process represented by this Process object has terminated. This method returns immediately if the subprocess has already terminated. If the subprocess has not yet terminated, the calling thread will be blocked until the subprocess exits.
Returns:
the exit value of the subprocess represented by this Process object. By convention, the value 0 indicates normal termination.
Throws:
InterruptedException - if the current thread is interrupted by another thread while it is waiting, then the wait is ended and an InterruptedException is thrown
I have a command like
cp -R Folder1/* Folder2/
or
rm -r /images/*.gif
It is not working to I try to run a sample program through Java
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec(cmd);
return proc.waitFor();
What am i doing wrong?
When you run a process, Java creates three outputs, the exit code, the STDOUT, and the STDERR. A good program running an external process, will check all three.
You are just waiting for the process to terminate, and return the exit code.
An easy way to see what's happening is to 'inherit' the STDOUT/STDERR streams using a ProcessBuilder:
ProcessBuilder pbuilder = new ProcessBuilder("cp", "-R", "Folder1/*", "Folder2/");
pbuilder.inheritIO();
Process proc = pbuilder.start();
return proc.waitFor();
you will get a better idea of what went wrong.
Note also that I used separate String arguments for the command. This helps with ensuring the arguments are passed right to the underlying process.
Try like this:
List<String> cmd = new ArrayList<String>();
cmd.add("bash");
cmd.add("-c");
cmd.add(" rm -rf *.txt");
add the above list in ProcessBuilder then execute.
I'm writing an application with a Java GUI which calls some FORTRAN code. I want to return a file (solution.ps) which is updated and compiled based on changes in the FORTRAN code, which are created earlier in my ActionPerformed method. However the code I have at present just returns the old version of the file rather than waiting for the updated results of the cmd compilation. Is there a way to make the cmd wait for the process to run before completing the next step? (It works fine running directly from cmd)
I've searched but can't find anything except process.waitFor() which won't seem to pause the execution at the right point. Tried Thread.waitFor() too.
I'm thinking this could be useful for anyone who wants to send user inputs to another program and return a compiled result which uses these inputs.
Anyway here is the code, thanks in advance for any help and I hope I made the problem clear.
String[] command ={"cmd",};
try {
Process p = Runtime.getRuntime().exec(command);
new Thread(new SyncPipe(p.getErrorStream(), System.err)).start();
new Thread(new SyncPipe(p.getInputStream(), System.out)).start();
PrintWriter stdin = new PrintWriter(p.getOutputStream());
stdin.println("cd c:\\g77");
stdin.println("g77setup.bat");
stdin.println("cd c:\\users\\laurence\\workspace\\areaplanner");
stdin.println("g77 -O4 genpack.f -o genpack");
stdin.println("genpack");
stdin.println("5");
/*
* The following line sets the time to run the FORTRAN code for
* - need to wait for this to complete before calling mpost
*/
stdin.println("30");
stdin.println("mpost solution.mp");
stdin.println("latex solution.tex");
stdin.println("dvips solution.dvi -o solution.ps");
stdin.close();
} catch(IOException e4){}
You are only runnng the windows shell command. To fix, suggest writing the batch file first and wait for it to finish:
String command = "cmd /c mybatchfile.bat";
Process p = Runtime.getRuntime().exec(command);
p.waitFor();
To get another section to kick off before the the first set of commands have completed, you will have to write another batch file and repeat the above. Make sure you have both process then in separate threads.
Try using waitFor so as to make the current thread wait for the process to finish its job.
Process p = Runtime.getRuntime().exec(command);
p.waitFor()
The command in your code is incomplete. And also it is advisable to use a ProcessBuilder.start() instead of Process.
I'm invoking the execution of a BAT file from Java with the Runtime object.
Is it possible to hide the BAT window during the execution of the script? How is it possible?
Try using javaw rather than java to run the script.
http://docs.oracle.com/javase/1.4.2/docs/tooldocs/windows/java.html
Update: Sorry, I think I read the question wrong. I know I've suppressed a .bat window doing something along these lines before:
http://www.geekstogo.com/forum/topic/56092-hide-the-command-prompt-windows/
Invoke start as the first command in your process builder, with the /b option:
ProcessBuilder builder = new ProcessBuilder("start", "/b", "<mybatchcommand>");
// .. set environment, handle streams
builder.start();
The /b options suppresses the command window.
Process p = Runtime.getRuntime().exec("scriptName.vbs");
In scriptName.vbs you write
var WindowStyle_Hidden = 0
var objShell = WScript.CreateObject("WScript.Shell")
var result = objShell.Run("cmd.exe /c abc.bat", WindowStyle_Hidden)
You would think that launching a bat file from Java would be an easy task but no... I have a bat file that does some sql commands for a loop of values read from a text file. It is more or less like this:
FOR /F %%x in (%CD%\listOfThings.txt) do sqlcmd -Slocalhost\MSSQL %1 %2 -d %3 -i %CD%\SQLScripts\\%%x
exit
Don't worry about the specifics they are not important. What i want is to simply run this bat file from within Java and have it wait until execution is finished. Apparently it is not easy. What i have so far is this:
Runtime.getRuntime().exec("cmd /K start SQLScriptsToRun.bat"
+" -U"+getUser()
+" -P"+getPass()
+" " + projectName);
return true;
The problem is that the exec() method returns immediately. The bat file runs for a good 2-3 minutes. I tried removing the start but to no avail. I tried many variations but it got me nowhere. Any ideas on how to do this simple task?
You should not ignore the return value of .exec(). It gives you a Process object that you can waitFor(), like this:
final Process process = Runtime.getRuntime().exec("blahblahblah");
final int exitVal = process.waitFor();
// if exitVal == 0, the command succeeded
you need to use waitFor on the process exec call returns.