从 BASH 脚本检查 Java 版本的正确方法

如何检查 bash 脚本中 JAVA 是否可用(在 PATH 中或通过 JAVA _ HOME) ,并确保版本至少为1.5?

100548 次浏览

您可以发出 java -version并读取和解析输出

java -version 2>&1 >/dev/null | grep 'java version' | awk '{print $3}'

你可透过以下途径获取 java 版本:

JAVA_VER=$(java -version 2>&1 | sed -n ';s/.* version "\(.*\)\.\(.*\)\..*".*/\1\2/p;')

它会给你 16的 java,如 1.6.0_1315的版本,如 1.5.0_17和110的 openjdk 11.0.6 2020-01-14 LTS

所以你可以很容易地在 shell 中进行比较:

[ "$JAVA_VER" -ge 15 ] && echo "ok, java is 1.5 or newer" || echo "it's too old..."

更新: 正如注释中提到的,这段代码可以很好地使用 openjdk 和 JAVA _ TOOL _ OPTION。

比如:

if type -p java; then
echo found java executable in PATH
_java=java
elif [[ -n "$JAVA_HOME" ]] && [[ -x "$JAVA_HOME/bin/java" ]];  then
echo found java executable in JAVA_HOME
_java="$JAVA_HOME/bin/java"
else
echo "no java"
fi


if [[ "$_java" ]]; then
version=$("$_java" -version 2>&1 | awk -F '"' '/version/ {print $2}')
echo version "$version"
if [[ "$version" > "1.5" ]]; then
echo version is more than 1.5
else
echo version is less than 1.5
fi
fi

我知道这是一个非常古老的线索,但这仍然会对其他人有所帮助。

要了解您是否正在运行 Java5、6或7,首先键入 java -version

在您的输出中将有一行与此类似: Java 版本“1.7.0 _ 55”

然后使用此表将“行话”结果转换为版本号。

0 _ 55是 Java 7
0 _ 75是 Java 6
0 _ 65是 Java5 < br >

从 Oracle 站点上的页面获取的信息
Http://www.oracle.com/technetwork/java/javase/7u55-relnotes-2177812.html

我最后使用的方法是:

# Work out the JAVA version we are working with:
JAVA_VER_MAJOR=""
JAVA_VER_MINOR=""
JAVA_VER_BUILD=""


# Based on: http://stackoverflow.com/a/32026447
for token in $(java -version 2>&1 | grep -i version)
do
if [[ $token =~ \"([[:digit:]])\.([[:digit:]])\.(.*)\" ]]
then
JAVA_VER_MAJOR=${BASH_REMATCH[1]}
JAVA_VER_MINOR=${BASH_REMATCH[2]}
JAVA_VER_BUILD=${BASH_REMATCH[3]}
break
fi
done

即使由于 grep 执行了过滤,将 JAVA _ TOOL _ OPTION 设置为某个值,它也会正常工作。

不同答案的组合:

JAVA_VER=$(java -version 2>&1 | grep -i version | sed 's/.*version ".*\.\(.*\)\..*"/\1/; 1q')
  • 返回 Java7的 7和 Java8的 8
  • 使用 OpenJDK 和 Oracle JDK 工作
  • 即使设置了 JAVA _ TOOL _ OPTION 也可以工作

我编写了一个 bash 函数,它应该可以用于 JDK9和 JDK10。

#!/bin/bash


# returns the JDK version.
# 8 for 1.8.0_nn, 9 for 9-ea etc, and "no_java" for undetected
jdk_version() {
local result
local java_cmd
if [[ -n $(type -p java) ]]
then
java_cmd=java
elif [[ (-n "$JAVA_HOME") && (-x "$JAVA_HOME/bin/java") ]]
then
java_cmd="$JAVA_HOME/bin/java"
fi
local IFS=$'\n'
# remove \r for Cygwin
local lines=$("$java_cmd" -Xms32M -Xmx32M -version 2>&1 | tr '\r' '\n')
if [[ -z $java_cmd ]]
then
result=no_java
else
for line in $lines; do
if [[ (-z $result) && ($line = *"version \""*) ]]
then
local ver=$(echo $line | sed -e 's/.*version "\(.*\)"\(.*\)/\1/; 1q')
# on macOS, sed doesn't support '?'
if [[ $ver = "1."* ]]
then
result=$(echo $ver | sed -e 's/1\.\([0-9]*\)\(.*\)/\1/; 1q')
else
result=$(echo $ver | sed -e 's/\([0-9]*\)\(.*\)/\1/; 1q')
fi
fi
done
fi
echo "$result"
}


v="$(jdk_version)"
echo $v

这将返回针对 Java8的 8("1.8.0_151"等)和针对 Java9的 9("9-Debian"等) ,这将使进一步的比较更加容易。

使用 bashj,一个扩展的 bash 版本(https://sourceforge.net/projects/bashj/) ,您可以得到一个相当紧凑的解决方案:

#!/usr/bin/bashj
echo System.getProperty("java.runtime.version")

答案由集成的 JVM 提供(脚本的执行时间为 ~ 0.017“ ,调用本身的执行时间为 ~ 0.004”)。

我也遇到过类似的问题,我想检查安装了哪个版本的 Java 来执行两种类型的应用程序启动。 下面的代码解决了我的问题

jdk_version() {
local result
local java_cmd
if [[ -n $(type -p java) ]]
then
java_cmd=java
elif [[ (-n "$JAVA_HOME") && (-x "$JAVA_HOME/bin/java") ]]
then
java_cmd="$JAVA_HOME/bin/java"
fi
local IFS=$'\n'
# remove \r for Cygwin
local lines=$("$java_cmd" -Xms32M -Xmx32M -version 2>&1 | tr '\r' '\n')
if [[ -z $java_cmd ]]
then
result=no_java
else
for line in $lines; do
if [[ (-z $result) && ($line = *"version \""*) ]]
then
local ver=$(echo $line | sed -e 's/.*version "\(.*\)"\(.*\)/\1/; 1q')
# on macOS, sed doesn't support '?'
if [[ $ver = "1."* ]]
then
result=$(echo $ver | sed -e 's/1\.\([0-9]*\)\(.*\)/\1/; 1q')
else
result=$(echo $ver | sed -e 's/\([0-9]*\)\(.*\)/\1/; 1q')
fi
fi
done
fi
echo "$result"
}


_java="$(jdk_version)"
echo $_java


if [[ "$_java" > "$8" ]]; then
echo version is more than 8


else
echo version is less than 8


fi

来源

我希望能帮上忙

上面的答案只适用于特定的 Java 版本(通常适用于 Java9之前的版本或 Java8之后的版本)。

我编写了一个简单的一行程序,它将为 Java 版本6到11返回一个整数(可能还包括所有未来版本,直到他们再次更改它!).

基本上就是把“1”去掉了在版本号的开始,如果它存在,然后只考虑第一个数字之前的下一个“.

java -version 2>&1 | head -1 | cut -d'"' -f2 | sed '/^1\./s///' | cut -d'.' -f1

  1. 终点站
java -version |& grep 'version' |& awk -F\" '{ split($2,a,"."); print a[1]"."a[2]}'
  1. 在 BASH
#!/bin/bash




echo `java -version 2>&1 | grep 'version' 2>&1 | awk -F\" '{ split($2,a,"."); print a[1]"."a[2]}'`
jver=`java -version 2>&1 | grep 'version' 2>&1 | awk -F\" '{ split($2,a,"."); print a[1]"."a[2]}'`


if [[ $jver == "1.8" ]]; then
echo $jver is java 8
else
echo $jver is java 11
fi

在 SUN 和 Linux 中工作

您还可以将 jdk 类的版本号与 javap进行比较:

javap -verbose java.lang.String | grep "major version" | cut -d " " -f5

如果它的 java 8,这将打印52,和55为 java 11。有了这个,您可以进行一个简单的比较,而不必处理版本字符串解析。

这里有一个很好的可移植 bash 函数: http://eed3si9n.com/detecting-java-version-bash

jdk_version() {
local result
local java_cmd
if [[ -n $(type -p java) ]]
then
java_cmd=java
elif [[ (-n "$JAVA_HOME") && (-x "$JAVA_HOME/bin/java") ]]
then
java_cmd="$JAVA_HOME/bin/java"
fi
local IFS=$'\n'
# remove \r for Cygwin
local lines=$("$java_cmd" -Xms32M -Xmx32M -version 2>&1 | tr '\r' '\n')
if [[ -z $java_cmd ]]
then
result=no_java
else
for line in $lines; do
if [[ (-z $result) && ($line = *"version \""*) ]]
then
local ver=$(echo $line | sed -e 's/.*version "\(.*\)"\(.*\)/\1/; 1q')
# on macOS, sed doesn't support '?'
if [[ $ver = "1."* ]]
then
result=$(echo $ver | sed -e 's/1\.\([0-9]*\)\(.*\)/\1/; 1q')
else
result=$(echo $ver | sed -e 's/\([0-9]*\)\(.*\)/\1/; 1q')
fi
fi
done
fi
echo "$result"
}

另一种方式是: 一个名为 release的文件位于 $JAVA_HOME中。 在 Java15(Debian)上,它的内容如下:

IMPLEMENTOR="Debian"
JAVA_VERSION="15.0.1"
JAVA_VERSION_DATE="2020-10-20"
MODULES="java.base java.compiler java.datatransfer java.xml java.prefs java.desktop java.instrument java.logging java.management java.security.sasl java.naming java.rmi java.management.rmi java.net.http java.scripting java.security.jgss java.transaction.xa java.sql java.sql.rowset java.xml.crypto java.se java.smartcardio jdk.accessibility jdk.internal.vm.ci jdk.management jdk.unsupported jdk.internal.vm.compiler jdk.aot jdk.internal.jvmstat jdk.attach jdk.charsets jdk.compiler jdk.crypto.ec jdk.crypto.cryptoki jdk.dynalink jdk.internal.ed jdk.editpad jdk.hotspot.agent jdk.httpserver jdk.incubator.foreign jdk.internal.opt jdk.jdeps jdk.jlink jdk.incubator.jpackage jdk.internal.le jdk.internal.vm.compiler.management jdk.jartool jdk.javadoc jdk.jcmd jdk.management.agent jdk.jconsole jdk.jdwp.agent jdk.jdi jdk.jfr jdk.jshell jdk.jsobject jdk.jstatd jdk.localedata jdk.management.jfr jdk.naming.dns jdk.naming.rmi jdk.net jdk.nio.mapmode jdk.sctp jdk.security.auth jdk.security.jgss jdk.unsupported.desktop jdk.xml.dom jdk.zipfs"
OS_ARCH="x86_64"
OS_NAME="Linux"
SOURCE=""

您可以看到包含版本号的 JAVA_VERSION

比如说,

major=$(echo $JAVA_VERSION | cut -d. -f1)

major设置为值15(= Major 版本号) ,您可以进一步使用该值。

这是一个非常简单的解决方案。

我发现下面的作品相当不错。它是 Micha RajerJMJ答案的结合

version=$(java -version 2>&1 | sed -n ';s/.* version "\(.*\)\.\(.*\)\..*"/\1\2/p;' | awk '{ print $1 }').

我已经安装了 openJDK 13,如果没有 awk命令,第一个答案就会打印出来: 130 2020-01-14。因此,添加 awk '{ print $1 }'只提供了版本。

只使用带有 Perl 样式 regex 的 grep 确定 Java 版本可以这样做:

java -version 2>&1 | grep -oP 'version "?(1\.)?\K\d+'

这将为 Java9或更高版本打印主版本,为低于9的版本打印次版本,例如,用于 Java1.88和用于 Java11.0.411

它可以这样使用:

JAVA_MAJOR_VERSION=$(java -version 2>&1 | grep -oP 'version "?(1\.)?\K\d+' || true)
if [[ $JAVA_MAJOR_VERSION -lt 8 ]]; then
echo "Java 8 or higher is required!"
exit 1
fi

添加 || true是为了防止在未安装 Java 且启用了 Shell 选项 set -e的情况下脚本中止。

使用 Bash 内置的解析功能获取 java 版本字符串:

#!/usr/bin/env bash


IFS='"' read -r _ java_version_string _ < <(java -version 2>&1)


java_version_major java_version_minor java_version_build java_version_patch \
<<<"$java_version_string"


# Debug demo output
declare -p java_version_major java_version_minor java_version_build \
java_version_patch

演示输出:

declare -- java_version_major="17"
declare -- java_version_minor="0"
declare -- java_version_build="3"
declare -- java_version_patch=""