I am executing startup.bat programatically to start a tomcat server.
ProcessBuilder processUnzip = new ProcessBuilder("cmd", "/c", "start", "C:\\apache-tomcat-6.0.37\\startup.bat");
I need to wait till the complete startup.bat process is over. But the program ends immediately after the startup.bat is started.
Is there a way to wait till startup process is over
Update:
My requirement is to deploy a WAR file in a tomcat instance. I cannot use hot deployment or dynamic deployment. I have to do a static deployment. Basically the task is to automate the manual process of build deployment in tomcat.
You are facing this problem because startup.bat opens up a new window with Tomcat console and returns immediately.
Even if you use catalina.bat instead of startup.bat, that would still not work as that process would terminate only when Tomcat stops.
Technically, You would never know whether the tomcat is started on or until the logs tell you so. So the approach you are taking might not work.
The only crude solution I can think of is (with the same code you have), once you start the Tomcat, keep checking the console log file, at intervals, for specific string (like Server started etc) which indicate that the server has started.
BTW, if you could tell us your specific use case (why are you doing this ?), community here might come up with better alternatives.
To automate the process, you should copy the app to be deployed into tomcat deployments folder before you start the server up. If you copy any .war package to TOMCAT/webapps folder, it will get deployed by Tomcat when it starts up.
So what you need to do is to just copy the file. here are four different examples on how to do that in Java. Either that, or you can just exec a copy command.
Possibly easiest and least error prone is to do it using Files, in java 7:
Files.copy(source.toPath(), dest.toPath());
and after that is finished, then exec start command.
Update: with shutdown, you have the wait issue. You can wait doing something like this in a batch file:
CALL shutdown.bat
:LOOP
tasklist /FI "WINDOWTITLE eq Tomcat" | find /C /I ".exe" > NUL
IF ERRORLEVEL 1 (
GOTO :EOF
) ELSE (
ECHO Tomcat is still running
SLEEP 1
GOTO LOOP
)
This code assumes a Tomcat window with name 'Tomcat'. If you run Tomcat as a service, for example, that assumption is not true. For service however there are more reliable means using sc query:
SC stop "tomcat"
:LOOP
SC query "tomcat" | FIND "STATE" | FIND "RUNNING" > NUL
IF ERRORLEVEL 1 (
GOTO :EOF
) ELSE (
ECHO Tomcat is still running
SLEEP 1
GOTO LOOP
)
Here assuming service name "tomcat".
Update2: forgot we're talking about java here - with the bat above, you can use java .waitFor(), or you can program the same logic in a java file as well.
You can use Runtime to create a process and then wait for the process to finish.
You do that by doing the following.
Process process = Runtime.getRuntime().exec("cmd /c start file.bat");
int exit_value = process.waitFor();
Where in your case the file.bat is the file you want to execute.
Remove the start command to run the batch file in the foreground - then, waitFor() will wait for the batch file completion:
Process p = Runtime.getRuntime().exec("cmd /c " + path +
"\RunFromCode.bat");
If RunFromCode.bat executes the EXIT command, the command window is automatically closed. Otherwise, the command window remains open until you explicitly exit it with EXIT - the java process is waiting until the window is closed in either case.
Related
How can I configure Tomcat to automatically restart when get an out of memory [OOME] error.
As i think
-XX:OnOutOfMemoryError="/yourscripts/tomcat-restart"
But not sure here "yourscripts" stand for what directory?
The value you provide to -XX:OnOutOfMemoryError must be the fully qualified path to an executable (can be executable script). That script must return basically immediately so that the jvm can continue and shutdown. So it needs to attempt to stop and start tomcat in the background. This may result in effectively 2 scripts:
Script 1:
#!/bin/bash
script2.sh &
Script 2:
# stop tomcat
# make sure it is dead (kill "zombie" process if necessary)
# start tomcat
The -XX:OnOutOfMemoryError shoudl point to script 1.
We have created a Play application in Java and are deploying it to a dev-environment virtual machine using Atlassian Bamboo's SSH task: cd path/to/application/directory && start "" play run. This goes to the proper location, launches a new console, and starts play: the server is started successfully and we can access the site with no issues.
The problem is that the deployment task in Bamboo never stops because it is still monitoring the console where play run was called -- in the Bamboo status, we are seeing things like Deploying for 7,565 minutes. We thought adding the start "" would fix that issue, but in Bamboo it is the same as just doing the play run. Also, when we need to redeploy, we must first stop the deployment in process, and manually relaunch it.
Two questions:
How can we start the server from Bamboo in such a way that the deployment plan finishes?
How can we stop/kill the previous server from Bamboo at the beginning of the next deployment?
Bamboo is pretty bad for background tasks. Had a similar problem, eventually, we wrote a bash script that was run in background.
start.sh &1> /dev/null &2 > /dev/null &
not at all familiar with WAMP stack or the play cli, but try running it as a powershell command, which should run in and exit immediately
powershell -command "& <your command here>"
or failing that
powershell -command "& start-job { <your command here>} "
For Windows you can run background tasks using Groovy script.
Groovy can execute an external program as an process:
"/bin/application.exe".execute()
And then you can check that application is running:
println "tasklist /fi \"imagename eq application.exe\"".execute().text
I looked at this post,and they said to use a batch script to restart a tomcat server using a webapp. The issue is that if you use Runtime.exec("batch.bat"), once you do the kill for the tomcat server, the server dies and the runtime dies.
I did a quick test of this by adding some prints to my batch file to be sure:
echo "lol" > file1.txt
net stop tomcatservice
echo "lol2" > file2.txt
net start tomcatservice
echo "lol3" > file3.txt
Only file1 was created as suspected.
Is there a way to do what I want? Is there a way for me to restart the tomcat server on a schedule through code in my webapp?
Use Runtime.exec("cmd /c start batch.bat") it starts a new process so it wont be terminated when the server stops.
Create a batch file and write shutdown.bat followed by startup.bat. Call that batch file from your java code using Runtime. It should do the trick for you.
I'm currently making an effort to create test cases for one of our java applications.
In my code, my java application calls a batch file, which in turn starts a separate java process, that returns an error code that I need to consume from the calling java application.
I'm doing the following to invoke my batch file:
Process process = runTime.exec(new String[]{"cmd.exe","/c",scriptPath});
exitValue = process.waitFor();
The batch file is as follows:
#echo off
cd %~dp0
java -cp frames.FrameDriver
SET exitcode=%errorlevel%
exit /B %exitcode%
Now with the above code and batch file, my JUnit framework just hangs on this particular test case, as if it's waiting for it to end. Now when JUnit is hanging on the test case, going to the Task Manager, and ending the java.exe process would allow the JUnit framework to continue with the other cases.
Running the .bat file by double clicking it runs the Java application normally.
Adding the START batch command before the java command in my batch file seems to fix the hanging problem, but I can't seem to get the correct exit code from my Java application as it's always 0. (The Java application exits with an error code using System.exit(INTEGER_VALUE)). I'm assuming that the %errorlevel% value is being overwritten by the "start" command's own exit value.
Can anyone please tell me how to solve this problem?
Thanks.
P.S: If it makes any difference, I'm using JDK 5 and Netbeans 5.5.1.
Don't use the /B on your exit. Here is how I would do a script:
#ECHO off
ECHO Running %~nx0 in %~dp0
CALL :myfunction World
java.exe -cp frames.FrameDriver
IF NOT ERRORLEVEL 0 (
SET exitcode=1
) ELSE (
SET exitcode=0
)
GOTO :END
:myfunction
ECHO Hello %~1
EXIT /B 0
:END
EXIT %exitcode%
NOTE: Also, you can execute java program in 3 different ways:
java.exe -cp frames.FrameDriver
CALL java.exe -cp frames.FrameDriver
cmd.exe /c java.exe -cp frames.FrameDriver
This is very critical since, your Java command may exit with a exit code and in order to pass the exit code correctly to the ERRORLEVEL var, you need to use the correct method above, which I am unsure about.
We have a jboss application server running a webapp. We need to implement a "restart" button somewhere in the UI that causes the entire application server to restart. Our naive implementation was to call our /etc/init.d script with the restart command. This shuts down our application server then restarts it.
However, it appears that when the java process shuts down, the child process running the restart scripts dies as well, before getting to the point in the script where it starts the app server again.
We tried variations on adding '&' to the places where scripts are called, but that didn't help. Is there some where to fire the script and die without killing the script process?
Try using the nohup command to run something from within the script that you execute via Java. That is, if the script that you execute from Java currently runs this:
/etc/init.d/myservice restart
then change it to do this:
nohup /etc/init.d/myservice restart
Also, ensure that you DO NOT have stdin, stdout, or stderr being intercepted by the Java process. This could cause problems, potentially. Thus, maybe try this (assuming bash or sh):
nohup /etc/init.d/myservice restart >/dev/null 2>&1
Set your signal handlers in the restart script to ignore your signal with trap:
trap "" 2 # ignore SIGINT
trap "" 15 # ignore SIGTERM
After doing this, you'll need to kill your restart script with some other signal when needed, probably SIGKILL.