ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Linux下JDK 11.0.15 tar.gz解压安装与环境变量配置指南

Linux下JDK 11.0.15 tar.gz解压安装与环境变量配置指南

简介:Linux JDK 11.0.15 64位安装包(jdk-11.0.15_linux-x64_bin.tar.gz)专为x86_64架构的Linux系统设计,主要面向需要搭建Java开发或运行环境的软件开发者、运维人员以及系统管理员,能够快速解决从零配置JDK基础环境的问题。资源包共包含392个文件,其中jmod模块文件用于封装模块化运行组件,license与copyright文件保留原始授权与版权声明,so动态链接库提供底层系统接口支持,md说明文档收录了大量工具使用说明,整体压缩后约161MB,目录结构接近官方发行版原始布局,便于按模块检索与集成。压缩包内含javac、java、javadoc、jdb、jar等全套开发工具,以及JConsole、VisualVM、JLink等辅助组件,可用于编译调试、性能监控、定制运行时等常见开发运维场景。Java 11新增的局部变量类型推断、HTTP客户端API、模块化系统等特性,均在该版本内获得完整支持,能帮助开发者更高效地编写和维护企业级应用。目前已有804人学习下载,适合Linux平台上的个人开发者与团队快速获取稳定可用的JDK环境,也为需要离线安装、版本归档或批量部署的服务器场景提供了可靠方案。

1. 一个 tar.gz 解决 Linux 服务器上 Java 环境的老大难:jdk-11.0.15_linux-x64_bin.tar.gz 到底怎么用

如果你在一台没有外网的生产服务器上被java: command not found卡住过,就知道一个离线可用的 JDK 压缩包有多值钱。jdk-11.0.15_linux-x64_bin.tar.gz 正是这种刚需资源:Oracle 官方发布的 JDK 11.0.15,面向 Linux x64 架构,tar.gz 格式解压即用,不依赖 yum、apt 或任何网络源。这份资源适合三类人:给内网服务器装 Java 环境的运维、需要固定 JDK 版本跑项目的开发、以及被各种在线安装教程坑过、想老老实实手动部署的人。JDK 11 是 LTS 长期支持版本,11.0.15 是 2022 年 4 月的 CPU 更新,对 Spring Boot、Hadoop、Gradle 这类技术栈都是稳妥选择。下面从选型原理讲到环境变量配置,再把最容易翻车的坑拆开,最后给你一个能直接复用的一键部署脚本。

2. 装之前先搞懂选型:tar.gz 格式、x64 架构与 JDK 11.0.15 的定位

2.1 为什么选 tar.gz 而不是 rpm、deb 或源码编译

Linux 上装 JDK 常见有四条路:包管理器直接 yum/apt 装、rpm/deb 包、官方 tar.gz、源码编译。大部分新手第一反应是yum install java-11-openjdk,这条路在能联网、能配源的机器上确实快,但到了内网、离线、或者有国产化系统(统信 UOS、麒麟这类)的环境里,包源里往往没有你想要的版本,或者版本的编号和你项目的依赖对不上。tar.gz 最大的优势是"不挑系统":它不依赖 rpm 数据库、不依赖 deb 仓库、不写任何系统目录,解压到哪就是哪,删掉一个目录就算卸干净。这正是"后悔药"最好吃的一种安装方式,装错了成本极低。

rpm 和 deb 呢?它们在标准发行版上体验不错,但有个硬伤:包管理器会记录依赖和版本,卸载要经过包管理器,重装也受仓库版本约束。而且 rpm 包的 JDK 经常把文件散到 /usr/lib/jvm 底下一堆子目录,想找一个明确的可执行文件反而费劲。源码编译更不用说,OpenJDK 源码编译需要 bootstrapping(先用一个已存在的 JDK 去编新 JDK),还要装一堆构建依赖,耗时以小时计,生产环境里基本没人这么干。

所以我的习惯是:凡是要固定版本、离线部署、多版本并存,一律用官方 tar.gz。文件名 jdk-11.0.15_linux-x64_bin.tar.gz 本身就是一份完整的说明——jdk-11.0.15 是版本号,linux-x64 是平台与架构,bin 表示这是编译好的二进制发行版,不是源码包(源码包一般是 openjdk-11.0.15+7-src.tar.gz 这类命名)。把这个命名规则记住,以后看到任何 JDK 包都能一眼判断能不能用,不用再打开网页反复确认。

安装方式离线可用版本固定卸载干净度适用场景
yum/apt依赖源一般中(残留依赖)公网开发机
rpm/deb依赖仓库中中标准发行版
tar.gz完全离线高高(删目录)内网/生产/多版本
源码编译可以高高定制补丁,极少用

2.2 确认系统是 x64:架构搞错后面全是坑

标题里写的 linux-x64 对应 x86_64 架构,这是绝大多数 Intel/AMD 服务器和台式机的架构。但"64 位系统装错了 arm 版 JDK"这种翻车我见过不止一次:有的人在云台上的 ARM 实例上下载了 x64 包,解压后一执行./java直接报No such file or directory;也有人反过来,在 x64 机器上下载了 aarch64 包。所以解压之前,先花十秒钟确认三件事:内核架构、操作系统发行版、系统的实际位数。这一步看起来多余,但嵌入式 Linux 开发板上翻车的概率最高,很多 armv7 的板子被当成 x64 机器部署,浪费一下午。

# 查看 CPU 架构,x86_64 即 x64,对应包名里的 linux-x64 uname -m # 或者 arch # 查看内核位数,64 表示 64 位内核 getconf LONG_BIT # 查看发行版信息,便于判断该用哪个安装路径 cat /etc/os-release

输出说明:uname -m返回 x86_64,直接对应文件名里的 linux-x64;如果是 aarch64 或 arm64,说明这是 ARM 服务器,这个 x64 包不能用。getconf LONG_BIT返回 64 不代表一定能跑 x64 程序,要配合uname -m一起看,有些老机器是 32 位内核(i686/i386),那里只能装 32 位 JDK。另外提醒一句,别只信云厂商控制台标注的"64 位",有的共享主机实际给的是 32 位兼容内核,进系统跑一下uname -m最保险。

提示:云控制台标注的架构不一定等于系统实际内核架构,一切以uname -m的输出为准。

2.3 版本号里的门道:11.0.15 是什么,和 OpenJDK 有什么区别

JDK 的版本号分三段:11 是主版本,属于 LTS(长期支持)版本,官方策略是每两年出一个 LTS,中间的功能版本(12、13、14……)只支持六个月。生产环境选 LTS 是基本共识,这也是为什么现在很多项目还在 JDK 8 和 JDK 11 之间徘徊,而不是盲目追最新版。0.15 是 Update 版本,对应 Oracle 的 CPU(Critical Patch Update)节奏,每季度发布一次,包含安全修复和高危漏洞补丁。11.0.15 是 2022 年 4 月那一批 CPU 版本,修了一批中间件远程代码执行相关的漏洞。对安全审计比较严的团队来说,CPU 版本号本身就是合规证据。

再说 Oracle JDK 和 OpenJDK 的区别。JDK 11 开始,Oracle 把 JDK 和 OpenJDK 的功能基本对齐,二进制层面行为一致,两者的差异主要在版权与支持服务:Oracle JDK 的二进制发行版有独立的许可协议,商业使用要留意条款;OpenJDK 是 GPL 协议,更自由。技术上,同一个版本号的 Oracle JDK 和 OpenJDK,跑同一段 Java 代码结果一致,区别主要在个别工具组件和更新节奏上。生产内网环境如果对许可敏感,团队通常会选 OpenJDK 或 Adoptium 的构建;如果就是需要一个干净的官方二进制,Oracle 的 tar.gz 也没问题。文件里带_bin后缀的,就是官方编译好的二进制,解压后的目录结构里会有 bin、lib、conf、legal 这些标准子目录,这也是我判断一个 JDK 包正不正规的直观依据。

这边顺带点一个高频场景:很多人问"为什么我装的 JDK 11,IDEA 里却报版本不对",多半是项目 SDK 选的版本和系统 PATH 里 JAVA_HOME 指向的不是同一个。JMeter 默认要求 JDK 8+,DBeaver 自己管一个 JRE 且新版对 JDK 版本有要求,这些工具各看各的配置,和系统全局变量经常不是一回事。所以版本选型不只是"下个包装上"这么简单,得先想清楚这套 JDK 是给谁用的,再决定装到哪、配哪些变量。

3. 安装落地:解压、目录规划与 JAVA_HOME 环境变量配置

3.1 解压到哪:目录规划和权限是第一步

解压目标路径一般有两个流派:系统级装到 /usr/local/java 或 /opt/java,只有 root 能写;用户级装到~/java或~/tools,当前用户自用,不需要 sudo。系统级的好处是多人共用一台机器时,所有账号都能读取同一份 JDK 并共享 JAVA_HOME;用户级的好处是不碰系统目录、不怕污染,尤其在帮别人排查"装崩了"的时候,用户级直接删目录没有任何副作用。我的建议是:生产服务器统一放 /usr/local/java,开发机可以放用户目录。

拿到 jdk-11.0.15_linux-x64_bin.tar.gz 这个文件后,先别急着解压。有个小坑:包内最外层目录名通常就是 jdk-11.0.15,但有些渠道下载的包可能被二次打包,解压出来是个名字乱七八糟的目录。所以解压前先看一眼压缩包内的顶层结构,确认没有意外再正式解压,这一步二十秒就能省掉好几小时的排错。

# 先看包内首层结构,确认顶层目录名是 jdk-11.0.15 tar -tzf jdk-11.0.15_linux-x64_bin.tar.gz | head -5 # 创建目标目录并解压,-C 指定解压目标位置 sudo mkdir -p /usr/local/java sudo tar -xzf jdk-11.0.15_linux-x64_bin.tar.gz -C /usr/local/java/ # 确认解压结果,标准 JDK 目录里应该有 bin、conf、lib 等 ls -l /usr/local/java/

解压后目录里应该有 bin、conf、include、jmods、legal、lib 这几个标准子目录,以及 release、README 等文件。如果只有一堆散落的 class 文件,那这个包八成不是标准的官方二进制包。下一步建议做一个不带版本号的软链接,方便以后升级路径不变:ln -s /usr/local/java/jdk-11.0.15 /usr/local/java/current。这样 JAVA_HOME 指向 current,下次换 JDK 版本只要换软链接,不用改一堆环境变量,这个习惯在跑多版本共存时尤其有用。

3.2 JAVA_HOME、PATH 与 CLASSPATH:环境变量到底配什么

环境变量配置是这份资源落地过程中翻车率最高的一步,热搜里常年挂着"jdk环境变量配置失败"和"找不到jdk"这类诉求。先明确三个变量的职责:JAVA_HOME 告诉系统和各种工具 JDK 装在哪,PATH 告诉 shell 去哪找 java 这个命令,CLASSPATH 告诉 JVM 去哪找用户自定义的类。JDK 9 引入模块系统之后,CLASSPATH 的必要性已经大幅降低,很多项目根本不配也能正常跑。老教程里几乎都有export CLASSPATH=.:$JAVA_HOME/lib这种写法,我一般建议新手直接不配,省得后期调试 class 冲突的时候多一个变量干扰。真要用到外部 jar,用-cp参数指定更清晰。

配置文件的选择:/etc/profile 对所有登录用户生效,但只在登录 shell 时读取;~/.bashrc 对当前用户的所有交互式 shell 生效。生产服务器上我推荐写到 /etc/profile.d/java.sh——这是 /etc/profile 默认会遍历加载的目录,既保持了全局生效,又不用直接改 /etc/profile 这个又长又重要的文件,卸载的时候删一个文件就干净了。

# 编辑环境变量文件,推荐 /etc/profile.d/java.sh sudo tee /etc/profile.d/java.sh > /dev/null <<'EOF' export JAVA_HOME=/usr/local/java/current export PATH=$JAVA_HOME/bin:$PATH EOF # 立即生效 source /etc/profile.d/java.sh # 验证,确认路径正确 echo $JAVA_HOME which java

这段配置里有三个细节要解释。第一,PATH 的拼接顺序是$JAVA_HOME/bin在前、$PATH在后,这样 shell 会优先找到新 JDK 的 java,而不是系统自带的旧 openjdk;顺序写反了,前面有一个旧版本就会把新的盖掉。第二,tee 加 heredoc 写文件比 vim 安全,生成的文件权限和内容都可控,管道里的 EOF 加引号是为了防止变量被提前展开。如果你写的是<<EOF而不是<<'EOF',$JAVA_HOME会被当前 shell 先求值,写进文件的内容就变成空串了,这是非常隐蔽的坑。第三,PATH=...和export PATH=...的差别是前者只在当前 shell 生效且不导出给子进程,而 java 命令是 shell 的子进程,不 export 就找不到,这也是很多"配完不生效"的根源。

注意:PATH 的拼接顺序决定优先级,$JAVA_HOME/bin必须放在$PATH前面,否则系统里其他位置的 java 会抢先生效。

不少人在 ~/.bashrc 里也配了一份,结果 /etc/profile.d 和 ~/.bashrc 各写各的,后来排查的时候两个文件里值不一致,互相覆盖,非常头大。我的建议是选定一个位置:多用户生产机全部走系统级 /etc/profile.d,本机开发走用户级 ~/.bashrc,别两处都写,不然总有一天你会对着两个文件里的不同值发呆。

3.3 验证安装:java -version、javac -version 与 which java

配完环境变量,表面验证是 java -version,但这一步有个细节:java -version 输出的是运行时的版本,javac -version 输出的是编译器的版本,两者来源应该是同一个 JDK。如果 JAVA_HOME 和 PATH 配得不一致——比如 JAVA_HOME 指向 11,但 PATH 里前面的目录有个 8 的 java——就会出现 java -version 显示 1.8、javac -version 显示 11 这种分裂状态。所以验证要三步一起做,缺一步都可能漏掉问题。

# 1) 确认 JAVA_HOME 指向正确,输出应为 /usr/local/java/current echo $JAVA_HOME # 2) 确认 java 和 javac 分别来自哪里,两条路径应指向同一处 which java which javac # 3) 确认版本输出一致且为 11.0.15 java -version javac -version

java -version 的正常输出是三行:openjdk version "11.0.15"、OpenJDK Runtime Environment、OpenJDK 64-Bit Server VM;javac -version 输出只有一行:javac 11.0.15。看到 64-Bit 字样,说明架构也对上了。我还会顺手跑一个 jshell 做冒烟测试:jshell 是 JDK 9 之后自带的交互式命令行,输入System.getProperty("java.version")回车,能返回 11.0.15 就说明 JVM 本身能正常加载。更完整一点的做法是写一个最简的 Hello 程序编译运行,验证编译器和运行时链路完整,这个放到第 6 章的脚本里一起体现。如果 java -version 报的是别的版本,或者直接 command not found,那就是下一章要讲的坑,按现象对号入座去排查。

4. 避坑指南:java -version 不对或找不到时,逐个排查这五处

环境变量的坑看着像玄学,其实每条都有确定的原因。以下五条是我自己踩过和帮同事擦过的血泪经验,按现象对号入座,每一条都按"现象、原因、解决"的顺序展开,照着走一遍基本都能收工。

4.1 现象:java -version 显示的是旧版本

配置完明明 export 了新路径,java -version 打出来的还是 1.8 或者另一个 JDK,这是"jdk环境变量配置失败"里最高频的一类。原因很简单:PATH 里存在多个 java 可执行文件,而你的新路径排在后面。系统自带的 openjdk 通常软链在 /usr/bin/java,/usr/bin 在 PATH 里的位置往往很靠前;或者之前装过别的 JDK,bin 目录也在 PATH 里占着位置。

解决:先看清楚系统上到底有几个 java。用type -a java列出所有能找到的 java 路径,再用ls -l查每个路径的软链指向,找到罪魁祸首。然后把 PATH 顺序调整成$JAVA_HOME/bin在最前;如果这个旧 java 是系统自带的,并且你确定不需要它,可以先把 /usr/bin/java 的软链mv改名备份,留个后悔药,别直接 rm。改完记得重新 source 配置,或者干脆开一个新终端窗口——旧窗口的 PATH 不会自动刷新成新值,这个细节坑了很多人。

4.2 现象:bash: java: command not found

配置写完了,source 也执行了,但 java -version 还是提示 command not found。常见原因有三个:一是 export 那行根本没执行到,比如写进了 ~/.bashrc 但当前场景是个登录 shell,或者 source 的文件路径不对;二是拼写错误,JAVA_HOME 写成了 JAVAHOME 或少了个字母,shell 里拼错变量名不会报错,只会按空串处理,所以是无声失败;三是写了PATH=$JAVA_HOME/bin而不是$JAVA_HOME/bin:$PATH,等于把系统 PATH 整个丢弃,java 找不到的同时,ls、vim 这些命令也全没了。

解决:先echo $JAVA_HOME,如果输出为空,八成是变量名写错或文件没被读取;再echo $PATH,看系统路径还在不在;然后用bash -x /etc/profile.d/java.sh逐行跟踪执行,看哪一步断了。我一般会把 export 语句复制到命令行手动跑一遍,确认值正确后再回头查文件。如果手动执行有效、source 后无效,多半是文件读取顺序的问题,把配置挪到 /etc/profile.d/ 下,或者改写到 ~/.bash_profile,确保登录 shell 能读到。

4.3 现象:./java: No such file or directory(不是 command not found)

这条特别迷惑人:执行$JAVA_HOME/bin/java时报No such file or directory,但文件明明就在那里,ls 也看得到。实际原因是这个二进制无法被当前系统加载——最常见的是 32 位系统上跑了 64 位 JDK,或者架构不匹配;另一个常见原因是缺少 glibc 依赖,系统的 glibc 版本太低,新 JDK 要求更高版本的库,加载器找不到符号就会报这个错。

解决:用file $JAVA_HOME/bin/java看 ELF 格式,输出会注明 64-bit 还是 32-bit,以及依赖的 glibc 版本;再用ldd $JAVA_HOME/bin/java列出动态库依赖,看有没有 not found 的项。如果是架构不匹配,只能换对应架构的 JDK 包;如果是 glibc 太旧,要么升级系统基础库(生产机器上先评估风险),要么换更老的 JDK 版本。注意这两条都跟环境变量无关,所以排查顺序应该是:先确认自己没装错包,再回头查配置。

4.4 现象:PATH 被覆盖,ls、vim、sudo 全没了

这是比 command not found 更恐怖的一种:source 完配置,终端里 ls、vim、sudo 全报 command not found,shell 像是废了。原因就是我前面强调过的:export PATH=$JAVA_HOME/bin把原本的 PATH 整个覆盖,系统命令全在 /usr/bin、/bin 这些原始路径里,一个都没保留,自然全找不到了。

解决:新开一个终端窗口有时候能救回来,因为新窗口会重新加载配置文件;如果连新窗口都不行,就用绝对路径救急:/usr/bin/ls或/bin/ls,先把 PATH 恢复原样再修配置。正确写法是export PATH=$JAVA_HOME/bin:$PATH,注意$PATH一定要拼在后面。这个坑被反复强调,但实际操作时太容易手滑,尤其是从 Windows 习惯切过来的同学,把分号误写成冒号的也有。所以我给团队定的规矩是:环境变量的每一行 export 写完后,先echo $PATH看一眼,确认原来的路径还在,再继续下一步。

4.5 现象:source 完生效,重启服务器又失效

昨天配置得好好的,java -version 也正常,今天重启服务器回来就 command not found 了。这种情况十有八九是配置没写进持久化文件,只是临时在命令行里 export 了一下;或者写进了 ~/.bashrc 但登录时用的是 .bash_profile,而 .bash_profile 里没有source ~/.bashrc,这是某些发行版的默认行为差异。还有一个隐蔽原因:写进了 /etc/profile.d/java.sh 但文件权限不对,或者被 SELinux 拦了读取。

解决:检查你改的文件到底在哪个读取列表里。登录 shell 会读 /etc/profile、~/.bash_profile、~/.bash_login;交互式非登录 shell 读 ~/.bashrc。稳妥做法是把全局配置放进 /etc/profile.d/java.sh,并确认权限是 644、属主 root;用户级配置放进 ~/.bash_profile 并在里面加一行source ~/.bashrc(如果发行版默认没加)。改完用 logout 重新登录一次验证,而不是只 source 一下,这样才算真正模拟了重启场景。Ubuntu 上还有一种情况是 update-alternatives 抢着管理 java,重启后 alternatives 把软链改了,这属于系统包管理和手动安装打架,处理方式放到第 5 章讲。

5. 多 JDK 共存与卸载:一台机器装多个版本怎么不打架

5.1 update-alternatives:Debian/Ubuntu 系的原生切换工具

实际工作中经常要在一台机器上同时存在 JDK 8 和 JDK 11,比如老的 Spring Boot 项目要 8,新的要 11;或者 JMeter 要 JDK 8,IDEA 要 JDK 17。Debian/Ubuntu 系里,包管理器安装的 java 默认走 update-alternatives 这套机制,它维护一组"候选版本"软链,用命令可以随时切换当前默认版本。我们手动装的 tar.gz 也可以注册进这套机制,让系统统一接管,避免两套管理方式互相打架。

# 把 tar.gz 安装的 JDK 注册进 alternatives sudo update-alternatives --install /usr/bin/java java /usr/local/java/jdk-11.0.15/bin/java 1100 sudo update-alternatives --install /usr/bin/javac javac /usr/local/java/jdk-11.0.15/bin/javac 1100 # 列出所有候选并交互式切换 sudo update-alternatives --config java sudo update-alternatives --config javac # 查看当前生效版本 update-alternatives --display java

参数说明:--install 后面依次是链接目标、链接名、候选程序路径、优先级,优先级数字越大越靠前;--config 会弹出交互式列表,输入编号即可切换;--display 列出当前所有候选和状态。注册的时候要注意 java 和 javac 是两条独立的链接,很多人只注册了 java 没注册 javac,结果 java -version 是对的,javac 还是旧的,一编译就报错。另外 openjdk 的 alternatives 注册项由包管理器维护,手动注册的项优先级设得足够高(比如 1100),就能盖过系统默认,切换逻辑清清楚楚。

5.2 手动软链方案:CentOS/RHEL 和其他发行版的通用做法

CentOS 上 alternatives 命令也存在,但很多运维在纯净生产机上更喜欢纯软链管理:JAVA_HOME 指向一个 current 软链,current 指向具体版本目录,切换版本就是换软链指向,一条链路,谁看了都懂。这个方案在任何发行版都通用,包括前面提到的国产化系统,因为底层就是标准文件系统操作,不依赖任何发行版的包管理机制。

# 建立 current 软链和 PATH 入口 sudo ln -sfn /usr/local/java/jdk-11.0.15 /usr/local/java/current sudo ln -sfn /usr/local/java/current/bin/java /usr/bin/java sudo ln -sfn /usr/local/java/current/bin/javac /usr/bin/javac # 要切到另一个版本时,只需要改 current 指向 sudo ln -sfn /usr/local/java/jdk-8u202-linux-x64 /usr/local/java/current # 验证 java -version

ln -sfn 的三个参数:-s 是软链,-f 是强制覆盖,-n 在目标是软链时不给它追加斜杠,这第三个参数在重复执行时很关键,不加 -n 可能导致链接嵌套错误。这套方案的维护成本在于:每装一个新 JDK 都要记得把目录放进 /usr/local/java 并更新 current。我的习惯是目录名一律带完整版本号(jdk-11.0.15、jdk-8u202),不带任何含糊的 latest 字样,因为没有命名比完整版本号更不会产生歧义。很多工具需要单独指定 JDK 路径:IDEA 在 Project Structure 里设置 SDK,DBeaver 在配置里指定 JRE 路径,JMeter 靠 JMETER_HOME 和 JAVA_HOME 决定,这些配置各自独立,跟系统 PATH 无关。理解了这一点,就不会再出现"系统里装了 11,DBeaver 却提示版本不够"的困惑了,那问题不在你的安装,而在工具的独立配置指向了别处。

5.3 卸载 JDK:好多机器是装的时候爽快、卸的时候翻车

卸 tar.gz 装的 JDK 是最简单的:删目录、删配置、删软链。但现实世界里经常是"装的时候用了 yum,卸的时候以为删目录就行",或者反过来。ubuntu 卸载 jdk 的热搜常年挂着,就是因为 apt remove 之后残留还在、alternatives 还挂着旧链接。卸载前先确认安装方式,再按对应方式清理,别凭感觉来。

安装方式卸载命令/步骤残留风险
tar.gz删目录 + 删 /etc/profile.d 配置 + 删软链低
apt(Ubuntu/Debian)sudo apt remove openjdk-* 后 purge中(alternatives 残留)
yum/dnf(CentOS)sudo yum remove java-*中
# 1) 删除 tar.gz 安装的目录和配置 sudo rm -rf /usr/local/java/jdk-11.0.15 sudo rm -f /etc/profile.d/java.sh # 2) 清理软链 sudo unlink /usr/bin/java sudo unlink /usr/bin/javac # 3) 如果是 alternatives 方式,先移除注册再清理 sudo update-alternatives --remove java /usr/local/java/jdk-11.0.15/bin/java sudo update-alternatives --remove javac /usr/local/java/jdk-11.0.15/bin/javac # 4) 验证彻底清除,没有输出说明系统里已经没有 java type -a java || echo "java 已不存在"

rm -rf 之前强烈建议先 mv 到一个临时目录(比如 /tmp/jdk-bak)观察几天,确认没有项目还在用再删,这是运维事故里最便宜的后悔药。update-alternatives --remove 的参数要和 --install 时完全一致,路径写错会报错说找不到条目。最后一步 type -a java 如果还有输出,说明有别的 java 还软链在系统路径里,顺着输出继续清理。卸载做对了,多 JDK 管理才算闭环,否则下次装新版时,旧版残留的软链会在 PATH 优先级里捣乱,兜兜转转又回到第 4 章的坑里。

6. 进阶:一个脚本把 JDK 部署固化下来,以后不再手敲

环境变量配完、坑也踩过一轮之后,我最后做的一件事是把整个流程固化成一个脚本。这样做的好处是:换一台机器、帮同事排查、甚至半年后自己重装服务器,都不需要回忆当年是怎么一步步配的。脚本要覆盖解压、路径规划、环境变量写入、软链、验证五件事,并且每一步失败都要给明确提示,不能黑匣子一样跑完没反应。脚本本身也适用于其他版本——JDK 8、JDK 17、JDK 21 的 tar.gz 都长一个样,想降级或升级,换一个包路径重新跑一遍就行,current 软链自然会切过去。

#!/bin/bash # jdk_install.sh - JDK tar.gz 一键部署脚本,适配 jdk-11.0.15_linux-x64_bin.tar.gz # 用法: sudo bash jdk_install.sh /path/to/jdk-11.0.15_linux-x64_bin.tar.gz set -euo pipefail PKG="$1" INSTALL_DIR="/usr/local/java" LINK_NAME="current" # 0) 前置检查:架构必须匹配,不匹配直接退出,避免 No such file 的坑 if [ "$(uname -m)" != "x86_64" ]; then echo "架构不匹配,当前是 $(uname -m),需要 x86_64" exit 1 fi # 1) 解压并建立 current 软链 mkdir -p "$INSTALL_DIR" tar -xzf "$PKG" -C "$INSTALL_DIR" VERSION_DIR=$(find "$INSTALL_DIR" -maxdepth 1 -type d -name 'jdk-*' | sort | tail -1) ln -sfn "$VERSION_DIR" "$INSTALL_DIR/$LINK_NAME" # 2) 写入全局环境变量 tee /etc/profile.d/java.sh > /dev/null <<'EOF' export JAVA_HOME=/usr/local/java/current export PATH=$JAVA_HOME/bin:$PATH EOF # 3) 验证:source 后直接检查版本,失败会被 set -e 拦住并停住 . /etc/profile.d/java.sh java -version && javac -version echo "部署完成: $VERSION_DIR"

set -euo pipefail 三件套是脚本的保命符:-e 让任何非零退出码中断脚本,-u 让未定义变量报错而不是静默当空串,-o pipefail 让管道命令不吞错误。前置检查里 uname -m 不等于 x86_64 直接退出,从源头避免架构不匹配。find 那行是为了拿到解压出来的完整版本目录名,用 sort 加 tail 确保取到最新的那个。tee 写环境变量用了带引号的 EOF,防止变量提前展开,这是我把第 3 章那个配置坑记下来之后总结的写法。

拿到这个脚本后我一般会再扩展两层:把type -a java的检查加进去,检测到 PATH 里存在多个 java 时打印警告;检测到 alternatives 注册项冲突时提示用 update-alternatives 接管现场。从那以后我每次给服务器装 JDK,都强制自己走一遍这个脚本,解压、配置、验证一条龙,再也没有出现过"装完了进不去"或者"以为装好了其实 PATH 被覆盖"的事。希望帮到你。

本文还有配套的精品资源,点击获取

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进