如何从 bash 脚本检查 Java 是否可用(在 PATH 中或通过 JAVA_HOME)并确保版本至少为 1.5?
也许是这样的:
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
您可以通过以下方式获取java版本:
JAVA_VER=$(java -version 2>&1 | sed -n ';s/.* version "\(.*\)\.\(.*\)\..*".*/\1\2/p;')
它将为您提供
16
(适用于 Java,如 1.6.0_13
)、15
(适用于 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_OPTIONS 一起正常工作,如评论中所述。
上述答案仅适用于特定的 Java 版本(通常适用于 Java 9 之前的版本或 Java 8 之后的版本。
我编写了一个简单的单行代码,它将返回 Java 版本 6 到 11 的整数(可能还有所有未来版本,直到他们再次更改它!)。
它基本上删除了“1”。在版本号的开头(如果存在),然后仅考虑下一个“.”之前的第一个数字。
java -version 2>&1 | head -1 | cut -d'"' -f2 | sed '/^1\./s///' | cut -d'.' -f1
您可以发出
java -version
并读取并解析输出
java -version 2>&1 >/dev/null | grep 'java version' | awk '{print $3}'
您还可以通过
javap
来比较jdk类版本号:
javap -verbose java.lang.String | grep "major version" | cut -d " " -f5
如果是java 8,这将打印52,而java 11则打印55。有了这个,你可以进行简单的比较,而不必处理版本字符串解析。
我编写了一个适用于 JDK 9 和 JDK 10 的 bash 函数。
#!/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
这对于 Java 8(
8
等)返回 "1.8.0_151"
,对于 Java 9(9
等)返回 "9-Debian"
,这应该可以更轻松地进行进一步比较。
仅使用 grep 和 Perl 风格的正则表达式来确定 Java 版本可以像这样完成:
java -version 2>&1 | grep -oP 'version "?(1\.)?\K\d+'
这将打印 Java 9 或更高版本的主要版本和低于 9 的版本的次要版本,例如
8
表示 Java 1.8
和 11
表示 Java 11.0.4
。
可以这样使用:
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
的情况下脚本中止。
不同答案的组合:
JAVA_VER=$(java -version 2>&1 | grep -i version | sed 's/.*version ".*\.\(.*\)\..*"/\1/; 1q')
7
,对于 Java 8 返回
8
java -version |& grep 'version' |& awk -F\" '{ split($2,a,"."); print a[1]"."a[2]}'
#!/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
我最终使用的方法是:
# 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
即使 JAVA_TOOL_OPTIONS 由于 grep 完成的过滤而设置为某些值,它也能正常工作。
另一种方法是: 名为
release
的文件位于 $JAVA_HOME
中。
在 Java 15 (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(=主版本号),您可以进一步使用它。
这是一个非常简单的解决方案。
获取java版本字符串,使用Bash内置的解析功能:
#!/usr/bin/env bash
java_cmd=${1:-java}
# Captures version string between double-quotes
IFS='"' read -r _ java_version_string _ < <("${java_cmd}" -version 2>&1)
# Splits version string at dots and (underscore for patch number)
IFS='._' read -r \
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
示例
系统默认Java 17:
declare -- java_version_major="17"
declare -- java_version_minor="0"
declare -- java_version_build="3"
declare -- java_version_patch=""
作为参数提供的特定 Java 8 路径:
declare -- java_version_major="1"
declare -- java_version_minor="8"
declare -- java_version_build="0"
declare -- java_version_patch="352"
我有一个类似的问题,我想检查安装了哪个版本的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
我希望对您有所帮助
这里有一个很好的便携式 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"
}
我知道这是一个非常古老的线程,但这仍然对其他人有帮助。
要了解您运行的是 Java 5、6 还是 7,请首先输入
java -version
。
输出中会有一行看起来与此类似:java version "1.7.0_55"
然后使用此表将“行话”结果转换为版本号。
1.7.0_55 是 Java 7
1.6.0_75 是 Java 6
1.5.0_65 是 Java 5
取自 Oracle 网站页面的信息
http://www.oracle.com/technetwork/java/javase/7u55-relnotes-2177812.html
使用bashj,一个扩展的bash版本(https://sourceforge.net/projects/bashj/),你会得到一个相当紧凑的解决方案:
#!/usr/bin/bashj
echo System.getProperty("java.runtime.version")
答案由集成的 JVM 提供(脚本的执行时间约为 0.017 英寸,调用本身的执行时间约为 0.004 英寸)。
我发现以下作品相当不错。它是 Michał Šrajer 和 jmj
的答案的组合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 }'
只为我提供了版本。
这个问题仍然相关,所以发布我的答案。
通过使用内置的 Bash 变量扩展并避免创建多个子 shell,使用稍微复杂的方式
line=$(java -version 2>&1 | head -1) && echo ${${${line#*\"}#1.}%%.*}
可以将其捕获到如下变量中,以便在脚本中进行进一步检查
version=$(line=$(java -version 2>&1 | head -1) && echo ${${${line#*\"}#1.}%%.*})