问题场景:
在服务器端用于数据抽取的kittle工具有时候可能出现各种问题,dos窗口异常关闭而导致数据抽取工作的异常,所以分析针对该问题研究了一点解决方案。
原因分析:
经过百度,很多都是kittle内存的问题,但是我们领导要的是内存是正常值,然后考虑它本身自启动问题。
解决方案:
附上内存解决方案技术贴:http://blog.csdn.net/huangyanlong/article/details/42453831
从应用自启动的方面考虑:
解决思路:
使用批处理脚本监控kittle进程是否已经启动,如果启动,则该脚本什么都不做,自动结束。如果进程没有启动,则使用命令行方式启动kittle。该监控任务使用windows系统自带的定时任务去定期检查它。
首先必须清楚使用命令行启动kittle的指令:
kitchen /file:(kjb文件全路径) /level:basic>>(日志文件全路径)
指令含义这里不解释。
从指令上来看,他是调用的本地kittle文件里面的一个kitchen.bat脚本执行该任务的。
所以进kitchen.bat脚本查看:
@echo off
setlocal
SET initialDir=%cd%
pushd %~dp0
SET STARTTITLE="Kitchen"
SET SPOON_CONSOLE=1
call Spoon.bat -main org.pentaho.di.kitchen.Kitchen -initialDir "%initialDir%"\ %*
popd
由脚本内容可以看出,其实它的本质上还是调用的spoon.bat这个批处理程序。同样的,我们进spoon.bat查看:
@echo off
setlocal
cd /D %~dp0
REM **************************************************
REM ** Set console window properties **
REM **************************************************
REM TITLE Spoon console
REM COLOR F0
:: **************************************************
:: ** Kettle home **
:: **************************************************
if "%KETTLE_DIR%"=="" set KETTLE_DIR=%~dp0
if %KETTLE_DIR:~-1%==\ set KETTLE_DIR=%KETTLE_DIR:~0,-1%
cd %KETTLE_DIR%
REM Special console/debug options when called from SpoonConsole.bat or SpoonDebug.bat
if "%SPOON_CONSOLE%"=="1" set PENTAHO_JAVA=java.exe
if not "%SPOON_CONSOLE%"=="1" set PENTAHO_JAVA=javaw.exe
set IS64BITJAVA=0
call "%~dp0set-pentaho-env.bat"
REM **************************************************
REM Platform Specific SWT **
REM **************************************************
REM The following line is predicated on the 64-bit Sun
REM java output from -version which
REM looks like this (at the time of this writing):
REM
REM java version "1.6.0_17"
REM Java(TM) SE Runtime Environment (build 1.6.0_17-b04)
REM Java HotSpot(TM) 64-Bit Server VM (build 14.3-b01, mixed mode)
REM
REM Below is a logic to find the directory where java can found. We will
REM temporarily change the directory to that folder where we can run java there
pushd "%_PENTAHO_JAVA_HOME%"
if exist java.exe goto USEJAVAFROMPENTAHOJAVAHOME
cd bin
if exist java.exe goto USEJAVAFROMPENTAHOJAVAHOME
popd
pushd "%_PENTAHO_JAVA_HOME%\jre\bin"
if exist java.exe goto USEJAVAFROMPATH
goto USEJAVAFROMPATH
:USEJAVAFROMPENTAHOJAVAHOME
FOR /F %%a IN ('.\java.exe -version 2^>^&1^|%windir%\system32\find /C "64-Bit"') DO (SET /a IS64BITJAVA=%%a)
GOTO CHECK32VS64BITJAVA
:USEJAVAFROMPATH
FOR /F %%a IN ('java -version 2^>^&1^|%windir%\system32\find /C "64-Bit"') DO (SET /a IS64BITJAVA=%%a)
GOTO CHECK32VS64BITJAVA
:CHECK32VS64BITJAVA
IF %IS64BITJAVA% == 1 GOTO :USE64
:USE32
REM ===========================================
REM Using 32bit Java, so include 32bit SWT Jar
REM ===========================================
set LIBSPATH=libswt\win32
GOTO :CONTINUE
:USE64
REM ===========================================
REM Using 64bit java, so include 64bit SWT Jar
REM ===========================================
set LIBSPATH=libswt\win64
set SWTJAR=..\libswt\win64
:CONTINUE
popd
REM **********************
REM Collect arguments
REM **********************
set _cmdline=
:TopArg
if %1!==! goto EndArg
set _cmdline=%_cmdline% %1
shift
goto TopArg
:EndArg
REM ******************************************************************
REM ** Set java runtime options **
REM ** Change 2048m to higher values in case you run out of memory **
REM ** or set the PENTAHO_DI_JAVA_OPTIONS environment variable **
REM ******************************************************************
if "%PENTAHO_DI_JAVA_OPTIONS%"=="" set PENTAHO_DI_JAVA_OPTIONS="-Xms512m" "-Xmx512m" "-XX:MaxPermSize=256m"
set OPT=%OPT% %PENTAHO_DI_JAVA_OPTIONS% "-Dhttps.protocols=TLSv1,TLSv1.1,TLSv1.2" "-Djava.library.path=%LIBSPATH%" "-DKETTLE_HOME=%KETTLE_HOME%" "-DKETTLE_REPOSITORY=%KETTLE_REPOSITORY%" "-DKETTLE_USER=%KETTLE_USER%" "-DKETTLE_PASSWORD=%KETTLE_PASSWORD%" "-DKETTLE_PLUGIN_PACKAGES=%KETTLE_PLUGIN_PACKAGES%" "-DKETTLE_LOG_SIZE_LIMIT=%KETTLE_LOG_SIZE_LIMIT%" "-DKETTLE_JNDI_ROOT=%KETTLE_JNDI_ROOT%"
REM ***************
REM ** Run... **
REM ***************
if %STARTTITLE%!==! SET STARTTITLE="Spoon"
REM Eventually call java instead of javaw and do not run in a separate window
if not "%SPOON_CONSOLE%"=="1" set SPOON_START_OPTION=start %STARTTITLE%
@echo on
%SPOON_START_OPTION% "%_PENTAHO_JAVA%" %OPT% -jar launcher\pentaho-application-launcher-7.0.0.0-25.jar -lib ..\%LIBSPATH% %_cmdline%
@echo off
if "%SPOON_PAUSE%"=="1" pause
以上可以看出:
1、其实该文件就是kittle软件的启动入口,通过上一步的参数判断,判断是直接启动还是从kitchen.bat启动的,如果是从kitchen.bat开始启动,则使用java.exe方式启动该软件;如果是直接双击启动,就没有读取到kitchen.bat里面传递过来的参数,所以使用javax.exe方式启动(总所周知javax.exe是启动java界面的程序)。
2、命令行启动的调用链:命令行输入指令>>kitchen.bat>>spoon.bat>>java.exe
分析调用链:
1、命令行指定调用kitchen.bat脚本,该脚本定义了一个参数:SPOON_CONSOLE,并赋值为1。
2、kitchen.bat调用spoon.bat,在spoon.bat中,通过读取上一步给定的参数来指定运行程序java.exe。
使用过tomcat的同学可能知道,tomcat启动的本质也是调用java.exe该进程,为了防止冲突,所以必须改变我们监控的对象java.exe,那么,问题来了:如何才能改变我们所需要的监控对象的进程名称?由此,百度到一个可以创建属于自己的进程方法:http://blog.csdn.net/fangdengfu123/article/details/70051498
由此我们通过逆向思维可以分析出,必须在spoon中改变原有指向的运行程序,但是又不能改变kittle的正常使用,所以这里又两种方案:
1、创建spoon.bat副本,在该副本中改变PENTAHO_JAVA的值(也就是将运行程序指向我们自己的启动程序);
2、创建kitchen.bat副本,在该副本中还是调用spoon.bat,但是修改SPOON_CONSOLE的参数值,然后在spoon.bat中对该参数进行判断,如果等于我们设置的值,则将PENTAHO_JAVA的值指向我们的程序入口。
那么本质上我们只要对java.exe进行监控,由此诞生了我们自己写的表层的批处理脚本:
@echo off
:after
:check javaKittleProHuizong.exe
tasklist >list.txt
find /i "javaKittleProHuizong.exe" list.txt
if "%errorlevel%"=="1" (goto before) else (goto over)
:before
cd e:\data-integration
start kittlePreHuizong.bat
echo "use ping to delay"
set SLEEP=ping 127.0.0.1 /n
echo %time%
%SLEEP% 30 > nul
echo %time%
:over
end
该脚本主要任务就是检查指定的javaKittleProHuizong.exe是否存在,如果存在,则直接跳到程序结束位置;如果不存在,调用我们创建的kittlePreHuizong.bat副本。
kittlePreHuizong.bat中就是一条启动kittle的指令。
然后创建我们的kittlePreHuizong.bat批处理程序:
@echo off
setlocal
SET initialDir=%cd%
pushd %~dp0
SET STARTTITLE="KitchenPreHuizong"
SET SPOON_CONSOLE=1
call SpoonPreHuizong.bat -main org.pentaho.di.kitchen.Kitchen -initialDir "%initialDir%"\ %*
popd
该脚本调用我们复制的spoon.bat副本:
SpoonPreHuizong.bat
在该副本中,我们只修改了变量的引用地址。
if “%SPOON_CONSOLE%”==”1” set PENTAHO_JAVA=javaKittleProHuizong.exe
然后在windows的定时任务里面创建定时任务定时调用该监控脚本即可。
虽然可以让该监控dos一直开着进行定时延迟然后检查进程,但是保不准负责监控的dos异常关闭,所以还是定时任务稳妥些。