Adding parameters to Runtime.getRuntime()? - java

void restartWeb() {
try {
String[] command = new String[] {"webRestarter.exe" , ">>","webLog.log"};
Runtime.getRuntime().exec(command);
} catch (java.io.IOException err) {
webServer.logError(err.getMessage());
}
}
Why doesn't this work? How could I fix it so it does work like I want it to?
-- Executes webRestarter.exe with parameters >>webLog.log
So it'd spit out something like this:
webRestarter.exe>>webLog.log

You simply can't use pipes in a exec call. Pipes are a functionality of the shell and not of the operating system. So we have to call the shell executable and pass the command. Try this instead:
String[] command = new String[] {"cmd.exe", "/c", "start webRestarter.exe", ">>","webLog.log"};

Parameters are passed directly to the webRestarter.exe command. You can't use parameters to redirect standard output to a file, as this is usually done by your command line interpreter.
However, the exec() method returns a Process object, which you could use to retrieve standard output and write it to a file.
Sources:
http://download.oracle.com/javase/6/docs/api/java/lang/Runtime.html#exec%28java.lang.String%29
http://download.oracle.com/javase/6/docs/api/java/lang/Process.html

If I'm not mistaken, pipes, redirects etc are a function of a shell. In this context, these are just arguments. You could handle this as simply as using cmd.exe with a /c switch as part of your command, I believe it'll handle this correctly, or handle the standard input/output yourself (though that's notoriously fraught with problems, I prefer something like commons-exec).

Just thought I'd mention two things that might be handy for working with Processes.
ProcessBuilder
is a good way to obtain a Process (in
code intended to run in a 1.5+ JRE).
It is recommended to carefully
read and implement all the
recommendations of When
Runtime.exec() won't.

Related

How to Run a jar from another jar and show the console output from the first runnable during the execution

I'm running a jar file from another jar like here somebody answers but waiting for the process.
Process proc = Runtime.getRuntime().exec("java -jar A.jar" + stringParams);
try {
proc.waitFor();
} catch (InterruptedException e) {
e.printStackTrace();
}
InputStream in = proc.getInputStream();
InputStream err = proc.getErrorStream();
My problem comes when i have no feedback on the status of the program that is called, but i don't want my program continues beyond those lines. I would need the standard and error outputs but the results are shown when the execution is over. Is there any way of executing and getting those streams while the jar is still running?
Buffered/unbuffered
It seems like an issue with buffered output.
Executed process (in this case java -jar <path>) buffers output and writes it only when it's done (in big chunks, we don't like that!)
So one way to go is execute process through unbuffering (very hacky tools):
unbuffered <command>
stdbuf -i0 -o0 -e0 <command>
use terminal emulation
Hacking
stdbuf is part of GNU tools.
https://www.gnu.org/software/coreutils/manual/html_node/stdbuf-invocation.html
unbuffered is part of expect package.
https://wiki.tcl.tk/3548
The key thing is making the program thinking that it's in interactive mode (like you are launching it from console).
The first two options are very hacky and do not work in all cases (idk if java command works with them?)
Emulation
The third option is most promising.
We launch a program (terminal emulator) that emulates interactive terminal making program think it's working in real active session!
Pty4j
You might use pty4j too:
From there: https://github.com/traff/pty4j
// The command to run in a PTY...
String[] cmd = { "java", "-jar", "path_to_jar" };
// The initial environment to pass to the PTY child process...
String[] env = { "TERM=xterm" };
PtyProcess pty = PtyProcess.exec(cmd, env);
OutputStream os = pty.getOutputStream();
InputStream is = pty.getInputStream();
// ... work with the streams ...
// wait until the PTY child process terminates...
int result = pty.waitFor();
// free up resources.
pty.close();
Zt-exec
Maybe it's worth trying zt-exec?
I have no idea how it executes commands.
But it may be it (I didn't test that).
Using https://github.com/zeroturnaround/zt-exec
new ProcessExecutor().command("java", "-jar path_to_jar")
.redirectOutput(new LogOutputStream() {
#Override
protected void processLine(String line) {
...
}
})
.execute();
That should work, but I didn't test that.
In general, there are no ways to nicely resolve your problem.
Depending on what platforms you want to target consider using unbuffered, stdbuff or the (slowest) terminal emulation...
Please let me know if that helps and good luck! :)

Executing commands using Java Runtime

I was successfully using AutoIt to execute commands but I was thinking I could get a more stable implementation via Runtime. That way I know the commands will always be executed and won't get thrown by Interruption exceptions, and other random crap. Is there something about Runtime that I don't know which won't allow for continuous execution of commands? Does it not have a memory for the outputs of previous commands, i.e. is it not running in a persistent command line?
The following commands navigate to a folder and execute a Maven script. How would I get this to work? If there were 10+ more commands that follow, would they execute within in the same process?
sendCommand("cmd.exe cd homepath/plugins");
sendCommand("mvn archetype:generate -DarchetypeCatalog=file://homepath/.m2/repository");
private static void sendCommand(String text) throws IOException {
Runtime.getRuntime().exec(text);
}
Runtime.exec() returns a Process instance. Call waitFor() on this object to wait until it is complete before running a next command. You can communicate with a Process via its getInputStream()/getOutputStream() methods.
Also read the Javadoc. For Runtime.exec it says "Executes the specified string command in a separate process."
A few things.
You should use Process and ProcessBuilder instead.
The commands have to be split up and tokenized according to arguments.
The way you have it written, those two commands will not be executed in the same process.
Fortunately for you, ProcessBuilder supports changing the working directory of the command anyway.
As an example:
sendCommand("homepath/plugins", "mvn", "archetype:generate", "-DarchetypeCatalog=file://homepath/.m2/repository");
private static void sendCommand(String workingDirectory, String... command) throws IOException {
Process proc = new ProcessBuilder(command).directory(new File(workingDirectory)).start();
int status = proc.waitFor();
if (status != 0) {
// Handle non-zero exit code, which means the command failed
}
}
Notice how a) the command has been split up, and b) that the working directory is passed in and set using ProcessBuilder.directory(File). This will get your desired behavior, but note that each command will still be a separate process, and there's no way to combine them with Java. You'd have to use Maven's features to get them all to run at once by specifying multiple build targets.

Command prompt doesn't open with Runtime.getRuntime().exec

I've created a GUI (swing) that executes a batch file that contains a command prompt .exe file execution with specific parameters.
When I run the batch file manually (by double clicking it), everything is as expected.
The problem is: the command prompt window doesn't open to show progress, moreover, it doesn't really start to work (only initiated) until I exit the GUI (forking?). When it starts to work, is works somewhere in the background and seen only in the task manager.
Only a blank command prompt window is opened.
From digging little bit around, I've constructed this command that gives me same result as above:
Runtime.getRuntime().exec("cmd.exe /c start \"Encoding\" cmd.exe /c start md \"" + Gui.outputDirField.getText() + "\\encoderOutput\" & cd \"" + Gui.outputDirField.getText() + "\\encoderOutput\" & \"" + Gui._batFile + "\" & pause");
Could you please assist?
Sorry if it sounds stupid..
this way works for me:
new Thread() {
#Override public void run() {
try {
Runtime.getRuntime().exec("cmd.exe /c start " + Gui._batFile);
} catch (IOException e1) {
e1.printStackTrace();
}
}
}.run();
trashgod may be on to something. We ran into issues with paths with spaces. This is from the release notes for jre 7u21
Changes to Runtime.exec
On Windows platform, the decoding of command strings specified to Runtime.exec(String), Runtime.exec(String,String[]) and Runtime.exec(String,String[],File) methods, has been improved to follow the specification more closely. This may cause problems for applications that are using one or more of these methods with commands that contain spaces in the program name, or are invoking these methods with commands that are not quoted correctly.
For example, Runtime.getRuntime().exec("C:\\My Programs\\foo.exe bar") is an attempt to launch the program "C:\\My" with the arguments "Programs\\foo.exe" and "bar". This command is likely to fail with an exception to indicate "C:\My" cannot be found.
The example Runtime.getRuntime().exec("\"C:\\My Programs\\foo.exe\" bar") is an attempt to launch the program "\"C:\\My". This command will fail with an exception to indicate the program has an embedded quote.
Applications that need to launch programs with spaces in the program name should consider using the variants of Runtime.exec that allow the command and arguments to be specified in an array.
Alternatively, the preferred way to create operating systems processes since JDK 5.0 is using java.lang.ProcessBuilder. The ProcessBuilder class has a much more complete API for setting the environment, working directory and redirecting streams for the process.
Does your bat file requiere user interaction or why are you putting a pause on your command? If so, the Runtime.exec just runs the file with no window, why would you want a Window? >ou can get a Process object as a result from the exec, from this object you can get an InputStream (and if needed, an OutputStream) so you can print your output or interact with the process.

How to run Different commands from Java Code?

I want to run different commands which can be executed on my command prompt or terminal through Java.
I did search few place but did not get appropriate reply.
I want to run a compiler which is set in the environment as VISAGE_HOME as well as run GRADLE so as to do all my build tasks.
I want to invoke all these commands from within Java Program.
Since it is a swing application I would like to invoke these commands on click of button or some other events.
My Problem is that I am not able to program this :( .
Neither do I know an API which would do this. I went through some sample codes but most of them have same kind of example codes of executing the shell commands or command prompt commands. None showed me to do the above stuff.
Have a look at ProcessBuilder. The Process object it returns has a waitFor method so you can wait for the process to finish. Then you can start your next process.
For example
Process p = new ProcessBuilder("runYourCommand").start();
InputStream in = process.getInputStream();
InputStreamReader inr = new InputStreamReader(in);
BufferedReader br = new BufferedReader(inr);
String inputLine;
while ((inputLine = br.readLine()) != null) {
System.out.println(inputLine);
}
p.waitFor();
Another interesting method on ProcessBuilder is environment(). This will return the environment variables that you can access. From the API docs
Map<String, String> env = pb.environment();
env.put("VAR1", "myValue");
Something like this:
String cmd = "gedit";
Runtime run = Runtime.getRuntime();
Process pr = run.exec(cmd);
Firstly, ProcessBuilder is your friend...
You could have a look at;
Getting started with Java’s ProcessBuilder (Linux focus)
Using ProcessBuilder to Make System Calls
Run processbuilder and get in and output
ProcessBuilder and how redirecting input and output from operating system's processes
Executing Operating System Commands from Java
Secondly, You will need to use System.getenv to find the value of the specified environment variable and substitute it yourself.
nb: Thanks to Guillaume Polet for pointing out that the Process will automatically include the path environment variable to find commands.
Also, remember, DO NOT EXECUTE ANY BLOCKING PROCESS ON THE EDT.
Executing external commands are inherently blocking actions, while not explicitly, taking into account needing to consume the output of the process or wanting to know about the processes termination, these would require you to perform some kind of blocking action. Don't do this on the EDT. It will cause you program to appear as if it's hung.
You can use the Runtime.exec methods to run commands from within Java. The system enviroment variables are normally not visible from within the jvm. You could use a launcher, that submits these system enviroment properties as jvm properties to your java application.
According to http://javarevisited.blogspot.de/2011/02/how-to-execute-native-shell-commands.html implementing the following into your code after including "java.lang.Runtime" should perfectly work:
try {
Process process = Runtime.getRuntime().exec("Command to be executed");
} catch (Exception e) {
e.printStackTrace(System.err);
}

How do I launch a completely independent process from a Java program?

I am working on a program written in Java which, for some actions, launches external programs using user-configured command lines. Currently it uses Runtime.exec() and does not retain the Process reference (the launched programs are either a text editor or archive utility, so no need for the system in/out/err streams).
There is a minor problem with this though, in that when the Java program exits, it doesn't really quit until all the launched programs are exited.
I would greatly prefer it if the launched programs were completely independent of the JVM which launched them.
The target operating system is multiple, with Windows, Linux and Mac being the minimum, but any GUI system with a JVM is really what is desired (hence the user configurability of the actual command lines).
Does anyone know how to make the launched program execute completely independently of the JVM?
Edit in response to a comment
The launch code is as follows. The code may launch an editor positioned at a specific line and column, or it may launch an archive viewer. Quoted values in the configured command line are treated as ECMA-262 encoded, and are decoded and the quotes stripped to form the desired exec parameter.
The launch occurs on the EDT.
static Throwable launch(String cmd, File fil, int lin, int col) throws Throwable {
String frs[][]={
{ "$FILE$" ,fil.getAbsolutePath().replace('\\','/') },
{ "$LINE$" ,(lin>0 ? Integer.toString(lin) : "") },
{ "$COLUMN$",(col>0 ? Integer.toString(col) : "") },
};
String[] arr; // array of parsed tokens (exec(cmd) does not handle quoted values)
cmd=TextUtil.replace(cmd,frs,true,"$$","$");
arr=(String[])ArrayUtil.removeNulls(TextUtil.stringComponents(cmd,' ',-1,true,true,true));
for(int xa=0; xa<arr.length; xa++) {
if(TextUtil.isQuoted(arr[xa],true)) {
arr[xa]=TextDecode.ecma262(TextUtil.stripQuotes(arr[xa]));
}
}
log.println("Launching: "+cmd);
Runtime.getRuntime().exec(arr);
return null;
}
This appears to be happening only when the program is launched from my IDE. I am closing this question since the problem exists only in my development environment; it is not a problem in production. From the test program in one of the answers, and further testing I have conducted I am satisfied that it is not a problem that will be seen by any user of the program on any platform.
There is a parent child relation between your processes and you have to break that.
For Windows you can try:
Runtime.getRuntime().exec("cmd /c start editor.exe");
For Linux the process seem to run detached anyway, no nohup necessary.
I tried it with gvim, midori and acroread.
import java.io.IOException;
public class Exec {
public static void main(String[] args) {
try {
Runtime.getRuntime().exec("/usr/bin/acroread");
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("Finished");
}
}
I think it is not possible to to it with Runtime.exec in a platform independent way.
for POSIX-Compatible system:
Runtime.getRuntime().exec(new String[]{"/bin/sh", "-c", "your command"}).waitFor();
I have some observations that may help other people facing similar issue.
When you use Runtime.getRuntime().exec() and then you ignore the java.lang.Process handle you get back (like in the code from original poster), there is a chance that the launched process may hang.
I have faced this issue in Windows environment and traced the problem to the stdout and stderr streams. If the launched application is writing to these streams, and the buffer for these stream fills up then the launched application may appear to hang when it tries to write to the streams. The solutions are:
Capture the Process handle and empty out the streams continually - but if you want to terminate the java application right after launching the process then this is not a feasible solution
Execute the process call as cmd /c <<process>> (this is only for Windows environment).
Suffix the process command and redirect the stdout and stderr streams to nul using 'command > nul 2>&1'
It may help if you post a test section of minimal code needed to reproduce the problem. I tested the following code on Windows and a Linux system.
public class Main {
/**
* #param args the command line arguments
*/
public static void main(String[] args) throws Exception {
Runtime.getRuntime().exec(args[0]);
}
}
And tested with the following on Linux:
java -jar JustForTesting.jar /home/monceaux/Desktop/__TMP/test.sh
where test.sh looks like:
#!/bin/bash
ping -i 20 localhost
as well as this on Linux:
java -jar JustForTesting.jar gedit
And tested this on Windows:
java -jar JustForTesting.jar notepad.exe
All of these launched their intended programs, but the Java application had no problems exiting. I have the following versions of Sun's JVM as reported by java -version :
Windows: 1.6.0_13-b03
Linux: 1.6.0_10-b33
I have not had a chance to test on my Mac yet. Perhaps there is some interaction occuring with other code in your project that may not be clear. You may want to try this test app and see what the results are.
You want to launch the program in the background, and separate it from the parent. I'd consider nohup(1).
I suspect this would require a actual process fork. Basically, the C equivalent of what you want is:
pid_t id = fork();
if(id == 0)
system(command_line);
The problem is you can't do a fork() in pure Java. What I would do is:
Thread t = new Thread(new Runnable()
{
public void run()
{
try
{
Runtime.getRuntime().exec(command);
}
catch(IOException e)
{
// Handle error.
e.printStackTrace();
}
}
});
t.start();
That way the JVM still won't exit, but no GUI and only a limited memory footprint will remain.
I tried everything mentioned here but without success. Main parent Java process can't quit until the quit of subthread even with cmd /c start and redirecting streams tu nul.
Only one reliable solution for me is this:
try {
Runtime.getRuntime().exec("psexec -i cmd /c start cmd.cmd");
}
catch (Exception e) {
// handle it
}
I know that this is not clear, but this small utility from SysInternals is very helpful and proven. Here is the link.
One way I can think of is to use Runtime.addShutdownHook to register a thread that kills off all the processes (you'd need to retain the process objects somewhere of course).
The shutdown hook is only called when the JVM exits so it should work fine.
A little bit of a hack but effective.

Categories

Resources