I have my middle layer jar file running on the linux server. I want that jar file running in background non-stop.
nohup java -jar RushMiddleLayer.jar &
But when i re-run this command, another new instance of the jar created and running.
I have searched through google. They suggested some options.
"Bind a ServerSocket". But which is not working for me. Process killed after press enter or Ctrl+C.
I want to have two benefits from the jar. One is always running with fail. Another if restart the jar using the same command (nohup java -jar RushMiddleLayer.jar &).
It should replace the existing jar, not create the new instance.
Just to make sure I understand what you want, you want a jar file that runs in the background and it is only able to be launched once and once only?
If this is what you want, there is two ways to achieve this:
Use a port as a semaphore (as you suggested)
Use a file as a semaphore.
For option 1,
The code should be as simple as something like:
try {
serverSocket = new ServerSocket(port);
} catch (IOException e) {
System.out.println("Could not listen on port: " + port);
// ...
}
An IOException will be thrown, if you cannot open server socket on this port. However, this could also occur if some other application is using this port. So be careful what port number you choose.
For option 2,
You simply use a FileWriter and create a dummy file and keep this file open until the jar/program is finished (or closed). When a second instance of the jar attempts to open, an exception will be thrown and it won't be able to start due to the fact that it will try to open the file for writing which produces an IOException because only one process can have a write handle to a file at the same time.
Related
Info about the project: I am creating a C++ console application that manages a Minecraft server by listening to port activity. When server port is pinged, it starts the server and then periodically checks if there are established connections on that port. If none, the server is shut down and app goes into listening mode once again.
The problem arises when the server is stopped. Somehow my main console app is getting killed by the child server process and I can't seem to find out how and why or any solutions to this.
My console app creates a new cmd.exe child process that runs a "java -jar server.jar" command when starting the server. When stopping the server a simple "stop" message is written to the standard input of the child process. This all works fine and the java server stops.
However as soon as the child process exits, the console app unexpectedly crashes and the Windows "Program has stopped working." dialog appears. The curious thing is that I have tested the application on my programming laptop that runs Windows 10 and it runs without any issues there both in release and debug mode. My server machine is running Windows 7 however, so it seems to somehow be a Windows 7 problem.
Now there's no code I can really show you since it's the java and cmd.exe child process performing the exit and I of course didn't code the server.jar file. But I will attach an image link of the console when it crashes just for fun.
The child process does not have a separate window, it inherits handles from the parent console app and writes to the parent's STDOUT so messages from the child show in the main app's console.
I have tried starting the child process with CREATE_NEW_PROCESS_GROUP flag, still crashes.
I have tried ignoring SIGINT and SIGTERM signals, still crashes.
I have also verified that the application doesn't start execution of the commands following the server shutdown call (writing stop message to stdin of server process) so they can't be the problem.
If anyone has any tips or ideas about what could be the issue I'm all ears. Thanks!
Console application crashes, Windows "Program has stopped working." dialog is not shown on picture.
EDIT:
Okay, so I created a minimal reproducible example. Here is all the needed code (for C++ main function):
//security attributes for pipes
SECURITY_ATTRIBUTES saAttr;
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
saAttr.bInheritHandle = TRUE;
saAttr.lpSecurityDescriptor = NULL;
//handles for child standard input/output
HANDLE child_stdin_rd = NULL;
HANDLE child_stdin_wr = NULL;
if (!CreatePipe(&child_stdin_rd, &child_stdin_wr, &saAttr, 0))
return -1;
if (!SetHandleInformation(child_stdin_wr, HANDLE_FLAG_INHERIT, 0))
return -1;
STARTUPINFOW startupInfo;
ZeroMemory(&startupInfo, sizeof(STARTUPINFOW));
startupInfo.cb = sizeof(STARTUPINFOW);
startupInfo.hStdInput = child_stdin_rd;
startupInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
startupInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE);
startupInfo.dwFlags |= STARTF_USESTDHANDLES;
PROCESS_INFORMATION processInfo;
ZeroMemory(&processInfo, sizeof(PROCESS_INFORMATION));
//cmd.exe path
wstring exepath = L"c:\\windows\\system32\\cmd.exe";
//cmd command to start server
wstring command = L"cmd.exe /c java -Xms1G -Xmx4G -jar server.jar nogui";
LPWSTR com = new wchar_t[command.size() + 1];
copy(command.begin(), command.end(), com);
com[command.size()] = 0;
if (!CreateProcessW(exepath.c_str(), com, 0, 0, TRUE, CREATE_NEW_PROCESS_GROUP, 0, 0, &startupInfo, &processInfo))
return -1;
//sleep for 1 min, letting server start up
this_thread::sleep_for(chrono::minutes(1));
//command to stop server
string stopCmd = "stop\n\0";
DWORD stopCmdByteSize = stopCmd.size() * sizeof(char);
if (!WriteFile(child_stdin_wr, stopCmd.c_str(), stopCmdByteSize, 0, 0))
return -1;
CloseHandle(processInfo.hProcess);
CloseHandle(processInfo.hThread);
CloseHandle(child_stdin_wr);
To reproduce this, your machine would need to be running Windows 7 and in the same folder as the application must be a Minecraft server.jar file (version 1.15.2 at time of writing this) which you can get from their website. Also, the server might need some setting up first, running it for the first time by double-clicking .jar file creates all needed server files, you must open "eula.txt" and accept the EULA by changing eula=false to eula=true. Then the server should be good to go.
Like stated before, I didn't code the server.jar file and thus do not know the complete behavior of the java server program.
Bug found! Problem solved!
Ahh, after some vigorous thinking and reading the docs again to verify the code is correct I found the culprit.
In the call to the WriteFile() function I forgot to give it a pointer to a DWORD so that it can update the number of bytes the function has written.
So the following code:
if (!WriteFile(child_stdin_wr, stopCmd.c_str(), stopCmdByteSize, 0, 0))
return -1;
Needed to be changed to:
DWORD bytesWritten = 0;
if (!WriteFile(child_stdin_wr, stopCmd.c_str(), stopCmdByteSize, &bytesWritten, 0))
return -1;
So I guess it was a kind of undefined behavior that Windows 10 could handle but Windows 7 couldn't, resulting in the program crashing.. Kind of feel embarrassed for writing this lengthy post because of a small error in a function call, but there you have it folks! Thanks to those who gave tips! :)
You may have better luck using RCON, which is a protocol built into the Java edition server used to remotely manage a server with a simple TCP packet format, rather than trying to write commands to the standard input of the server directly.
See wiki.vg's page on RCON for an explanation on the packet format.
I would like to know how to create a file / directory in remote machine using Java11 ?
I did try to use:
process = Runtime.getRuntime()
.exec("ssh root#" + hostname + " 'mkdir -p "+mdbDir+"'")
.wait() or waitFor();
But i am getting an exception even though i use wait()
java.lang.IllegalThreadStateException: process has not exited
Please let me know what can be done.
You should only call Process.waitFor() without Process.wait(). Object.wait is about synchronization. It has nothing to do with process management.
You have a good example here about how to use an SSHClient from sshj, more specific for the task that you want to do:
Send ssh command from Java code
Moreover, you will probably need a trusted connection with the target server. Check if an SSH connection from your system requires a password, if your system and the server has a trusted connection it will no ask for the password.
If you still want to use your approach without a library I guess that the problem is that the execution is waiting for some input like adding the host to the knowhosts or the password, and that is the reason for the process not exiting.
`I have written a below code for running exe that presently is ran through windows service. I want to call it by java program. But i am getting below error in image. I dont know how to go through installutil or debug this error. Please help me on this.
`
import java.io.*;
public class exec {
public static void main(String[] args)throws Exception {
try {
String cmd = "D://OGLWindowsService//OGL_21052014//OGL_25_Feb_2015//OGLService.exe";
Runtime run = Runtime.getRuntime();
Process pr = run.exec(cmd);
}
catch(Exception ex) {
System.out.println(ex.getMessage());
}
}
}
You actually have the answer for your question in your first screen. windows tells you that this program is designed to be the Service and could not run from the command line. It also suggests that you use insyalutil to set your program as a service and then Windows will run it when it will need it.
Ususally service runs for some events. Most common - user connects to particular port associated with this service (for example port 80) and when such request occurs then Windows starts service progarm (IIS to answer http call) and delegate this request to this new program. Or delegeates it immediately if program is already running.
So, as you can see, Windows is in charge of the service programs. You cannot start them from command line of from another process (that's your example). You can start/stop/restart process manually in the service control window but that's still not command line or your process.
This question to readers who have used Highcharts Export Server:
I am trying to run Highcharts-3.0.2 as an export server in Java. I set it up with tomcat-7.0.41 and tried to use the example supplied (/demo). While the /demo page loaded successfully, on sending the request to generate image the log shows:
[ERROR] [http-bio-8080-exec-6 07:00:08] (SVGConverter.java:requestServer:109) POOL EXHAUSTED!!
I get the same message on every subsequent request.
On studying the code I found that when the application starts among others the following steps are executed:
AbstractPool calls on the objectfactory to create a new Server object and adds it to the blocking queue.
T object = objectFactory.create();
queue.add(object);
poolSize.getAndIncrement();
The Server object is a new java.lang.Process object. After it is created it listens on the inputstream stream.
process = new ProcessBuilder(commands).start();
final BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String readLine = bufferedReader.readLine();
if (readLine == null || !readLine.contains("ready")) {
throw new RuntimeException("Error, PhantomJS couldnot start");
}
The readLine() blocks and the control is not returned and the Server instance is never added to the queue. Hence, the pool exhausted error.
So, there must be something on the inputstream to be read so that the control can proceed. My question is what is it that I have missed here?
RESOLVED: The problem was in app.properties. The parameter script in app.properties when left empty does not work in tomcat either contrary to the documentation. It is the convertor script highcharts-convertor.js which when executed in the process (see code above) returns a string on the inputstream.
Edit Jumped the gun too soon! The parameter script when left empty works as described in the documentation. I can see in the log:
[DEBUG] [pool-1-thread-1 01:46:35] (ServerObjectFactory.java:create:33) in makeObject,
C:\Users\...\webapp\phantomjs,
C:/Users/.../workspaces/.../.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/...highcharts-convert.js, 127.0.0.1
I do not understand what goes wrong when the command is constructed correctly with all the required parameters?
Explicitly giving the complete path to the highcharts-convertor.js for the parameter script in the app.properties works.
Is anybody experiencing this behavior?
I'm working in eclipse juno service release 2, buildid:20130225-0426, Highcharts-3.0.2, tomcat-7.0.41, win7 64bit
For us using jetty or tomcat we had to explicitly give the location of both the files and, this is the kicker, make sure that all the files in the target directories listed in your app.properties files are not Read Only.
exec = C:/jetty-distribution-9.0.3.v20130506/webapps/Scripts/phantomjs/phantomjs.exe
script = C:/jetty-distribution-9.0.3.v20130506/webapps/Scripts/phantomjs/highcharts-convert.js
The C:/jetty-distribution-9.0.3.v20130506/webapps/Scripts/phantomjs directory and all contents were not flagged as Read Only. This, for some reason, allowed the scripts and phatomjs.exe to be executable by the WAR.
The export-server for java is updated lately. We noticed many people had problems with the location of the phantomJS javascripts. All javascript files necessary for phantomjs are now unzipped to a temporary location and picked up from them for later use by the application.
With this you don't have to specify any longer the filelocation of the scripts.
I have my application in Java which invokes a browser [IE or Firefox etc ] ..
Requirement is when my Java Application exits i have to kill all the web pages [Child processes ] i have opened from my Application in IE/Firefox etc..
I use the following code .
Note : cmd contains "System Browser exe path and URL"
static ArrayList<Process> pro = new ArrayList<Process>();
String cmd=" ";
Process p = Runtime.getRuntime().exec(cmd);
pro.add(p);
I maintain a static arraylist to add all the process objects .
To kill the process i invoked i use the below code
Iterator<Process> iter = pro.iterator();
while(iter.hasNext()){
Process p = iter.next();
System.out.println("Now Killing "+p.toString());
p.destroy();
}
This code[p.destroy();] is working fine for Internet Explorer , But its not working for Firefox/Chrome...
Since Firefox runs as a Main process and the process what i invoke goes as its child :(...
I have to use generic fix for Windows and Linux..
I can even go for C++ file fix which does this with some search criteria ..so that i can execute that executable from my code using
Runtime.getRuntime().exec("executable cmd");
In windows, you can run :
wmic process get description, executablepath, processid | findstr firefox
which will give you the PID of the firefox process. Then you can use tskill PID to kill
the process.
Good question.
There are several solution.
The first is the following. Run browser not directly but using script (shell for unix, bat file for windows) that will report you the process ID of the browser that it runs. Then use kill -9 PID on linux and taskkill on windows.
This solution will require you writing scripts for different platform (at list for 2).
But I have other suggestion. If the URL that you are opening in browser is yours (I mean you can add some javascript there) you can do the following. The URL that you are opening will create AJAX call to server. When you close your application you should say to server to send command to the browser to close it. At this moment javascript that is running into the browser will close its window. This is the most cross-platform solution.
BTW I think that the server that is used by mentioned AJAX component may be your own application. And the signal that you send to the AJAX component is just connection error. Really, if your application is the server and you are closing it, the AJAX call will fail. This 100% means that the browser should be closed too.
try using pkill (killing by process name) command.
Runtime.getRuntime().exec("pkill firefox");
or in c++
system("pkill firefox");
But it's not platform independent. It will run on Unix-like operating system, and not in windows.