Java: Kill all subprocesses on unix - java

I got an application written in java which runs on Unix and starts two sub-processes (via Runtime.getRuntime().exec()) on startup. If the application crashed for some reason, the sub processes won't get killed.
Now, I added a shutdown hook which gets fired on every crash, ok so far. But I'd like to send a SIGTERM signal (or at least SIGINT) on UNIX console for every sub process of the application. I should be able to find their process IDs via ps, but I did not make it to extract the PID correctly and send a signal for every process.
Can anyone help?
Thank you very much!

What I'm suggesting it is not an official feature, but a tricks.
This is how I get process id for my java applications. I never found another way.
public static final String getPid() {
try {
RuntimeMXBean runtimeBean = ManagementFactory.getRuntimeMXBean();
String name = runtimeBean.getName();
int k = name.indexOf('#');
if (k > 0)
return name.substring(0, k);
} catch (Exception ex) {
}
return null;
}
This works on win, mac and linux.

Related

JMX results are confusing

I am trying to learn JMX for the last few days and now got confuse here.
I have written a simple JMX programe which is using the APIs of package java.lang.management and trying to extract the Pid, CPU time, user time. In my result I am only getting the results of current JVM thread which is my JMX programe itself but I thought I should get the result of all the processes running over JVM on the same machine. How I will get the pids, cpu time, user time for all java processes running in JVM(LINUX/WDs).
How should I can get the pids, cpu time, user time for all non-java processes running in my machine(LINUX/WDs).
My code is below:
public void update() throws Exception{
final ThreadMXBean bean = ManagementFactory.getThreadMXBean();
final long[] ids = bean.getAllThreadIds();
final ThreadInfo[] infos = bean.getThreadInfo(ids);
for (long id : ids) {
if (id == threadId) {
continue; // Exclude polling thread
}
final long c = bean.getThreadCpuTime(id);
final long u = bean.getThreadUserTime(id);
if (c == -1 || u == -1) {
continue; // Thread died
}
}
String name = null;
for (int i = 0; i < infos.length; i++) {
name = infos[i].getThreadName();
System.out.print("The name of the id is /n" + name);
}
}
I am always getting the result:
The name of the id is Attach Listener
The name of the id is Signal Dispatcher
The name of the id is Finalizer
The name of the id is Reference Handler
The name of the id is main
I have some other java processes running on my machine they are not been included in the results of bean.getAllThreadIds() API..
Ah, now I see what you want to do. I'm afraid I have some bad news.
The APIs that are exposed through ManagementFactory allow you to monitor only the JVM in which your code is running. To monitor other JVMs, you have to use the JMX Remoting API (javax.management.remote), and that introduces a whole new range of issues you have to deal with.
It sounds like what you want to do is basically write your own management console using the stock APIs provided by out-of-the-box JDK. Short answer: you can't get there from here. Slightly longer answer: you can get there from here, but the road is long, winding, uphill (nearly) the entire way, and when you're done you will most likely wish you had gone a different route (read that: use a management console that has already been written).
I recommend you use JConsole or some other management console to monitor your application(s). In my experience it is usually only important that a human (not a program) interpret the stats that are provided by the various MBeans whose references are obtainable through the ManagementFactory static methods. After all, if a program had access to, say, the amount of CPU used by some other process, what conceivable use would it have with that information (other than to provide it in some human-readable format)?

How to use system.out.println when using a servlet

I want to debug a program by using system.out.println() and what to
check the flow and variables value in eclipse while running a JIRA
plugin which is a Servlet .
When I make some changes to the code in eclipse it reflects on the
browser but when I use system.out.println where should i see the
output ?
Example Code :
#RequiresXsrfCheck
protected String doExecute()
{
LOG.info("BulkCloneDetails doExecute start...");
filterUrl = null;
cloneSubTasks = false;
cloneAttachments = false;
deleteAfterClone = false;
requestId = null;
issues = null;
getServerInfoFromPage();
**System.out.println("Print something here");**
errorsCollection.put("filterPath", i18n.getText("Remote login failed"));
addErrors(errorsCollection);
return SUCCESS;
}
You can put a tail on a file in Terminal so that you can see how it is interacted with. On a webapp I am working on I use the below method.
Username$ cd /Applications/tomcat/apache-tomcat-6.0.16/logs
Then type
tail –f catalina.out
This will then print to your Terminal window. I have had to use this method on a few projects. I advise you to use system.out.println("Name of the File I am printing from") so that if you have several of such then you will know where they are coming from and in what order.
In Eclipse you will be having a number of console options and one would be for Apache Tomcat.
Switch to that console window for observing your messages.
Hope This helps.

How to send a string to the terminal without having it to be a standard command?

I am writing a program in Java that needs to use terminal command to work.
My function basically looks like this :
public void sendLoginCommand() throws IOException
{
System.out.println("\n------------Sending Login Command------------\n");
String cmd="qskdjqhsdqsd";
Runtime rt = Runtime.getRuntime();
Process p=rt.exec(cmd);
}
public Process sendPassword(String password) throws IOException
{
System.out.println("\n------------Sending Password------------\n");
String cmd=password;
Runtime rt = Runtime.getRuntime();
Process p=rt.exec(cmd);
return p;
}
public void login(String password) throws IOException
{
sendLoginCommand();
Process p = sendPassword(password);
System.out.println("\n------------Reading Terminal Output------------\n");
Reader in = new InputStreamReader(p.getInputStream());
in = new BufferedReader(in);
char[] buffer = new char[20];
int len = in.read(buffer);
String s = new String(buffer, 0, len);
System.out.println(s);
if(s.equals("Password invalid.")) loggedIn=false;
else loggedIn=true;
}
Here, the program sends correctly th p4 login command, but then, the terminal asks for a password.
When I use the same lines that with the sendLoginCommand(), the program returns an error.
Apparently, we can send only standard commands throught Process.
I was hoping that someone knew how to send a normal string to the terminal
Thank you in advance
Your immediate problem is that you are starting separate processes for each of the 'commands' you are invoking. The password 'command' is being issued to a process that is totally unaware of the previous 'login' command.
Having said that, your more dire problem is a serious misunderstanding of what the Process class is used for and how to interact with external programs from within Java.
Here's one tutorial that may help further your education on the topic, I would advise Googling for others.
I have found the answer to my question.
The problem was that the second response of the terminal was in fact in the first one, and the password had to be sent in the middle of it.
Here is the code (I agree, my explanation is a little vague) :
String s="";
Process p = Runtime.getRuntime().exec("p4 login");
BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
char a=(char)in.read();
while(a>0 && a<256)
{
a=(char)in.read();
if(nb==14) new PrintWriter(p.getOutputStream(),true).println(password);
if(nb>16) s=s+a;
nb++;
}
if(s.startsWith("User")) loggedIn=true;
else loggedIn=false;
In order to communicate with a process, you don't start another process but write to its stdin. There's actually code in there that tries to do such a thing. Have sendLoginCommand return the created process; delete all code in sendPassword, in fact delete the whole method. In your main code write your password to the process's output stream. So what I'm saying is
new PrintWriter(sendLoginCommand().getOutputStream()).println(password);
As a side note, i strongly advice to use a pre-packaged library that already encapsulates all the technical stuff about the process communication in Java.
A good library about that is commons-exec (http://commons.apache.org/exec/.
It comes with command line helper, background thread to read the sysout/syserr output, an optional watchdog to kill the process after a given amount of time, and so on (it works of course on nearly all os).

How to launch two java program in the same time through another one?

i'm a beginner and i try to code very simple java programs and
here i have two java programs.
the first program for selecting recent files from a folder.
the second program for concatenating these recents files.
what i want is to create a third java program that
-will launch the first program.
-then wait for 10s
-launch the second java program.
i want to keep separately the first and second program.
because i want to use them for a further application.
is it that possible?
Do i have to use Process method like if i want to launch notepad.exe through java?
or else?
Thank you
There is nothing special about the main method. You can call it directly from your third program if you like.
public static void main(String[] args) throws Exception {
Program1.main(args);
Thread.sleep(10000);
Program2.main(args);
}
If you want to launch them as separate java processes, you should use the ProcessBuilder. You can also do this in groovy, very simply as:
"java <arguments>".execute()
Otherwise you can "launch" it by calling the main method as suggested by #Heathen, though they would both be running in the same JVM with that method.
You can use Process method as you described, but it isn't a wise solution to rely on an arbitrary timeout for the first program finishing. Instead you should wait for the first one exiting.
By the way, you could generate two jar files, one for each job. You then can easily create one application out each one of them and you can easily combine them to create a third application for the combined job. This is much better than creating processed from Java.
ProcessBuilder builder1 = new ProcessBuilder("firstProgram", "arg1", "arg2", ...);
ProcessBuilder builder2 = new ProcessBuilder("secondProgram", "arg1", "arg2", ...);
Process proc1 = builder1.start();
//Pauses for 10 seconds
Thread.sleep(10000);
Process proc2 = builder2.start();
//This next part is necessary to wait for the programs to finish. If you want them to
//run independently of the main thread, you can omit this part
int exitVal1 = proc1.waitFor();
int exitVal2 = proc2.waitFor();
You can get to the input, output, and error streams of a Process object, useful if you want to interact with the running process.
You can find more information about the Process object at
http://download.oracle.com/javase/6/docs/api/java/lang/Process.html
For example my code is:
import java.io.IOException;
public class Launcher
{
public static void main(String args[]) throws IOException, InterruptedException
{
try {
Process[] proc = new Process[2];
proc[0] = new ProcessBuilder("calc.exe").start();
Thread.sleep(3000);
proc[1] = new ProcessBuilder("D:\\NetBeansProjects\\GetIPAddress\\dist\\GetIPAddress.jar").start();
try {
Thread.sleep(3000);
}
catch (InterruptedException ex)
{
}
proc[0].destroy();
Thread.sleep(3000);
proc[1].destroy();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
If i replace the proc[1] by notepad.exe it's working well
thank you

How to allow running only one instance of a Java program at a time?

I need to prevent users from starting my Java application (WebStart Swing app) multiple times. So if the application is already running it shouldn't be possible to start it again or show a warning / be closed again.
Is there some convenient way to achieve this? I thought about blocking a port or write sth to a file. But hopefully you can access some system properties or the JVM?
btw. target platform is Windows XP with Java 1.5
I think your suggestion of opening a port to listen when you start your application is the best idea.
It's very easy to do and you don't need to worry about cleaning it up when you close your application. For example, if you write to a file but someone then kills the processes using Task Manager the file won't get deleted.
Also, if I remember correctly there is no easy way of getting the PID of a Java process from inside the JVM so don't try and formulate a solution using PIDs.
Something like this should do the trick:
private static final int PORT = 9999;
private static ServerSocket socket;
private static void checkIfRunning() {
try {
//Bind to localhost adapter with a zero connection queue
socket = new ServerSocket(PORT,0,InetAddress.getByAddress(new byte[] {127,0,0,1}));
}
catch (BindException e) {
System.err.println("Already running.");
System.exit(1);
}
catch (IOException e) {
System.err.println("Unexpected error.");
e.printStackTrace();
System.exit(2);
}
}
This sample code explicitly binds to 127.0.0.1 which should avoid any firewall warnings, as any traffic on this address must be from the local system.
When picking a port try to avoid one mentioned in the list of Well Known Ports. You should ideally make the port used configurable in a file or via a command line switch in case of conflicts.
As the question states that WebStart is being used, the obvious solution is to use javax.jnlp.SingleInstanceService.
This service is available in 1.5. Note that 1.5 is currently most of the way through its End Of Service Life period. Get with Java SE 6!
I think that the better idea would be to use file lock (quite an old idea :) ). Since Java 1.4 a new I/O library was introduced, that allows file locking.
Once the application starts it tries to acquire lock on a file (or create it if does not exist), when the application exits the lock is relased. If application cannot acquire a lock, it quits.
The example how to do file locking is for example in Java Developers Almanac.
If you want to use file locking in Java Web Start application or an applet you need to sing the application or the applet.
You can use JUnique library. It provides support for running single-instance java application and is open-source.
http://www.sauronsoftware.it/projects/junique/
See also my full answer at How to implement a single instance Java application?
We do the same in C++ by creating a kernal mutex object and looking for it at start up. The advantages are the same as using a socket, ie when the process dies/crashes/exits/is killed, the mutex object is cleaned up by the kernel.
I'm not a Java programmer, so I am not sure whether you can do the same kind of thing in Java?
I've create the cross platform AppLock class.
http://mixeddev.info/articles/2015/02/01/run-single-jvm-app-instance.html
It is using file lock technique.
Update. At 2016-10-14 I've created package compatible with maven/gradle https://github.com/jneat/jneat and explained it here http://mixeddev.info/articles/2015/06/01/synchronize-different-jvm-instances.html
You could use the registry, although this halfheartedly defeats the purpose of using a high-level language like java. At least your target platform is windows =D
Try JUnique:
String appId = "com.example.win.run.main";
boolean alreadyRunning;
try {
JUnique.acquireLock(appId);
alreadyRunning = false;
} catch (AlreadyLockedException e) {
alreadyRunning = true;
}
if (alreadyRunning) {
Sysout("An Instance of this app is already running");
System.exit(1);
}
I've seen so many of this questions and I was looking to solve the same problem in a platform independent way that doesn't take the chance to collide with firewalls or get into socket stuff.
So, here's what I did:
import java.io.File;
import java.io.IOException;
/**
* This static class is in charge of file-locking the program
* so no more than one instance can be run at the same time.
* #author nirei
*/
public class SingleInstanceLock {
private static final String LOCK_FILEPATH = System.getProperty("java.io.tmpdir") + File.separator + "lector.lock";
private static final File lock = new File(LOCK_FILEPATH);
private static boolean locked = false;
private SingleInstanceLock() {}
/**
* Creates the lock file if it's not present and requests its deletion on
* program termination or informs that the program is already running if
* that's the case.
* #return true - if the operation was succesful or if the program already has the lock.<br>
* false - if the program is already running
* #throws IOException if the lock file cannot be created.
*/
public static boolean lock() throws IOException {
if(locked) return true;
if(lock.exists()) return false;
lock.createNewFile();
lock.deleteOnExit();
locked = true;
return true;
}
}
Using System.getProperty("java.io.tmpdir") for the lockfile path makes sure that you will always create your lock on the same place.
Then, from your program you just call something like:
blah blah main(blah blah blah) {
try() {
if(!SingleInstanceLock.lock()) {
System.out.println("The program is already running");
System.exit(0);
}
} catch (IOException e) {
System.err.println("Couldn't create lock file or w/e");
System.exit(1);
}
}
And that does it for me. Now, if you kill the program it won't delete the lock file but you can solve this by writing the program's PID into the lockfile and making the lock() method check if that process is already running. This is left as an assingment for anyone interested. :)

Categories

Resources