Showing posts with label Apache Procrun. Show all posts
Showing posts with label Apache Procrun. Show all posts

Windows Batch Tricks: Use Delayed Expansion


One trick thing in Windows Batch is how it substitutes variable value: Variable expansion occurs when the command is read. This is especially confusing in if, for and multiple statements block.

If you run the following script, the output would be: VAR is still: first here: first
set VAR=first
if "%VAR%" == "first" (
set VAR=second
echo VAR is still: first here: %VAR%
if "%VAR%" == "second" @echo You will never see this
)
The batch processor treats the whole if block as one command, it expands the variables once and only once, before it executes the if block, so it is actually run:
if "first" == "first" (
set VAR=second
echo VAR is still: first here: first
if "first" == "second" @echo You will never see this
)
EnableDelayedExpansion
The rescue is Delayed Expansion, it will cause variables to be expanded at execution time rather than at parse time. It is enabled by Setlocal EnableDelayedExpansion, and use !variable_name! to tell batch processor to expand variable value at runtime.
Practical Example: Get jvm.dll path
When use Apache Procrun to wrap one Java Application as windows Services as described in this article: Windows BAT: Using Apache Procrun to Install Java Application As Windows Service

We try to get jvm.dll path from environment variable: APP_JAVA_HOME, JAVA_HOME, and set its value to PR_JVM.
The final version is like this:

@echo off 
setlocal enabledelayedexpansion
set PR_JVM=auto
IF "%PR_JVM%" == "auto" (
set NEW_JAVA_HOME=%CV_JAVA_HOME%
if "!NEW_JAVA_HOME!" == "" (
set NEW_JAVA_HOME=%JAVA_HOME%
)
echo Using NEW_JAVA_HOME: !NEW_JAVA_HOME!
  IF not "!NEW_JAVA_HOME!" == "" (
 echo !NEW_JAVA_HOME! not empty, try to use it.
 for /F "delims=" %%i in ('dir "!NEW_JAVA_HOME!" /B /S  /a-d ^| findstr jvm.dll') do (
echo found "%%i"
set "NEW_PR_JVM=%%i"
)
 IF exist "!NEW_PR_JVM!" (
 SET "PR_JVM=!NEW_PR_JVM!"
echo NEW_PR_JVM: !NEW_PR_JVM!
)
  )
)
echo final PR_JVM: %PR_JVM%
"%PRUNSRV%" "//US//%SERVICE_NAME%" --DisplayName "%PR_DESPLAYNAME%" --Description "%PR_DESCRIPTION%" --StdOutput auto --StdError auto ^
--Classpath="%MYCLASSPATH%" --Jvm="%PR_JVM%" --JvmOptions="%PR_JAVA_OPTIONS%" --StartPath "%APP_HOME%" --Startup=auto ^
--StartMode=jvm --StartClass=StartClass --StartParams="%START_PARAMS%" ^
--StopMode=jvm  --StopClass=StopClass  --StopParams="%STOP_PARAMS%"

ENDLOCAL

The output looks like:
Using NEW_JAVA_HOME: C:\Program Files\Java\jdk1.6.0_38
C:\Program Files\Java\jdk1.6.0_38 not empty, try to use it.
found "C:\Program Files\Java\jdk1.6.0_38\jre\bin\server\jvm.dll"
NEW_PR_JVM: C:\Program Files\Java\jdk1.6.0_38\jre\bin\server\jvm.dll
final PR_JVM: C:\Program Files\Java\jdk1.6.0_38\jre\bin\server\jvm.dll

The origin version is like, which doesn't work because how batch processor expand variable value:
@echo off 
setlocal
set PR_JVM=auto
rem set CV_JAVA_HOME=
IF "%PR_JVM%" == "auto" (
set NEW_JAVA_HOME=%CV_JAVA_HOME%
if "%CV_JAVA_HOME%" == "" (
set NEW_JAVA_HOME=%JAVA_HOME%
)
echo Using NEW_JAVA_HOME: %NEW_JAVA_HOME%
  IF not "%CV_JAVA_HOME%" == "" (
 echo %CV_JAVA_HOME% not empty, try to use it.
 for /F "delims=" %%i in ('dir "%CV_JAVA_HOME%" /B /S  /a-d ^| findstr jvm.dll') do (
echo found "%%i"
set "NEW_PR_JVM=%%i"
)
 IF exist "%NEW_PR_JVM%" (
 SET "PR_JVM=%NEW_PR_JVM%"
echo NEW_PR_JVM: %NEW_PR_JVM%
)
  )
)
echo final PR_JVM: %PR_JVM%
ENDLOCAL

The output looks like:
Using NEW_JAVA_HOME:
C:\Program Files\Java\jre7 not empty, try to use it.
found "C:\Program Files\Java\jre7\bin\server\jvm.dll"
final PR_JVM: auto

Resources
EnableDelayedExpansion
Environment variable expansion occurs when the command is read
Batch file :How to set a variable inside a loop for /F
http://stackoverflow.com/questions/691047/batch-file-variables-initialized-in-a-for-loop

Using Apache Procrun to Rename Process Name of a Java Program in Windows


If we run a java application, its process name would be java.exe. There may be multiple java.exe in a system, it's hard to distinguish them. Customer may kill our application by mistake. So we want our java application have a good meaningful name such as MyApp.exe.

One approach is to use executable wrapper like 
Launch4jWinRun4JJanelNSIS to creates native Windows launchers for java application.

Another approach described is to use Apache Procrun to run the java application as a windows service. 

If we run java application in jvm mode, the default process name would be prunsrv.exe.

But we can easily give the process an meaningful name such as MyApp.exe. All we need do is rename prunsrv.exe to MyApp.exe: in install|start|stop|uninstall scripts, we replace every occurrence of prunsrv.exe to MyApp.exe.

set PRUNSRV=%~dp0%MyApp.exe
"%PRUNSRV%" //IS//%SERVICE_JAVA% --Install="%PRUNSRV%"

Compare with the first approach, running java application as a service allows us to make it start automatically when windows starts, easier to manage the service using sc start|stop|delete serviceName or net start|stop commands.

In task manager, we can see the process of our Java application is MyApp.exe:
T

Please read the full code from  
Windows BAT: Using Apache Procrun to Install Java Application As Windows Service

Labels

ANT (6) Algorithm (69) Algorithm Series (35) Android (7) Big Data (7) Blogger (14) Bugs (6) Cache (5) Chrome (19) Code Example (29) Code Quality (7) Coding Skills (5) Database (7) Debug (16) Design (5) Dev Tips (63) Eclipse (32) Git (5) Google (33) Guava (7) How to (9) Http Client (8) IDE (7) Interview (88) J2EE (13) J2SE (49) JSON (7) Java (186) JavaScript (27) Learning code (9) Lesson Learned (6) Linux (26) Lucene-Solr (112) Mac (10) Maven (8) Network (9) Nutch2 (18) Performance (9) PowerShell (11) Problem Solving (11) Programmer Skills (6) Scala (6) Security (9) Soft Skills (38) Spring (22) System Design (11) Testing (7) Text Mining (14) Tips (17) Tools (24) Troubleshooting (29) UIMA (9) Web Development (19) Windows (21) adsense (5) bat (8) regex (5) xml (5)