Reputation: 303
I am trying to convert a bash script to batch, but I am having a trouble for this one issue. The script runs a java server in the background, waits for 5 seconds, then exit with exitcode. But in batch, I am unable...
runserver.sh
java -jar java_server.jar &
pid=$!
sleep 5
kill -0 $pid
cmdStatus=$?
if [ $cmdStatus -ne 0 ]
then
exit 1
fi
exit 0
runserver.bat
@echo off
set EXITCODE=0
start /b java -jar java_server.jar
timeout /t 5
for /f "tokens=1 delims= " %%i in ('jps -m ^| findstr java_server') do set PID=%%i
IF "%PID" == "" (
set EXITCODE=1
)
EXIT EXITCODE
but if I run the above batchscript, I am never able to disown the java process and it never exists
Upvotes: 0
Views: 2248
Reputation: 49097
The first mistake in batch file code is missing %
in line IF "%PID" == ""
to really compare the value of the environment variable PID
enclosed in double quotes with the string ""
. So correct would be IF "%PID%" == ""
. For more details on string comparisons see Symbol equivalent to NEQ, LSS, GTR, etc. in Windows batch files.
The second mistake is not using two times %
on last command line EXIT EXITCODE
around the environment variable EXITCODE
to reference its value which would be correct written as EXIT %EXITCODE%
.
But the batch file should be better written as follows:
@echo off
cd /D "%~dp0"
start "" /B javaw.exe -jar "%~dp0java_server.jar"
%SystemRoot%\System32\timeout.exe /T 5 /NOBREAK >nul
jps -m 2>nul | %SystemRoot%\System32\findstr.exe /L "java_server" >nul
The batch file first makes the directory of the batch file the current directory because of java_server.jar
is most likely in directory of the batch file. %~dp0
expands to drive and path of argument 0 which is the batch file. The file path referenced with %~dp0
always ends with a backslash which is the directory separator on Windows which should be taken into account on concatenating this string with a file or folder name. The command CD fails only if the batch file is stored on a network resource accessed with a UNC path because of Windows prevents by default that a directory referenced with a UNC path instead of a drive letter becomes the current directory for downwards compatibility reasons because of many console applications work not correct with current directory not being on a drive with a drive letter.
The command START interprets first double quoted string as title for the console window opened on running a Windows console application in a separate command process. In this case no console window is opened because of using option /B
although java.exe
is a Windows console application. For that reason explicitly specifying an empty string with ""
as window title like on starting a Windows GUI application is advisable to avoid that any other double quoted argument string is interpreted as optional window title.
The option /B
is interpreted as background. Most people think that the started application is detached from current command process. This is true for Windows GUI applications, but not for console applications like java.exe
. The handle STDIN of current command process is bind with STDIN of started console application. Also the output to the handles STDOUT and STDERR of started application are redirected to console window of the running command process which nevertheless continues immediately with execution of batch script. The option /B
means just running the console application parallel to current command process without opening a new console window, but not in running the application completely detached from running command process.
The solution is quite simple in this case because there is also javaw.exe
, the Windows version of Java designed for running a Java application completely in background detached from the process starting it.
A batch file for general usage works best on specifying all files with full qualified file name which means with full path, file name and file extension. Java executable can be installed everywhere and so the folder path for this executable can't be specified in the batch file. Windows command processor has to find the executable javaw
in current directory or in any folder in list of folders of local environment variable PATH
. But it is at least possible to specify the executable javaw
with its file extension .exe
as this file extension is well known.
The JAR file java_server.jar
is specified with full path on assuming that this file is stored in same directory as the batch file. The batch file directory should be already the current directory and so %~dp0
would not be needed at all, but it does not matter to specify the file for safety with full path.
Next the standard Windows console application TIMEOUT is called with full qualified file name with options to wait 5 seconds unbreakable (requires Windows 7 or newer) and redirecting its output to device NUL.
I don't know anything about the file jps
and have not even installed Java. For that reason I assume jps
is an executable or script of which file extension listed in local environment variable PATHEXT
and stored in directory of the batch file or any other directory of which path is listed in local environment variable PATH
. It would be of course better to specify this file with file extension and if possible also with full path.
The standard output of jps
is redirected to standard input of Windows standard console application FINDSTR and the error output to device NUL to suppress it.
FINDSTR runs a case-sensitive, literal string search for java_server
on standard output of jps
. The output of FINDSTR is of no interest and therefore redirected also to device NUL to suppress it.
FINDSTR exits with 0
on searched string really found and with 1
on nothing found. The batch file should exit with 1
on not successfully starting Java server and with 0
on Java server running. This matches exactly with exit code of FINDSTR and so nothing else must be done.
cmd.exe
exits the execution of a batch file always with last exit code set by an application or command during batch file execution. This can be verified on commenting out second command line with rem
and save it, running this batch file from within a command prompt window and running next in command prompt window if errorlevel 1 echo Java server not running!
resulting in expected output Java server not running!
. Then rem
needs to be removed from second command line of batch file before saving the batch file which is run once again from within the command prompt window. After second batch file execution finished, running once again if errorlevel 1 echo Java server not running!
results in no output while running if errorlevel 0 echo Java server is running.
results in output Java server is running.
as expected.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
call /?
... explains %~dp0
cd /?
echo /?
findstr /?
if /?
start /?
See also:
Upvotes: 1