如何获得Maven项目版本的bash命令行

以前我发过一个关于如何从命令行改变Maven项目的问题,这引起了我一个新的问题。

以前我能够得到版本号,因为版本存储为一个易于从命令行(bash)进行grep和parsing的属性。 现在,pom.xml元素用于此,它不再是唯一的,因为所有的依赖关系,也许其他人也使用这个。 我认为没有办法获得当前的版本号与bash脚本没有外部工具来parsingxml或一些非常上下文感知sed命令。

我的意见中最干净的解决scheme是Maven发布此版本信息。 我正在考虑写一个自定义的maven插件来检索不同的属性,但我想我会先问在这里。

那么,有没有简单的方法将${project.version}的值${project.version}命令行? 提前致谢。

感谢您的帮助。 我不得不手动cd到目录,但可以很容易地完成。 在我的bash脚本中

 version=`cd $project_loc && mvn org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate -Dexpression=project.version | sed -n -e '/^\[.*\]/ !{ /^[0-9]/ { p; q } }'` 

这给了我当前的版本,然后我可以推进。 剔除可能是简单的,但我想我想尽可能健壮,所以我对以数字开头的第一行感到满意,并尝试将其作为版本号处理。

 # Advances the last number of the given version string by one. function advance_version () { local v=$1 # Get the last number. First remove any suffixes (such as '-SNAPSHOT'). local cleaned=`echo $v | sed -e 's/[^0-9][^0-9]*$//'` local last_num=`echo $cleaned | sed -e 's/[0-9]*\.//g'` local next_num=$(($last_num+1)) # Finally replace the last number in version string with the new one. echo $v | sed -e "s/[0-9][0-9]*\([^0-9]*\)$/$next_num/" } 

我通过简单的调用来使用它

 new_version=$(advance_version $version) 

希望这有助于某人。

Maven Help Plugin不知何故已经为此提出了一些build议:

  • help:evaluate评估用户在交互模式下给出的Mavenexpression式。

这里是你将如何在命令行上调用它来获取${project.version}

 mvn org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate \ -Dexpression=project.version 

Tom的Exec Maven插件的解决scheme要好得多,但还是比它需要的复杂。 对我来说,这很简单:

 set -o errexit MVN_VERSION=$(mvn -q \ -Dexec.executable="echo" \ -Dexec.args='${project.version}' \ --non-recursive \ org.codehaus.mojo:exec-maven-plugin:1.3.1:exec) 
 mvn org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate -Dexpression=project.version | grep -v '\[' 

最好的答案是在我看来很垃圾,你必须使用一堆的grep来破解Maven的控制台输出。 为什么不使用正确的工具来完成这项工作? 使用xpath语法是检索版本号的最佳方法,因为它是访问XML数据结构的预期方法。 下面的expression式使用元素的“本地名称”遍历pom,换句话说,忽略xml中可能存在或不存在的名称空间声明。

 xmllint --xpath "//*[local-name()='project']/*[local-name()='version']/text()" pom.xml 
 python -c "import xml.etree.ElementTree as ET; \ print(ET.parse(open('pom.xml')).getroot().find( \ '{http://maven.apache.org/POM/4.0.0}version').text)" 

只要你有python 2.5或更高,这应该工作。 如果您的版本低于此值,请安装python-lxml并将导入更改为lxml.etree。 这种方法很快,不需要下载任何额外的插件。 它也适用于不能用xmllintvalidation的畸形的pom.xml文件,就像我需要parsing的文件一样。 在Mac和Linux上testing。

如果你不介意把这个版本写入临时文件,还有另外一个解决scheme(没有grep / sed)对我来说很好。 ( 编辑 :请参阅rjrjr的答案更简单的解决scheme,没有任何临时文件的麻烦)

我使用Exec Maven插件以及echo二进制文件。 与Maven Help Plugin相比,Exec Plugin允许将输出redirect到一个文件中,该文件可以绕过grep / sed,甚至可以parsing奇怪的东西,比如多行版本string(带有版本标签中的CDATA块),至less在一定程度上。

 #!/usr/bin/env sh MVN_VERSION="" VERSION_FILE=$( mktemp mvn_project_version_XXXXX ) trap "rm -f -- \"$VERSION_FILE\"" INT EXIT mvn -Dexec.executable="echo" \ -Dexec.args='${project.version}' \ -Dexec.outputFile="$VERSION_FILE" \ --non-recursive \ --batch-mode \ org.codehaus.mojo:exec-maven-plugin:1.3.1:exec > /dev/null 2>&1 || { echo "Maven invocation failed!" 1>&2; exit 1; } # if you just care about the first line of the version, which will be # sufficent for pretty much every use case I can imagine, you can use # the read builtin [ -s "$VERSION_FILE" ] && read -r MVN_VERSION < "$VERSION_FILE" # Otherwise, you could use cat. # Note that this still has issues when there are leading whitespaces # in the multiline version string #MVN_VERSION=$( cat "$VERSION_FILE" ) printf "Maven project version: %s\n" "$MVN_VERSION" 

当我在这里使用一些其他的答案时,我一直在遇到旁边的情况,所以这里还有另外一个select。

 version=$(printf 'VER\t${project.version}' | mvn help:evaluate | grep '^VER' | cut -f2) 

我注意到一些虚假的Downloaded:行打破了我原来的任务。 这是我已经解决的filter; 希望它有帮助!

 version=$(mvn org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate -Dexpression=project.version | egrep -v '^\[|Downloading:' | tr -d ' \n') 

编辑

不是100%确定为什么,但是当通过Jenkins中的后生成脚本运行时,输出以[INFO]version ,例如[INFO]0.3.2

我倾倒输出到一个文件,并通过我的第一个filter直接从BASH运行,它工作正常..,所以再次,不知道jenkins土地上发生了什么事情。

为了100%在jenkins,我已经添加了一个后续sedfilter; 这是我最新的

 version=$(mvn org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate -Dexpression=project.version | egrep -v '^\[|Downloading:' | tr -d ' \n' | sed -E 's/\[.*\]//g') 

编辑

最后一个logging在这里..我发现tr 仍然导致像/r/n0.3.2 (只有当通过jenkins运行时)。 切换到awk ,问题消失了! 我最后的工作结果

 mvn org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate -Dexpression=project.version \ | egrep -v '^\[|Downloading:' | sed 's/[^0-9\.]//g' | awk 1 ORS='' 

只是为了logging,可以直接在命令行中configurationMaven的简单SLF4J日志logging,通过configuration只输出我们需要的内容:

  • org.slf4j.simpleLogger.defaultLogLevel=WARN
  • org.slf4j.simpleLogger.log.org.apache.maven.plugins.help=INFO

http://www.slf4j.org/api/org/slf4j/impl/SimpleLogger.html所logging

 MAVEN_OPTS="\ -Dorg.slf4j.simpleLogger.defaultLogLevel=WARN \ -Dorg.slf4j.simpleLogger.log.org.apache.maven.plugins.help=INFO" \ mvn help:evaluate -o -Dexpression=project.version 

因此,可以简单地运行tail -1并得到:

 $ MAVEN_OPTS="\ -Dorg.slf4j.simpleLogger.defaultLogLevel=WARN \ -Dorg.slf4j.simpleLogger.log.org.apache.maven.plugins.help=INFO" \ mvn help:evaluate -o -Dexpression=project.version | tail -1 1.0.0-SNAPSHOT 

请注意,这是一个单线程。 MAVEN_OPTS正在被重写只为这个特定的mvn执行。

这将避免从输出中删除日志条目:

 mvn -Dexec.executable='echo' -Dexec.args='${project.version}' --non-recursive exec:exec -q 

输出maven项目版本的一体化解决scheme,并抑制[INFO]Download消息的无关输出:

 mvn -o org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate -Dexpression=project.version | grep -v '\[' 

同样的事情,但分成两行:

 mvn -o org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate \ -Dexpression=project.version | grep -v '\[' 

输出: 4.3-SNAPSHOT

所以,在一个简单的bash脚本中使用你的project.version

 projectVersion=`mvn -o org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate -Dexpression=project.version | grep -v '\['` cd "target/"$projectVersion"-build" 

在这个页面上的其他解决scheme似乎并没有把所有的技巧结合起来。

我最近开发了Release Candidate Maven插件,它可以解决这个确切的问题,所以你不必使用任何hacky shell脚本和parsingmaven-help-plugin的输出。

例如,要将Maven项目的版本打印到terminal,请运行:

 mvn com.smartcodeltd:release-candidate-maven-plugin:LATEST:version 

它给出的输出类似于maven-help-plugin

 [INFO] Detected version: '1.0.0-SNAPSHOT' 1.0.0-SNAPSHOT [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ 

但是,您也可以指定任意的输出格式 (以便可以通过CI服务器(如TeamCity )从日志中获取版本):

 mvn com.smartcodeltd:release-candidate-maven-plugin:LATEST:version \ -DoutputTemplate="##teamcity[setParameter name='env.PROJECT_VERSION' value='{{ version }}']" 

其结果是:

 [INFO] Detected version: '1.0.0-SNAPSHOT' ##teamcity[setParameter name='env.PROJECT_VERSION' value='1.0.0-SNAPSHOT'] [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ 

将输出保存到文件(以便像Jenkins这样的CI服务器可以使用它 ):

 mvn com.smartcodeltd:release-candidate-maven-plugin:LATEST:version \ -DoutputTemplate="PROJECT_VERSION={{ version }}" \ -DoutputUri="file://\${project.basedir}/version.properties" 

生成的version.properties文件如下所示:

 PROJECT_VERSION=1.0.0-SNAPSHOT 

除上述之外, Release Candidate还允许您根据您在POM中定义的API版本来设置项目的版本 (您可能在CI服务器上执行的操作)。

如果您希望看到一个候选版本作为Maven生命周期的一部分,请查看我的其他开源项目 – 针对Jenkins的构build监视器的pom.xml

这工作对我来说,离线,而不依赖于mvn:

 VERSION=$(grep --max-count=1 '<version>' <your_path>/pom.xml | awk -F '>' '{ print $2 }' | awk -F '<' '{ print $1 }') echo $VERSION 

Exec插件没有任何输出parsing工作,因为输出可以被redirect到文件,并通过EnvInject插件注入作业环境:

在这里输入图像描述

一个简单的maven解决scheme

 mvn -q -N org.codehaus.mojo:exec-maven-plugin:1.3.1:exec \ -Dexec.executable='echo' \ -Dexec.args='${project.version}' 

并为奖励分析了部分版本

 mvn -q -N org.codehaus.mojo:build-helper-maven-plugin:3.0.0:parse-version \ org.codehaus.mojo:exec-maven-plugin:1.3.1:exec \ -Dexec.executable='echo' \ -Dexec.args='${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}' 

应该更容易,因为这个bug已经修复了maven-help-plugin 3.0.0: MPH-99评估在安静模式下没有输出 。

要么你有mvn给你答案(大多数答案build议),或者你从pom.xml提取答案。 第二种方法唯一的缺点是你可以非常容易地提取<version/>标签的值,但是只有它是字面的 ,也就是不是Maven属性才有意义。 无论如何我select了这个方法,因为:

  • mvn是冗长的方式,我只是不喜欢过滤它的输出。
  • 与读取pom.xml相比,启动mvn非常慢。
  • 我总是在<version/>使用文字值。

mvn-version是一个zsh shell脚本,使用xmlstarlet读取pom.xml并打印项目版本(如果存在)或父项目版本(如果存在):

 $ mvn-version . 1.0.0-SNAPSHOT 

好处是它比运行mvn更快:

 $ time mvn-version . 1.1.0-SNAPSHOT mvn-version . 0.01s user 0.01s system 75% cpu 0.019 total $ time mvn org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate \ > -Dexpression=project.version mvn org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate 4.17s user 0.21s system 240% cpu 1.823 total 

我的机器上的差异大于两个数量级。

 VERSION=$(head -50 pom.xml | awk -F'>' '/SNAPSHOT/ {print $2}' | awk -F'<' '{print $1}') 

这是我用来得到版本号,认为会有一个更好的maven的方式来这样做

 mvn help:evaluate -Dexpression=project.version | sed -e 1h -e '2,3{H;g}' -e '/\[INFO\] BUILD SUCCESS/ q' -e '1,2d' -e '{N;D}' | sed -e '1q' 

我只是添加了我最近实施的小型sedfilter改进,以从maven输出中提取project.version

Maven页脚非常标准:

 [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 1.609s [INFO] Finished at: Wed May 21 18:02:38 MSK 2014 [INFO] Final Memory: 17M/736M [INFO] ------------------------------------------------------------------------ 

所以你可以使用下面的代码:

 > version=$(mvn help:evaluate -Dexpression=project.version | tail -8 | head -1) > echo $version