简介:名为 gcc_rpm.tar.gz 的资源,是一套面向 CentOS/RHEL 等 Linux 环境的 GCC 离线安装工具集合,专为无法访问在线软件仓库或网络受限的开发者、运维人员准备。核心内容包含 GCC 4.4.7 系列完整可用的 RPM 依赖包,涵盖 gcc、gcc-c++、glibc-devel、libstdc++-devel、kernel-headers、mpfr、ppl、cloog-ppl 等组件,并附带 install_gcc.sh 一键安装脚本与 Readme.md 操作说明,无须手工逐条处理依赖顺序,能显著降低部署门槛。包体方面,共计 24 个文件,其中 22 个为 x86_64 架构的 RPM 安装包,另有 1 个 Shell 脚本和 1 个说明文档,压缩后约 24.11MB。文件按离线部署思路组织,将编译工具链所需的系统库、头文件与自动安装脚本集中打包,便于在隔离内网中快速完成环境搭建,也方便后续统一查询与移除。目前已有 3991 人学习/下载这份离线包,适合需要在无网络环境下搭建 C/C++ 编译工具链的用户。相比在线安装,这套离线包能有效规避网络抖动与依赖缺失问题,帮助快速恢复编译能力,同时借助 RPM 包管理机制保持系统软件库的一致性与可维护性。
1. 离线服务器装不上 gcc 时,gcc_rpm.tar.gz 就是那颗后悔药
在内网服务器上敲gcc -v得到 "command not found" 的那一刻,很多人才意识到 Linux 发行版的软件源是件奢侈品。没有外网、Yum 源只剩 DVD 镜像里那点老掉牙的包,或者干脆是企业安全策略把网络出口全堵死——这种场景下,别人丢给你一个gcc_rpm.tar.gz,说“拿去解压然后 rpm 装”,这玩意儿到底靠不靠谱,怎么装不翻车,就是今天这篇笔记要解决的问题。
这个包名本身说明了一切:gcc 的 RPM 包被压缩成了 tar.gz 格式,用来绕过“没有 yum、不能在线拉依赖”的限制。它能解决的问题很实在:把 gcc 及其依赖在离线状态下一把装齐。适合三类人:内网运维要把新机器装上编译环境、在麒麟或 CentOS 上给旧系统升 gcc 版本、以及被“Ubuntu 下 apt 装 gcc 失败”折腾到想放弃的初学者。它不解决的是 gcc 本身的用法问题——装上只是第一步,让系统真正用上新版本才是后面四章的戏码。
2. 拆包看货:tar.gz 的壳和 RPM 的瓤,到底谁在依赖谁
2.1 先解压,再谈其他:tar 命令的两种打开方式
拿到gcc_rpm.tar.gz后的第一个动作永远是解压,不是直接rpm -ivh gcc_rpm.tar.gz。RPM 工具不认 tar.gz 这种壳,直接指定会报error: open of gcc_rpm.tar.gz failed。这个错我见过不少新人犯,原因就是没搞明白 tar.gz 是传输格式,RPM 包才是真正的安装单元。
# 方式一:先解压到当前目录 tar -xzvf gcc_rpm.tar.gz # 方式二:解压到指定目录,方便管理 mkdir /root/gcc-offline && tar -xzvf gcc_rpm.tar.gz -C /root/gcc-offline-x是解压、-z表示处理 gzip 压缩、-v打印过程、-f指定文件名。解压到独立目录是更好的习惯,后续安装时可以清楚地看到包里有哪些 rpm 文件,排查时不用在整个文件系统里乱翻。解压完成后,ls -lh看目录,如果里面躺着十几个 .rpm 文件,恭喜,这就是标准的离线包结构。
2.2 用 rpm -qip 认清包里是哪个 gcc 版本
解压出来的 rpm 文件往往不止一个,常见组成是 gcc 主体、gcc-c++、gcc-gfortran、cpp、libgcc 以及一系列 libstdc++ 相关包。盲目地全量安装容易踩依赖冲突,先逐个看包的元信息是必要步骤。
# 查看单个 rpm 包的版本、架构、依赖信息 rpm -qip gcc-*.rpm | head -30 # 查看这个包依赖什么 rpm -qpR gcc-*.rpm | head -20-qi是 info 的缩写,-p表示针对的是未安装的 rpm 文件而非系统已装的包。先看版本号,确认是不是你要的目标版本;再看Architecture,x86_64 的包装不到 aarch64 的机器上;最后用-qpR列出依赖,方便对照包目录里有没有对应的依赖 rpm。这一步是后面所有安装操作的安全带,省掉它,后面碰到缺少 libmpfr.so.4之类报错就得回头查。
2.3 依赖关系先摸清:ldd 与 rpm 的依赖闭环
RPM 的依赖检查不是玄学,是硬性的Requires字段在管。离线安装最怕的就是缺依赖,而 gcc 的依赖链往往是层层嵌套:gcc 依赖 cpp,cpp 依赖 libmpfr,libmpfr 依赖 libc。如果打包的人没打全,装到一半就会卡住。
# 查看系统里有哪些相关库已存在 rpm -qa | grep -E "libmpfr|libgcc|libstdc++" # 用 ldd 检查某个二进制缺哪些共享库 ldd /usr/bin/gcc | grep "not found"rpm -qa列出已安装包,grep过滤出关键库名。ldd则直接检查可执行文件的动态链接情况,输出中带not found就是缺库。把这两条命令的输出和 rpm 包目录里的文件对照一遍,就能在动手之前判断这个包是否完整。手动依赖检查确实繁琐,但相比装到一半失败再回滚,这点成本很低了。
3. 离线安装 RPM 包:-ivh、--nodeps 与 --force 的正确用法
3.1 按顺序安装:先依赖后主体
依赖检查通过之后,安装顺序有讲究。RPM 不会自动帮你拉依赖,必须按依赖层级来装。一般顺序是:底层库(libgcc、libstdc++)→ 编译器驱动(cpp)→ 主包(gcc)→ 附加语言包(gcc-c++、gcc-gfortran)。
cd /root/gcc-offline # 先装底层库 rpm -ivh libgcc-*.rpm libstdc++-*.rpm # 再装 cpp 和 gcc 主包 rpm -ivh cpp-*.rpm gcc-*.rpm # 最后装附加语言支持 rpm -ivh gcc-c++-*.rpm gcc-gfortran-*.rpm-i是 install,-v是 verbose 输出,-h显示安装进度条。*.rpm这类通配符在文件多时可以减少输入量,但如果目录里有版本冲突的包,建议还是精确到文件名更稳。每装完一组就执行echo $?检查返回值,0 代表成功,非 0 就要停下来定位问题。一口气装完不回头是离线安装最常见翻车姿势,没有之一。
3.2 --nodeps 什么时候用:明知缺依赖也要装的救急手段
--nodeps是 RPM 安装中最有争议的参数。它的作用是跳过依赖检查强行安装,适合两种场景:一是你确认系统里已经有了所需依赖,只是 RPM 数据库里没记录;二是打包的人漏打了某个依赖包,你手上也没有,只能靠系统里现成的库先撑过去。
# 强行安装并跳过依赖检查 rpm -ivh --nodeps gcc-*.rpm # 如果文件冲突,比如旧版本占用了同名文件 rpm -ivh --nodeps --force gcc-*.rpm--force是强制执行,它包含了两层意思:覆盖已安装的同名包、覆盖文件冲突。这两者都是双刃剑,--force覆盖了旧版本后如果新版本有问题,降级回去并不难,但--nodeps可能导致装完的 gcc 在运行时才报缺库错误。判断标准是:缺的依赖是否在系统里有对应文件。可以用ldconfig -p | grep 库名来验证。
3.3 装完必须验证:gcc -v 与 rpm -qa 双保险
安装完成后的验证不能只看 gcc 命令能不能用。系统里可能同时存在多版本 gcc,新装的未必被 PATH 优先命中。验证命令要看得更深。
# 验证 gcc 版本 gcc -v 2>&1 | tail -1 # 查看 RPM 数据库里装的 gcc 信息 rpm -qa | grep gcc # 查看 gcc 实际路径 which gccgcc -v输出的最后一行一般是gcc version x.x.x。rpm -qa | grep gcc确认安装记录入库。which gcc确认命令路径。如果gcc -v显示的还是旧版本,说明新装的 gcc 没有被 PATH 优先指向,这就进入了第 4 章的核心问题。别急着高兴说“装完了”,版本没切过去等于白干。
4. 升级 gcc 后还是旧版本:PATH 与软链接到底卡在哪
4.1 先查 gcc 实际指向:alias 与 PATH 的优先级
装完新版 gcc,执行gcc -v却显示旧版本号,这是离线升级场景里发生率最高的怪现象。原因往往不在安装环节,而在命令解析的优先级链条上。Shell 找命令的顺序是:alias → 函数 → PATH 中的目录依次查找。也就是说,即使新版本装进了/usr/local/bin,只要/usr/bin里的旧版也在 PATH 中且排更前面,执行的还是旧版。
# 查看 gcc 实际是哪个文件 which -a gcc # 查看当前 gcc 的 alias 定义 type -a gcc # 查看 PATH 顺序 echo $PATH | tr ':' '\n' | grep -E "local|usr/bin"which -a会列出 PATH 中所有匹配的 gcc,type -a能显示 alias 和函数定义。如果有 alias 层遮蔽,bash 会优先用 alias 展开,这时候改 PATH 是没用的。检查完这些,确认新版本路径没被优先级更高的目录或别名遮住,再去动 PATH 才有意义。很多教程一上来就叫你改 PATH,不改 alias,方向就错了。
4.2 软链接才是重头戏:ln -sf 把版本切换做实
RPM 包装出来的 gcc 往往在/usr/bin/gcc或/usr/local/bin/gcc,如果同路径下已经存在旧版本,rpm 包默认会处理这个冲突,但处理方式不一定是你要的——有可能 RPM 装到了独立路径,而/usr/bin/gcc的软链接还指向旧的。
# 备份旧版软链接 mv /usr/bin/gcc /usr/bin/gcc.bak # 建立新软链接 ln -sf /usr/local/bin/gcc /usr/bin/gcc # 确认链接生效 ls -l /usr/bin/gccln -sf中-s是软链接、-f是强制覆盖。先备份再改链接,是穷人的后悔药。需要注意 RPM 包管理的文件不要直接用 mv 去移,最好用rpm -e卸载旧包或rpm --replacefiles处理文件冲突,因为 RPM 数据库里记录的文件路径变了,后面校验和升级都会出幺蛾子。如果要卸载旧版本,rpm -e gcc-旧版本号更稳妥。
4.3 动态库版本冲突:libstdc++.so.6 指向谁,g++ 说了不算
光切了 gcc 的软链接,编译 C++ 程序时还可能遇到运行时错误,比如version GLIBCXX_3.4.30 not found。这是 libstdc++.so.6 这个动态库还在指向旧版本导致的。g++ 编译时链接的头文件可能来自新版,但运行时的动态库由ld.so的缓存决定。
# 查看系统里 libstdc++ 的版本 strings /usr/lib64/libstdc++.so.6 | grep GLIBCXX | tail -5 # 查找所有 libstdc++.so.6 位置 find / -name "libstdc++.so.6*" 2>/dev/null # 更新动态链接缓存 ldconfigstrings加grep GLIBCXX能列出该动态库支持的 ABI 版本。新装的 gcc 一般会带新版本的 libstdc++.so.6,如果系统的 ldconfig 还没把它登记进缓存,就需要手动指定LD_LIBRARY_PATH或用 ldconfig 刷新。这里的核心认知是:编译期和运行期用的是两套库路径,只修 gcc 的软链接没有用,库链接的更新必须同步做。
5. 避坑:gcc_rpm.tar.gz 安装的 5 个常见故障与排查
5.1 报错“没找到 rpm 命令”:发行版用错包管理器的典型症状
现象:Ubuntu/Debian 系统上执行rpm -ivh,提示bash: rpm: command not found。
原因:rpm 命令是 Red Hat 系发行版的包管理工具,Debian/Ubuntu 系默认用 dpkg/apt。把为 CentOS 打包的 gcc_rpm.tar.gz 拿到 Ubuntu 上装,rpm 工具根本不存在。这是新手最常见的场景错位。
解决:先确认发行版:cat /etc/os-release看 ID 字段。如果是 debian/ubuntu,要么改用dpkg -i安装 .deb 包,要么先apt install rpm装上 rpm 工具再尝试——但这通常没意义,因为 RPM 包是为 yum/rpm 系发行的,硬装大概率仍然缺依赖。正确做法是找到对应发行版的 gcc 离线包,或者直接用apt-get download在能联网的 Ubuntu 机器上把 .deb 包拉下来再拷贝安装。
5.2 依赖错误libmpfr.so.4: cannot open shared object file
现象:gcc 命令能执行,但编译任何程序时都报找不到 libmpfr 相关共享库。
原因:安装时用了--nodeps跳过了依赖检查,但系统里实际上没有 libmpfr 或版本不匹配(系统里只有 .so.6,而 gcc 需要 .so.4)。RPM 数据库虽然记录了 gcc 已安装,运行期链接却过不了关。
解决:find / -name "libmpfr*"看系统里有哪些版本。如果只是软链接不对,ln -s /usr/lib64/libmpfr.so.6 /usr/lib64/libmpfr.so.4即可;如果根本没有这个库,去 gcc_rpm.tar.gz 里找有没有 libmpfr 相关的 rpm 装了它。确认所有依赖都在包里时,把--nodeps换成正常安装流程。
5.3 升级 gcc 后编译 C++ 时报GLIBCXX_3.4.x not found
现象:gcc 版本显示是对的 (比如 11.x),但编译出的 C++ 程序一运行就报缺GLIBCXX_3.4.29之类符号。
原因:gcc 的软链接切到了新版,但运行时的 libstdc++.so.6 还是旧版。新版 gcc 编译的 C++ 代码需要新版 ABI,动态链接却加载了旧库。
解决:找新版本的 libstdc++.so.6,通常在新装的 gcc 包里有附带,或者从 gcc_rpm.tar.gz 里解压出来。把它放到/usr/lib64后执行ldconfig刷新链接缓存。装完一定要用第 4.3 节的strings命令验证新库的 GLIBCXX 版本范围。这一步不做,g++ 编译出来的一切程序都会在别的机器上翻车。
5.4 安装时文件冲突file /usr/bin/gcc conflicts
现象:rpm -ivh安装时报file /usr/bin/gcc from install of gcc-... conflicts with file from package gcc-旧版本。
原因:系统里已经通过 RPM 安装了旧版本 gcc,新版本的 rpm 包试图覆盖同一个路径下的同名文件,RPM 默认拒绝这种冲突覆盖。
解决:优先用rpm -e卸载旧版本再装新的,这是最干净的路径。如果担心卸载失败或者有其他包依赖旧版,用rpm -ivh --replacefiles只替换文件冲突,保留旧包在 RPM 数据库的记录。生产服务器上,我一般会先确认没有关键包依赖旧版 gcc 再卸载。
5.5 麒麟系统装完 gcc,yum 装 mysql 时依赖检查挂了
现象:内网麒麟服务器手动装完 gcc_rpm.tar.gz 后,再用 yum 安装 mysql 相关 rpm 包,yum 报依赖错误或 gcc 版本异常。
原因:手动 rpm 安装绕过了 yum 的依赖数据库。yum 在后续操作时做全量依赖解析,发现 RPM 数据库的状态和自己的元数据缓存不一致,于是报错。常见原因还包括:手动装的 gcc 与 yum 源里某些包的版本约束冲突。
解决:手动装完 rpm 后执行yum clean all && yum makecache重建元数据。如果是架构或版本冲突,先rpm -qa | grep gcc确认当前安装版本,再看 yum 源里 mysql 相关包对 gcc 的版本要求是Requires: gcc >= x还是= x,按需调整。手动安装 RPM 包的代价就是后续所有 yum 操作都要多留一份心眼。
6. 用 rpm -V 校验安装结果与文件清单,给离线包做一张后悔药清单
离线安装最大的不安来自“不敢确定装完整、不敢确定没破坏系统”。RPM 提供了验证机制,比单纯跑gcc -v可靠得多,这就是rpm -V命令。它逐文件比对 RPM 数据库里记录的文件属性(权限、属主、大小、MD5 校验和),任何被篡改或缺失的文件都会被标记出来。
# 校验所有 gcc 相关包的完整性 rpm -V gcc gcc-c++ cpp libgcc libstdc++ # 校验时忽略文件大小,只查 MD5 和权限 rpm -V --nomd5 gcc正常输出应该没有任何一行,有输出就代表对应文件有问题。输出格式中第一列的字符含义:S是大小变化、M是权限变更、5是 MD5 校验和不符、L是软链接目标变化。建议装完立即跑一次rpm -V,把结果保存下来作为基准,等系统跑一段时间后再校验,能对比出后续哪些操作可能动了 gcc 相关的文件。
再配合rpm -ql拿到文件清单,就知道 gcc 都往系统里放了什么:
# 列出 gcc 包安装的所有文件 rpm -ql gcc # 输出到文件留档,方便排查 rpm -ql gcc > /root/gcc-file-list.txt我的习惯是每次离线安装做完,都留三样东西:rpm -qa | grep gcc的版本快照、rpm -V的完整性基线、rpm -ql的文件清单。下次遇到任何 gcc 诡异行为,先对比这三样,大部分问题能定位到是文件被动过还是版本被挤掉。这也是离线环境维护和在线环境最大的区别——你没有 yum 历史可以查,只能靠自己的记录和 RPM 数据库的校验存活。这套“装完立即做基线”的方法救过我很多次,希望帮到你。
本文还有配套的精品资源,点击获取