Cannot run Java Runtime.exec() on Opensuse - java

I am using Runtime.getRuntime().exec function to launch independent GUI Java application for subroutine task.
The code used is in simple manner:
Runtime.getRuntime().exec("java -jar /home/user/jar.jar");
Executing the code doesn't cause any process launch nor error occured! ProcessBuilder has same effect.
Checked to work correctly on Windows.
As seems, on some platforms it is ignored on system level outside Java, as JRE does not return any kind of error.
EDT: I edited the code to read stderr and stdout by parallel thread to preserve main app execution:
Process p = Runtime.getRuntime().exec(runCmd);
new DaemonFailPrint(p).start();
Thread code is:
public class DaemonFailPrint extends Thread {
private Process process;
public DaemonFailPrint(Process process) {
this.process = process;
}
#Override
public void run() {
try {
process.waitFor();
String out = "";
while (process.getInputStream().available() > 0) {
out += (char) process.getInputStream().read();
}
out += System.lineSeparator();
while (process.getInputStream().available() > 0) {
out += (char) process.getErrorStream().read();
}
JOptionPane.showMessageDialog(null, out);
} catch (InterruptedException | IOException ex) {
JOptionPane.showMessageDialog(null, ex);
}
}
}
The result is: I got empty message box straight after subprocess is "launched".
The mean is Process object seems to be created and finished in same time, but no error out exists.

The Runtime::exec() does not wait for the process to exit, so if you want to detect errors in the executed program itself, you'd need to use something like:
Process process = Runtime.getRuntime().exec("java -jar /home/user/jar.jar");
int rc = process.waitFor();
if (rc != 0)
{
System.err.println("The process failed with error: " + rc);
}
It might be, that the jar is not found or cannot be executed etc., those errors you normally see on the console, but if you have no console, the only clue might be the return code.
You might also want to check here how to capture the output console:
Capturing stdout when calling Runtime.exec
Seems that you can use process.getInputStream() to connect to the output stream of the process. So you can simply copy it to the console to see what happened.

So far so good! I found the answer recently by myself, still don't have a reason why it works this way, but I suppose it's all about internal difference of handling new processes in VM's on different platforms.
I had to edit the code this way, and now it works:
String[] runcmd = {"java","-jar","/home/user/jar.jar"};
Runtime.getRuntime().exec(runcmd);
Now it seems to work perfect. As I see it fails to process the file and execute then command with parameters given as same string while no error thrown on Java code level, it's possibly lost in VM internals.

Related

Trying to show the execution of bat file in eclipse console [duplicate]

In my Java application, I want to run a batch file that calls "scons -Q implicit-deps-changed build\file_load_type export\file_load_type"
It seems that I can't even get my batch file to execute. I'm out of ideas.
This is what I have in Java:
Runtime.
getRuntime().
exec("build.bat", null, new File("."));
Previously, I had a Python Sconscript file that I wanted to run but since that didn't work I decided I would call the script via a batch file but that method has not been successful as of yet.
Batch files are not an executable. They need an application to run them (i.e. cmd).
On UNIX, the script file has shebang (#!) at the start of a file to specify the program that executes it. Double-clicking in Windows is performed by Windows Explorer. CreateProcess does not know anything about that.
Runtime.
getRuntime().
exec("cmd /c start \"\" build.bat");
Note: With the start \"\" command, a separate command window will be opened with a blank title and any output from the batch file will be displayed there. It should also work with just `cmd /c build.bat", in which case the output can be read from the sub-process in Java if desired.
Sometimes the thread execution process time is higher than JVM thread waiting process time, it use to happen when the process you're invoking takes some time to be processed, use the waitFor() command as follows:
try{
Process p = Runtime.getRuntime().exec("file location here, don't forget using / instead of \\ to make it interoperable");
p.waitFor();
}catch( IOException ex ){
//Validate the case the file can't be accesed (not enought permissions)
}catch( InterruptedException ex ){
//Validate the case the process is being stopped by some external situation
}
This way the JVM will stop until the process you're invoking is done before it continue with the thread execution stack.
Runtime runtime = Runtime.getRuntime();
try {
Process p1 = runtime.exec("cmd /c start D:\\temp\\a.bat");
InputStream is = p1.getInputStream();
int i = 0;
while( (i = is.read() ) != -1) {
System.out.print((char)i);
}
} catch(IOException ioException) {
System.out.println(ioException.getMessage() );
}
ProcessBuilder is the Java 5/6 way to run external processes.
To run batch files using java if that's you're talking about...
String path="cmd /c start d:\\sample\\sample.bat";
Runtime rn=Runtime.getRuntime();
Process pr=rn.exec(path);`
This should do it.
The executable used to run batch scripts is cmd.exe which uses the /c flag to specify the name of the batch file to run:
Runtime.getRuntime().exec(new String[]{"cmd.exe", "/c", "build.bat"});
Theoretically you should also be able to run Scons in this manner, though I haven't tested this:
Runtime.getRuntime().exec(new String[]{"scons", "-Q", "implicit-deps-changed", "build\file_load_type", "export\file_load_type"});
EDIT: Amara, you say that this isn't working. The error you listed is the error you'd get when running Java from a Cygwin terminal on a Windows box; is this what you're doing? The problem with that is that Windows and Cygwin have different paths, so the Windows version of Java won't find the scons executable on your Cygwin path. I can explain further if this turns out to be your problem.
Process p = Runtime.getRuntime().exec(
new String[]{"cmd", "/C", "orgreg.bat"},
null,
new File("D://TEST//home//libs//"));
tested with jdk1.5 and jdk1.6
This was working fine for me, hope it helps others too.
to get this i have struggled more days. :(
I had the same issue. However sometimes CMD failed to run my files.
That's why i create a temp.bat on my desktop, next this temp.bat is going to run my file, and next the temp file is going to be deleted.
I know this is a bigger code, however worked for me in 100% when even Runtime.getRuntime().exec() failed.
// creating a string for the Userprofile (either C:\Admin or whatever)
String userprofile = System.getenv("USERPROFILE");
BufferedWriter writer = null;
try {
//create a temporary file
File logFile = new File(userprofile+"\\Desktop\\temp.bat");
writer = new BufferedWriter(new FileWriter(logFile));
// Here comes the lines for the batch file!
// First line is #echo off
// Next line is the directory of our file
// Then we open our file in that directory and exit the cmd
// To seperate each line, please use \r\n
writer.write("cd %ProgramFiles(x86)%\\SOME_FOLDER \r\nstart xyz.bat \r\nexit");
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
// Close the writer regardless of what happens...
writer.close();
} catch (Exception e) {
}
}
// running our temp.bat file
Runtime rt = Runtime.getRuntime();
try {
Process pr = rt.exec("cmd /c start \"\" \""+userprofile+"\\Desktop\\temp.bat" );
pr.getOutputStream().close();
} catch (IOException ex) {
Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, null, ex);
}
// deleting our temp file
File databl = new File(userprofile+"\\Desktop\\temp.bat");
databl.delete();
The following is working fine:
String path="cmd /c start d:\\sample\\sample.bat";
Runtime rn=Runtime.getRuntime();
Process pr=rn.exec(path);
This code will execute two commands.bat that exist in the path C:/folders/folder.
Runtime.getRuntime().exec("cd C:/folders/folder & call commands.bat");
import java.io.IOException;
public class TestBatch {
public static void main(String[] args) {
{
try {
String[] command = {"cmd.exe", "/C", "Start", "C:\\temp\\runtest.bat"};
Process p = Runtime.getRuntime().exec(command);
} catch (IOException ex) {
}
}
}
}
To expand on #Isha's anwser you could just do the following to get the returned output (post-facto not in rea-ltime) of the script that was run:
try {
Process process = Runtime.getRuntime().exec("cmd /c start D:\\temp\\a.bat");
System.out.println(process.getText());
} catch(IOException e) {
e.printStackTrace();
}

Batch file stopped in Java

I have a Java program (in jar) which will invoke a batch file by passing parameters. The same batch file will be invoked 10 times with different values passing through parameter.
Which means the batch will be running in parallel with 10 instances.
The issue here is, all the process getting stopped at some point without any reason.
Please advise how to fix it.
public static void run(String batpath)
{
try
{
System.out.println("Call a batch file");
Process p= Runtime.getRuntime().exec("cmd /c CD D:\\ && cd "+v_Base_Path+" && "+batpath+" ");
p.waitFor();
}
catch(Exception e)
{
System.out.println(e.getMessage());
}
}
}
Naturally, the first thing to check is whether your command cmd /C CD ... works correctly outside of Java.
Then, the recommended way to launch subprocesses is with ProcessBuilder:
The following is for Java 7 (see this answer for a Java 6 solution).
public class Processes
{
public static void main(String... args)
{
for (int i = 0; i < 10; i++)
{
try
{
System.out.println("Call a batch file " + i);
new ProcessBuilder("cmd", "/C", "echo", "hello").inheritIO().start();
//new ProcessBuilder("bad", "/C", "echo", "hello").inheritIO().start();
}
catch (Exception e)
{
System.out.println(e.getMessage());
}
}
}
}
This enables you to print out the standard output and error streams, so you can see any output from your batch files. Without this, you won't see any clue as to what is wrong with the subprocesses.
If you use the commented-out "bad" line above instead of the "good" line, then you should see errors instead of "hello"s.
(If your batch files don't produce any output or error text, or are hanging forever, then there's nothing you can do at the Java level to debug and fix them - you have to look at them directly to find out why they are not working).
Your batch files may actually be hanging because you are not reading the output streams, as mentioned in the Process documentation:
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.
See the excellent (though now somewhat out-of-date now that Java 7 and 8 are out) When Runtime.exec() won't article for a detailed discussion.

Java - Command Execution in Runtime

I tried out a simple program to execute Linux command at run time. But the following program gets compiled and runs without any error, but the text file is not getting created as intended.Is there anything wrong in this program?
import java.io.*;
class ExecuteJava
{
public static void main(String args[])
{
String historycmd = "cat ~/.bash_history >> Documents/history.txt";
try
{
Runtime runtime = Runtime.getRuntime();
Process proc = runtime.exec(historycmd);
}
catch(Exception e)
{
System.out.println(e);
}
}
}
Try accessing some of the functions Process provides. I'd start with exitValue. Typically a -1 indicates something went wrong while a 0 means nothing especially bad happened.
Also try InputStream and Error Stream, and read them fully. See if either has useful feedback for you.
Other than that, try what andy256 suggests in comments. Ensure the Documents directory exists in the executing directory of the program.
The append operator >> is meant to be interpreted as part of the command shell. Use
String[] historycmd =
{ "bash", "-c", "cat ~/.bash_history >> Documents/history.txt"};

Windows Java child process doesn't input or output when set to parent's standard IO (Command Prompt)

Under Windows, I am unable to reliably manipulate my child process' I/O when my program has been started from the command line. It's frustrating as it is standard for servers to use a console for I/O. GUIs are nice, but I'd really prefer to stick to the command line and keep things simple. I've noticed that child process I/O is just fine when I'm executing my server from the Eclipse IDE, but it's a whole different story being ran from the command line. I can't read or write to the child process, but the process would still be running. I've written some test code below that demonstrates this problem, and I'm hoping the problem could be reproduced on another machine, and then hopefully get a solution out of it. When executed from Eclipse, inherited I/O works as expected. However, when executed from the Windows command prompt, nothing can be read or written to the child process. In both cases, redirecting child process output to a file always succeeds, but input still can't be passed to the child. If there is already a solution to this problem then please link the page.
JRE/JDK Implementation:
>java -version
java version "1.7.0_01"
Java(TM) SE Runtime Environment (build 1.7.0_01-b08)
Java HotSpot(TM) 64-Bit Server VM (build 21.1-b02, mixed mode)
Consider the following code:
package com.comp8nerd4u2.io.test;
/*
* These tests attempt to confirm what I'm experiencing under my build environment
*/
import java.io.File;
import java.io.IOException;
public final class PIOTest {
/** The command to run as a child process. The command itself isn't the test, but what you use to run this Java program is the test. */
private static final String[] COMMAND = {"cmd.exe", "/c", "echo This is a test. Feel free to change this."}; // Change this to just {"cmd.exe"} or some other program that accepts input and you'll see how frustrating this is
/** Controls how the test process is built */
private static final ProcessBuilder PB = new ProcessBuilder(COMMAND);
/** How long to allow the process to run before forcibly terminating it. */
private static final long PROCESS_TIMEOUT = 10000L;
private static final Runnable R = new TimedInterruptWorker(PROCESS_TIMEOUT);
private static int n = 0;
static {
PB.redirectErrorStream(true);
}
private PIOTest() {}
public static void main(String[] args) {
// ----- Begin Tests -----
/*
* Test #1: Let's test putting our command's output onto our standard I/O streams
* Goal condition: Child process outputs expected output, and exits before the timeout. If child process expects input, it should accept entered input.
* Known success factors: Parent process' standard I/O is piped to Eclipse. Tests would probably succeed with Netbeans as well
* Known fail factors: Parent process' standard I/O is piped to Windows Command Prompt
* Result under fail condition: Child process hangs if it fills up its output buffer or requests input, but exits on its own otherwise, unless it took longer than the timeout.
*/
PB.inheritIO();
doTest();
// Test #2: Let's test putting our command's output into a file
PB.redirectOutput(new File("piotest.txt"));
doTest();
}
/**
* Performs the I/O test.
*/
private static void doTest() {
n++;
Process p = null;
try {
p = PB.start();
} catch (IOException e) {
e.printStackTrace();
return;
}
try {
Thread t = new Thread(R);
t.setDaemon(true);
t.start();
System.out.format("[Test #%d] Child exited with status code %d\n", n, p.waitFor());
t.interrupt();
} catch (InterruptedException e) {
p.destroy();
System.out.format("[Test #%d] Child took longer than the timeout.\n", n);
}
}
/**
* Useful for sending interrupts after a certain amount of time has passed.
*
* #author comp8nerd4u2
*/
private static final class TimedInterruptWorker implements Runnable {
private long timeout = 0;
private Thread target = null;
public TimedInterruptWorker(long timeout) {
this(timeout, Thread.currentThread());
}
public TimedInterruptWorker(long timeout, Thread target) {
this.timeout = timeout;
this.target = target;
}
#Override
public void run() {
try {
Thread.sleep(timeout);
} catch (InterruptedException e) {
return;
}
target.interrupt();
}
}
}
UPDATE: I modified the test to accept any command at runtime, and uploaded it to my linux vps server. I ran it from a ssh session and all child processes' I/O can be read and written to with ease. There was one thing that I have noticed. When I opened a interactive bash shell as a child process, and then redirect it's output to a file, CentOS stopped my program, I think. That or my program crashed.
[admin#comp8nerd4u2 piotest]$ java -jar piotest.jar
Enter command to run : bash
[admin#comp8nerd4u2 piotest]$ [Test #1] Child took longer than the timeout.
[1]+ Stopped java -jar piotest.jar
[admin#comp8nerd4u2 piotest]$
First line is my typing in the command. Second line is the bash shell that was spawned but i never typed anything into it so my program kills it after the timeout. It gets ready for the second test, creates the "piotest.txt" file, and then either crashes or is stopped by the OS. The actual test itself was unchanged, except that the test now allows you to enter what command to run at runtime. This works fine in linux, but not in windows. I'm hoping that someone who knows the Win32 API can somehow explain why this test fails in windows.
Have you seen this article? http://www.javaworld.com/jw-12-2000/jw-1229-traps.html?page=1
It sounds to me like you need to service the input/output streams on Windows. The article is about Runtime.exec, but I bet the native code for ProcessBuilder is very similar and has the same type of issues on Windows.
My guess as to why this works on Eclipse on Windows is that Eclipse is servicing the streams on your behalf in order to display things in the Console view.
I know I'm late in answering, but I came across this question before coming across the answer, and wanted to save anybody else in the same boat some searching.
This is actually a known bug for Windows: https://bugs.openjdk.java.net/browse/JDK-8023130
You can get around it by redirecting the streams yourself:
Process p = pb.start();
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = null;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
p.waitFor();
br.close();

Compile and run source code from Java application

I need to compile and run source code (single file), written in Python, Pascal or C, from my Java application.
I will need to know:
if compile process was successful
the return output of the compiled program
How could I accomplish that?
I have been doing the same thing..
public String compile()
{
String log="";
try {
String s= null;
//change this string to your compilers location
Process p = Runtime.getRuntime().exec("cmd /C \"C:\\Program Files\\CodeBlocks\\MinGW\\bin\\mingw32-g++.exe\" temp.cpp ");
BufferedReader stdError = new BufferedReader(new
InputStreamReader(p.getErrorStream()));
boolean error=false;
log+="\n....\n";
while ((s = stdError.readLine()) != null) {
log+=s;
error=true;
log+="\n";
}
if(error==false) log+="Compilation successful !!!";
} catch (IOException e) {
e.printStackTrace();
}
return log;
}
public int runProgram()
{
int ret = -1;
try
{
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec("cmd.exe /c start a.exe");
proc.waitFor();
ret = proc.exitValue();
} catch (Throwable t)
{
t.printStackTrace();
return ret;
}
return ret;
}
This are 2 functions used in my MiDE first one used to compile. Change the address to your compilers location. and returns the log(in case compilation was failed) to see the errors.
The 2nd one runs the compiled code. Returning the exit code to check whether it terminated correctly.
I am not a very good java coder . i guess you can improve my code a lot better ;) .. in case you do please inform me. And i am also looking for a answer on how to communicate with the created process
You could use java.lang.ProcessBuilder to execute commands and check the status.
Here JAVADOC : http://download.oracle.com/javase/1.5.0/docs/api/java/lang/ProcessBuilder.html
In general, you'll want to launch a Process that runs the external program (first the compiler, and then the compiled binary in your case), using either Runtime.getRuntime().exec() or a ProcessBuilder to spawn the Process (since your compiler probably takes a complicated set of options, the ProcessBuilder is likely a better option). This will allow you to grab the output from the process as it executes (so you can monitor the compiler output for warnings or errors), as well as its return code.
You may find the following examples helpful:
http://www.rgagnon.com/javadetails/java-0014.html
To get the return code of a running Process, just use the waitFor() method. This is convenient if you don't care about any of the output and just want the return value.
You're probably going to want to use Runtime.exec() to call the respective compiler. Check out the JavaDoc for more information about how to deal with the output, etc.
If you're mainly doing code snippets you might try running Python code using Jython. See Howto multithreaded jython scripts running from java? for details.

Categories