多个平台的|多个平台的 Java Launcher 脚本
附Java/C/C++/机器学习/算法与数据结构/前端/安卓/Python/程序员必读书籍书单大全:
书单导航页(点击右侧 极客侠栈 即可打开个人博客):极客侠栈
①【Java】学习之路吐血整理技术书从入门到进阶最全50+本(珍藏版)
②【算法数据结构+acm】从入门到进阶吐血整理书单50+本(珍藏版)
③【数据库】从入门到进阶必读18本技术书籍网盘吐血整理网盘(珍藏版)
④【Web前端】从HTML到JS到AJAX到HTTP从框架到全栈帮你走更少弯路(珍藏版)
⑤【python】书最全已整理好(从入门到进阶)(珍藏版)
⑥【机器学习】+python整理技术书(从入门到进阶已经整理好)(珍藏版)
⑦【C语言】推荐书籍从入门到进阶带你走上大牛之路(珍藏版)
⑧【安卓】入门到进阶推荐书籍整理pdf书单整理(珍藏版)
⑨【架构师】之路史诗级必读书单吐血整理四个维度系列80+本书(珍藏版)
⑩【C++】吐血整理推荐书单从入门到进阶成神之路100+本(珍藏)
?【ios】IOS书单从入门到进阶吐血整理(珍藏版)
--------------------------------------------------------------------------------------------------------------------
通常对于服务来说,过长的命令往往让人感到厌烦,人们需要的只是简单的操作,并且能够支持复杂的功能,对于 Java 开发的服务来说更是如此。
一个比较复杂的 Jar 服务使用Java启动,命令如下
java -Xms512m -Xmx512m -jar fuck.jar --config config.server -port 10086实际上许多虚拟机的语言的 Host 命令格式也是类似的。
我们分析可以知道对于基于虚拟机的语言,命令行基本上是 host+vm 运行参数+执行文件路径+输入参数。 当然如果参数较少,我们完全不用写一个 Launcher 脚本来管理服务。
Launcher 脚本需要提供的命令至少有:
- start
- stop
- restart
- status
- help
在 Windows 上早期,部分软件使用 cmd 来写启动器,然而 cmd 的功能孱弱,微软适时的推出了 PowerShell,PowerShell 在功能上非常强大,甚至要优于Shell,所以采用 PowerShell 来写启动器,并且写一个 cmd 辅助脚本启动PowerShell。
@echo offif 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
doif [ "X$line" = "X[$blockname]" ];
then
begin_block=1
continue
fiif [ $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
fineed_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=https://www.it610.com/article/$(echo $line | awk -F='{gsub("","",$2);
print $2}')
#echo "'$field':'$value'"
if [ "X$fieldname" = "X$field" ];
then
#echo "result value:'$result'"
echo $value
break
fifi
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 = https://www.it610.com/article/$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。
启动
Windows
launcher -startLinux
./launcher -start重启
launcher -restart停止服务
launcher -restart查看状态:
launcher -status帮助:
launcher -help###最终 上述代码已经托管到 GIT@OSC
项目:http://git.oschina.net/ipvb/ServiceLauncher 使用MIT协议,欢迎 Pull Request.
【多个平台的|多个平台的 Java Launcher 脚本】
推荐阅读
- 热闹中的孤独
- JAVA(抽象类与接口的区别&重载与重写&内存泄漏)
- 放屁有这三个特征的,请注意啦!这说明你的身体毒素太多
- 一个人的旅行,三亚
- 布丽吉特,人生绝对的赢家
- 慢慢的美丽
- 尽力
- 一个小故事,我的思考。
- 家乡的那条小河
- 《真与假的困惑》???|《真与假的困惑》??? ——致良知是一种伟大的力量