news 2026/9/28 5:55:31

CentOS 7.9 升级 OpenSSH 10.0p1: RPM 打包适配全记录

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
CentOS 7.9 升级 OpenSSH 10.0p1: RPM 打包适配全记录

最近在做一批 CentOS 7.9 服务器的安全整改,等保漏洞扫描报告里,OpenSSH 相关的 CVE 占了很大篇幅。系统自带的 OpenSSH 7.4p1 服役多年,面对 OpenSSH 10.0p1 这一版本号的整改目标,最稳妥的交付方式就是打成 RPM 安装包,然后批量分发。这篇文章是我这次 centos7.9 + openssh10.0p1-rpm 适配过程的全记录,从为什么选 RPM 方案、怎么改 spec 文件,到安装替换和回滚兜底,按实际操作顺序过一遍。你要是也在做着同样的事,可以直接拿这些步骤做参考。

CentOS 7.9 的官方生命周期已经结束,但生产环境里它还在大量运行,短时间内不可能全部迁移。对运维来说,能用 RPM 管理起来的东西才是可控的:包可以查询、可以回滚、可以用 yum 仓库分发。OpenSSH 升级这种事,最怕的就是一时手快在一台服务器上直接 make install,等出了问题连“当初装了什么”都说不清楚。下面内容完全围绕这个场景展开,读者对象是负责系统安全、业务服务器维护的运维工程师,也包括准备做自研 RPM 包的同学。

1. 决定打 RPM 而不是二进制编译的几个现实原因

1.1 编译安装的包管理盲区

大部分人拿到 OpenSSH 新版源码,第一反应就是解压然后三条命令:./configure、make、make install。单台机器临时用没问题,但放到几十台甚至上百台的服务器里,痛点会立刻暴露:rpm -qa 查不到你的 OpenSSH 版本,yum update 可能直接覆盖掉你手工装的文件,卸载的时候只能自己手动清理,根本不知道哪些文件是编译产生的。更麻烦的是,OpenSSH 这类系统级服务还牵扯到 PAM 模块、SELinux 安全上下文、systemd 服务文件,手工编译很容易把 /usr/libexec/openssh/sftp-server 这类辅助二进制放错位置,导致升级后 SFTP 服务时好时坏。

还有一个隐蔽问题:很多 CentOS 7.9 服务器为了过等保,基线检查会跑 rpm -qa 核验软件版本和补丁状态。如果 OpenSSH 是通过编译安装的,检查脚本可能直接判定为“不符合”,因为你根本没进入 RPM 体系。为了安全和合规之间的对齐,把 OpenSSH 10.0p1 做成 RPM 安装包不是可选项,而是必须项。

1.2 “el7 通用 RPM”最好别乱下

有些人喜欢去网上找现成的 openssh-10.0p1-xxx.el7.x86_64.rpm 直接安装,这个做法我其实是反对的。首先,别人打的包你并不知道他的编译参数是什么,比如没有启用 PAM 支持,那么 sshd 在登录验证时就会绕过系统 PAM 配置,轻则密码登录异常,重则影响账号锁定的安全策略。其次,很多第三方仓库编译环境并不是干净的 CentOS 7.9,他可能用的是高版本 glibc 或 OpenSSL 动态库,放到你的机器上启动 sshd 时会直接报 missing symbol 或 version not found。

拿这个场景来说,网上下载的 RPM 包如果依赖了当前系统没有的 libcrypto.so.1.1,你在 CentOS 7.9 上就会看到 sshd 起不来的现象。与其去猜别人怎么编译的,不如自己从头构建一个能追溯、能复现的 RPM 包。自己打出来的包放进内网 yum 仓库,后面所有机器都是同一条链路,出现问题时能快速定位是编译选项问题还是系统环境问题。

1.3 RPM 打包其实没有想象中复杂

很多运维对 rpmbuild 有畏惧感,总觉得写 spec 文件是发行版工程师才能干的事。实际用下来,OpenSSH 这个项目在源码包里带了完整的 spec 模板路径,CentOS 7 自身也有开源的 openssh.spec 可以参考。我们要做的不是从零写一份规范,而是在已有规范基础上做版本升级和依赖适配,核心工作主要集中在版本号、Source 地址、编译选项、文件清单这几块。

另外,打成 RPM 之后还有一个优势:可以用 rpmbuild 的构建结果直接做验证。rpm -qpl 可以列出包内所有文件路径,rpm -qpR 可以查看运行时依赖,rpm -qpc 能确认哪些是配置文件。这些信息在出现故障时都是排查的抓手。相比编译安装之后只能靠 find 命令猜测文件位置,RPM 体系的可观察性强太多了。

2. 准备构建环境:镜像源、依赖与源码校验

2.1 先确认系统现状

构建之前先把系统底数摸清楚,避免打到一半发现环境太干净或者版本不对。我在构建机上执行的第一组命令是:

cat /etc/redhat-release uname -r rpm -qa | grep openssh ssh -V 2>&1 sshd -V 2>&1

这里要注意ssh -V和sshd -V默认输出到 stderr,所以用2>&1重定向一下。正常情况下 CentOS 7.9 会返回 OpenSSH_7.4p1 这样的版本信息。另外确认一下架构,我这批服务器全是 x86_64,所以后续包名都按 x86_64 处理。

如果系统特别精简,连 rpm 命令都提示 not found,那就要先用 yum 安装 rpm 基础包。正常情况下 CentOS 7.9 不会缺 rpm,但某些容器镜像或裁剪系统确实会有这种极端情况,提前确认一下不浪费时间。

2.2 配置可用的 yum 源

因为 CentOS 7 已经结束维护,默认的 mirrors.centos.org 路径可能已经失效或不稳定,建议把 yum 源切到阿里云的开源镜像站。这里有个细节:CentOS 7 停更后,源路径从/centos/变成了/centos-vault/,一定要用 vault 路径,否则 yum 会报 404。

简单配置一个 base 源:

cat > /etc/yum.repos.d/CentOS-Base.repo <<'EOF' [base] name=CentOS-7.9-vault baseurl=https://mirrors.aliyun.com/centos-vault/7.9.2009/os/x86_64/ gpgcheck=0 enabled=1 EOF yum clean all yum makecache fast

如果还要装 EPEL 包,可以再把 epel-release 装一下。不过 OpenSSH 构建所需的依赖基本都在 base 源里,EPEL 不是必须的。这一步做好之后,后面 yum 安装工具链才能顺畅。

2.3 安装 rpmbuild 工具链与关键依赖

构建 RPM 需要一套完整的工具链,直接一条 yum 命令全部装齐:

yum install -y rpm-build rpmdevtools gcc make autoconf automake libtool yum install -y zlib-devel openssl-devel pam-devel krb5-devel audit-libs-devel

这里重点讲一下为什么需要这些依赖:

  • rpm-build 提供 rpmbuild 命令本体,rpmdevtools 提供 rpmdev-setuptree 之类的辅助脚本;
  • gcc、make、autoconf、automake、libtool 是编译源码的基本工具链;
  • zlib-devel 提供压缩库头文件,OpenSSH 传输层依赖 zlib;
  • openssl-devel 提供加密库头文件,新版 OpenSSH 虽然在某些版本后对 OpenSSL 的依赖有所减弱,但 configure 检测时最好还是要保证头文件存在;
  • pam-devel 是 PAM 认证支持的关键依赖,如果缺少,configure 会直接提示找不到 pam 相关头文件;
  • krb5-devel 和 audit-libs-devel 分别对应 GSSAPI 认证和 Linux 审计模块,等保环境下这两项一般都要开启。

很多人只装了 gcc 就开始 ./configure,结果卡在 PAM headers not found,非常浪费时间。在 CentOS 7 上,依赖最好一次装全,后续 rpmbuild 才能一气呵成。

2.4 下载源码并校验完整性

OpenSSH 官方源码发布在 OpenBSD 的可移植版发布目录下。我用 wget 下载 openssh-10.0p1.tar.gz,然后立刻做 sha256 校验:

wget https://cdn.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-10.0p1.tar.gz sha256sum openssh-10.0p1.tar.gz

校验值建议和官网上发布的校验信息核对,这一步不能省。源码包被篡改这种事虽然概率低,但 OpenSSH 是直接暴露在公网的服务,任何供应链风险都可能导致严重后果。下载完源码后把它放到 rpmbuild 的 SOURCES 目录,这个目录在后续的 spec 构建中会被自动引用。

如果你所在环境的服务器出网受限,也可以找一台能出网的机器先下载好,再通过内网传输到构建机。只要源码包完整性和路径没问题,构建结果是一致的。

3. 改造 openssh.spec:适配老系统是核心工作量

3.1 从旧 SRPM 提炼 spec,而不是从零写

OpenSSH 这种复杂组件的 spec 文件涉及太多细节,从零写会踩很多坑。我的做法是先把 CentOS 7.9 自带的 OpenSSH SRPM 拉下来,从里面提取旧 spec 作为基础,然后在此基础上修改。获取旧 SRPM 的命令:

yum install -y yum-utils yumdownloader --source openssh rpm -ivh openssh-7.4p1-*.el7.src.rpm

执行完 rpm -ivh 之后,源码包会解压到~/rpmbuild/SOURCES和~/rpmbuild/SPECS,其中~/rpmbuild/SPECS/openssh.spec就是我们要改的起点。这里要注意:CentOS 7 的 spec 里带了一堆针对旧版本的补丁,比如 CVE 修复补丁、GSSAPI 兼容补丁等。到了 OpenSSH 10.0p1,很多修复已经合入上游源码,这些旧补丁要么直接删除,要么会打不上,需要逐个确认。

3.2 版本号、Source0 与构建依赖的调整

spec 文件里最核心的几处修改必须准确。先看版本相关字段:

Version: 10.0p1 Release: 1.el7 Source0: https://cdn.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz

我保留了%{version}变量,这样以后升级到 10.1 之类的新版时,只需要改 Version 字段,Source0 的 URL 会自动变化,省得手动改一串地址。

BuildRequires 需要根据实际情况调整。CentOS 7 默认的 spec 里已经写了 openssl-devel、zlib-devel、pam-devel 等,基本不用大动。但要注意如果新版本源码的 configure 增加了新的检测项,可能还需要补充对应开发包。我这次构建时没有新增依赖,所以这部分改动最少。

3.3 configure 参数里藏着 SELinux / PAM 兼容性

spec 中%configure或显式 configure 参数是决定 RPM 行为的关键。我这次比较关注的是下面这几个参数:

--sysconfdir=/etc/ssh --with-pam --with-selinux --with-kerberos5 --with-audit=linux --with-privsep-path=/var/empty/sshd --with-md5-passwords

--sysconfdir=/etc/ssh保证配置文件仍然放在老位置,--with-pam必须开,否则 CentOS 的密码认证、账号锁定策略全部失效;--with-selinux开启后 sshd 会主动设置正确的文件安全上下文,避免 SSH 私钥目录被 SELinux 拦截;--with-kerberos5是给 GSSAPI 认证留的口子,企业环境里跳板机认证经常要用。

--with-md5-passwords这个选项在 OpenSSH 5.4 以后的版本中默认就不太推荐了,但 CentOS 7 的用户数据库里如果有老哈希格式的密码,开这个选项能减少升级后的认证兼容性问题。按实际安全策略决定,如果你们已经强制 sha256 以上哈希,可以不开。

构建服务器默认不会自动生成这些 configure 参数,我建议直接改动 spec 中的%configure段,把上面的参数按需写入,这样构建出的 RPM 才真正适合生产环境。

3.4 补丁维护与配置文件的 %config 声明

旧 spec 的 Patch 列表是这次适配最容易翻车的地方。CentOS 7 的 openssh.spec 中有一长串Patch0:、Patch1:等定义,并在%prep阶段用%patch应用。这些补丁是对应 7.4p1 源码的,换到 10.0p1 之后,很多 hunk 根本找不到上下文。

我在处理时把所有不适用于新版本的补丁全部注释掉,只保留了针对 SELinux 策略和 SSH 配置路径类的必要补丁。如果上游 10.0p1 已经合入了相同内容,那这些补丁就是多余的,留着反而会让%prep阶段直接构建失败。

配置文件的%config声明也不要乱动。OpenSSH 的 RPM 里通常把/etc/ssh/ssh_config和/etc/ssh/sshd_config标记为%config(noreplace),这意味着升级安装时,如果配置文件已经被本地修改过,RPM 不会直接覆盖,而是生成.rpmnew后缀文件。这个机制在生产环境中非常重要,否则升级一次 SSH,你手写的 AllowUsers 配置就被冲没了。

3.5 执行 rpmbuild 并检查产物

spec 改好后,进入真正的构建环节:

cd ~/rpmbuild/SPECS rpmbuild -ba openssh.spec

-ba表示同时构建二进制包和源码包。如果第一次构建报错,不要慌,大概率是缺依赖或者补丁没删干净。补充依赖后重新执行即可。

构建成功后,进入~/rpmbuild/RPMS/x86_64/目录,产物应该是这几个包:

openssh-10.0p1-1.el7.x86_64.rpm openssh-clients-10.0p1-1.el7.x86_64.rpm openssh-server-10.0p1-1.el7.x86_64.rpm

先用 rpm 查询命令验证一下包内容:

cd ~/rpmbuild/RPMS/x86_64/ rpm -qpl openssh-10.0p1-1.el7.x86_64.rpm rpm -qpl openssh-server-10.0p1-1.el7.x86_64.rpm rpm -qpR openssh-server-10.0p1-1.el7.x86_64.rpm

重点看两个地方:一是/usr/sbin/sshd、/usr/libexec/openssh/sftp-server这些关键二进制是否落在预期路径;二是运行时依赖是否出现了当前系统无法满足的高版本 glibc 或 OpenSSL 动态库。如果rpm -qpR输出的依赖都很正常,这个包才允许进入安装环节。

4. 安装替换:Uvh 背后的那些细节问题

4.1 安装前必须完成的备份动作

不管 RPM 包构建得多完美,替换系统 SSH 服务时都必须先做备份。生产事故往往不是新版本不能用,而是新旧交替时配置文件的迁移出了问题。安装前我习惯做这样几件事:

cp -a /etc/ssh /etc/ssh.bak.$(date +%Y%m%d) cp /usr/sbin/sshd /usr/sbin/sshd.bak cp /etc/pam.d/sshd /etc/pam.d/sshd.bak

这里最重要的备份是/etc/ssh目录。机器上现有的 SSH host key 如果丢了,所有已知主机的指纹缓存都会失效,影响大量客户端连接。RPM 安装包内的%post脚本如果没有检测到现有 host key,可能会重新生成,虽然技术上不影响功能,但会导致很多客户机报警 host key 变更。

还要确认一下/etc/pam.d/sshd的备份,新版 OpenSSH 如果带了 PAM 配置,有时会覆盖或新增配置文件,一旦认证链路被破坏,远程登录直接断掉。

4.2 使用 rpm -Uvh 而不是 rpm -e

新包下载好之后,很多人会因为担心旧版本冲突,先 rpm -e 卸载旧包再安装新包。在 OpenSSH 升级场景中,这是非常危险的操作。因为 rpm -e openssh-server 时会同时删掉 sshd 服务、依赖和 systemd 配置,如果在远程操作,极大概率把自己锁在机器外面。

正确的替换方式是用 rpm -Uvh 做原位升级:

rpm -Uvh ~/rpmbuild/RPMS/x86_64/openssh-10.0p1-1.el7.x86_64.rpm \ ~/rpmbuild/RPMS/x86_64/openssh-server-10.0p1-1.el7.x86_64.rpm \ ~/rpmbuild/RPMS/x86_64/openssh-clients-10.0p1-1.el7.x86_64.rpm

Uvh 会自动处理旧包卸载和新包安装的顺序,并且会执行新包 spec 中的%post脚本。如果构建时报错提示某个文件已经被旧包占用,不要用 rpm -e 硬删,检查一下是否同时装了 openssh-server 和 openssh-server-sysvinit 之类的叠叠包,一起升级掉就行。

安装完成后先不要急着断开当前 SSH 会话。执行ssh -V确认客户端版本,再执行sshd -V确认服务端版本,有一个不对都说明包没装对。

4.3 启动失败时的救援排查链路

如果在另一台测试机上做了升级,但 sshd 启动失败,不要慌,按固定链路排查。首先测试配置语法:

/usr/sbin/sshd -t -f /etc/ssh/sshd_config

这个命令会直接输出配置文件的语法错误。常见的错误类型是老配置文件中使用了新版已经不支持的指令,比如Protocol 2,1或者废弃的Ciphers选项。用编辑器把对应行处理掉,或者干脆把/etc/ssh/sshd_config先改名,让系统使用默认配置启动,再逐步 diff 差异。

如果语法测试通过但服务仍然起不来,查看系统日志:

tail -100 /var/log/messages tail -100 /var/log/secure

日志里经常出现的关键词是Bad owner or permissions,这时检查/var/empty/sshd目录权限。这个目录被 sshd 用作权限分离的 chroot 环境,必须归 root 所有,且不建议开放写权限。很多管理员在排查时把它改成 777,反而加剧了问题,正确做法是:

chown root:root /var/empty/sshd chmod 0755 /var/empty/sshd

另外别忘了 SELinux 上下文。CentOS 7 开启了 SELinux 后,新装的二进制文件上下文可能不是 sshd 标准上下文,导致 sshd 无法读取密钥或监听端口。执行一次恢复操作:

restorecon -Rv /etc/ssh /usr/sbin/sshd /usr/sbin/sftp-server /usr/libexec/openssh

如果在测试机上确认了一切正常,再回到生产机器上执行同样的升级流程。远程操作时一定要先开一个备用会话,或者确保有带外管理通道,否则 sshd 重启失败后你可能只能去物理机房。

4.4 验证新版本和密钥管理

替换完成后除了 version 验证,还要确认 host key 没有被覆盖。如果你的备份里有/etc/ssh/ssh_host_rsa_key,升级后应该还在,我一般对比一下文件指纹:

ssh-keygen -lf /etc/ssh/ssh_host_rsa_key

如果指纹和升级前一致,说明密钥没有被重新生成,客户端不会报 host key changed。如果发现密钥确实变了,日志里会有 SSH 服务自己重新生成的记录,这通常不是大问题,但需要尽快通知相关维护人员更新 known_hosts。

服务状态验证方面,执行systemctl status sshd -l,看到 active (running) 后,再从另一台机器上做一次完整的 SSH 登录、scp 传输、sftp 登录测试。这三件事都通过,安装替换才算真正成功。

5. 批量分发:把 RPM 做成内网 yum 仓库

5.1 仓库搭建与客户端配置

单台构建完成后,接下来的问题是怎么把包干净地分发到几十台机器上。我用的是内网 yum 仓库方案。构建机上创建一个目录,把 RPM 文件统一放进去,然后使用 createrepo 生成仓库元数据:

yum install -y createrepo mkdir -p /data/repo/openssh-10.0p1 cp ~/rpmbuild/RPMS/x86_64/openssh*.rpm /data/repo/openssh-10.0p1/ createrepo /data/repo/openssh-10.0p1/

客户端机器上新建一个 repo 文件:

cat > /etc/yum.repos.d/openssh-local.repo <<'EOF' [openssh-local] name=OpenSSH 10.0p1 Local Repo baseurl=http://build-server-ip/data/repo/openssh-10.0p1 gpgcheck=0 enabled=1 EOF

这里我把 gpgcheck 暂时设置为 0,因为是内网小道,包是自己构建的,安全性可控。如果公司有 RPM 签名体系,建议给包打上 GPG 签名后再发布,客户端 gpgcheck=1,避免包在传输链路中被篡改。后面如果要做规范化,可以用rpmsign对包签名。

5.2 灰度策略与脚本自保

批量升级 SSH 这种高危操作,绝对不能一下子全量执行。即使 RPM 包在测试机上验证过,每台服务器的配置和运行状态也都不一样。我这次先选了 3 台非核心、非关键链路机器做灰度。

灰度机上安装时,最好专门写一个带自保机制的脚本。所谓自保,是指脚本在升级完成并重启 sshd 后,不要立即退出,而是等待一段时间并检测 sshd 是否稳定运行。简单实现如下:

systemctl restart sshd sleep 20 if systemctl is-active sshd | grep -q active; then echo "sshd upgrade ok on $(hostname)" else echo "sshd failed on $(hostname), please use console" fi

听起来简单但非常实用。没有这一步,脚本跑完就断开 SSH,等你想再登录时发现服务已经挂了,只能用远程管理卡或者人工进机房。灰度 3 台全部正常后,再扩大到 10 台、最后全量。

5.3 回滚方案的两种兜底路径

批量升级之前一定要把回滚路径想清楚。我的建议是把升级前的 RPM 包版本号记下来,并在内网仓库中保留旧版本包:

# 从 yum 缓存或安装介质中找到旧版本 rpm rpm -Uvh --oldpackage openssh-7.4p1-22.el7_9.x86_64.rpm \ openssh-server-7.4p1-22.el7_9.x86_64.rpm \ openssh-clients-7.4p1-22.el7_9.x86_64.rpm

--oldpackage参数允许高版本包被低版本包降级替换,这是 RPM 体系里特有的回滚能力。如果机器已经接入了上面的 yum 仓库,更省事的方式是用yum downgrade:

yum downgrade openssh openssh-server openssh-clients

只要 yum 仓库里还留着旧版本,它就会自动完成降级。但注意,yum downgrade 时旧版本包的 spec 脚本也会执行,因此在回滚后同样要用sshd -t检查配置,并用新会话验证登录。

6. 复盘:这次适配过程中踩过的坑

6.1 pam-devel 缺失引发的编译中断

第一次构建时,我在一台最小化安装的机器上执行 rpmbuild,结果 configure 阶段直接报configure: error: *** Cannot find PAM headers.。原因很简单,没装 pam-devel。这个错误很典型,很多人以为只要系统有 PAM 运行时库就可以编译,但编译需要的是开发头文件,即 /usr/include/security/pam_appl.h 这一层的文件。

后来我把 pam-devel 装上重新构建,一路顺畅。这种事在 spec 里其实已经写了 BuildRequires: pam-devel,但如果你用了系统的 gcc 从源码直接 configure,就很容易漏掉。提醒一下,别跳步,依赖包装齐再动手。

6.2 /var/empty/sshd 权限被误改

测试过程中遇到过一回 sshd 启动报Missing privilege separation directory: /var/empty/sshd,当时检查了一圈发现 /var/empty/sshd 目录被之前的加固脚本改成了 0700,属主也不是 root。OpenSSH 的 privilege separation 机制要求这个目录归 root 所有且不能有 group / other 的写权限,但改成只有 root 可进入有时候反而让 sshd 自己都进不去。

用chown root:root /var/empty/sshd和chmod 0755恢复之后,服务立刻正常。这个问题不大,但很隐蔽,特别是有些安全扫描工具会建议把系统目录权限收紧,误伤到 /var/empty 就会牵连 sshd。

6.3 老配置文件中的废弃参数

升级后第一次启动测试时,我遇到过sshd: error: sshd_config line 12: Deprecated option RSAAuthentication这类提示。CentOS 7.9 的老配置里有很多为老版本 OpenSSH 准备的参数,例如RSAAuthentication yes、Protocol 2,1,在新的 OpenSSH 10.0p1 中已经被彻底移除或不再需要。

处理方法只有一种:把废弃参数注释掉或直接删除。不要指望新版本兼容所有旧参数,越大的跨版本升级越要做配置清理。稳妥做法是让新包先以默认配置启动,然后逐项把必要的配置(AllowUsers、PermitRootLogin 等)添加回来,每加一项sshd -t验证一次。

6.4 gpgcheck 拦住了批量安装

批量分发阶段还有一个有意思的问题。客户端 yum repo 配置好后,执行yum install openssh时报Public key for openssh-10.0p1-1.el7.x86_64.rpm is not installed。这是因为我在构建机上没有给 RPM 做 GPG 签名,但有些客户端 repo 配置文件里保留了 gpgcheck=1 的默认值。

既然是内网仓库,我直接把本地 repo 写成 gpgcheck=0,一次性绕开。如果公司安全规范要求签名,就得额外引入 rpmsign 流程,把私钥放到构建机上给每个 RPM 签名,并在客户端注入公钥。这个倒不算坑,只是流程规范问题,提前统一就不会在分发时卡住。

回到这次适配本身,我认为最核心的收获是:在 CentOS 7.9 这种老系统上引入新版本 OpenSSH,RPM 化不是可有可无的加分项,而是控制风险的基础。把 spec 文件、依赖、编译参数和回滚流程固定下来以后,后续版本升级就只是重复操作,不会再像第一次这样需要反复试错。如果你现在也在做类似的事,建议先把 spec 文件版本管理起来,至少存到 git 里,以后每次升级都能留痕。最后想提醒一句,CentOS 7 终究是有服务生命周期的,RPM 包解决的是存量机器上的问题,系统整体迁移的计划还是趁早排上日程比较好。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/28 5:55:29

无人机空中基站覆盖仿真:基于Matlab的六边形蜂窝网络可靠性分析

做无人机空中基站仿真&#xff0c;最头疼的事情不是无人机本身&#xff0c;而是怎样把“覆盖”这件事说清楚。我自己的习惯是&#xff0c;先把地面蜂窝网络搭出来&#xff0c;再把无人机塞进去&#xff0c;逐项对比覆盖率和可靠性指标&#xff0c;这样结论才有说服力。这篇文章…

作者头像 李华
网站建设 2026/9/28 5:54:54

中英集运链路全解析:深圳至英国集运服务商选择的核心维度

1. 深圳到英国&#xff1a;一条被低估的中英集运链路先聊个现象。我在深圳做跨境物流这行快八年&#xff0c;每年经手的对英包裹少说也有大几十万件&#xff0c;但直到现在&#xff0c;还有大量在英国的华人、留学生和做跨境生意的卖家&#xff0c;用的是“邮政直发”或者“找朋…

作者头像 李华
网站建设 2026/9/28 5:54:37

联想Tab M10 FHD PLUS刷机:TWRP注入与Magisk Root完整指南

玩安卓的人&#xff0c;手里没一两台联想系的设备都不好意思说自己折腾过。这台联想Tab M10 FHD PLUS&#xff0c;2019年出的骁龙429平台平板&#xff0c;平时看视频、刷网课问题不大&#xff0c;但原厂系统预装多、后台占用高&#xff0c;用久了明显发烫加卡顿。我一向信奉“既…

作者头像 李华
网站建设 2026/9/28 5:54:13

AI编程“王炸”实战:Claude 4.5接入TaoToken,重塑开发工作流

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/28 5:54:13

STM32开发参考方案怎么找?四类资源渠道与搜索技巧全梳理

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华