ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

离线安装 gcc_rpm.tar.gz 全攻略:拆包、依赖排序与避坑指南

离线安装 gcc_rpm.tar.gz 全攻略:拆包、依赖排序与避坑指南 简介一套面向Linux离线环境的GCC编译工具链RPM安装包专为无外网、内网隔离或yum源不可用的服务器场景设计解决因缺少gcc、gcc-c及底层依赖而无法编译源码的常见问题适合运维人员与开发者在搭建初始化环境时使用。压缩包共24个文件主体为22个x86_64架构的RPM包除gcc-4.4.7和gcc-c外还覆盖glibc-devel、libstdc-devel、kernel-headers、mpfr、ppl等编译链接常用的头文件与运行库配套install_gcc.sh自动化安装脚本和Readme.md说明文档整体约24.11MB解压即可得到完整的离线依赖集。已有3991人学习下载。借助此包用户无需连接在线仓库也无需手工逐条处理RPM依赖关系脚本可按依赖顺序自动完成安装特别适合在CentOS/RHEL 6.x等老版本系统上从零部署GCC工具链。对网络受限的数据中心、内网工作站和嵌入式交叉编译场景而言这份资源能显著降低编译环境搭建的门槛减少因依赖缺失导致的反复排错与离线补包工作。1. 拿到 gcc_rpm.tar.gz 先别急着一把梭这是个离线工具链黑匣子拿到gcc_rpm.tar.gz这个压缩包大部分人的第一反应是解包后rpm -ivh *.rpm一把梭然后被依赖错误、版本残留和“没找到 rpm 命令”轮流教育。这个包在麒麟、CentOS、Rocky 这些 rpm 系发行版里很常见通常是一组 gcc、gcc-c、binutils、libstdc 等 rpm 文件的合集专门用来解决内网离线环境下没有 C/C 编译器、装 MySQL 源码包或编译扩展时找不到编译器的困境。和在线yum install gcc不同离线装 gcc 的核心不是“下载”而是“排依赖顺序”和“对平台版本”顺序错了再好的包也装不上。这篇笔记就按我的实操顺序讲清楚拆包、排依赖、落盘、验证这套流程并列出几个最常见的坑和对应排查命令。2. 拆包前先弄清楚 gcc 的依赖结构为什么离线安装最容易翻车2.1 gcc 不是单个 rpm集合包里到底装了哪些组件gcc这个命令在 RHEL 系系统里对应着一堆 rpm 包。gcc 主包只是编译驱动真正干活的是它调用的cc1前端、as汇编器和ld链接器cc1在 gcc 包里cpp由独立的 cpp 包提供binutils提供 as 和 ldlibgcc提供最低层运行时。想编译 C 还需要gcc-c、libstdc-devel和头文件再加上glibc-devel、kernel-headers、make才算一个完整的工具链。这就是为什么压缩包解出来之后光 rpm 文件就有几十个。拿到包的第一步应该先看一眼里面有什么不解包也能预览。常见的做法是# 列出包内所有 .rpm 文件按文件名排序 tar -tzf gcc_rpm.tar.gz | grep \.rpm$ | sort # 只关心和编译器相关的关键包 tar -tzf gcc_rpm.tar.gz | grep -E /(gcc|gcc-c\\|cpp|binutils|libgcc|libstdc\\|glibc-devel|kernel-headers|make)-[^/]*\.rpm$tar -tzf是列出归档内容而不是解压-z表示 gzip 压缩-f指定文件。第二个命令用正则过滤出工具链相关包这能让你在解包之前就确认包里有没有gcc-c、libstdc-devel这些东西。如果发现只有 gcc 主包没有 gcc-c那你就只能编 C 不能编 C省得白忙活。2.2 依赖是怎么咬合的先从底层库开始排离线安装失败九成是依赖顺序搞反了。rpm 包之间的依赖关系可以用rpm -qpR预先查看-q是查询-p指定未安装的 rpm 文件-R列出 Requires 字段。你不需要把整个包解出来用管道抽一个文件就行# 先找到 gcc-c 对应的完整包名 pkg$(tar -tzf gcc_rpm.tar.gz | grep gcc-c | grep \.rpm$ | head -1) # 把该 rpm 抽到标准输出重定向成临时文件再查它的依赖 tar -xOf gcc_rpm.tar.gz $pkg /tmp/gcc-c.rpm rpm -qpR /tmp/gcc-c.rpm这里tar -xOf的作用是把归档里的单个文件直接写到标准输出不落盘配合重定向得到一个临时 rpm 文件再用rpm -qpR查依赖。输出的 Requires 里一般会出现libgcc、libstdc-devel、gcc 某个版本号。这些依赖就是后续安装顺序的依据先装系统库和libgcc再装binutils和cpp然后装 gcc 主包最后装 gcc-c。我一般会先用rpm -qpR把所有包扫一遍把依赖关系按层拆开心里有数再动手。2.3 三个安装方案的取舍rpm 直装、yum localinstall 与本地仓库离线装 gcc 不只是rpm -ivh一条路根据场景有三套做法方案适合场景依赖处理方式主要限制rpm -Uvh批量直装包数量少、系统干净按命令行顺序逐个处理顺序错了就失败yum localinstall系统里已有可用 yum 源yum 自动补依赖纯离线且无本地源时无效createrepo建本地源包多、反复装、还要升级yum/dnf 按元数据解析额外依赖 createrepo 工具如果目标机器只是临时装一次我选 rpm 直装最直接。如果机器上原本就有 yum 源yum localinstall *.rpm会让 yum 帮你补依赖离线但有本地镜像时很好用。如果是要给很多台机器装或者后续还要升级 gcc那就把整个解包目录做成一个本地 yum 源createrepo生成元数据后用yum --disablerepo* --enablerepolocal来装。这个方案最稳但需要机器上先有 createrepo 工具本身又是个鸡生蛋的问题。注意很多 gcc_rpm.tar.gz 是从新系统上 collect 出来的如果目标机器的 glibc 版本太老依赖检查能过、装完也能跑但运行时就报 GLIBCXX 找不到。平台版本不匹配不是安装阶段的错是包选型的错。2.4 在非 rpm 发行版上拿到这个包Ubuntu 与 macOS 的边界gcc_rpm.tar.gz的适用面明确是 rpm 系。Ubuntu 用 dpkg 体系直接 rpm 安装必定报错。常见做法是用 alien 转换但我很少推荐这条路C/C 工具链的依赖关系跨包管理器转换后经常残缺头文件路径、alternatives 机制和系统自带的 gcc 冲突概率很高。在 Ubuntu 上想装 gccsudo apt install build-essential才是正道。如果是在 macOS 上rpm 包根本没有意义用 clang 或brew install gcc更合理。至于“macOS 上能不能编译 Windows 的 exe”那是另一回事需要x86_64-w64-mingw32-gcc或 clang 的--target参数和 gcc_rpm.tar.gz 完全是两套东西别指望 Linux 的 rpm 包能交叉出 Windows 可执行文件。3. 从解包到版本验证离线安装 gcc_rpm.tar.gz 的完整流程3.1 解包与内容核对先列出全部 rpm 文件解包这一步没什么技巧但有个细节我反复翻过车不要在 root 下解包到系统目录用普通用户解到自己的工作目录。tar 在 root 下会保留归档里的属主和权限万一包里有个文件的属主信息有问题后面排查起来非常被动。普通用户解包后rpm 安装时 root 身份才接管属主反而更干净。mkdir -p ~/gcc-pkgs tar -xzf gcc_rpm.tar.gz -C ~/gcc-pkgs cd ~/gcc-pkgs # 列出所有 rpm 文件数一下数量 find . -type f -name *.rpm | sort | tee rpm-list.txt wc -l rpm-list.txt # 看看包里有没有非 rpm 文件README、脚本、源码包 find . -type f ! -name *.rpm | head -20tar -xzf解包-C指定目标目录。.rpm文件的清单保存在rpm-list.txt后面排序和核对我都是对着这个文件做。非 rpm 文件值得花十秒看一眼有的包会附带一个安装脚本或说明文档里面可能写了作者建议的安装顺序跟着走能少踩一半坑。如果你下载的 tar.gz 里是直接散落的 rpm 而不是带目录结构的find的结果会简单很多逻辑一样。3.2 “没找到 rpm 命令”的应对与发行版识别第一次在麒麟或某些精简系统上装这个包执行rpm直接报bash: rpm: command not found。先别慌这个报错有两种可能一是系统真的没有 rpm 命令二是在某些容器或最小化系统里 rpm 没被装进默认 PATH。先确认发行版和包管理器cat /etc/os-release which rpm yum dnf 2/dev/null/etc/os-release里的ID字段会告诉你系统是什么底子。IDcentos、IDkylin这类都有 rpm。如果which rpm没有输出但系统是 rpm 系最常见的原因是 PATH 里没带 /usr/bin 或 /bin用绝对路径/usr/bin/rpm --version再试一次。如果确认系统是 Debian/Ubuntu 底子那就别挣扎 rpm 了正确的动作是# Ubuntu/Debian 上优先直接装系统自带 gcc sudo apt update sudo apt install gcc g make # 实在要用手里的 rpm 包alien 转 deb 是最后手段 sudo apt install alien alien -k --scripts gcc-c*.rpm sudo dpkg -i gcc-c*.debalien -k保留版本号--scripts保留 rpm 里的脚本。但说实话alien 转过去的工具链依赖经常缺装了 gcc 结果头文件找不到还是得回头apt install build-essential。我一般只在“必须要用指定版本 gcc”的场景下才走 alien普通场景直接放弃这个 rpm 包。3.3 按依赖顺序安装先 --test 试跑再分段 rpm -Uvh在 rpm 系机器上安装前先做一次依赖试跑。--test会让 rpm 只检查依赖和冲突不实际落盘错误日志不会弄脏系统。这一步跑出来的“缺谁”就是后面要补的顺序。cd ~/gcc-pkgs # 试跑只检查依赖不实际安装 rpm -Uvh --test *.rpm 21 | tee /tmp/rpm-test.log # 从日志里挑出“缺谁”的行看缺哪些依赖 grep -E is needed by /tmp/rpm-test.log | sort | uniq -c--test输出的xxx is needed by yyy就是缺的依赖yyy是哪个包需要它xxx是缺失的包名。把这些缺失项和 rpm-list.txt 对比如果缺的包就在列表里说明是顺序问题按依赖层级重新排如果列表里压根没有例如缺的是glibc-devel.x86_64但包里没有那这个 tar.gz 本身就不完整后面的安装注定失败。真正安装时我习惯分三段执行不搞*.rpm一把梭cd ~/gcc-pkgs # 第一段底层运行库和 C 库头文件 rpm -Uvh libgcc*.rpm glibc-devel*.rpm kernel-headers*.rpm \ libstdc*.rpm 21 | tee -a /tmp/gcc-install.log # 第二段编译工具链主体 # 注意用 gcc-[0-9]* 而不是 gcc-*否则会匹配到 gcc-c、gcc-gfortran rpm -Uvh binutils*.rpm cpp*.rpm gcc-[0-9]*.rpm 21 | tee -a /tmp/gcc-install.log # 第三段C 扩展与外围工具 rpm -Uvh gcc-c*.rpm make*.rpm gdb*.rpm 21 | tee -a /tmp/gcc-install.log分段的好处是失败时能立刻定位是哪一段挂的。第二段里gcc-[0-9]*是关键shell 的通配符gcc-*会同时匹配gcc-c、gcc-gfortran把 gcc-c 提前到第二段安装一旦它依赖的 libstdc-devel 没到位整批事务回滚前面装的白装。分段的安装顺序原理很简单rpm 的事务顺序就是命令行顺序按层来才不会互相咬。3.4 验证安装结果gcc --version 与 rpm 查询装完别急着写代码先确认版本号和数据库状态。这一步能拦下“永远不知道哪来的旧版本”问题# 版本号确认 gcc --version g --version # rpm 数据库确认哪些包真的装上了 rpm -q gcc gcc-c libgcc libstdc-devel # 看 gcc 实际路径和软链指向 type -a gcc ls -l /usr/bin/gcc*type -a gcc会打印出所有叫 gcc 的可执行路径如果输出里既有/usr/bin/gcc又有/usr/local/bin/gcc那gcc --version未必是刚装的这个版本后文会专门说这个坑。rpm -q同时查询多个包返回package gcc is not installed就直接定位到没装上的包。这一段做到位后面的编译验证才能确认是“新装的 gcc 在工作”而不是系统旧的残留物在起作用。4. 安装 gcc_rpm.tar.gz 的常见问题排查5个真实踩坑记录4.1 装完还是旧版本which 与 PATH 的双重欺骗现象rpm -qa | grep gcc明明显示新版本已经装进去了但gcc --version输出的还是旧版本号rpm -q gcc和实际命令行为对不上。原因大多数发行版的/usr/bin/gcc是指向 alternatives 机制的软链接旧版本 gcc 还注册在 alternatives 里或者排在前面。另一种常见情况是 PATH 里/usr/local/bin在前面而那里恰好有一个以前手工编译的旧版 gccshell 优先找到了它。解决# 看所有叫 gcc 的可执行文件路径 type -a gcc # 逐个路径验证真实版本 /usr/bin/gcc --version /usr/local/bin/gcc --version # alternatives 接管时手动切换版本 sudo update-alternatives --config gcctype -a输出顺序就是 PATH 查找顺序第一个就是 shell 实际用的那个。如果问题是 PATH 导致要么把 /usr/bin 挪到 PATH 前面要么直接改软链接ln -sf /usr/bin/gcc-新版本 /usr/bin/gcc。alternatives 的条目可以用update-alternatives --install重新注册--config里选择默认版本。这个问题几乎每个升级过 gcc 的人都遇到过我不信有谁能跳过。4.2 运行时提示 libstdc.so.6 版本不满足现象编译阶段一切正常程序一运行就报libstdc.so.6: cannot open shared object file或者GLIBCXX_3.4.x not found。原因链接时 g 把新版本 libstdc.so.6 的动态依赖写进了 ELF 文件但运行环境的系统库路径/usr/lib64下面还是旧版本的 libstdc.so.6没有新版本导出的 GLIBCXX 符号。这是 gcc_rpm.tar.gz 跨系统拷贝安装最常见的翻车现场本质是“安装环境”和“运行环境”不是同一套库。解决# 确认运行库路径里是什么版本 strings /usr/lib64/libstdc.so.6 | grep ^GLIBCXX # 看程序实际依赖的是哪个库 ldd ./your_program | grep stdc # 将新版本库目录加入动态链接器路径 echo /opt/gcc-libs | sudo tee /etc/ld.so.conf.d/gcc-local.conf sudo ldconfigldd显示的是编译时记录的依赖路径strings grep GLIBCXX则是看运行系统库实际能提供哪些符号。如果缺正确做法是把新库目录写进/etc/ld.so.conf.d/然后ldconfig而不是把旧库文件夹里的文件替换掉。用--nodeps --replacefiles硬覆盖系统核心 libstdc.so.6 是条死路系统里所有已有程序都会因为库接口不兼容而挂掉这个后悔药买不到。4.3 依赖循环与 --nodeps 的代价现象rpm -Uvh --test *.rpm报 A is needed by B同时 B is needed by A看起来死循环无从下手。原因同一批包里确实存在循环依赖典型的是 gcc 主包和 cpp 包互相咬版本比如 gcc 需要cpp 版本号cpp 又需要gcc 版本号。在线安装时 yum 能通过临时安装解决这个问题离线 rpm 直装就没有这个待遇。解决先按依赖层手动装最底层不按字母序装。循环依赖通常集中在 gcc 和 cpp 之间先rpm -Uvh cpp*.rpm再rpm -Uvh gcc-[0-9]*.rpm层被打破后循环自然消失。只有打破层仍然无解的极少数情况才考虑--nodeps但要清楚代价装上去之后 rpm 数据库里的依赖记录是残缺的后续yum update每次都会报“已安装的软件包有问题”那时候要么一直带病运行要么手工把依赖补全。我一般把--nodeps当成最后手段不在开局就用。4.4 通配符误伤gcc-* 把 gcc-c 也一起装进来现象执行rpm -Uvh gcc-*.rpm没有报错装完后gcc --version正常但g --version提示命令不存在。原因shell 的通配符gcc-*会匹配所有以gcc-开头的文件gcc-c-版本.rpm也在其中。如果安装顺序里 gcc-c 在 gcc 主包之前被 rpm 处理而它的依赖还没准备好rpm 事务可能把这一整批初始化失败gcc 主体也没装上但 gcc 主包如果单独成功就会造成“gcc 有、g 无”的残缺状态。解决# 先列出所有 gcc 开头的包看清楚有哪些 ls gcc*.rpm # 用正则或显式文件名安装避免通配符误匹配 rpm -Uvh gcc-[0-9]*.rpm gcc-c*.rpm # 安装后验证 rpm -q gcc-cgcc-[0-9]*只匹配主包和 main 版本号开头的文件不会带上 gcc-c。这类问题表面上看着小实际很恶心因为安装时完全没报错到编译 C 程序那天才暴露排查时如果不往通配符方向想会怀疑人生。我现在的习惯是安装命令里永远不写裸*.rpm都是先ls确认再动手。4.5 rpmdb 损坏与批量安装中断的后遗症现象安装到一半机器断电或者 CtrlC 中断之后任何 rpm 命令都报rpmdb: Lock table is out of a valid state或者rpmdb: Database damaged。原因rpm 数据库升级时被强行打断__db.*文件处于半写状态锁表标记失效了。解决# 重建 rpm 数据库不会动已经安装的包 sudo rpm --rebuilddb # 重建后确认关键包状态 rpm -qa gcc gcc-c libgccrpm --rebuilddb会用现有/var/lib/rpm目录里的数据重建数据库索引已安装的包记录不会丢失锁表状态会被清掉。如果rpm -qa输出有包但版本和预期不符那说明中断发生在事务中间需要重新执行之前的安装命令。这不算难修的故障但遇到时别重复执行安装命令先把 db 修好否则会带来更多冲突。5. 装完只是开始用 gcc 写第一个程序、配置 vscode 一键编译5.1 最小程序验证编译与动态库装完新 gcc 后我习惯先写一个 5 行的 C 程序验证链路而不是直接去编业务代码cat hello.c EOF #include stdio.h int main(void) { printf(gcc ok\n); return 0; } EOF gcc hello.c -o hello ./hello ldd hello | grep stdcgcc hello.c -o hello指定输出文件名默认会生成a.out。如果这条能跑通说明工具链、系统头文件、C 运行库都是通的。ldd那一步看动态库解析到哪里如果还指向旧路径返回 4.2 去配置。5.2 vscode 里配置一键编译运行vscode 里编译 C 文件需要配置 tasks.json我这里给一个最小可用的版本CtrlShiftB 就能编译当前文件{ version: 2.0.0, tasks: [ { label: gcc build current file, type: shell, command: gcc, args: [ -g, ${file}, -o, ${fileDirname}/${fileBasenameNoExtension} ], group: { kind: build, isDefault: true }, problemMatcher: [$gcc] } ] }${file}是当前打开的文件路径${fileBasenameNoExtension}是去掉扩展名的文件名-g生成调试信息problemMatcher让 vscode 能解析 gcc 的编译错误输出。写 C 时把command改成g就行。这套配置不用插件也能跑适合刚搭好环境的场景。5.3 别把 Linux 的 rpm 包带进 macOS 或跨平台场景最后说一个边界gcc_rpm.tar.gz 只能在 rpm 系 Linux 上安装使用。macOS 上的 clang 和 Linux 的 gcc 动态库格式不同即使硬把这套 rpm 解包出来也无法被系统链接器识别。想在 macOS 上编译 Windows exe正确路径是x86_64-w64-mingw32-gcc或者 clang 的--targetx86_64-w64-windows-gnu这和本文讨论的离线包是两条完全不同的路线。我现在装完这个包后不急着删解包目录留着 rpm-list.txt等哪天 yum update 报依赖问题时回查它是最快的定位方式。希望帮到你。本文还有配套的精品资源点击获取
返回列表