简介面向Linux运维、开发人员及离线环境使用者这份gcc_rpm.tar.gz是一套面向CentOS 6/EL6类x86_64系统的GCC 4.4.7离线RPM依赖包集合专为解决无外网或网络受限服务器上无法在线安装编译器的问题。压缩包内收录了gcc、gcc-c、cpp、glibc-devel、kernel-headers、libstdc-devel等22个rpm安装包并包含mpfr、ppl、cloog-ppl等数学与优化支撑库覆盖编译C/C程序所需的核心编译器、头文件与底层依赖同时附带一键安装脚本install_gcc.sh与Readme.md说明文档可按照脚本自动完成依赖安装与版本验证也可根据说明手动处理特殊环境差异。整个资源共24个文件压缩后大小约24.11MB体量紧凑便于在离线内网间快速拷贝与分发。目前已有3991人学习下载足见其在众多初始化环境搭建场景中被反复使用。借助这套包读者无需逐一下载排查依赖即可在隔离网络内快速部署可用的GCC编译环境提升部署效率减少踩坑时间。1. 一个 gcc_rpm.tar.gz解决的是离线装 GCC 的硬仗如果你也遇到过这种场景内网服务器没有任何外网权限yum 源连不上但项目要在上面编译 C/C 代码机器上却连 gcc 都没有——那这份 gcc_rpm.tar.gz 就是为你准备的。它本质上是一个把编译链所需的 rpm 包和依赖打成一包的离线资源典型内容包括 gcc、gcc-c、libgcc、glibc-devel 以及对应的 cpp 和 kernel-headers 等一组相互依赖的 rpm 文件。适合两类人一类是要在内网裸机上快速拉起编译环境的一线运维和开发另一类是需要在多台离线机器上重复搭建同版本编译链、不想逐台在线安装的交付实施人员。它的核心价值不是省一次网速而是把依赖关系一并锁死让离线安装从“碰运气”变成“按清单执行”。2. 拆包与依赖盘点先看清里面是什么再决定怎么装拿到手的 gcc_rpm.tar.gz 是一个黑匣子直接解压安装是最常见也最容易翻车的做法。正确的打开方式是先温和地检查再动手这个习惯能帮你避免后面一连串的依赖地狱。本地的 RPM 包不像源码包那样解压就能用它的安装顺序、依赖满足情况、与系统已有 glibc 的兼容性都会影响最终结果。2.1 解压前的三重检查完整性、清单、路径污染第一步不是 tar而是确认包本身没损坏也要看清内部文件会不会在解压时污染当前目录。我一般会按下面的顺序来# 1. 校验压缩包完整性md5sum 和 sha256sum 都过一遍 md5sum gcc_rpm.tar.gz sha256sum gcc_rpm.tar.gz # 2. 预览包内文件清单不解压只列目录树 tar tzf gcc_rpm.tar.gz # 3. 确认包内所有文件都在单独的子目录下而不是散落在根目录 tar tzf gcc_rpm.tar.gz | awk -F/ {print $1} | sort -u这三条命令的逻辑并不复杂前两条确认文件没在传输过程中损坏第三条则是检查压缩包内是“一个顶层文件夹”还是“一堆文件平铺”。后者在解压时会把 rpm 文件直接撒进当前目录严重时还会覆盖同名文件属于必须提前排除的隐患。实际操作中我曾经见过有的人在 /root 下直接解压结果包内一个叫 localtime 的配置文件把系统时区给顶掉了那已经是另一个维度的灾难了。所以第三条命令输出如果只有一行目录名说明结构正常如果输出多行或者直接是 .rpm 后缀那就要先建子目录再解压。2.2 依赖清单为什么不能闭眼 rpm -ivh *.rpm假设包目录是 gcc_rpms里面是十几个 rpm。新手最容易犯的错是用一条 rpm -ivh *.rpm 试图把全部装上结果报一屏的依赖缺失然后开始手动找包。原因很好理解rpm 安装时会立刻检查依赖是否满足而通配符展开后安装顺序是字典序不是依赖顺序。gcc-c 排在 gcc 前面极常见于是 gcc-c 找 gcc 的时候gcc 还没装上必然失败。正确的做法是在安装之前先逐个查看 rpm 的依赖关系# 解压到一个独立目录避免污染当前环境 mkdir -p ~/offline-gcc tar xzf gcc_rpm.tar.gz -C ~/offline-gcc # 选中核心包查看它依赖什么 rpm -qpR ~/offline-gcc/gcc-c-*.rpm # 查看它提供什么确认包本身能提供哪些被依赖的库 rpm -qp --provides ~/offline-gcc/gcc-c-*.rpm命令里的 -q 表示查询-p 表示对未安装的 rpm 文件查询-R 列出依赖--provides 列出它向外提供的符号和库。这个步骤建议对每个 rpm 都跑一遍然后把输出汇总成一张依赖表。常见做法是写个循环脚本把所有 rpm 的依赖打到一个文件里再用 sort 和 uniq 去重这样整个包的有效依赖一目了然。这个包如果来源正规通常内部依赖是闭环的但 glibc 和 libgcc 这类基础库经常依赖系统已有的版本一旦发现系统 glibc 版本低于包内要求后面的安装基本不可能成功这时候就得考虑从系统镜像源里找配套版本而不是硬装。典型的包内清单会是下面这个样子具体以 tar tzf 输出为准文件名作用注意事项gcc-*.rpm核心 C 编译器依赖 cpp 和 glibc-develgcc-c-*.rpmC 编译器依赖 gcc 与 libstdc-develcpp-*.rpmC 预处理器gcc 的硬依赖glibc-devel-*.rpm开发头文件和静态库依赖 glibc 主包libgcc-*.rpm底层运行时库几乎必须最先装kernel-headers-*.rpm内核头文件某些场景下 glibc-devel 需要提示如果包里只有两三个 rpm说明作者已经预合并了依赖如果十几个则说明是完整依赖链。前者在安装时几乎不会出问题后者反而要重点检查版本兼容性。3. 本地 yum 仓库搭建与安装执行把依赖交给工具而不是赌运气依赖盘点清楚之后安装路径有两条一条是搭本地 yum 源用 yum 来自动解决依赖这是我最推荐的生产环境做法另一条是按依赖顺序手动 rpm 安装适合包很小或临时验证的场景。两条路都需要把包先解压到固定目录。3.1 用 createrepo 构建本地 yum 源一劳永逸的推荐做法只要机器上有 python 和 createrepo 工具没有的话可以先用下面第 3.2 节的临时方案就可以把解压出来的目录变成 yum 源之后无论装哪个包依赖都由 yum 自行处理# 安装 createrepo如果系统连不上外网先从包内找或者用已有 rpm yum install -y createrepo # 生成仓库元数据 createrepo ~/offline-gcc # 编写本地 repo 配置文件 cat /etc/yum.repos.d/offline-gcc.repo EOF [offline-gcc] nameOffline GCC RPMS baseurlfile:///root/offline-gcc enabled1 gpgcheck0 EOF # 清理缓存并验证仓库可用 yum clean all yum repolistcreaterepo 的作用是扫描目录内所有 rpm生成 repodata 元数据让 yum 能识别这个文件夹为一个软件仓库。repo 文件里的 baseurl 用的是 file:// 协议指向本地绝对路径enabled1 表示启用该仓库gpgcheck0 表示跳过 GPG 签名校验——离线内网环境下通常没有导入签名 Key这里设为 0 最常见。注意 baseurl 路径必须与 createrepo 执行时用的目录完全一致写错或写相对路径都会导致 yum 报 “Cannot retrieve repository metadata”。完成后直接用 yum 安装你要的东西yum install -y gcc gcc-c此时 yum 会在本地仓库内自行寻找 gcc 和 gcc-c 的所有依赖按依赖顺序解析安装。这也是整套流程里最省心的部分依赖解析交给工具你只需要确保包内依赖闭环。用 yum 还有一层好处后续如果机器上要装其他编译相关软件比如 make、autoconf 的离线包可以把它们也扔进 ~/offline-gcc 并重新执行 createrepo变成一个不断生长的内网软件仓库。3.2 手动 rpm 安装的兜底方案什么时候才用本地 yum 源是首选但如果包内只有三五个 rpm或者系统里的 yum 本身就有问题手动按依赖顺序安装才是更快的路径。手动安装的核心是顺序先装底层库再装编译器本体。cd ~/offline-gcc # 先安装运行时库再装预处理器最后装 gcc 和 gcc-c rpm -ivh libgcc-*.rpm rpm -ivh cpp-*.rpm rpm -ivh glibc-devel-*.rpm kernel-headers-*.rpm rpm -ivh gcc-*.rpm rpm -ivh gcc-c-*.rpm # 遇到依赖缺失时先查询是哪个包提供的 rpm -qp --provides *.rpm | grep -i 缺失的关键字这里的顺序不是固定的实际以第 2 章查到的依赖表为准。rpm -ivh 的 i 表示安装v 显示详情h 显示进度条用 -Uvh 则是升级安装如果系统里已有旧版本 gcc-Uvh 更合适它会把旧包替换掉。需要特别提的是 --nodeps 参数。出问题时很容易听到有人说“加个 --nodeps 强装”这确实能装上去但代价是安装完成后 gcc 可能因为找不到 libmpfr.so 或 libmpc.so 而编译失败而且这种失败往往是在你编译第一个正经项目时才暴露——到时候排查起来远比安装时更痛苦。我的习惯是只有在依赖缺失的包完全不参与编译主链路比如只缺一个文档相关的 rpm时才用 --nodeps编译器主链路必须依赖完整。4. 安装后的三重验证从命令可用到项目可编译很多人装完 gcc看到 which gcc 有输出就认为大功告成这是严重的误判。离线安装的 rpm 包经常出现版本与系统 glibc 不匹配、头文件路径不对、默认库缺失等问题而这些在 gcc -v 阶段根本不会暴露。我一般会做三层验证每一层解决一个层面的问题。4.1 版本与链接验证看 gcc 到底是不是你想要的# 验证版本重点看 gcc version 那一行 gcc -v g -v # 验证编译器的实际调用路径 which gcc ls -l /usr/bin/gcc # 验证安装出来的包确实来自刚才的 rpm rpm -qa | grep -E ^gcc|^gcc-c|^libgcc|^cppgcc -v 的输出值得多看几眼最后一行会显示 configure 时的配置参数其中 --with-arch 和 --with-abi 决定生成二进制兼容哪种 CPU 架构。如果包是用较新的 CPU 特性编译的拿到老服务器上即使安装成功编译时也可能报非法指令。所以这一步不是看看版本号就完了要确认配置参数与目标机器 CPU 匹配。rpm -qa 的过滤则能确认安装来源——如果你看到同名的包却来自系统自带 repo那说明刚才安装可能被系统原有版本覆盖了这在已经有部分编译环境的机器上偶尔会出现。4.2 编译冒烟测试从 hello world 到多文件项目编译器本身没问题不代表头文件和库路径没问题。写个带系统调用的程序来实测是必须的# 写一个使用 math 库的测试程序顺带验证链接路径 cat test.c EOF #include stdio.h #include math.h int main(void) { printf(sqrt(2)%.6f\n, sqrt(2.0)); return 0; } EOF # 编译并链接数学库 gcc test.c -o test -lm -Wall # 运行验证 ./test命令里的 -lm 是链接 libm.so 数学库-Wall 打开常见警告。这个测试的价值在于如果头文件路径不对会报 fatal error: math.h: No such file or directory如果库路径不对会报 cannot find -lm如果 glibc 版本不兼容会在运行时直接 segfault。三个典型卡点一次覆盖。更进一步建议再拿一个真实的小项目试 make——因为 make 涉及环境变量 CC 的读取和 include 路径的传递很多环境问题只有走到 make 这一步才暴露# 如果项目里有 Makefile强制指定编译器再跑一次 make clean make CCgcc CXXg -j$(nproc)用 -j 并行编译能加速但并行也会把内存吃满小机器建议把 nproc 换成实际核数的一半。这一步通过基本可以判定这套编译链在“编译”这个层面是可用的。4.3 多版本切换用 alternatives 管理不冲突的 GCC如果机器上将来还要装另一个版本的 gcc比如为了兼容旧代码直接覆盖安装一定会出问题。RPM 体系里的标准做法是用 alternatives 机制管理# 查看当前 gcc 版本 gcc --version # 注册为新版本路径必须是实际二进制路径 alternatives --install /usr/bin/gcc gcc /usr/local/gcc-4.8/bin/gcc 50 alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-9 80 # 手动切换 alternatives --config gccalternatives 的机制不复杂/usr/bin/gcc 本身是一个符号链接指向当前选中的版本install 后面的数字是优先级数字大的默认生效--config 可以在已注册的多个版本间手动选择。同一套机制也适用于 g 和 cpp记得分别注册。这一步在生产环境里很有价值特别是部署老项目时编译器的降级往往比改代码更快。5. 避坑与常见问题离线装 GCC 最容易翻车的五个现场离线安装的坑很多不是 rpm 本身的问题而是环境差异导致的。以下五条是我实际迭代中踩过、也帮别人排过的典型问题按“现象 → 原因 → 解决”写清楚。5.1 缺少 libmpfr.so.4 导致 gcc 执行报错现象rpm 全部安装成功gcc -v 却报 error while loading shared libraries: libmpfr.so.4: cannot open shared object file。原因gcc 运行时依赖的 mpfr 库版本号与系统里已有版本对不上常见于系统自带 libmpfr.so.6 而包内 gcc 编译时链接的是 .so.4。解决先看 gcc 链接的是哪个库用 ldd /usr/bin/gcc 查具体依赖再去包内或系统镜像源里找对应版本的 mpfr rpm如果找不到下载一个同版本的 mpfr 源码包内网编译安装并导出 LD_LIBRARY_PATH。这种事情最容易出现在老包配新系统或者新包配老系统上所以在第 2 章解压后先跑 rpm -qpR 看依赖这一步真不是走过场。5.2 configure: C compiler cannot create executables现象编译某个开源软件时configure 阶段报这个错并退出。原因缺少完整的编译工具链最常见的是没有安装 glibc-devel导致缺少 crt1.o 和 crti.o 这些启动文件也可能因为 --nodeps 强装后系统里 gcc 和 glibc-devel 版本不匹配。解决确认 glibc-devel 和 kernel-headers 是否安装rpm -qa 过滤查补齐后再跑 configure如果确认都装了用 gcc -v 的配置参数对比系统 glibc 版本差异过大就要换包。这个报错最迷惑人的点在于它提示“编译错误”但问题往往不在 gcc 本身而在启动文件缺失。这台机器如果之前装过精简版系统通常就是第 2 类原因。5.3 安装时提示 file /usr/bin/gcc conflicts between attempted installs现象rpm 安装时报 conflict文件冲突安装中止。原因系统里已经存在一个 gcc通常是发行版自带的新 rpm 包里的 /usr/bin/gcc 与旧包文件冲突rpm 默认不会覆盖已存在文件。解决确认现有版本与目标版本哪个更合适——如果不打算保留旧的先 rpm -e 移除旧包注意同时检查哪些包依赖旧 gcc如果两个都要留把新包解压到 /opt 下的独立目录用 alternatives 注册切换而不是强行覆盖。我见过有人用 rpm -ivh --replacefiles 强压上去结果 /usr/bin/gcc 变成了一个新版本的二进制但配套的 headers 还在旧位置最后编译任何东西都缺头文件。5.4 明明装了 gcc-c却提示 g: Command not found现象gcc 能用g 报 not found。原因包内 gcc-c 没有安装成功或者安装时依赖顺序错误导致 g 链接文件没生成还有一种可能是 gcc-c 依赖的 libstdc-devel 没装上g 主程序虽然落盘但运行即报错。解决先 rpm -qa | grep g 确认包是否真的在再查 /usr/bin/g 是否为软链接、指向是否存在如果包不在按第 3.2 节的顺序重装 gcc-c 并确保 libstdc-devel 提前装好。这里有一个非常隐蔽的情况某些精简包里的 gcc-c 被作者拆掉了只留了 gcc 和 cpp而 README 里没写等用户真的编译 C 时才发现。5.5 编译成功但运行报段错误且每次位置不同现象gcc -lm 编译通过但 ./test 跑起来时不时段错误。原因编译器版本与系统 glibc 不兼容生成的可执行文件使用了高版本 glibc 里才有的符号如 __printf_chk 的某些实现运行时的低版本 glibc 解析失败另一个常见原因是包内 gcc 是另一个发行版打包的rpm 安装时不检测 ABI 兼容性。解决用 ldd ./test 查看实际链接的 glibc 版本再用 objdump -T /lib64/libc.so.6 | grep 相关符号确认系统是否提供如果确认是版本差最稳妥的出路是找一个与目标系统同发行版的 gcc 离线包不要继续在这个包上折腾。这种问题最考验排查耐心因为它不是稳定的报错很容易被误判为代码 bug而根源往往在“这个 gcc 是给另一个系统打的”平台不匹配。6. 把整套安装固化成一个脚本下次用时不再碰运气手动操作跑通一遍后最重要的收尾是把过程固化成可复用脚本而不是把经验留在脑子里。离线安装这种活儿隔两三个月再装一批机器操作细节基本都会忘光脚本才是真正的“后悔药”。下面是我常用的最小脚本骨架#!/bin/bash # install_offline_gcc.sh —— 离线安装 gcc_rpm 资源包 # 用法: ./install_offline_gcc.sh /path/to/gcc_rpm.tar.gz set -euo pipefail PKG$1 WORKDIR/opt/offline-gcc-install rm -rf $WORKDIR mkdir -p $WORKDIR tar xzf $PKG -C $WORKDIR --strip-components1 # 生成本地仓库 createrepo $WORKDIR || yum install -y createrepo # 配置临时 repo cat /etc/yum.repos.d/offline-gcc.repo EOF [offline-gcc] nameOffline GCC RPMS baseurlfile://$WORKDIR enabled1 gpgcheck0 EOF yum clean all yum install -y gcc gcc-c # 验证 gcc -v g -v # 冒烟测试 cat /tmp/smoke.c EOF #include stdio.h int main(void) { puts(smoke ok); return 0; } EOF gcc /tmp/smoke.c -o /tmp/smoke /tmp/smoke echo GCC installed: $(gcc --version | head -1)脚本里 set -euo pipefail 的含义是任何命令失败立即退出、变量必须事先定义、管道中任一环节失败视为整体失败这三条加在一起保证脚本不会带着中间错误硬往下跑。--strip-components1 在解压时去掉顶层目录让 rpm 文件直接铺在 WORKDIR 下方便 createrepo 扫描。如果你不想在 /etc/yum.repos.d 里留痕迹脚本跑完可以加一句 rm -f /etc/yum.repos.d/offline-gcc.repo仓库目录也可以保留之后想补装其他包随时能重建。从那以后我每次在新机器上搭编译环境都强制自己走一遍“先查包内依赖、再建本地源、最后跑冒烟测试”的流程不再凭手感做事。这套脚本连同验证步骤折腾完再奇怪的 gcc 离线包也能在十分钟内判断出能不能用。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?