多个平台的Java Launcher脚本

通常对于服务来说,过长的命令往往让人感到厌烦,人们需要的只是简单的操作,并且能够支持复杂的功能,对于Java开发的服务来说更是如此。
一个比较复杂的Jar服务使用Java启动,命令如下

java -Xms512m -Xmx512m -jar fuck.jar –config config.server -port 10086

实际上许多虚拟机的语言的Host命令格式也是类似的。
我们分析可以知道对于基于虚拟机的语言,命令行基本上是 host+vm运行参数+执行文件路径+输入参数。
当然如果参数较少,我们完全不用写一个Launcher脚本来管理服务。

Launcher脚本需要提供的命令至少有:
1. start
2. stop
3. restart
4. status
5. help

实现

在Linux系统上,启动脚本应该是简单的,不许要过多依赖的,一般而言推荐使用shell脚本,实际上很多软件在Linux上的Launcher都是使用Shell语言。android studio,brackets Codebox ,甚至Chrome Firefox都有shell脚本的启动器。
在Windows上早期,部分软件使用cmd来写启动器,然而cmd的功能孱弱,微软适时的推出了PowerShell,PowerShell在功能上非常强大,甚至要优于Shell,所以采用PowerShell来写启动器,并且写一个cmd辅助脚本启动PowerShell。

@echo off

if not exist "%~dp0launcher.ps1" goto NotFound
PowerShell -NoProfile -NoLogo -ExecutionPolicy unrestricted -Command "[System.Threading.Thread]::CurrentThread.CurrentCulture = ‘‘; [System.Threading.Thread]::CurrentThread.CurrentUICulture = ‘‘;& ‘%~dp0launcher.ps1‘ %*"
goto :EOF
:NotFound
echo Not Found launcher.ps1 in %~dp0,Please reset your launcher
PAUSE

配置文件的读取

选择合适的配置文件能够简化操作,对于简单的Shell脚本而言,复杂的配置文件是难以实现的。我将Launcher的配置文件分为两类,一个是JVM的参数,也就是上面的 “-Xms512m -Xmx512m” 这种文件的格式就是按行读取,行首存在‘#’字符就抛弃。
另一类是基于INI-Style 的配置文件,主要是JDK的路径,需要运行的jar包的路径,以及重定向的设置,由于Windows和Linux的文件系统存在差异,所以在涉及到文件系统的设置迁移到了Windows和Posix节

Bash解析Ini文件:



function GetPrivateProfileString()
{
	if [ ! -f $1 ] || [ $# -ne 3 ];then
		return 1
	fi
	blockname=$2
	fieldname=$3

	begin_block=0
	end_block=0

	cat $1 | while read line
	do

		if [ "X$line" = "X[$blockname]" ];then
			begin_block=1
			continue
		fi

		if [ $begin_block -eq 1 ];then
			end_block=$(echo $line | awk ‘BEGIN{ret=0} /^\[.*\]$/{ret=1} END{print ret}‘)
			if [ $end_block -eq 1 ];then
				#echo "end block"
				break
			fi

			need_ignore=$(echo $line | awk ‘BEGIN{ret=0} /^#/{ret=1} /^$/{ret=1} END{print ret}‘)
			if [ $need_ignore -eq 1 ];then
				#echo "ignored line:" $line
				continue
			fi
			field=$(echo $line | awk -F= ‘{gsub(" |\t","",$1); print $1}‘)
			#####Fix Me We Support Space Value
			value=$(echo $line | awk -F= ‘{gsub("","",$2); print $2}‘)
			#echo "‘$field‘:‘$value‘"
			if [ "X$fieldname" = "X$field" ];then
				#echo "result value:‘$result‘"
				echo $value
				break
			fi

		fi
	done
	return 0
}

PowerShell解析Ini文件:

Function Parser-IniFile
{
    param(
        [Parameter(Position=0,Mandatory=$True,HelpMessage="Enter Your Ini File Path")]
        [ValidateNotNullorEmpty()]
        [String]$File
        )
    $ini = @{}
    $section = "NO_SECTION"
    $ini[$section] = @{}
    switch -regex -file $File {
        "^\[(.+)\]$" {
            $section = $matches[1].Trim()
            $ini[$section] = @{}
        }
        "^\s*([^#].+?)\s*=\s*(.*)" {
            $name,$value = $matches[1..2]
            # skip comments that start with semicolon:
            if (!($name.StartsWith(";"))) {
                $ini[$section][$name] = $value.Trim()
            }
        }
    }
    $ini
}

JDK的检测

查看Java路径,通常来说,launcher脚本会从launcher.cfg读取Posix(Windows) 节的JAVA_HOME键值,如果没有JAVA_HOME的变量就读取环境变量的JAVA_HOME,如果存在JAVA_HOME,但实际路径上并不存在,或者没有存在JAVA_HOME,那么再从查找java的路径。而JAVA_HOME的设置可以在有多个JDK的时候仍然正确的选择JDK.而不用带来冲突。

	jdkenv=$(GetPrivateProfileString launcher.cfg Posix JAVA_HOME)
	javabin=`which java`
	if [ -f "$jdkenv/bin/java" ]; then
		javabin="$jdkenv/bin/java"
	fi

Get-JavaSE函数是为了支持从注册表查询JDK安装。所以单独的写了一个函数。



Function Get-JavaSE
{
    $jdk=$env:JAVA_HOME
    #This is regedit search java
    return $jdk
}

$JdkRawEnv=$IniAttr["Windows"]["JAVA_HOME"]

$JavaEnv="$env:JAVA_HOME"
IF($JdkRawEnv -eq $null)
{
    $JavaEnv=Get-JavaSE
}else{
    $JavaEnv=$JdkRawEnv
}

进程的管理

先说PowerShell,PowerShell是面向对象的,我们可以轻松的获得进城对象。
我们使用Start-Process 启动一个进程。在这个cmdlet中 我们添加 -PassThru就可以得到一个进程对象

$ProcessObj= Start-Process -FilePath "${JavaExe}" -PassThru -Argumentlist "${VMOptions} -jar ${PrefixDir}\${AppPackage} $Parameters"  -RedirectStandardOutput "${StdoutFile}" -RedirectStandardError "${StdErrorFile}" -WindowStyle Hidden

$ProcessObj 可以拿到进程的Id,进程的镜像名,以及进程的资源占用情况。

当然进程对象在Get-Process也是可用的。

使用Get-Process获得一个进程,如果有进程id再好不过。如果不存在id对应的进程则会抛出异常

  $Obj=Get-Process -Id $javaid

结束一个进程需要Stop-Process 只需要输入 -Id id即可。

而对于Linux,有文件系统/proc,同样可以实现PowerShell的功能。判断进程是否存在可以检测 /proc/id是否存在,可以检查/proc/id/status 查看资源占用什么的。

我们在launcher脚本所在目录(通常也是jar包所在目录)当启动java进程成功后,我们将pid写入到launcher.lock.pid 在需要停止和重启的时候使用launcher.lock.pid存储的id来操作即可。

在PowerShell中可以用Get-Content 读取pid。在Linux中可以用cat。

最终

上述代码已经托管到[email protected]
项目:ServiceLauncher 使用MIT协议,欢迎Pull Request.

时间: 2024-10-11 11:29:35

多个平台的Java Launcher脚本的相关文章

微信公众平台接入Java实例,结合BAE

关于注册公众账号这块不详细介绍 注册完成,审核认证完,就可以开始玩了 1.如何成为开发者? 需要填写接口配置信息,需要自己的服务器资源,一般自己没有服务器,所以可以采用云服务器,例如BAE,SAE,阿里云服务器.这里用BAE 2.打开百度开放云平台官网,注册,登陆,点击开发者服务管理 2.1.点击"创建工程" 填写工程相关信息,应用名称自定义,类型选择java-tomcat,域名唯一,代码管理工具选择svn     到这里,bae应用创建完了. 3.现在来实现TOKEN验证的代码部分

微信开发 BAE运平台和java语音,微信mysql数据库开发实例 --图文开发教程

持续更新中 BAE java开发mysql数据库 图文教程 BAE java语言开发mysql源代码下载: 目前微信开发.BAE开发.java开发.mysql开发的教程很多,但是没有一个详细的介绍基于BAE平台.java语言和mysql数据库的微信开发教程.所以写了该教程,希望能给大家一点启发. 教程分为: 1.申请BAE账户: 2.在BAE平台建立web服务器应用: 3.在BAE平台建立mysql数据库服务器应用: 4.使用eclipse开发基于BAE平台的处理微信消息的web服务器系统: 5

java ScriptEngine 使用 (java运行脚本文件)

转自:http://www.tuicool.com/articles/imEbQbA Java SE 6最引人注目的新功能之一就是内嵌了脚本支持.在默认情况下,Java SE 6只支持JavaScript,但这并不以为着Java SE 6只能支持JavaScript.在Java SE 6中提供了一些接口来定义一个脚本规范,也就是JSR223.通过实现这些接口,Java SE 6可以支持任意的脚本语言(如PHP或Ruby). 运行第一个脚本程序 在使用Java SE 6运行脚本之前,必须要知道你的

老李分享:loadrunner的java user脚本开发

老李分享:loadrunner的java user脚本开发 poptest在性能测试loadrunner的课程里,以web协议为主,同时也讲解其他协议的脚本开发,对于一个性能测试工程师需要掌握一个以上的协议,在这里大家可以看看javauser的脚本开发环境如何搭建. 有对java比较熟悉的朋友,完全可以直接调用javauser来解析协议报文,处理逻辑请求. 脚本开发环境: loadrunner11.0 jdk1.6.32_x86_32 脚本开发 1.选择JavaVuser协议 2.配置java环

【原创】LoadRunner Java Vuser脚本的配置和调试指南

1 编写目的 本文介绍了Loadrunner多负载压力机的配置,并通过测试Java Vuser的数据库连接脚本对配置结果进行了验证,同时对配置过程中遇到的问题和解决的过程进行了记录,关于Java数据库编程的深入学习,大家可以参考其他Java相关教程. 文中的内容大部分来源于本人工作中解决问题的实际经验,另一部分来源于网络,所有内容本人都亲自验证,但难免有疏漏之处,如有疑问,请大家不吝赐教. 文中Loadrunner版本为9.5,操作系统类型为Windows XP和Windows 2003 Ser

2016.5.10(编写Java无脚本的JSP页面)

JSP表达式语言EL JSP页面中显示结果 jsp:useBean和jsp:getProperty两个元素冗长而笨拙 jsp:getProperty只支持对简单Bean属性的访问 使用JSP EL <jsp:getProperty>的property属性只能访问Bean的属性,而不能访问嵌套的属性 使用JSP EL(即表达式语言Expression Language) <%@ page contentType="text/html; charset=gb2312" %

如何为Android,Mac和Windows平台创建Java JNI动态链接库

Java Native Interface (JNI) 是Java和C/C++之间的桥梁.在一些情况下,为了提高Java程序的性能,扩展Java程序的功能,我们需要使用JNI.比如数据库的调用,当我们下载一个JDBC的jar包之后,解压可以看到里面包含了不同平台的动态链接库: 这篇文章介绍如何为Android,Mac和Windows平台,创建一个最简单的JNI动态链接库. 参考文章: Getting Started with JNI on Android, Windows and Mac And

BeanShell Processor_使用Java处理脚本

版权声明:本文为博主原创文章,未经博主允许不得转载. [try-catch] 建议使用Try----Catch块,这样Java语句出现问题时,日志更清晰: try { //java代码 } catch (Throwable ex) { log.error("something wrong in BeanShell PostProcessor", ex); throw ex; } [获取当前年月日时分秒毫秒] 如下示例:获取当前年月日时分秒毫秒并构造成形如"2017-08-16

python 生成java entity脚本

生成java实体的脚本 import MySQLdb import sys dbhost='192.168.2.200' dbport=3306 dbuser='root' dbpassword='zufangbao69fc' dbname='houseloan' dbtypes = {'int':'Integer', 'bigint':'Long', 'bit':'Boolean', 'datetime':'Date', 'decimal':'BigDecimal', 'varchar':'S