CentOS 8 安装 Apache Commons Net 指南

在 CentOS 8(EOL)上通过 centos-vault 存档源安装 OpenJDK 11 与 Maven,并以 Maven 依赖、官方二进制包两种方式集成 Apache Commons Net 3.13.0 的实测指南

Apache Commons NetApache Commons Net2026/10/15

CentOS 8 安装 Apache Commons Net 指南

目标:在 CentOS 8 服务器上完成 Apache Commons Net 3.13.0 的安装与最小验证,Maven 依赖与官方二进制包两种集成方式全部编译、运行成功。已在 CentOS Linux 8.4.2105(x86_64)+ OpenJDK 11.0.13 + Maven 3.5.4 实测通过。

一、环境信息

  • OS:CentOS Linux release 8.4.2105(CentOS Linux 8 的最终版本,已于 2021-12-31 EOL)
  • 架构:x86_64
  • JDK:OpenJDK 11.0.13(RPM 包 java-11-openjdk-devel,1:11.0.13.0.8-1.el8_4)
  • 构建工具:Apache Maven 3.5.4(RPM 包 maven,1:3.5.4-5.module_el8.0.0+39+6a9b6e22)
  • 组件版本:Apache Commons Net 3.13.0(2026-03-15 发布的官方最新稳定版)
  • Maven 坐标:commons-net:commons-net:3.13.0
  • 工作目录:/root/commons-net-demo(Maven 方案)、/root/jar-run(JAR 直跑方案)

二、前置条件

CentOS 8 已停止维护,官方 mirrorlist.centos.org 已下线,本文所有软件都从 centos-vault 存档仓库与 Apache/Maven 官方下载站获取。Commons Net 本身是纯 Java 客户端工具集(FTP/SMTP/POP3/Telnet/NTP/TFTP 等客户端与子网计算工具),安装即"把 JAR 放进构建路径",不需要任何系统级服务。

检查基础网络可达性:

cat /etc/redhat-release
curl -sI https://downloads.apache.org/commons/net/ | head -1
curl -sI https://repo1.maven.org/maven2/commons-net/commons-net/ | head -1

实测回显:

CentOS Linux release 8.4.2105
HTTP/1.1 200 OK
HTTP/2 200

💡 技术拓展:EOL 的 CentOS 8 找软件源时有三种典型去处:

渠道说明状态
mirrorlist.centos.org原始动态镜像列表已下线,不再解析
vault.centos.org官方存档国外网络可用,国内访问经常被拒(实测返回 403)
国内云厂商 centos-vault 镜像(本文用阿里云)与 vault 内容同步的存档镜像国内访问稳定,实测可用

本文采用阿里云 centos-vault 镜像作为存档源。

三、版本选型说明

Commons Net 版本选型与 Ubuntu 篇一致:官方 binaries/ 目录当前只有 3.13.0 系列文件(commons-net-3.13.0-bin.tar.gz 及其 .sha512/.asc 校验件),3.13.0 于 2026-03-15 发布,是最新稳定版。

CentOS 8 上需要重点选型的是 JDK。实测查询存档仓库:

dnf list java-17-openjdk java-17-openjdk-devel

实测回显:

Last metadata expiration check: 0:00:01 ago on Thu Oct 15 01:04:42 2026.
Error: No matching Packages to list

Java 17 没有进入 CentOS Linux 8 的存档仓库。仓库里可用的 JDK 版本以 java-11-openjdk-devel 为最高 LTS:

dnf list --showduplicates java-11-openjdk-devel maven

实测回显:

Available Packages
java-11-openjdk-devel.x86_64   1:11.0.10.0.9-8.el8                     appstream
java-11-openjdk-devel.x86_64   1:11.0.11.0.9-2.el8_4                   appstream
java-11-openjdk-devel.x86_64   1:11.0.12.0.7-0.el8_4                   appstream
java-11-openjdk-devel.x86_64   1:11.0.13.0.8-1.el8_4                   appstream
maven.noarch                   1:3.5.4-5.module_el8.0.0+39+6a9b6e22    appstream

选型结论:Commons Net 3.13.0 的官方 JAR 字节码基线为 Java 8(实测 javap -verbose 输出 major version: 52),Java 8 及以上均可运行,因此 JDK 11 RPM 完全满足要求;Maven 使用仓库自带的 3.5.4。若坚持要 JDK 17,需要从上游发行版(如 Adoptium Temurin)的 tar 包自行安装,不属于 RPM 管理,本文不展开。

四、方案 A:修复存档源 + RPM 安装 JDK/Maven + Maven 依赖集成(推荐)

4.1 把软件源指向 centos-vault 存档

先看修改前的 AppStream 源定义:

grep -E "^mirrorlist=|^#baseurl=" /etc/yum.repos.d/CentOS-Linux-AppStream.repo

实测回显:

mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=AppStream&infra=$infra
#baseurl=http://mirror.centos.org/$contentdir/$releasever/AppStream/$basearch/os/

把 mirrorlist 全部注释、baseurl 改指阿里云存档镜像、去掉存档目录结构中不再存在的 $contentdir 层级,并把 $releasever 固定为 8.4.2105(镜像按完整版本号组织目录,而系统默认 $releasever 是 8,不固定会 404):

echo "8.4.2105" > /etc/dnf/vars/releasever
sed -i -e 's|mirrorlist=|#mirrorlist=|g' \
       -e 's|#baseurl=http://mirror.centos.org|baseurl=http://mirrors.aliyun.com/centos-vault|g' \
       -e 's|$contentdir/||g' /etc/yum.repos.d/CentOS-Linux-*.repo
grep -E "^#mirrorlist=|^baseurl=" /etc/yum.repos.d/CentOS-Linux-AppStream.repo

实测回显:

#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=AppStream&infra=$infra
baseurl=http://mirrors.aliyun.com/centos-vault/$releasever/AppStream/$basearch/os/

刷新缓存验证:

dnf clean all
dnf makecache

输出节选(实测末尾):

CentOS Linux 8.4.2105 - AppStream               2.5 MB/s | 9.6 MB     00:03
CentOS Linux 8.4.2105 - BaseOS                  2.8 MB/s | 8.5 MB     00:03
CentOS Linux 8.4.2105 - Extras                   36 kB/s |  10 kB     00:00
Metadata cache created.

验证结果:三个存档仓库全部建成元数据缓存,源修复完成。

4.2 安装 JDK 11 与 Maven

dnf install -y java-11-openjdk-devel maven

输出节选(实测):

Installing:
 java-11-openjdk-devel                     x86_64  1:11.0.13.0.8-1.el8_4                         appstream  3.4 M
 maven                                     noarch  1:3.5.4-5.module_el8.0.0+39+6a9b6e22          appstream   27 k
Installing dependencies:
 adwaita-cursor-theme                      noarch  3.28.0-2.el8                                  appstream  647 k
 adwaita-icon-theme                        noarch  3.28.0-2.el8                                  appstream   11 M
 alsa-lib                                  x86_64  1.2.4-5.el8                                   appstream  471 k

要点提示(实测踩坑):这条命令会连带把 java-1.8.0-openjdk 全家装进来(Maven 模块的依赖链需要它),且系统默认 java 立刻指向 1.8:

java -version

实测回显:

openjdk version "1.8.0_312"
OpenJDK Runtime Environment (build 1.8.0_312-b07)
OpenJDK 64-Bit Server VM (build 25.312-b07, mixed mode)

用 alternatives 把 java 与 javac 切到 11:

alternatives --set java java-11-openjdk.x86_64
alternatives --set javac java-11-openjdk.x86_64
java -version
javac -version

实测回显:

openjdk version "11.0.13" 2021-10-19 LTS
OpenJDK Runtime Environment 18.9 (build 11.0.13+8-LTS)
javac 11.0.13

4.3 固定 Maven 使用的 JVM(实测必做)

java/javac 切到 11 后,Maven 3.5.4 仍然默认绑定 1.8(el8 的 Maven 不读 alternatives,读自己的 JVM 定位逻辑):

mvn -version | head -3

实测回显:

Apache Maven 3.5.4 (Red Hat 3.5.4-5)
Maven home: /usr/share/maven
Java version: 1.8.0_312, vendor: Red Hat, Inc., runtime: /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.312.b07-1.el8_4.x86_64/jre

显式设置 JAVA_HOME 后 Maven 才用上 JDK 11:

export JAVA_HOME=/usr/lib/jvm/java-11
echo "export JAVA_HOME=/usr/lib/jvm/java-11" > /etc/profile.d/java11.sh
mvn -version | head -3

实测回显:

Apache Maven 3.5.4 (Red Hat 3.5.4-5)
Maven home: /usr/share/maven
Java version: 11.0.13, vendor: Red Hat, Inc., runtime: /usr/lib/jvm/java-11-openjdk-11.0.13.0.8-1.el8_4.x86_64

4.4 创建最小验证工程并构建运行

mkdir -p /root/commons-net-demo/src/main/java
cd /root/commons-net-demo

创建 pom.xml(与 Ubuntu 篇完全一致:maven.compiler.release=8 证明 Java 8 基线可用,固定 compiler 插件 3.11.0):

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>demo</groupId>
  <artifactId>commons-net-demo</artifactId>
  <version>1.0.0</version>
  <packaging>jar</packaging>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.release>8</maven.compiler.release>
  </properties>

  <dependencies>
    <dependency>
      <groupId>commons-net</groupId>
      <artifactId>commons-net</artifactId>
      <version>3.13.0</version>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.11.0</version>
      </plugin>
    </plugins>
  </build>
</project>

创建 src/main/java/SubnetDemo.java(无需任何网络服务的最小验证程序):

import org.apache.commons.net.util.SubnetUtils;
import org.apache.commons.net.util.SubnetUtils.SubnetInfo;

public class SubnetDemo {
    public static void main(String[] args) {
        SubnetUtils su = new SubnetUtils("192.168.56.0/26");
        SubnetInfo info = su.getInfo();
        System.out.println("[不含网络号/广播号] low=" + info.getLowAddress()
                + " high=" + info.getHighAddress()
                + " 可用地址数=" + info.getAddressCountLong());
        su.setInclusiveHostCount(true);
        info = su.getInfo();
        System.out.println("[含网络号/广播号]   low=" + info.getLowAddress()
                + " high=" + info.getHighAddress()
                + " 可用地址数=" + info.getAddressCountLong());
        System.out.println("network=" + info.getNetworkAddress()
                + " netmask=" + info.getNetmask()
                + " broadcast=" + info.getBroadcastAddress());
        System.out.println("isInRange(192.168.56.100) = " + info.isInRange("192.168.56.100"));
        System.out.println("isInRange(192.168.57.100) = " + info.isInRange("192.168.57.100"));
        System.out.println("commons-net OK");
    }
}

编译(首次构建需从中央仓库下载插件与依赖,耗时约两分钟):

export JAVA_HOME=/usr/lib/jvm/java-11
mvn -B compile

输出节选(实测末尾):

[INFO] Compiling 1 source file with javac [debug release 8] to target/classes
[INFO] BUILD SUCCESS
[INFO] Total time:  01:55 min
[INFO] Finished at: 2026-10-15T01:09:27Z

依赖树确认(注意 commons-io 是 3.13.0 的传递依赖):

mvn -q dependency:tree -DoutputFile=deptree.txt
cat deptree.txt

实测回显:

demo:commons-net-demo:jar:1.0.0
\- commons-net:commons-net:jar:3.13.0:compile
   \- commons-io:commons-io:jar:2.21.0:compile

运行验证程序:

java -Dfile.encoding=UTF-8 -cp target/classes:$HOME/.m2/repository/commons-net/commons-net/3.13.0/commons-net-3.13.0.jar:$HOME/.m2/repository/commons-io/commons-io/2.21.0/commons-io-2.21.0.jar SubnetDemo

实测回显:

[不含网络号/广播号] low=192.168.56.1 high=192.168.56.62 可用地址数=62
[含网络号/广播号]   low=192.168.56.0 high=192.168.56.63 可用地址数=64
network=192.168.56.0 netmask=255.255.255.192 broadcast=192.168.56.63
isInRange(192.168.56.100) = false
isInRange(192.168.57.100) = false
commons-net OK

验证结果:/26 网段解析、范围判断全部正确,安装完成。

五、方案 B:官方二进制包手动集成(不使用 Maven)

5.1 下载与校验

cd /root
curl -O https://downloads.apache.org/commons/net/binaries/commons-net-3.13.0-bin.tar.gz
curl -O https://downloads.apache.org/commons/net/binaries/commons-net-3.13.0-bin.tar.gz.sha512
ls -l commons-net-3.13.0-bin.tar.gz
echo "期望: $(cut -d " " -f1 commons-net-3.13.0-bin.tar.gz.sha512)"
echo "实测: $(sha512sum commons-net-3.13.0-bin.tar.gz | cut -d " " -f1)"

实测回显(期望与实测哈希一致):

-rw-r--r-- 1 root root 2352355 Oct 15 01:12 commons-net-3.13.0-bin.tar.gz
期望: 4827d6ea3cfcfba317dfac35c0ca013b737935253639302c274ebf2adeaa4d2fa36ccc36f92be32f76dd25c8bef72a116b308ca3e823b50af1b843f389c30b6f
实测: 4827d6ea3cfcfba317dfac35c0ca013b737935253639302c274ebf2adeaa4d2fa36ccc36f92be32f76dd25c8bef72a116b308ca3e823b50af1b843f389c30b6f

5.2 编译与运行

tar xzf commons-net-3.13.0-bin.tar.gz
ls commons-net-3.13.0/
ls -l commons-net-3.13.0/commons-net-3.13.0.jar

实测回显:

LICENSE.txt
NOTICE.txt
README.md
RELEASE-NOTES.txt
apidocs
commons-net-3.13.0-sources.jar
commons-net-3.13.0.jar
commons-net-examples-3.13.0.jar
org
-rw-r--r-- 1 root root 337311 Mar 15  2026 commons-net-3.13.0/commons-net-3.13.0.jar

顺手复核字节码基线(用 JDK 11 的 javap 看 major version):

javap -verbose -cp commons-net-3.13.0/commons-net-3.13.0.jar org.apache.commons.net.ftp.FTPClient 2>/dev/null | grep -E "major|minor"

实测回显:

  minor version: 0
  major version: 52

编译运行验证程序:

mkdir -p /root/jar-run && cd /root/jar-run
cp /root/commons-net-3.13.0/commons-net-3.13.0.jar .
cp /root/commons-net-demo/src/main/java/SubnetDemo.java .
javac -encoding UTF-8 -cp commons-net-3.13.0.jar -d out SubnetDemo.java
java -Dfile.encoding=UTF-8 -cp out:commons-net-3.13.0.jar SubnetDemo

实测回显:

[不含网络号/广播号] low=192.168.56.1 high=192.168.56.62 可用地址数=62
[含网络号/广播号]   low=192.168.56.0 high=192.168.56.63 可用地址数=64
network=192.168.56.0 netmask=255.255.255.192 broadcast=192.168.56.63
isInRange(192.168.56.100) = false
isInRange(192.168.57.100) = false
commons-net OK

验证结果:与方案 A 一致。要点提示:SubnetUtils 纯工具类只挂一个 JAR 即可运行;FTP 传输路径实测还会加载 commons-io 的类(3.13.0 起的运行时依赖),届时需把 commons-io-2.21.0.jar 一并加入 classpath,否则抛 NoClassDefFoundError。

六、方案对比与选择建议

维度方案 A:RPM + Maven 依赖方案 B:官方 bin 包直跑
版本升级改 POM 版本号即可重新下载、校验、解压
传递依赖自动带入 commons-io需手工补齐,容易漏
离线/内网需私服或提前拉取只需一个 tar 包
系统包管理JDK/Maven 归 dnf/alternatives 管全部游离在 RPM 之外
本文结论首选辅助、救急

选择建议:正式工程走方案 A;方案 B 适合无法访问中央仓库的内网节点。CentOS 8 的特殊之处在于方案 A 必须先完成 4.1 的存档源修复,且 4.2/4.3 的 JDK 版本切换与 JAVA_HOME 固定是实测绕不过去的步骤。

七、配置说明

  • Commons Net 本身没有配置文件,行为全部通过运行时 API 设置(超时、字符集、传输模式等),详见本系列《配置参数详解》。
  • JVM 层面建议显式指定编码:java -Dfile.encoding=UTF-8(本文运行命令均带该参数)。
  • JAVA_HOME 必须持久化,否则重开 shell 后 Maven 又会退回 1.8(见 4.3 的 /etc/profile.d/java11.sh)。
  • Maven 本地仓库位于 /root/.m2/repository,Commons Net 落在 /root/.m2/repository/commons-net/commons-net/3.13.0/。

八、多版本管理

与 Ubuntu 篇相同,多个 Commons Net 版本在本地仓库并列共存,切换只改 POM:

mvn -q dependency:get -Dartifact=commons-net:commons-net:3.11.1
ls -1 $HOME/.m2/repository/commons-net/commons-net/

实测回显:

3.11.1
3.13.0
mvn dependency:tree | grep commons-net

实测回显:

\- commons-net:commons-net:jar:3.13.0:compile

要点提示:同一工程内不要直接引入两个版本的 Commons Net,Maven 就近原则只保留一个,另一个的类一旦被引用将 ClassNotFoundException。

九、常见问题(FAQ)

  1. dnf makecache 报 Failed to download metadata for repo 'appstream'?说明还在用已下线的 mirrorlist 或把 $releasever 解析成了 8。按 4.1 固定 releasever=8.4.2105 并把 baseurl 指向存档镜像。
  2. vault.centos.org 直接访问返回 403?国内网络对该站不稳定,实测用阿里云 mirrors.aliyun.com/centos-vault 正常,结构与官方存档一致。
  3. 装完 JDK 11 后 java -version 还是 1.8?dnf install java-11-openjdk-devel maven 会连带安装 java-1.8.0-openjdk 并把默认 java 指向它,按 4.2 用 alternatives --set 切换。
  4. java 已经是 11,mvn -version 却显示 1.8.0_312?el8 的 Maven 不读 alternatives,按 4.3 显式 export JAVA_HOME=/usr/lib/jvm/java-11 并写入 /etc/profile.d/。
  5. 想要 JDK 17 跑 Commons Net?存档仓库实测没有 java-17-openjdk(dnf list 报 No matching Packages to list),需要上游 tar 包方案,Commons Net 3.13.0 的 Java 8 基线用 JDK 11 已完全够用。
  6. 运行 FTP 示例报 NoClassDefFoundError: org/apache/commons/io/output/ProxyOutputStream?3.13.0 的传输路径依赖 commons-io 2.21.0,JAR 直跑方案要手动加入 classpath;Maven 方案自动带入。

十、卸载与清理

先预览要移除的包(--assumeno 只打印事务摘要并中止,不真删):

dnf remove java-11-openjdk-devel maven --assumeno 2>&1 | tail -5

实测回显:

Transaction Summary
==================================================================================================================
Remove  134 Packages

Freed space: 442 M
Operation aborted.

确认无误后去掉 --assumeno 执行,并清理工程与仓库缓存:

dnf remove -y java-11-openjdk-devel maven
dnf autoremove -y
rm -f /etc/profile.d/java11.sh /etc/dnf/vars/releasever
rm -rf /root/commons-net-demo /root/jar-run
rm -rf /root/commons-net-3.13.0 /root/commons-net-3.13.0-bin.tar.gz /root/commons-net-3.13.0-bin.tar.gz.sha512
rm -rf /root/.m2/repository/commons-net

要点提示:rm /etc/dnf/vars/releasever 会让 $releasever 回到 8,若还打算继续用该存档源,保留这个文件即可。

十一、参考链接