简介:面向Ubuntu系统下需要离线安装开发工具与网卡驱动的用户,这份资源将gcc、make、build-essential及Realtek r8125驱动源码整合为一个rar压缩包,特别适合在无网络环境中为Realtek千兆网卡完成驱动安装。包内共42个文件,压缩后30.01MB,核心为23个deb安装包,涵盖gcc、g++、make、libc6-dev等编译依赖,同时包含r8125驱动所需的C源码、头文件、Makefile、autorun.sh安装脚本及readme说明,覆盖从依赖安装到驱动编译的完整链路。已有3768人学习下载,离线部署时只需先安装deb包,再执行make和make install即可让网卡正常工作,省去逐包查找依赖的繁琐步骤,是Ubuntu 18.04等系统配置Realtek网卡的实用工具包。
1. 断网环境下的 Ubuntu 装 Realtek 2.5G 网卡:先把编译链备齐,再碰 r8125 驱动
拿到一台没有外网的 Ubuntu 机器,装完系统才发现网卡不亮,lspci 一看是 Realtek 的螃蟹卡,大概率是驱动没装上。这时你面对的是个死循环:装驱动需要 gcc、make、build-essential 这些编译工具,而装这些工具又需要网络。网上很多教程默认你有外网,几个 apt install 敲下去就完事,但在纯内网或离线环境里,这一套全都不成立。这个资源的思路很直接——把 gcc、make、build-essential 连同一堆依赖打包成离线 deb,再把 r8125 网卡驱动源码放在一起,让断网环境下的人先装工具链、再编驱动,一条链路走完。它适合的就是手里只有离线机器、又急着把 Realtek 网卡用起来的运维或嵌入式开发者,不用费劲去别的机器上一个个找依赖,省的是来回倒腾的时间。
2. 编译工具链离线安装:本地源优先级与 dpkg 三个要点
2.1 先理清驱动编译时需要哪些东西
r8125 是瑞昱官方为 2.5G 网卡提供的驱动源码包,常见版本会带一个autorun.sh脚本,表面上看一条命令就能装完。但脚本背后跑的还是标准编译流程:调用 gcc 编译内核模块,调用 make 执行 Makefile,期间还会用到 build-essential 这个元包拉进来的 libc 开发文件、make、g++ 等。如果你跳过工具链直接跑./autorun.sh,通常会在make阶段报一堆找不到头文件或者命令不存在之类的错误,日志看起来像内核源码问题,实际原因是你根本没装编译器。这是很多人第一次离线装这个驱动时被卡住的原因——看到报错fatal error: linux/compiler.h: No such file or directory,条件反射以为是内核头文件不对,其实 gcc 都没就位。离线包里把 build-essential 以及它依赖的 gcc、g++、libc6-dev、dpkg-dev 这些 deb 全收进来,就是为了先补齐这一层。
还有一点容易忽略:内核头文件。make 编译内核模块时会去/usr/src/linux-headers-$(uname -r)找头文件,这套离线包里通常也包含对应的linux-headers-.*amd64、linux-libc-dev等包。如果你的系统内核版本和离线包自带的头文件不匹配,编译时会出现Cannot find kernel source或者Makefile: not found的提示。所以在进入编译环节之前,先把uname -r和离线包里的头文件版本对一遍,省得后面白折腾。工具链能装好只是第一步,版本匹配才是决定编译能不能顺利走完的关键。
2.2 两种安装方式:手动 dpkg 与搭建本地 apt 源
离线安装 deb 有两条路可以走,一是直接dpkg -i逐个安装,二是把所有 deb 放到一个目录里建立本地 apt 源,再用apt-get install安装。手动 dpkg 适合依赖关系简单的场景,但 build-essential 这个包会带来一串依赖,逐个dpkg -i容易把你绕晕。我一般会先把离线包解压到一个固定目录,然后直接dpkg -i这个目录下所有的 deb,让 dpkg 自己去解析大部分依赖。
# 解压离线包到本地目录 mkdir -p /opt/offline-debs/r8125 tar -xzf r8125-offline-package.tar.gz -C /opt/offline-debs/r8125 # 先刷一遍目录,确认 deb 文件都在且没有损坏 cd /opt/offline-debs/r8125 && ls -la *.deb | wc -l # 批量安装所有 deb(同目录依赖会自动解析) dpkg -i *.deb批量dpkg -i *.deb的逻辑是:dpkg 会先读取所有 deb 的依赖关系,把能装的先装上,装不上的会记录在案,最后统一提示。常见的报错是某些包依赖没被满足,这时候只要再跑一次apt-get -f install就能自动补齐,但离线环境下没有网络,apt-get -f install基本废掉。所以在执行前要检查 deb 包的完整性,用dpkg --info可以查看某个 deb 的依赖项,其中Depends后面列出的内容就是它要求其他包提供的东西。如果离线包作者已经把所有依赖收齐,批量安装会一气呵成,不用干预;如果中途报缺依赖,优先检查是不是漏了某个 dpkg 包,而不是怀疑安装命令本身。
另一种更省心的做法是把 deb 目录注册成本地 apt 源,这样可以用apt-get install来装,依赖解析交给 apt 处理。步骤稍微多一点,但后续一切以 apt 方式安装的软件都会自动从这个源补依赖,适合要在离线机器上反复装环境的人。建立本地源需要dpkg-scanpackages这个工具,它属于 dpkg-dev 包,离线包里一般会带上。
# 将离线 deb 目录初始化为本地源 cd /opt/offline-debs/r8125 dpkg-scanpackages . /dev/null | gzip > Packages.gz # 把本地源写入 apt 配置,注意 Sources 路径换成你自己的目录 echo 'deb [trusted=yes] file:///opt/offline-debs/r8125 ./' > /etc/apt/sources.list.d/local-offline.list apt-get update # 用 apt 安装,依赖自动解析,比手动 dpkg 更稳 apt-get install -y build-essentialdpkg-scanpackages后面的/dev/null是覆盖文件路径,这里不需要;[trusted=yes]是因为本地源没有签名,apt 默认会拒绝未签名的源,加上这个参数才能正常读取。用file://协议指向本地目录,apt 会在该目录下找Packages.gz作为包索引。这种方式的好处是后续装别的包时有依赖冲突可以直接看到,而且能在安装前模拟依赖解析——用apt-get install --dry-run build-essential跑一遍就能知道哪些包会被拉进来、哪些版本冲突,提前发现资源包本身是否有问题。
2.3 安装顺序的“依赖闭包”逻辑与验证
离线包里 deb 文件数量通常不少,动辄十几个。它们的依赖关系是一个有向图,比如 gcc 依赖 binutils、cpp、libc6-dev,而 libc6-dev 又依赖 libc6。dpkg 在安装时并不会自动按拓扑序处理,它只保证当前命令里的包安装完后系统状态是自洽的。所以如果你用手动方式一个包一个包地装,顺序错了就会跳出依赖不满足的提示。里面的惯用套路是先装 libc6 和 libc6-dev 这类底层库,再装 cpp、binutils、gcc,最后装 g++ 和 build-essential。你要是嫌麻烦,就直接dpkg -i *.deb,一条命令把所有包交给 dpkg 处理,它会先检查整个集合的依赖闭包,然后按尽可能合理的顺序装。
装完后要验证工具链可用,这是不能省的一步,不能只看dpkg -l build-essential显示已安装就过了。最直接的验证方式是编译一个极小的模块或者一个 hello world,确认 gcc、make、头文件三件套都在。注意这里不能只编译个可执行文件,因为驱动编译需要的是内核构建环境,能编普通 C 程序只能说明 gcc 和 libc 没问题,内核头文件是否匹配还要看/usr/src目录。
# 1. 检查编译工具版本 gcc --version | head -n 1 make --version | head -n 1 # 2. 检查内核头文件目录是否与当前内核匹配 uname -r ls -d /usr/src/linux-headers-$(uname -r) # 3. 编译一个可加载内核模块验证环境完整性 cat > /tmp/testmod.c <<'EOF' #include <linux/init.h> #include <linux/module.h> static int __init test_init(void) { return 0; } static void __exit test_exit(void) { } module_init(test_init); module_exit(test_exit); MODULE_LICENSE("GPL"); EOF make -C /usr/src/linux-headers-$(uname -r) M=/tmp testmod.komake -C指定内核头文件目录,M=/tmp表示要编译的模块源码所在的目录,这个参数是内核模块编译的标准用法:kbuild 系统会进入头文件目录读取 Makefile,然后把M指向的目录里的源码编译成.ko文件。如果这条命令跑到一半报gcc: error: elf.h: No such file or directory,说明 libc6-dev 还没装上,返回去检查 deb 集合是否完整。只有testmod.ko成功生成,才说明 gcc、make、内核头文件这一整条链是通的,后面编 r8125 才有戏。
3. r8125 驱动编译:从 autogen.sh 到 insmod 的完整链路
3.1 动手前先确认网卡识别与 r8125 源码版本
工具链就位后,不要把autorun.sh当成唯一入口。我在实际项目中更习惯手动分步执行,每一阶段都能看到输出,出问题也能定位到底卡在哪一步。网卡芯片型号要先用lspci确认是 RTL8125 而不是 RTL8168——这两个是不同的驱动,8168 用的是 r8168 驱动,拿 r8125 源码去编会直接报Device not supported或加载后不识别网卡。
# 1. 查看网卡 PCI 设备描述 lspci -vnn | grep -i realtek # 2. 查看内核是否已加载相关网卡驱动(可能加载了 r8169) lsmod | grep r8125 lsmod | grep r8169 # 3. 查看 ethtool 是否能识别当前网卡 ethtool eth0 2>&1 | head -n 10如果lspci显示类似Realtek Semiconductor Co., Ltd. RTL8125 2.5GbE Controller就说明识别的没错。内核自带的 r8169 驱动在一定版本之后也能驱动 RTL8125,但性能和特性上不如官方 r8125 驱动,而且有些主板上的 8125 网卡用 r8169 驱动会出现断流、速度协商不到 2.5G 的问题。这时候卸载 r8169 再加载 r8125 是常见操作,类同于你花大力气编译官方驱动的根本目的——内核自带驱动能用,但不好用,速度和稳定性都是玄学。若是lsmod里已经能看到r8125,说明之前装过,直接rmmod r8125重来即可。
r8125 源码包解压后会有一个src目录和autorun.sh,里面还经常有README.md。要先看README里写的支持内核版本范围,这一步能提前避开许多坑。有些版本源码对 6.x 内核支持有问题,编译时报implicit declaration of function之类的错误,根源是内核 API 变化而驱动源码没跟上。如果你的内核过新,源码包里可能缺少补丁;反过来如果内核过旧,源码里的新写法也会报错。确认源码版本与内核版本的开区间,比盲目 make 更重要。
3.2 手动编译流程:make 与模块参数说明
进入源码目录后,不走autorun.sh的好处是每一步都可控。r8125 源码包一般在解压后的r8125-x.xxx.x目录里有一个src子目录,Makefile 在src里面。一些版本需要在根目录先跑./autogen.sh生成 configure 文件,这一步生成的是用户态工具(如 rss 配置工具)的构建脚本。如果你只需要内核模块,可以直接进src目录执行 make,不需要生成 configure。但保险起见,还是先把 autogen.sh 跑一遍,它不会产生副作用,只会生成必要文件。
# 1. 解压源码包并进入目录 tar -xjf r8125-*.tar.bz2 cd r8125-*/src # 2. 清理上次编译的残留,避免 stale 对象文件干扰 make clean # 3. 编译内核模块,KSRC 指定内核头文件目录,一般会自动识别 make KSRC=/usr/src/linux-headers-$(uname -r) # 4. 查看生成的模块文件 ls -la *.komake clean是必做的一步。源码包里可能残留之前编译环境下的.o和.ko文件,直接 make 会用旧的编译产物,出现一些莫名其妙的符号错误。KSRC 参数是 r8125 Makefile 自定义的变量,指向内核头文件目录,部分版本 Makefile 会自动用uname -r拼接路径,不需要手动指定;你如果看到 make 输出里KERNELDIR字样,说明它走的是自动路径。编译成功的标志是出现r8125.ko文件。编译期间如果报错,最常见的两种情况是:头文件缺失(工具链问题,回到第 2 章排查)和源码与内核 API 不兼容(需要看具体报错去搜补丁)。
编译完成后不要急着make install,可以先手动insmod加载测试,有问题卸载也方便。模块参数可以加copybreak、tx_ring_size这些,但初次加载不需要带参数,让驱动用自己的默认值就行。
# 1. 先卸载可能冲突的内置驱动 rmmod r8169 2>/dev/null || true # 2. 加载编译好的 r8125 模块 insmod ./r8125.ko # 3. 确认模块加载成功,并查看是否识别到网卡 lsmod | grep r8125 ip link show # 4. 如果识别到网卡,用 ethtool 确认速率协商结果 ethtool eth0 | grep -i speedinsmod是强制加载指定路径的模块,不走 depmod 的模块依赖数据库,所以只要路径对就能加载。加载后ip link show里出现新的接口名(一般是 eth0 或 enpXsY),才说明驱动和硬件握手成功。用ethtool看 Speed 字段,能到 2500Mb/s 说明协商为 2.5G;如果显示 1000Mb/s,要检查对端设备、网线类别和端口速率限制。第一次 insmod 成功后不要马上重启,接下来要做持久化,不然重启后模块就不在了。
3.3 模块持久化与 depmod 的注册
insmod只是临时把模块加载进内核,重启后系统不会自动加载它。正规做法是把r8125.ko复制到/lib/modules/$(uname -r)/extra/目录,跑一遍depmod -a更新模块依赖,再把模块名写入/etc/modules-load.d/下的配置文件。depmod -a会扫描所有模块目录生成modules.dep,这个文件告诉系统模块之间的依赖关系;写入 modules-load.d 是让 systemd 在启动时按清单自动加载。没有这一步,你每次重启都要手动 insmod,非常麻烦。
# 1. 复制模块到内核模块目录(extra 目录不存在则创建) mkdir -p /lib/modules/$(uname -r)/extra cp r8125.ko /lib/modules/$(uname -r)/extra/ # 2. 更新模块依赖数据库 depmod -a # 3. 配置开机自动加载 echo "r8125" > /etc/modules-load.d/r8125.conf # 4. 加载并验证模块已被系统登记 modprobe r8125 lsmod | grep r8125modprobe和insmod不同,它会在/lib/modules/$(uname -r)/里搜索模块并处理依赖,日常运维优先用 modprobe 而不是 insmod。/etc/modules-load.d/r8125.conf里写的是模块名,不带.ko后缀。注意,如果之后内核升级,/lib/modules/$(uname -r)的$(uname -r)会变化,新内核目录下没有这个 .ko,需要重新编译。离线环境下内核升级不是高频操作,但一旦升级,整套工具链和驱动编译流程都得重走一遍,所以建议升级前先备份当前内核版本下的 .ko 文件和源码包。
4. 避坑排查:五个“装不上”的真相与处理顺序
4.1 死循环:系统装好没法联网,需要网卡驱动,装驱动又需要联网
离线机器的典型困境是网卡驱动没装,所以没有网络;没有网络,就没法下载安装编译工具链。很多人一上来就卡死在这个循环里,然后开始怀疑是不是网卡坏了。
解决:用另一台机器把整个离线包准备好,内容包括编译工具链 deb 和驱动源码,全部拷进 U 盘或移动硬盘,再插到离线机器上。也可以试试用 USB 共享网络(安卓手机开启 USB 热点)临时给机器上网,先装好工具链;但企业内网环境可能不允许外接设备,走 U 盘拷包最稳妥。我在实际项目中用过这个方法处理过数次死循环,痛点在于很多人只拷了驱动源码,没拷工具链,结果依然无法编译,离线包里直接带齐这两层,就省了这一步的折腾。
4.2 内核头文件版本与当前内核不一致
现象:make -C /usr/src/linux-headers-$(uname -r) M=...时报错linux/version.h: No such file or directory,或者Makefile: 在 /usr/src/linux-headers-xxx 没有文件。
原因:系统内核在装完系统后升级过一次,头文件只装了旧版本;或者离线包里的 linux-headers deb 和当前内核版本对不上。
解决:用dpkg -l | grep linux-headers查看已安装的头文件包,对比uname -r输出的内核版本。不一致时找对应版本的 linux-headers deb,装好后再编译。如果实在找不到头文件,另一个方案是换用内核自带的 r8169 驱动,不折腾 r8125,前提是内核版本较新(5.6+)且能接受功能上的折中。这个回退方案不算完美,但能让网卡先跑起来,等其他渠道拿到正确头文件再编译。
4.3 高版本 gcc 的“警告即错误”问题
现象:编译过程中大量warning:输出,然后以error: implicit declaration of function或其他告警类错误收尾,整个 make 退出。
原因:较新的 gcc(11/12/13)把很多原本只是警告的检查提升到了报错级别,老驱动源码没做适配。r8125 源码本身会维护兼容性,但个别版本遇到新 gcc 会出问题。
解决:改 Makefile 或 CFLAGS,把-Werror去掉。具体做法是在 make 命令行追加EXTRA_CFLAGS="-Wno-error",或者直接修改 src/Makefile 里 CFLAGS 那行,把-Werror字样删掉。不要动编译器的默认警告级别,只关掉“把警告当错误”的开关,不影响模块功能。如果报错里出现符号声明缺失,多半是驱动源码太老,需要找对应补丁或新版源码包。
4.4 Secure Boot 把模块挡在黑匣子外面
现象:insmod r8125.ko报Required key not available或Module verification failed,但模块明明编译成功了。
原因:UEFI Secure Boot 开启后,内核强制要求加载的模块带有合法签名,自编译模块没有签名,直接被拒。
解决:两个方向。一是临时关闭 Secure Boot,在 BIOS 里找到 Secure Boot 选项设为 Disabled,重启后重新加载模块。另一个是给模块签名,需要mokutil和openssl自己生成密钥并导入 MOK 列表,步骤复杂些,适合必须保持 Secure Boot 开启的场景。大部分离线机器是内网服务器,关闭 Secure Boot 风险可接受,我一般直接关掉。注意改 BIOS 后要按 F10 保存退出,进系统再 insmod。
4.5 模块加载后网卡不出现或者链路起不来
现象:模块 insmod 成功,lsmod | grep r8125有输出,但ip link里找不到新的网卡,或者网卡出现了但插上网线链路指示灯不亮。
原因:可能是驱动源码版本太老,不识别当前网卡的子系统 ID;也可能是硬件上有多个 Realtek 网卡,而驱动绑定到了错误的那一个。还有一种常见情况是之前在用的 r8169 驱动没有完全卸载,两个驱动同时抢占同一个 PCI 设备,导致 r8125 绑定失败。
解决:先lspci -k看当前设备驱动绑定情况,确认Kernel driver in use是 r8125 还是 r8169。还是 r8169 的话就rmmod r8169,再modprobe r8125。如果驱动已绑定但网卡没出现,用dmesg | tail -n 20看内核日志里 r8125 的报错信息,常见是no suitable device found——这就是网卡型号不被该版本驱动支持,要换新版源码包或改官方驱动版本。还有一种情形是系统里有多个网卡,驱动加载时按 PCI 顺序绑定,ip link里出现的接口名和你预期的不同,仔细看lspci -k的输出,核对 PCI 设备号即可。
5. 验证与进阶:从断网到重启不丢驱动的收尾习惯
这次收尾想讲一个很多人容易忽视的细节:驱动装好、网络通了以后,一定要跑一遍完整验证,不能只看ip a里面有地址就算完了。我在某次项目中遇到过驱动加载成功、网卡也有 IP,但重启后接口名从eth0变成了enp3s0,导致配置文件里的auto eth0全部失效,服务起不来。
验证分三步走。第一步是ethtool -i eth0查看driver: r8125和version字段,确保当前生效的确实是编译安装的驱动,而不是内核自带 r8169。第二步是systemctl restart networking或对应网络管理服务,然后ip link show确认接口状态是UP,并检查ethtool eth0的 Speed 是否为 2500Mb/s。第三步是重启一次机器,重启后先lsmod | grep r8125确认模块自动加载,再确认网络服务自动拉起。如果第三网络不通,多半是 modules-load.d 里的配置没生效,或者网络服务配置里写了旧接口名,用dmesg | grep r8125看启动日志来定位。
进阶用法方面,可以考虑把驱动编译纳入 DKMS 管理。虽然离线包里一般不直接包含 DKMS 配置,但你可以自己补一个。DKMS 的好处是内核升级时自动重编模块,不用手动复制 .ko 和重跑 depmod。做法是把 r8125 源码包放到/usr/src/r8125-版本号/,写一个dkms.conf,然后dkms add、dkms build、dkms install三步走。离线环境下 dkms 包本身要提前装好,如果你的离线包里有 dkms deb,就能一劳永逸。没有的话,保留源码包和编译记录,内核升级后手动重编也行。
# 查看驱动版本与模块参数 ethtool -i eth0 cat /sys/module/r8125/parameters/* # 如果打算用 DKMS 管理,先确认 dkms 装好 dpkg -l dkms # 模拟内核升级后的重编流程(不实际升级,只验证源码可用) make -C /usr/src/linux-headers-$(uname -r) M=$(pwd)/src clean make -C /usr/src/linux-headers-$(uname -r) M=$(pwd)/src驱动加载后的参数调优也可以关注一下,比如tx_ring_size和rx_ring_size默认值在 2.5G 高吞吐下可能需要调大。修改方式是在/etc/modprobe.d/r8125.conf里写options r8125 tx_ring_size 1024 rx_ring_size 1024,然后modprobe -r r8125 && modprobe r8125重新加载生效。不过调参前先确认你的业务场景是否真的打满了 2.5G 带宽,否则动了参数反而可能引入延迟。从那以后,我在离线环境装完任何驱动都会强制自己走完“模块加载确认、接口验证、重启回归”这三步,再顺手备份一份编译产物到本地,省得下次内核一更新就抓瞎。希望这次的笔记能帮你在断网机器上把 Realtek 网卡顺利点亮。
本文还有配套的精品资源,点击获取