I'm searching for a method to create a Process that keeps running after the main process of my application quit (it already do that) and that i can re-get in another instance of my application (after first instance exit).
I mean a thing like the screens in linux shells but for a java Process.
I don't know if that's possible...
It's not possible. You can't get a Process object for existing processes, nor for processes that aren't children of your process.
screen works by never actually exiting. When you detach from a screen session it continues running in the background, maintaining control over the processes started inside of it. Re-attaching to a session makes it visible again, but it was really running the whole time.
Related
I am working in an java application where i want to make sure that a given process in the computer is idle
ex:- if we start a download process in our computer my application should be able to monitor it (process) and tell when it is over,
Most operating systems provide user commands to monitor activity of a process, like CPU or I/O. Or, at a higher level, you can get the status (running or not) of a process by its process identifier. You could exec these tools from Java, but there's nothing in core Java to do this, nor am I aware of any libraries for this purpose.
However, if you are thinking about killing a process because it is "idle", that generally wouldn't be safe. You have to know enough about the process in question to be sure it's okay to kill it, and if you know that much about it, you'll probably find that there's a way to get it to shut itself down cleanly.
If you start the process from another process, you can detect when it finishes with Process.waitFor() You can even use its exit code.
I have few java application running 24/7. I'd like to write another java application, which checks if any of this applications crashes or not. If some application has crashed i'd like to restart it. Is there any solutions for this?
I see some ways but there should be better ways to do it :
If you have control over your running applications you can make each of them listen to a given port on the machine and reply to any request on it. Then you can simply ping that port to see if the app is running.
If you launch the apps by yourself you can store their pid and then check if the process with that pid is still alive.
Each app can create a file and update it regularly. Then your monitoring app can check if the file has been updated. if not, then the app is dead.
What i can think is you can define a new custom exception in those 24/7 running programs, add that exception to blocks where you think crash can occur, and then call some method of the another java application when this exception is called by the crash.
You can use wmic utility.
Like this : Process proc = Runtime.getRuntime().exec("wmic.exe");
Then you may check for the different params associated with your java app (javaw.exe) application.
You can perhaps use the ( http://quartz-scheduler.org/ ) Quartz scheduler, or the java.util.Timer api to wake up recurrently.and check for the process. Ever time u run the process I believe u can get the PID or process ID which can be stored.
Wake up at regular intervals and invoke a shell sript to check if the process is running. If not then spawn new Process using Runtime.getRuntime()
If you can use a simple solution, your application must update an external resource from inside the core functionality of the application. If the external resource is not updated for a while, you know that the core of your application has stopped.
If you use a separate thread to update the resource, your core functionality will crash but the thread keeps on running and you detect nothing.
The external resource can be a file. Write the current time stamp there. If the time stamp is not updated for a while, then the app has crashed. Or write to a network socket if your monitor is on a separate machine to detect hardware crashes (a monitor is pretty useless if it crashes with your application).
Your monitor must know the process identifier of the Java process so that it can kill it and restart it when needed. you can write the process identifier into a file if you start the app from a shell script.
There exists a billion dollar industry that produces this kind of software monitors. It is not a trivial task.
Is there any way to make the program go through the shutdown hook if the user forces java to close (through the task manager or by closing the corresponding batch file).
My program currently runs and executes well, if the user closes the GUI then it goes through a set of steps to disconnect from the database. However, if the user closes the Java or the batch file (running side by side with the GUI) then the connection to the database isn't closed.
Is it possible to somehow force the connection closed and maybe even delete something from the tables? The batch file will probably not be an issue when I jar the program but the process killing still will.
Nope.
The shutdown hook will react to Ctrl+C, normal closes, user logouts, and normal system shut downs (which request a graceful shutdown of all applications).
However, if someone is force-closing the app it's assumed that that's what you actually want - immediate termination with no further notice. This question has been asked many times, and is confused by the behavior of many applications that, when they are asked to force-close, they actually take a long time to finally terminate. This is because in the OS's efforts to release all resources, some resources (especially certain I/O and/or file resources) don't let go immediately.
In testing an app that starts, and is intended to be running until a graceful shutdown (e.g. server software) you should run it at the console/command-line, and press Ctrl+C to stop the program (which will run the shutdown hook) rather than using Task Manager, or KILL -9.
Furthermore, there's nothing Java could even do about it if it wanted to. A force-close happens at the OS level, at which point it releases the memory, file and I/O handles in use, etc. Java does not (nor does any other program) have control over a force-close. At this point, the OS is taking charge.
Like the title says, I have written a program runs 'in the background', preferably as a Windows service. (It happens to be written in Java, with the service part provided by the tanuki wrapper, if this matters. Also, I'm running Vista, but am assuming that this happens on all versions of Windows with UAC.) I run the service as 'User X'.
I also have a companion GUI program which is typically run from the start menu (unprivileged - i.e. 'asInvoker') - also as 'User X'.
The background program (aka the service) creates files. My main need is for the unelevated GUI program to be able to read, write, and delete these files that are created by the service.
This works without hassle as long as 'User X' is not a member of the Administrators group. (Of course an admin login is required to create the service, but that's okay.)
It also works if I turn off UAC, or if I run the background program not as a service (eg. from a command prompt).
But I just can't get it to work when 'User X' is a member of Administrators, and the background program is running as a service.
The symptoms of this problem are that process explorer shows my service process as running privileged (which I glean from the processes properties' Security tab showing 'BUILTIN\Administrators - Owner'). Also, all files created by the service are owned by 'Administrators'.
If I run my background program unprivileged from a command prompt, then process explorer shows 'BUILTIN\Administrators - Deny' and all files created by the program are owned by 'User X'.
Interesting question. I just looked up some information and cannot seem to find an answer for your question as asked initially, but I have a few alternative suggestions.
First, is it feasible to change your service app so that it creates the files required then it changes the permissions on them to what you want?
Second, does the service itself really have to run as "User X"? If so, why? Is there any way around that restriction? If you can bypass that requirement, then you can just make a normal user for the service to run as.
Third, you said preferably as a service, but not that this is a requirement. Does the environment this is used in allow you to use a scheduled task? The task scheduler itself runs as a system service, and it spawns other processes to do the work of the tasks you set up. And, when setting up a scheduled task, there is an option (a check box if you're using the GUI interface) to run the task with highest privileges or not. If you go this route, you can either have the task run at logon, or you can have it run at system start (in which case, make sure you do NOT have selected "run only if logged on"). This should otherwise be similar to your service setup.
Based on your comment below, I think the third suggestion might still be an option. You could still have status information similar to that of a service by making the program handle this in its own way. Your application could have a socket open for its cross-process communication. The background process could open a ServerSocket on a known port, and it could listen for status requests.
Your client application that your users are using could attempt to connect to this socket. If the socket connects, the process is running, otherwise it is not.
If you wanted only a "running/not running" status, this would be sufficient, and the ServerSocket could accept() a connection and then immediately shutdown and close the resulting Socket; you don't even have to accept or send any information since the initial connection is all you need.
If you want to keep the ability to startup/shutdown the task, you could use this same ServerSocket for that ability. If you aren't using the socket for any other data (only for the running-or-not mentioned above), you could have the background process terminate upon receiving any data at all on the socket, regardless of what it is, and the client (or whatever you use to shut down the background process) need only connect and send a byte instead of connect and immediately disconnect.
For startup, if you want to restrain the background process to one instance, there are a few ways to easily do that. I think you should be able to configure it via the task scheduler to only allow one instance of the task. Even if not, you could have a background process starting up connect to the given port it would otherwise listen on to see if it gets a connection from something else already there, if yes this is a second instance of it so abort. Or, even simpler yet, the creation of the ServerSocket should automatically fail if you are using a static port number, so just let the new ServerSocket(myPort) fail on its own, catch the exception, and abort. So there are three different ways to ensure that your process is acting like a proper service.
To start it up in the first place, you can tell the task scheduler to start it up on user logon, or on system boot as mentioned before. You can also configure the task so that users can initiate it themselves (if for whatever reason it's not already running), in fact, you could even have the client the user's are interacting with check on the status of the process and possibly start it automatically if it's not already started - try making a new process and exec() a command such as "schtasks /run /tn "Your Task Name""
I think that covers all the bases you mentioned, and then some. And all of the above should be pretty simple. If you do decide that this might be the route you'd like to take and if either I've overlooked something or you have other criteria which further restrict you from this, let us know again.
In the end I implemented a work-around using Windows scheduled tasks, similar to what is described above, but instead of implementing my own 'start/stop' interface, I wrote a Windows service that manages my program, run as a task. When the service starts, it starts a task, and when the service is asked to stop, is stops the task. So instead of using a socket for the parent to query if the child is running, I use schtasks /Query and parse the output. To make the task exit if the parent exits, I used an RMI keepalive method on my app that was already there.
Windows scheduled tasks have some undesirable defaults for a service that are modifiable through the task scheduler GUI, but not through schtasks' command-line options - namely ExecutionTimeLimit, DisallowStartIfOnBatteries, StopIfGoingOnBatteries.) But these options can be queried and modified using the '/XML' option to schtasks /Query and /Create. So that's what I did.
I also needed to detect if I'm running on a newer or older version of Windows, because if it's an older version (without UAC) then this will all be unnecessary but more importantly defining the task will not work without supplying a password, because the /NP option to schtasks is not available.
The only weakness (other than being complicated) that I know of with my implementation is due to schtasks' note on the /NP option - "Only local resources are available." This turns out to mean that mapped network drives won't be accessible (and I hope that's all it means.) I have SMB support implemented independently, in Java, in my app where it is needed, so this weakness wasn't the end of the world.
This was a lot of work for what can probably be done with a single Win32 call. Maybe one day I will figure out how to do that.
I need to spawn a process in Java (under Linux exclusively) that will continue to run after the JVM has exited. How can I do this?
Basically the Java app should spawn an updater which stops the Java app, updates files and then starts it again.
I'm interested in a hack & slash method to just get it working as well as a better design proposal if you have one :)
If you're spawning the process using java.lang.Process it should "just work" - I don't believe the spawned process will die when the JVM exits. You might find that the Ant libraries make it easier for you to control the spawning though.
It does actually "just work", unless you're trying to be clever.
My wrapped java.lang.Process was trying to capture the script's output, so when the JVM died, the script didn't have anywhere to send output so it just dies. If I don't try to capture the output, or the script doesn't generate any or redirects everything to a file or /dev/null, everything works as it should.
I was having trouble with this and the launched process was getting killed when the JVM shutdown.
Redirecting stdout and stderr to a file fixed the issue. I guess the process was tied to the launched java app as by default it was expecting to pass its output to it.
Here's the code that worked for me (minus exception handling):
ProcessBuilder pb = new ProcessBuilder(cmd);
pb.redirectOutput(logFile);
pb.redirectError(logFile);
Process p = pb.start();
I thought the whole point of Java was that it's fully contained within the JVM. It's kinda hard to run bytecode when there's no runtime.
If you're looking to have a totally separate process you might look into trying to start a second java.exe instance. Although for your application, it might be easier to simply make a synchronized block that stops (but doesn't kill) your app, does the updating, and then re-initializes your app's data.
It won't always "just work". When JVM spawns the child and then shuts down, the child process will also shutdown in some cases. That is expected behaviour of the process. Under WIN32 systems, it just works.
E.g. If WebLogic server was started up by a Java process, and then that process exits, it also sends the shutdown signal to the WebLogic via shutdown hook in JVM, which causes WebLogic to also shutdown.
If it "just works" for you then there is no problem, however if you find yourself in a position that child process also shutsdown with JVM it is worth having a look at the "nohup" command. The process won't respond to SIGTERM signal, but will respond to SIGKILL signal, as well as normal operations.
Update: The way described above is a bit of an overkill. Another way of doing this would be to use "&" on the end of command. This will spawn a new process that is not a child of current java process.
P.S. Sorry for so many updates, I have been learning and trying it from scratch.
>>don't believe the spawned process will die when the JVM exits.
Child process is always dying on my box(SuSE) whenever I kill java. I think, the child process will die if it's dealing with I/O of the parent process(i.e., java)
If you're looking at making an updater on Linux, you're probably barking up the wrong tree. I believe all major linux distros have a package manager built in. You should use the package manager to do your updating. Nothing frustrates me more than programs that try to self-update... (I'm looking at you, Eclipse)