【问题标题】:Correct way to check Java version from BASH script从 BASH 脚本检查 Java 版本的正确方法
【发布时间】:2011-11-12 04:20:53
【问题描述】:

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

【问题讨论】:

  • Java 5 已经停产了很长时间。 Java 6 很快就会报废。您应该优先迁移到 Java 6,并尽快迁移到 7。
  • @Brian:没什么;我希望有人有一个方便的“bash 搜索路径功能”。
  • @kittylyst:这是最低要求。我的软件不需要 Java 6 特性,所以没有必要强迫用户做出更好的东西。不过还是谢谢你指出来。

标签: java bash version dependency-management


【解决方案1】:

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

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

【讨论】:

  • 这非常接近我想要的。你知道有一个版本在调用locate 之前也会搜索$PATH(这并不总是可用)?
  • 两个链接都不起作用,我检查了我的互联网两次 :-)
  • @Ravi,对,我会编辑这些链接,到时候你可以使用java -version 2>&1 >/dev/null | grep 'java version' | awk '{print $3}'
  • 如果只对数字部分感兴趣并进一步在路径变量中使用,您可以使用类似java -version 2>&1 | head -1 | cut -d '"' -f 2
【解决方案2】:

您可以通过以下方式获取java版本:

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

它会给你16 for java 比如1.6.0_1315 for version like 1.5.0_17 and 110 for 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..."

更新: 如 cmets 中所述,此代码应与 openjdk 和 JAVA_TOOL_OPTIONS 一起正常工作。

【讨论】:

  • 'java -version' 与 OpenJDK 8 的结果略有不同,输出中的“java”被“openjdk”替换。此表达式适用于两种情况:sed 's/.*version "\(.*\)\.\(.*\)\..*"/\1\2/; 1q'
  • 如果设置了 JAVA_TOOL_OPTIONS 输出又略有不同,java 版本不在第一行。 eg: Pick up JAVA_TOOL_OPTIONS: -agentlib:hprof java version "1.7.0_60" Java(TM) SE Runtime Environment (build 1.7.0_60-b19) Java HotSpot(TM) 64-Bit Server VM (build 24.60-b09, mixed mode ) 转储 Java 堆...分配站点...完成
  • EmmanuelBourg 和 codebuddy,谢谢。我更新了代码以解决您发现的问题。
  • 这从 java 9 开始就不能正常工作了,并且从 java 10 开始就失败了
  • 在 Java 9 之后也应该对以下内容进行一些调整... JAVA_VER=$(java -version 2>&1 | sed -n ';s/.* version "(.*) \.(.*)\..*"/\1\2/p;')
【解决方案3】:

也许是这样的:

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

【讨论】:

  • 优秀。我错过了 type 内置函数。
  • 抱歉,无法格式化 cmets。当 Java 版本为 1.10 时,此操作失败。这是因为字符串comapre 不是数字比较。当版本为“1.5”时,答案也是错误的,虽然我猜那将是“1.5.0”,所以我想没关系。
  • 好点。你可以这样做:IFS=. read major minor extra <<<"$version"; if (( major == 1 && minor > 5 )); ...——必须检查无效的八进制数字,如“08”。
  • type -p java”在“sh”中不起作用;因此,为了可移植性,请在脚本中使用#!/bin/bash,而不是#!/bin/sh(尽管/bin/sh 实际上可能不是bourne shell,而是向后兼容的变体)
  • 为了比较版本,我建议:version1=$(echo "$version" | awk -F. '{printf("%03d%03d",$1,$2);}') 这将使您的主要和次要与每个 3 位对齐,然后与 if [ $version1 -ge 001008 ] ; then 比较
【解决方案4】:

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

要知道您运行的是 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

【讨论】:

  • 如果你有除了那些特定的 Java 次要版本之外的任何东西,例如
  • 好吧。我从 Oracle 官方网站上的一个页面获得了这些信息。我不知道这一切,我也不假装知道。如果您知道还有哪些其他 Java 版本,请随时在此消息下方添加子评论。
  • 1.5.0_anything 是 Java 5,1.6.0_anything 是 Java 6,1.7.0_anything 是 Java 7,1.8.0_anything 是 Java 8。次要版本一直在变化(尽管我认为没有永远不会成为 Java 5 或 6 的任何新版本)。
  • 另外,不能保证任何人都会拥有最新的次要版本。
  • 这很公平。你为什么不一开始就这么说?我有一种感觉,1.x... 意味着版本 x,但我不想做出这样的假设,以防我错了。
【解决方案5】:

我最终使用的方法是:

# 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 进行过滤而设置为某个值,它也会正常工作。

【讨论】:

  • Oneliner:if [[ $(java -version 2>&1 >/dev/null | grep 'java version' | awk '{print $3}') =~ \"([0-9])\.([0-9])\.([0-9])_(.*)\" ]]; then echo ${BASH_REMATCH[2]}; fi
【解决方案6】:

不同答案的组合:

JAVA_VER=$(java -version 2>&1 | grep -i version | sed 's/.*version ".*\.\(.*\)\..*"/\1/; 1q')
  • 对于 Java 7 返回 7,对于 Java 8 返回 8
  • 适用于 OpenJDK 和 Oracle JDK
  • 即使设置了 JAVA_TOOL_OPTIONS 也可以工作

【讨论】:

  • 对于 Java 10,返回 '0' 作为版本号
  • $ java -version 2>&1 | grep -i 版本 | sed 's/.*version ".*\.(.*)\..*"/\1/; 1q' --> 0 对于 java 版本“9.0.1”
  • 确实,下面的答案更适合 java 版本 > 9:stackoverflow.com/a/56243046/3193604
【解决方案7】:

我编写了一个适用于 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("1.8.0_151" 等)返回 8,为 Java 9("9-Debian" 等)返回 9,这样可以更轻松地进行进一步比较。

【讨论】:

    【解决方案8】:

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

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

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

    【讨论】:

      【解决方案9】:

      我有一个类似的问题,我想检查安装了哪个版本的 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
      

      source

      我希望对我有所帮助

      【讨论】:

      【解决方案10】:

      上述答案仅适用于特定的 Java 版本(通常适用于 Java 9 之前的版本或 Java 8 之后的版本。

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

      它基本上去掉了“1”。在版本号的开头,如果存在,则只考虑下一个“.”之前的第一个数字。

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

      【讨论】:

      • 这是我找到的最好的。
      【解决方案11】:
      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

      【讨论】:

      • 小改进:使用$(...) 代替反引号。它们更安全、支持嵌套并且更易于在大多数键盘/操作系统上键入。
      【解决方案12】:

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

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

      如果是java 8,这会打印52,java 11会打印55。这样你可以做一个简单的比较,你不必处理版本字符串解析。

      【讨论】:

      • 如果您只想知道主要版本,这是一个不错的技巧。有时,您想检查是否安装了某个补丁级别。
      • 太棒了,这是防弹!
      • 简单易用的主要版本检查
      【解决方案13】:

      这里有一个很好的便携式 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"
      }
      

      【讨论】:

        【解决方案14】:

        另一种方法是: 一个名为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(=主要版本号),您可以进一步使用它。

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

        【讨论】:

        • 有趣。我在几个 JDK(Oracle 和 OpenJDK)中找到了该文件。我认为它不会存在于 J9 或 Amazon JVM 中。另外,如果未定义 $JAVA_HOME,则需要弄清楚 Java 安装文件夹。
        【解决方案15】:

        我发现以下工作相当好。这是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 }' 只为我提供了版本。

        【讨论】:

          【解决方案16】:

          仅使用 grep 和 Perl 风格的正则表达式来确定 Java 版本可以这样完成:

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

          这将打印 Java 9 或更高版本的主要版本和低于 9 的版本的次要版本,例如 8 用于 Java 1.811 用于 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 的情况下中止。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2021-09-11
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2022-01-15
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多