简介Java程序的Shell脚本包装

 更新时间:2015年07月12日 11:57:01   投稿:goldensun  
这篇文章主要介绍了简介Java程序的Shell脚本包装,将Java运用于脚本程序当中,有时或许是个不错的主意~需要的朋友可以参考下

在许多Java工程中,经常会看到带有程序自定义参数调用Java命令的包装shell脚本。例如,
 

$ANT_HOME/bin/ant, $GROOVY_HOME/bin/groovy

,甚至在我们的TimeMachine Scheduler程序中也能见到
 

$TIMEMACHINE_HOME/bin/scheduler.sh

编写这些包装脚本很无聊而且容易出错。大多数的问题来自为程序设置正确的classpath。如果你正在为一个公司开发内部项目的话,那么你有可能远离纠结的路径以及环境变量问题。但是对于开源项目,人们需要使包装更加灵活和通用。大多数甚至提供了.bat版本。Windows DOS确实是个野蛮且被限制的终端而不能很好的满足你项目脚本需求。因此,我常鼓励别人尽量还是多使用Cygwi。至少它具备一个真实的bash shell。其他常见的问题就是这些包装很快就会失去控制而且在你的项目各处都会出现很多冗余脚本。

run-java包装脚本介绍

如果你看到 $TIMEMACHINE_HOME/bin/scheduler.sh 的代码,你会看到它其实是在同目录下循环调用run-java脚本。
 

DIR=$(dirname $0)
SCHEDULER_HOME=$DIR/..
$DIR/run-java -Dscheduler.home="$SCHEDULER_HOME" timemachine.scheduler.tool.SchedulerServer "$@"

正如你看到的,我们的 run-java 可以使用 -D 选项,不仅这样,它同样也能使用 -cp 选项!而且,你还能在main class后面指定这些选项!这样能够使得run-java被其他的脚本包装,并且仍旧能够添加额外的系统属性以及classpath。

例如,TimeMachine 附带了 Groovy 库,所以你可以简单的像这样调用
 

groovy:$TIMEMACHINE_HOME/bin/run-java groovy.ui.GroovyMain test.groovy

,而不用再次下载整个分支。

你可以很方便地在任何目录下使用,它确认自己的目录然后可以自动加载lib目录下的任何jar包。现在如果你想要附加更多的jar包来运行Groovy的话,可以如下使用 -cp 选项:
 

$TIMEMACHINE_HOME/bin/run-java -cp "$HOME/apps/my-app/lib/*" groovy.ui.GroovyMain test.groovy
通常如果你设置java classpath不够小心时会经常导致错误,但是使用 run-java 可以预先运行一次:
 
RUN_JAVA_DRY=1 $TIMEMACHINE_HOME/bin/run-java -cp "$HOME/apps/my-app/lib/*" groovy.ui.GroovyMain test.groovy

你只需在命令提示行中运行上面一整行代码即可。它将输出完整的附带所有选项和参数的java命令。

run-script还包含很多其它的选项,你可以通过查看其注释了解。当前的脚本能够在任何的Linux bash和Windows Cygwin中运行。


在开发中通过Maven使用 run-java

根据上面提到的示例,假设项目发布结构如下:

$TIMEMACHINE_HOME
 +- bin/run-java
 +- lib/*.jar

但是在开发过程中目录会是怎样呢?一个常见的用例便是:你希望能够运行target/classes下最新编译的代码而不是将整个项目打包或者发布。你同样可以在此种情况下使用 run-java 。首先,简单的将 bin/run-java 添加进你的项目,然后运行
 

mvn compile dependency:copy-dependencies

将会在target/dependency下生成所有的jar文件。就只需要做这些。run-java将自动的检测这些目录,并为你的main class创建正确的classpath。

如果你使用Eclipse来开发,那么你的target/classes目录将总是在更新的,run-java便能成为你项目开发中的瑰宝。

获取 run-java 包装脚本
 

#!/usr/bin/env bash
#
# Copyright 2012 Zemian Deng
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
 
# A wrapper script that run any Java6 application in unix/cygwin env.
#
# This script is assumed to be located in an application's "bin" directory. It will
# auto resolve any symbolic link and always run in relative to this application
# directory (which is one parent up from the script.) Therefore, this script can be
# run any where in the file system and it will still reference this application
# directory.
#
# This script will by default auto setup a Java classpath that picks up any "config"
# and "lib" directories under the application directory. It also will also add a
# any typical Maven project output directories such as "target/test-classes",
# "target/classes", and "target/dependency" into classpath. This can be disable by
# setting RUN_JAVA_NO_PARSE=1.
#
# If the "Default parameters" section bellow doesn't match to user's env, then user
# may override these variables in their terminal session or preset them in shell's
# profile startup script. The values of all path should be in cygwin/unix path,
# and this script will auto convert them into Windows path where is needed.
#
# User may customize the Java classpath by setting RUN_JAVA_CP, which will prefix to existing
# classpath, or use the "-cp" option, which will postfix to existing classpath.
#
# Usage:
# run-java [java_opts] <java_main_class> [-cp /more/classpath] [-Dsysprop=value]
#
# Example:
# run-java example.Hello
# run-java example.Hello -Dname=World
# run-java org.junit.runner.JUnitCore example.HelloTest -cp "C:\apps\lib\junit4.8.2\*"
#
# Created by: Zemian Deng 03/09/2012
 
# This run script dir (resolve to absolute path)
SCRIPT_DIR=$(cd $(dirname $0) && pwd) # This dir is where this script live.
APP_DIR=$(cd $SCRIPT_DIR/.. && pwd)  # Assume the application dir is one level up from script dir.
 
# Default parameters
JAVA_HOME=${JAVA_HOME:=/apps/jdk}  # This is the home directory of Java development kit.
RUN_JAVA_CP=${RUN_JAVA_CP:=$CLASSPATH}  # A classpath prefix before -classpath option, default to $CLASSPATH
RUN_JAVA_OPTS=${RUN_JAVA_OPTS:=}   # Java options (-Xmx512m -XX:MaxPermSize=128m etc)
RUN_JAVA_DEBUG=${RUN_JAVA_DEBUG:=}   # If not empty, print the full java command line before executing it.
RUN_JAVA_NO_PARSE=${RUN_JAVA_NO_PARSE:=} # If not empty, skip the auto parsing of -D and -cp options from script arguments.
RUN_JAVA_NO_AUTOCP=${RUN_JAVA_NO_AUTOCP:=} # If not empty, do not auto setup Java classpath
RUN_JAVA_DRY=${RUN_JAVA_DRY:=}    # If not empty, do not exec Java command, but just print
 
# OS specific support. $var _must_ be set to either true or false.
CYGWIN=false;
case "`uname`" in
 CYGWIN*) CYGWIN=true ;;
esac
 
# Define where is the java executable is
JAVA_CMD=java
if [ -d "$JAVA_HOME" ]; then
  JAVA_CMD="$JAVA_HOME/bin/java"
fi
 
# Auto setup applciation's Java Classpath (only if they exists)
if [ -z "$RUN_JAVA_NO_AUTOCP" ]; then
  if $CYGWIN; then
    # Provide Windows directory conversion
    JAVA_HOME_WIN=$(cygpath -aw "$JAVA_HOME")
    APP_DIR_WIN=$(cygpath -aw "$APP_DIR")
 
    if [ -d "$APP_DIR_WIN\config" ]; then RUN_JAVA_CP="$RUN_JAVA_CP;$APP_DIR_WIN\config" ; fi
    if [ -d "$APP_DIR_WIN\target\test-classes" ]; then RUN_JAVA_CP="$RUN_JAVA_CP;$APP_DIR_WIN\target\test-classes" ; fi
    if [ -d "$APP_DIR_WIN\target\classes" ]; then RUN_JAVA_CP="$RUN_JAVA_CP;$APP_DIR_WIN\target\classes" ; fi
    if [ -d "$APP_DIR_WIN\target\dependency" ]; then RUN_JAVA_CP="$RUN_JAVA_CP;$APP_DIR_WIN\target\dependency\*" ; fi
    if [ -d "$APP_DIR_WIN\lib" ]; then RUN_JAVA_CP="$RUN_JAVA_CP;$APP_DIR_WIN\lib\*" ; fi
  else
    if [ -d "$APP_DIR/config" ]; then RUN_JAVA_CP="$RUN_JAVA_CP:$APP_DIR/config" ; fi
    if [ -d "$APP_DIR/target/test-classes" ]; then RUN_JAVA_CP="$RUN_JAVA_CP:$APP_DIR/target/test-classes" ; fi
    if [ -d "$APP_DIR/target/classes" ]; then RUN_JAVA_CP="$RUN_JAVA_CP:$APP_DIR/target/classes" ; fi
    if [ -d "$APP_DIR/target/dependency" ]; then RUN_JAVA_CP="$RUN_JAVA_CP:$APP_DIR/target/dependency/*" ; fi
    if [ -d "$APP_DIR/lib" ]; then RUN_JAVA_CP="$RUN_JAVA_CP:$APP_DIR/lib/*" ; fi
  fi
fi
 
# Parse addition "-cp" and "-D" after the Java main class from script arguments
# This is done for convenient sake so users do not have to export RUN_JAVA_CP and RUN_JAVA_OPTS
# saparately, but now they can pass into end of this run-java script instead.
# This can be disable by setting RUN_JAVA_NO_PARSE=1.
if [ -z "$RUN_JAVA_NO_PARSE" ]; then 
  # Prepare variables for parsing
  FOUND_CP=
  declare -a NEW_ARGS
  IDX=0
   
  # Parse all arguments and look for "-cp" and "-D"
  for ARG in "$@"; do
    if [[ -n $FOUND_CP ]]; then 
      if [ "$OS" = "Windows_NT" ]; then
        # Can't use cygpath here, because cygpath will auto expand "*", which we do not
        # want. User will just have to use OS path when specifying "-cp" option.  
        #ARG=$(cygpath -w -a $ARG)
        RUN_JAVA_CP="$RUN_JAVA_CP;$ARG"
      else
        RUN_JAVA_CP="$RUN_JAVA_CP:$ARG"
      fi
      FOUND_CP=
    else
      case $ARG in
      '-cp')
        FOUND_CP=1
        ;;
      '-D'*)
        RUN_JAVA_OPTS="$RUN_JAVA_OPTS $ARG"
        ;;
      *)
        NEW_ARGS[$IDX]="$ARG"
        let IDX=$IDX+1
        ;;
      esac
    fi
  done
     
  # Display full Java command.
  if [ -n "$RUN_JAVA_DEBUG" ] || [ -n "$RUN_JAVA_DRY" ]; then
    echo "$JAVA_CMD" $RUN_JAVA_OPTS -cp "$RUN_JAVA_CP" "${NEW_ARGS[@]}"
  fi
   
  # Run Java Main class using parsed variables
  if [ -z "$RUN_JAVA_DRY" ]; then
    "$JAVA_CMD" $RUN_JAVA_OPTS -cp "$RUN_JAVA_CP" "${NEW_ARGS[@]}"
  fi
else
  # Display full Java command.
  if [ -n "$RUN_JAVA_DEBUG" ] || [ -n "$RUN_JAVA_DRY" ]; then
    echo "$JAVA_CMD" $RUN_JAVA_OPTS -cp "$RUN_JAVA_CP" "$@"
  fi
   
  # Run Java Main class
  if [ -z "$RUN_JAVA_DRY" ]; then
    "$JAVA_CMD" $RUN_JAVA_OPTS -cp "$RUN_JAVA_CP" "$@"
  fi
fi

相关文章

  • Java的SpringMVC中控制器返回XML数据问题

    Java的SpringMVC中控制器返回XML数据问题

    这篇文章主要介绍了Java的SpringMVC中控制器返回XML数据问题,控制器是处理HTTP请求的组件,它们接收来自客户端的请求,并将其转换为适当的响应,这些响应可以是动态生成的 HTML 页面,也可以是JSON或XML格式的数据,需要的朋友可以参考下
    2023-07-07
  • maven打包时候修改包名称带上git版本号和打包时间方式

    maven打包时候修改包名称带上git版本号和打包时间方式

    这篇文章主要介绍了maven打包时候修改包名称带上git版本号和打包时间方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-04-04
  • 搭建公司私有MAVEN仓库的方法

    搭建公司私有MAVEN仓库的方法

    这篇文章主要介绍了搭建公司私有MAVEN仓库的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-11-11
  • Java中优先队列PriorityQueue常用方法示例

    Java中优先队列PriorityQueue常用方法示例

    这篇文章主要介绍了Java中优先队列PriorityQueue常用方法示例,PriorityQueue是一种特殊的队列,满足队列的“队尾进、队头出”条件,但是每次插入或删除元素后,都对队列进行调整,使得队列始终构成最小堆(或最大堆),需要的朋友可以参考下
    2023-09-09
  • Java设置PDF有序和无序列表的知识点总结

    Java设置PDF有序和无序列表的知识点总结

    在本篇文章中小编给大家整理了关于Java设置PDF有序和无序列表的知识点,需要的朋友们参考下。
    2019-03-03
  • 详解利用SpringMVC拦截器控制Controller返回值

    详解利用SpringMVC拦截器控制Controller返回值

    这篇文章主要介绍了详解利用SpringMVC拦截器控制Controller返回值,通过定义一个StringResult注解,在访问方法的时候返回StringResult中的内容,有兴趣的可以了解一下。
    2017-01-01
  • Springboot+SpringSecurity+JWT实现用户登录和权限认证示例

    Springboot+SpringSecurity+JWT实现用户登录和权限认证示例

    这篇文章主要介绍了Springboot+SpringSecurity+JWT实现用户登录和权限认证示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-06-06
  • java实现求两个字符串最长公共子串的方法

    java实现求两个字符串最长公共子串的方法

    这篇文章主要介绍了java实现求两个字符串最长公共子串的方法,是一道华为OJ上的一道题目,涉及Java针对字符串的遍历、转换及流程控制等技巧,需要的朋友可以参考下
    2015-12-12
  • 生成PDF全攻略之在已有PDF上添加内容的实现方法

    生成PDF全攻略之在已有PDF上添加内容的实现方法

    下面小编就为大家带来一篇生成PDF全攻略之在已有PDF上添加内容的实现方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-06-06
  • 实例讲解使用Spring通过JPA连接到Db2

    实例讲解使用Spring通过JPA连接到Db2

    这篇文章主要介绍了通过实例讲解使用Spring通过JPA连接到Db2,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,下面我们来一起学习一下吧
    2019-06-06

最新评论