2. 旧系统资产盘点与依赖分析
升级或迁移一台运行多年的 RHEL 系统,最大的风险不是升级动作本身,而是"不知道自己有什么"。一台跑了五年的生产机,往往叠加了历任管理员手工安装的 RPM、第三方仓库、源码编译进 /usr/local 的组件、systemd 单元、cron 任务、监听端口和私有内核模块。这些资产之间还存在隐式依赖:某个业务进程依赖一个非标准端口的数据库,数据库又依赖某个特定版本的 OpenSSL,而 OpenSSL 来自一个已被禁用的第三方仓库。资产盘点的目标,就是把这些"看不见的线"画出来,形成一份可核对的清单,作为升级路径选择和回滚方案的输入。
盘点对象与工具映射
盘点不是漫无目的地敲命令,而是按"资产类别—工具—输出—用途"四列来组织。软件包层面用 rpm 与 yum(RHEL 8 起为 dnf,命令兼容);服务与开机行为用 systemctl;端口与文件句柄用 ss 与 lsof;定时任务用 crontab、systemctl list-timers 与 /etc/cron.*;硬件与驱动用 lspci -k、lsmod、ethtool -i。下面这张图给出各类资产之间的依赖关系与对应工具,是本节盘点的总览。
软件包盘点:区分"仓库内"与"仓库外"
第一步是拿到全量包清单并做来源分类。执行 rpm -qa --qf '%{NAME}\t%{VERSION}-%{RELEASE}\t%{VENDOR}\n' | sort,把结果重定向到文件。关键判断是包的来源:yum list installed 只能看到仓库可识别的包,而 rpm -qa 能看到全部。用 yumdb info <包名> | grep from_repo 可以查出某个包来自哪个仓库;如果返回空或报错,说明它是手工 rpm -ivh 安装的,这类包在升级时最容易出问题,因为新系统仓库里可能没有对应版本,或者被更高版本覆盖后无法回退。
还要识别"孤儿包"和"被替换包"。package-cleanup --orphans 列出已安装但当前仓库中不存在的包;yum check 检查依赖完整性。对于源码编译安装的组件,RPM 体系完全看不到,需要额外检查 /usr/local、/opt 下的目录,以及 ldconfig -p 输出的非标准库路径。一个实用做法是:find /usr/local /opt -maxdepth 3 -name '*.so*' -o -name 'bin' -type d,把结果与 RPM 清单对照,找出"影子资产"。
服务、端口与进程的三角定位
服务盘点的核心命令是 systemctl list-unit-files --type=service --state=enabled,它给出开机自启的服务集合。但要注意,很多老系统仍有 SysV init 脚本残留在 /etc/init.d/,以及被 chkconfig 管理的服务,这些在 systemd 下可能以兼容单元形式存在。用 systemctl list-units --type=service --state=running 看当前运行的服务,两者之差就是"已启用但未运行"或"运行但未启用"的异常项。
端口与进程的对应关系用 ss -tulnp 一次性拿到。输出中 Local Address:Port 与 users:(("进程名",pid=...,fd=...)) 直接关联。对于没有权限查看的进程,用 sudo lsof -i -P -n 补充。这里有一个容易忽略的点:ss 显示的是监听套接字,而 lsof 还能显示已建立的连接和打开的文件。如果某个业务进程依赖一个本地 Unix socket 或特定配置文件,lsof -p <pid> 会把它打开的所有文件列出来,这是判断"进程依赖哪些配置和库"的直接证据。
把三者串起来的方法是:从 ss 拿到端口和 PID,用 ps -fp <pid> 确认启动命令和运行用户,再用 systemctl status <pid> 或 cat /proc/<pid>/cgroup 反查它属于哪个 systemd 单元。这样就能建立"端口 → 进程 → 服务单元 → 软件包"的完整链路。
定时任务与硬件驱动
定时任务分散在四个位置:用户 crontab(crontab -l -u <user>)、/etc/crontab、/etc/cron.d/、以及 /etc/cron.{hourly,daily,weekly,monthly}/ 下的脚本。RHEL 7 以后还有 systemd timer,用 systemctl list-timers --all 查看。盘点时要记录每个任务的执行用户、命令路径和依赖的可执行文件——很多 cron 脚本调用的是 /usr/local/bin 下的自定义程序,这些程序在迁移后路径可能不存在。
硬件驱动是升级中最硬的约束。用 lspci -k 可以看到每个 PCI 设备正在使用的内核驱动模块;lsmod 列出已加载模块;ethtool -i <网卡> 显示网卡驱动的版本和来源。如果驱动是通过 DKMS 编译的(如某些 RAID 卡、万兆网卡、GPU 驱动),升级内核后必须重新编译,否则新内核启动时设备不可用。检查 dkms status 可以确认哪些模块由 DKMS 管理。对于闭源驱动,还要确认厂商是否提供新内核版本的兼容包,否则升级路径可能需要绕开或更换硬件。
packages.txt(全量包及来源)、services-ports.txt(服务、端口、进程、单元对应表)、deps-risk.txt(非仓库包、DKMS 模块、源码组件清单)。这三份文件是后续升级方案和回滚脚本的直接输入。依赖矩阵与风险标记
把上述信息汇总成一张依赖矩阵,行是业务功能,列是它依赖的资产,单元格标注版本和来源。例如"订单服务"依赖:端口 8080(Java 进程)、OpenJDK 11(来自第三方仓库)、MySQL 客户端库(系统 RPM)、/data/order 挂载点(LVM 逻辑卷)、以及一个每日 2:00 执行的备份 cron。矩阵中凡是"来源非官方仓库""DKMS 编译""源码安装""已停止维护的仓库"的单元格,都标为高风险。升级前必须为每个高风险项确定处置方式:替换为官方包、保留并单独迁移、或确认可废弃。
盘点的完成标准不是"命令都跑过了",而是能够回答三个问题:这台机器上跑着什么业务、每个业务依赖哪些具体资产、哪些资产在目标系统上无法直接延续。能回答这三个问题,升级路径的选择和回滚点的设置才有依据。