Java ProcessBuilder showing console of started java application? - java

I have a JAVA application that launches (using ProcessBuilder) another JAVA application like this:
String val = "something";
ProcessBuilder processBuilder = new ProcessBuilder("java", "-classpath", dir, appName, val);
Process p = processBuilder.start();
Now, this works fine, appName is launched with the parameter val and it runs and works ... great ... the problem is no Console Window appears ... appName does a LOT of outputting to the console and we need to see it ... how can I start the process with a console?
I am trying stuff like ("CMD.exe", "java", "-classpath", dir, appName, val), etc... but I can't get it right ...
Also, I can't redirect the streams, my program can actually start 5-10 of these appName's, each should have their own console window showing their own information.
Any help would be much appreciated.
Thanks,

console windows are generally not the most reliable form of logging. they only store a set amount of information (buffer) and can behave differently across platforms.
i strongly suggest logging to a file using something like log4j and if you need to see it real time use a tail like program (i see you're using windows).
in addition to this, seeing as you want the windows visible at all times and launching a tail program for each log might be annoying, i'd write my own log window in java swing.
the basic idea is to not rely on the OS too much.

Tried Runtime.getRuntime().exec("cscript java -classpath ..."); ?
Anyway, consider using a logging framwork (log4j, commons-logging), because opening 5 consoles is not the most clever thing to do.

I call a few shell scripts via Process to open a command line window and launch whatever I need. As long as the scripts don't detach - you can usually stop any shell command from doing this -java will still hold the running process.
I did it in linux but the concept should be similar.
#!/bin/bash
# To open a process in a new window.
gnome-terminal -x ./your-real-shell-script-here.sh "$#"
the real script will have your java execution in it, such as:
#!/bin/bash
java -jar your-jar-file.jar "$#"
I think you can use javaw to run on windows, so you might only need the one shell script.

A Console object only exists when you execute java.... from a console. Otherwise, the call to obtain one returns null.
If you want to see a console, you need to open a command shell console (e.g. windows cmd.exe or Unix bash shell window) and type:
java -classpath="..." com.example.appName arg1
If you want to run in a different manner, sorry to say, logging to Console is not for you. Instead, log using one of:
log4j
slf4j
logback

Related

Running Java program in a Docker Image

So I have a Docker network that has a Docker file with a bunch of information. I have a java program that is going to bring up the enviorment and then produce several commands to run within this enviorment. To be clear, the first command I need to run is NOT inside the Docker enviorment. I am having some challenges with the Process and Runtime classes.
First, say I wanted my java program to launch a new gnome terminal and then run a command to get into the docker network. I have this command,
Process process = Runtime.getRuntime().exec(new String[]{"gnome-terminal"});
Gnome terminal sucessfully comes up but any additional arguments I give in this array are just ignored. For example,
Process process = Runtime.getRuntime().exec(new String[]{"gnome-terminal","ls"});
Does not work. The command I ultimatly want to run would look something like this,
Process process = Runtime.getRuntime().exec(new String[]{"gnome-terminal","sudo","docker","exec","-it","sawtooth-shell-default", "bash"});
Second, Once I have this running, will additional commmands I run work within the Docker enviorment? I have a python file with a Stream handler that specifies the correct commands to run.
Other documentation on related issues was limited.
I made sure my code was wrapped in a runtime exception try catch and that I was running the correct .class file. Any help on this would be great!
Edit: I have also tried to run this in another linux terminal like Hyper and Tilda
I also am able to get a sudo sign in when I run the command like so,
Process process = Runtime.getRuntime().exec(new String[]{"gnome-terminal","--","sudo","docker","exec","-it","sawtooth-shell-default", "bash"});
However it closes immediatly after authorizing.
Okay this is what I was attempting to do.
https://www.atlassian.com/blog/software-teams/deploy-java-apps-with-docker-awesome
This site is outdated and I had to use this link for getting that latest version of the java PPA.
This process basically installs java into the docker contatiner so that I can run a java program that uses Runtime.

How can I open another command line application in Linux from a Java program?

I'm trying to write a small Java command-line application that will create a new file, and then open it with the systems default editor stored in $EDITOR, and then exit after the editor is closed.
So far, without luck, I've tried the following:
Desktop dt = Desktop.getDesktop();
dt.edit(file);
This method resulted in an UnsupportedOperationException, which sort of makes sense as I'm running my program from the terminal, not as a Java appliacation from the desktop.
Right now, I have this:
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec(commandString); // "vim newfile"
proc.waitFor();
This is working, but not how I need it to. When I run
ps a | grep vim
I can see that it is indeed running in the background, with the filename I've given it:
1000 pts/1 S+ 0:00 vim 2014-07-16.23-02
Any ideas on how to make this run in the foreground?
vim, like many interactive programs, expects its stdin to be a real terminal that it can send ioctl calls to. But when executing through Runtime.exec() stdin will be redirected to the parent process (see the Javadoc on Process for more information).
In Java 7, you should be able to use ProcessBuilder.inheritIO() to pass along the file handles. (Disclaimer: I haven't tried it, YMMV.)

Java: how to execute a process which is not attached to a Windows console?

Both, Runtime.exec() as well as ProcessBuilder seem to attach a console to the started process. On Windows 7, one can see a conhost.exe popping up in the Task Manager. My problem is now that the C process I'm trying to start performs following test to determine whether it has a console window to which it can issue prompts:
HANDLE cons = CreateFile("CONOUT$", GENERIC_WRITE,
FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
if (cons != INVALID_HANDLE_VALUE) {
// Prompt user; this makes my application hang
}
Is it possible with Java to start the C process in a way that upper test fails in order to avoid the prompt?
At least on OpenJDK 6, CreateProcess is being called with CREATE_NO_WINDOW. I would imagine that the Sun JDK's code is pretty similar. This makes me wonder if something else is causing that console to be present. Have you tried running your program with javaw.exe instead of java.exe?
Thinking outside of the box, maybe JGit is a better way to solve your particular problem.
Try this:
ProcessBuilder pb = new ProcessBuilder( "cmd", "/C start /B myprogram.exe param1 param2" );
The /B flag tells start to not create a new console, though I don't know whether or not start itself will end up allocating a console when called from Java.
Using Runtime is tricky cause you need to consume the output and input with streams.. See this article:
http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html
Instead try using the exec library of apache commons.. Here's something that will get you started:
http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html

Java option -XX:OnOutOfMemoryError does not work when called through exec in bash script

I have a java application and I want to run a script whenever it experiences and OutOfMemoryException
This works great:
$ java -server -XX:OnOutOfMemoryError="./oom_script %p" TestOOMClass
Unfortunately my application is run by a bash script in production. The script boils down to this:
cmd='java -server -XX:OnOutOfMemoryError="./oom_script %p" TestOOMClass'
##does a lot of checking and cmd building here
exec -a app ${cmd}
When run like this java never respects the double quotes and thinks %p is the class. how do I prevent this? I've tried double escaping but that doesn't work.
Since your program is run as a shell script, I would suggest putting this as the first line in your shell script after the shebang:
set -xv
Then, in the crontab, put 2>&1 at the end of the command line, so STDERR and STDOUT are merged. Crontab usually emails out the STDOUT of a command to root, so you can see what the output is. If not, then apend the following to the end of the command in your crontab:
> /somedir/output.$$ 2>&1
Make sure somedir exists, and after crontab runs your command, you'll see the verbose and debug output. Each line in your shell script will be displayed before it is executed -- both as written and as the shell actually interprets it.
The set -xv becomes very useful in debugging any sell script. There could be all sorts of environmental issues involved between the cronjob and the script running under your login. You might even find a shell issue. For example, crontab usually executes shell scripts in Bourne shell and you probably have Bash or Kornshell as your default shell. Whatever it is, you'll usually find out the issue very quickly when you turn on verbose/debug mode.
You don't even have to do this to the entire script. You can put set -xv anywhere in your script to turn on verbose/debug mode, and set +xv to turn it off.
I could make several pious high minded recommendations (use quotes, don't assume environment things, prefix your command line with "bash -c" to make sure you're using the right shell, etc.), but this would be guessing what could be wrong. In order to really debug this issue, I would need to see the machine, know the OS, see your entire shell script, and understand the entire environment. And, the first thing I would do is add set -xv in your shell script.
Quotes and escaping is an art. I would suggest you add echo ${cmd} before calling exec so you can see what it looks like then.
I would suggest using
cmd='java -server -XX:OnOutOfMemoryError=\\"./oom_script %p\\" TestOOMClass'
instead (untested). You need it to look like \" when being echoed.
an alternative i suggest (to bypass the problem, not solve it indeed) is to rung and bash script and access the $PPID:
PPID The process ID of the shell's parent. This variable is readonly.
then kill the process with that ID (please bare in mind that is an untested suggestion)

Launching jEdit From Java Swing App Using Runtime.getRuntime().exec()

I'm writing a Java Swing Application running on Red Hat Enterprise Linux 5 server that I would like to launch jEdit to view log files.
Here is some example code.
public static void main(String[] args) throws IOException, InterruptedException {
String cmd = "sh -c \"java -jar /tmp/jEdit/jedit.jar /tmp/test.txt\"";
System.out.println(cmd);
Runtime.getRuntime().exec(cmd);
}
The output is:
sh -c "java -jar /tmp/jEdit/jedit.jar /tmp/test.txt"
If I copy and paste the cmd output in a terminal window, it runs fine.
I have tried a bunch of cmd values, but I can never get the jEdit window to be visible.
With changes, this process works fine on Windows.
Is what I'm doing possible on Linux?
Thanks in advance!
As jEdit is implemented in Java, perhaps it would be easier to check the source for what the main method (in the class declared in the manifest file included in the jedit.jar) does and do the same thing without using Runtime.getRuntime().exec() at all.
If you do want to stick with it, you could try passing the individual commands as an array to exec(), this often solved such problems for me.
Linux uses the concept of display ports for its X-Windows system. This allows it to maintain a different desktop environment for each user. It also allows a user on remote machine to run a desktop app from the first machine but see the UI on the remote.
Windows, having only one available desktop environment at a time, does not.
First thing you definitely have to do is add the environment variable "DISPLAY=localhost:0" to the environment from which you are launching this. However, you may also need to run 'xhost +localhost' or this may not be allowed.
Double-check, too, that you didn't successfully launch a bunch of jEdit processes that are now zombies (using top) and kill them if necessary (using kill).
Runtime.exec() needs some special attention. The exec method that accepts a String uses the space character as a delimiter to break up the string into commands. You need to use the exec method that accepts a String[]. Read more here, specifically near the bottom.
I´ve done this once and I got the same problem
What I've done is to write the command line into a text file and then execute the text file as a shell script file.
It worked fine for me.
Jedit has a launcher script, /usr/bin/jedit I guess. Simply typing jedit in command prompt runs it, at least in current version, 4.5. Try that script instead of explicit java command.

Categories

Resources