
1. 为什么 CentOS 7 需要 SCL 源CentOS 7 的用户应该都有过这种体会系统自带的软件源里软件版本老得让人着急。Python 还是 2.7.5GCC 还停在 4.8.5Git 是 1.8.3PHP 是 5.4。你说用吧有些新项目、新语法根本不支持你说不用吧又没法直接升级因为 CentOS 7 的根基就是这些旧版本贸然替换系统组件很容易把整个系统搞挂。SCLSoftware Collections就是专门解决这个问题的东西。它由 Red Hat 官方维护可以在不改变系统默认环境的前提下安装多个版本的开发工具、运行时和数据库比如 Python 3.6/3.8、PHP 7.x、Node.js、MySQL、PostgreSQL 等等。安装之后这些软件以独立的目录形式存在通过scl enable命令临时切换使用不会和系统自带的旧版本冲突。类比一下它相当于给你家老房子单独开了几间新厨房每间厨房的灶具、厨具都是全新的但你原来的老厨房也没拆想用哪个进去用就行。本文就基于 CentOS 7 环境从零开始讲清楚 SCL 源的安装、配置、使用方法和我在实际部署中踩过的坑适合需要在老系统上跑新应用的开发、运维和测试人员参考。2. SCL 源安装前的环境准备与版本核实2.1 系统版本检查动手之前先确认你的系统确实是 CentOS 7。SCL 源对系统版本有严格要求拿 CentOS 8 的去装 CentOS 7 的 SCL 源肯定会出问题。cat /etc/redhat-release输出类似这样CentOS Linux release 7.9.2009 (Core)只要看到7.x就没问题。另外不管是 minimal 安装还是带桌面的版本都能用 SCL但 minimal 版需要确保wget、vim这些基础工具存在没有的话先装yum install -y wget vim2.2 网络连通性与 yum 基础状态SCL 源本质上是 yum 源所以网络要能正常访问外网。测试方式ping -c 3 mirrors.aliyun.com如果 ping 不通检查 DNS 配置/etc/resolv.conf和路由。另外在配置新源之前建议先看一眼现有 yum 源的状态避免多个源互相冲突yum repolist正常情况下能看到base、extras、updates这几个仓库。如果之前配置过第三方源建议先把它们临时禁用等 SCL 装好再决定是否恢复。我自己遇到过 epel 源和 SCL 源同时启用时某些软件包的依赖解析会出现诡异的问题后文会细说。2.3 为什么要选 SCL 而不是直接升级系统组件这里想多说一句。很多人知道有 SCL 之后会问为什么不直接把 GCC、Python 升级到新版本原因很简单CentOS 7 的底层工具链glibc、gcc、python和其他包存在大量依赖关系比如系统自带 yum 就依赖 Python 2.7你如果手贱把默认 Python 换成了 3.xyum 基本就废了还得花大量时间修。SCL 的思路就是把新版本软件独立安装到/opt/rh/下例如rh-python38装在/opt/rh/rh-python38/root/usr/bin/python3.8装完不干扰系统原有的/usr/bin/python2.7。而且 SCL 里所有软件都经过 RHEL/CentOS 官方测试稳定性有保障。这是我最推荐老系统用户使用它的原因。3. 安装 SCL 源两种方式对比与实操3.1 官方默认 SCL 源安装CentOS 7 的 SCL 源由 Software Collections 组织提供早期需要先安装一个叫centos-release-scl的包这个包会引入 SCL 仓库的 yum 配置。yum install -y centos-release-scl安装完成后检查一下yum repolist | grep scl你会看到centos-sclo-rh和centos-sclo-sclo这两个仓库。前者是红帽官方维护的 SCL 集合如rh-python38、rh-nodejs12后者是社区相关的包。有些版本还会自动启用centos-sclo-rh-testing这个测试仓库不建议长期开启后续我会讲为什么。3.2 国内镜像加速方式如果服务器在国内直接从官方拉 SCL 源可能很慢甚至超时。我更推荐先用阿里云镜像把 SCL 仓库的 URL 替换掉速度快很多尤其是安装大型软件集合时差距非常明显。做法是安装centos-release-scl后修改对应的 repo 文件vim /etc/yum.repos.d/CentOS-SCLo-scl.repo vim /etc/yum.repos.d/CentOS-SCLo-scl-rh.repo把里面的baseurl从官方地址替换为阿里云镜像baseurlhttp://mirrors.aliyun.com/centos/7/sclo/$basearch/rh/ baseurlhttp://mirrors.aliyun.com/centos/7/sclo/$basearch/sclo/修改完执行yum clean all yum makecache实测下来阿里云的同步频率很高软件包齐全下载速度基本能拉满带宽。如果你在北方或者某些场景下阿里云速度不理想可以用清华源mirrors.tuna.tsinghua.edu.cn或中科大源mirrors.ustc.edu.cn逻辑一样替换 baseurl 的域名就行。3.3 安装后验证仓库状态这一步不要省。源配好后至少验证两件事仓库列表是否正常加载、能否检索到想要的软件集合。yum repolist yum list available | grep rh-python如果能搜到rh-python38.x86_64之类的包说明源已经正常工作。此时候再安装具体集合就水到渠成了比如装 Python 3.8yum install -y rh-python38装完通过scl enable激活使用scl enable rh-python38 bash python3 --version不出意外你会看到 Python 3.8.x。4. SCL 源使用详解软件集合搜索、安装与管理4.1 如何找到你需要的软件集合SCL 官方仓库里的软件集合数量很多名字也有规律可循比如rh-python38、rh-nodejs12、rh-ruby26、rh-git227、devtoolset-9、httpd24、rh-mysql80、rh-postgresql12基本一眼能看出是什么版本。不确定的时候用下面这个命令列出所有可用集合yum list available | grep -E ^rh-|^devtoolset-|^httpd|^mysql|^postgresql更精细一点的搜索方式比如找所有 PHP 相关的集合yum list available | grep rh-php我平时最常装的就是devtoolset系列。CentOS 7 自带的 GCC 4.8.5 不支持 C14 完整特性很多新代码编译不过用devtoolset-9就能直接启用 GCC 9。安装yum install -y devtoolset-9使用scl enable devtoolset-9 bash gcc --version你会看到 GCC 9.3.1这个过程完全不碰系统默认的 GCC安全得很。4.2scl enable的两种用法scl enable是 SCL 的核心命令理解它你就理解了 SCL 的所有用法。第一种用法临时进入一个子 shell。命令scl enable rh-python38 bash你看提示符进到了一个 新环境此时python3指向的是 SCL 目录下的 Python 3.8which python3会给出/opt/rh/rh-python38/root/usr/bin/python3。退出这个 shell 后一切恢复原样。第二种用法直接在命令前加环境变量。适合写脚本或者单条命令执行scl enable rh-python38 python3 --version这种方式不需要进入子 shell很干净。多条命令可以加引号串起来scl enable rh-python38 pip3 install requests python3 app.py4.3 多软件集合同时启用如果你同时需要 Python 3.8 和 Node.js 12可以这样scl enable rh-python38 rh-nodejs12 bash然后在这个环境里同时使用两者的新版本。需要注意的坑是不同集合可能会对同一个环境变量比如PATH、LD_LIBRARY_PATH反复追加路径在某些场景下可能导致库冲突所以不建议同时启用太多 SCL 集合够用就行。4.4 让 SCL 软件开机自动生效scl enable的缺点是你开了新终端就没有了。如果你希望某个用户登录后自动使用 SCL 环境写入用户的~/.bashrc# 加入 bashrc 底部 source scl_source enable rh-python38这样每次登录都会自动激活 Python 3.8。如果要全局生效写入/etc/profile.d/scl-enable.sh#!/bin/bash source scl_source enable rh-python38 devtoolset-9写好后赋可执行权限chmod x /etc/profile.d/scl-enable.sh注意全局生效意味着所有用户默认都用 SCL 的版本如果某些服务依赖系统旧版本可能会出问题。所以我的建议是尽量用用户级别配置只在需要的账号上开启。5. 常见问题与排查技巧实录5.1 安装centos-release-scl时出现依赖冲突这是我遇到过最多的问题。报错信息通常是Error: Package: centos-release-scl-2-3.el7.centos.noarch Requires: centos-release-scl-rh原因多半是已经有了第三方的 scl 相关 repo或者extras仓库被禁用。解决办法先用yum repolist查看仓库状态确保extras是启用的再检查/etc/yum.repos.d/下有没有多余的 SCL 相关文件有就备份后删掉最后执行yum clean all yum update -y yum install -y centos-release-scl5.2 安装软件集合时报 404 或Could not resolve host如果确认网络没问题大概率是源地址失效了。官方 SCL 仓库偶尔会做地址调整配置好国内镜像之后这个问题基本就消失了。另外配置完新源后一定要记得yum clean all yum makecache有时候旧缓存里的元数据过期会导致 yum 找不到包clean 就能解决。5.3scl enable之后命令找不到能启用环境但python3还是系统旧版很多新手会被这个问题搞晕。检查是不是 scl 的enable_collection配置没生效。执行scl enable rh-python38 echo $PATH如果输出的 PATH 里看不到/opt/rh/rh-python38/root/usr/bin说明 SCL 的 shell 函数没加载成功。这时候检查/etc/profile.d下有没有scl.sh或scl-aliases.sh文件如果没有安装一下scl-utilsyum install -y scl-utils装完后重新登录终端再试。5.4 启用了 SCL 集合后系统命令变怪比如启用某个集合后发现grep、awk这些基础命令的行为不太一样了。这可能是因为该集合的 PATH 优先级太高覆盖了系统目录的某些同名工具。解决方案是调整 PATH 顺序——在.bashrc里手动把系统目录插到前面export PATH/usr/bin:/bin:$PATH一般来说 SCL 内部不会覆盖基础文本处理工具但偶尔会遇到把/usr/bin排到很后面的第三方配置手动调整一下就行。5.5 测试仓库导致的混乱前面提到centos-sclo-rh-testing这个 testing 仓库如果它被启用yum 可能会解析到开发中的软件包稳定性没保证。不建议长期开启。检查仓库列表后直接禁用yum-config-manager --disable centos-sclo-rh-testing或者修改/etc/yum.repos.d/CentOS-SCLo-scl-rh.repo把enabled1改成enabled0。5.6 常见问题速查表问题现象可能原因解决方法安装 SCL 源依赖冲突extras 仓库被禁用残留 scl repo 文件启用 extras清理/etc/yum.repos.d/下多余 scl 文件后重装yum 检索不到 SCL 包缓存过期源地址失效yum clean all yum makecache替换国内镜像scl enable后命令未切换scl-utils 未安装yum install -y scl-utils重新登录终端多个集合启用后库冲突PATH 排序问题在.bashrc中手动调整export PATH/usr/bin:/bin:$PATHSCL 源下载过慢官方源在国内速度不行改用阿里云、清华或中科大镜像开机不生效未配置 profile.d 或 bashrc用source scl_source enable collection写入配置文件6. 进阶结合 SCL 源做老系统新开发6.1 一个完整的实际部署案例假设你要在 CentOS 7 上部署一个 Python 3.8 Node.js 12 的项目同时还需要新版 Git 来拉取代码。传统做法是手动编译安装慢不说后续升级还得自己维护。用 SCL 大概 10 分钟就能搞定全套# 1. 安装 SCL 源 yum install -y centos-release-scl # 2. 安装所需集合 yum install -y rh-python38 rh-nodejs12 rh-git227 # 3. 进入开发环境 scl enable rh-python38 rh-nodejs12 rh-git227 bash # 4. 验证版本 python3 --version node -v git --version # 5. 开始你的项目 pip3 install -r requirements.txt npm install这套流程下来系统原有的 Python 2.7、Node 6、Git 1.8 一点没被动过如果新环境里跑出问题退出 shell 直接回到旧环境排查互不干扰。6.2 在 systemd 服务中使用 SCL很多人在 systemd 里配置服务时发现用scl enable执行命令会失败因为 systemd 的服务启动环境是干净的非交互 shellscl enable是 shell 函数无法直接使用。正确姿势是在ExecStart里显式调用scl_source[Unit] DescriptionMy Python App [Service] Typesimple ExecStart/bin/bash -lc source scl_source enable rh-python38; python3 /opt/myapp/app.py Restartalways Usermyapp [Install] WantedBymulti-user.target关键点是bash -lc里先source scl_source enable rh-python38再启动你的应用。这样服务就能正常工作并找到 SCL 环境下的 Python 和库文件。6.3 结合 Nginx 使用 SCL 版本的 PHP再比如你想在 CentOS 7 上跑 PHP 7.4 而不是默认的 PHP 5.4。SCL 里提供了rh-php74但要让 Nginx 调用它需要修改 php-fpm 的 systemd 服务。我的做法是yum install -y rh-php74-php-fpm systemctl enable rh-php74-php-fpm systemctl start rh-php74-php-fpm这个包已经做好了独立的 php-fpm 服务监听127.0.0.1:9000Nginx 的配置里把fastcgi_pass指过去就行完全不影响系统默认 PHP。SCL 在这个场景下最大的价值就是独立运行、按需启用。7. SCL 源维护建议与个人体会SCL 源安装本身不难难的是后续的维护意识。我见过很多服务器因为把centos-sclo-rh-testing长期开着某次 yum update 之后整套环境就无法启动了。所以第一个建议生产环境永远不要开 testing 仓库保持仓库列表干净。第二SCL 软件集合并不会自动更新到新的大版本。比如rh-python38就是 Python 3.8 系列不会因为 SCL 源更新就给你升级到 Python 3.9/3.10。想要新版本需要另行安装对应的新集合。这是 SCL 的设计理念决定的也意味着你升级时要主动去装新集合而不是等待源自动更新。第三SCL 和 EPEL、Remi、IUS 这些第三方源虽然可以共存但我在实践中发现还是分场景用比较好。比如 PHP 用户会更习惯 Remi 源因为它的版本迭代更激进SCL 则胜在和 RHEL 兼容性好、改动温和。两套混用的时候务必先yum update做一次完整依赖解析确认没有冲突再继续。在我的实际运维工作中SCL 源帮我在很多不支持大版本系统升级的旧服务器上孵化了新功能模块的开发和运行环境。这里面的关键不只是能装上更重要的是随时可以退出旧环境再恢复默认状态。这种可逆性是 SCL 最让人放心的地方也是我向老用户推荐它的首要理由。最后分享一个小技巧如果你不确定某个 SCL 集合具体包含哪些包可以先看这个集合的签名 key 和依赖列表rpm -qi centos-release-scl-rh rpm -qR rh-python38这些命令能帮你快速了解集合构成避免装完发现缺这个缺那个。操作之前多看两眼总比装完再排查要省时间。