在 CentOS/Fedora 上查找(未)使用的软件包?

Zab*_*man 3 package-management fedora centos yum

简而言之:从安装的所有 (rpm) 软件包中,我想确定未使用的软件包(例如,自过去 6 个月以来)。

总而言之:我有许多机器具有可观的服务记录。每次我从一个版本升级到另一个版本时,我都会惊讶于升级过程的进展情况。

然而,多年来安装了许多软件包(通过 yum),我知道其中一些已不再使用。我想摆脱这些,因为它们对资源使用和系统的整体安全有负面影响。

我正在寻找找到未使用包的最佳方法。

一种方法是手动筛选已安装的软件包?该方法有效,我学到了很多东西,但非常耗时。

所以我正在寻找一种自动方式来识别未使用的包,以便我可以手动清理它们。

我想前进的一种方法是监视服务器上所有使用过的文件,将它们链接到包并查看剩余的内容。有什么可用于此目的吗?

是否有更多创造性的方法来实现这一点?

Aar*_*ron 9

鉴于 RPM 和多个包共有的共享库的性质,我将采用构建我实际使用的包列表的方法,并将其与已安装的包列表进行比较。删除未使用的包有很多好处,例如释放磁盘空间、减少有助于提权的包、减少校验和数据库(即 OSSEC、aide、tripwire)的大小。

假设

  • atime 已启用。如果您使用的是 noatime 的挂载选项,则文件的访问时间将不会更新,并且无法用于确定访问了哪些文件。在文件系统上设置 noatime 以避免写入惩罚是很常见的。

免责声明:此方法有一些您需要考虑的风险。例如,如果您的服务器已经运行了几年,那么可能有守护进程在运行,它们使用自服务器/守护进程启动以来您没有访问过的旧文件。还有很多其他风险需要考虑,但你问了所以这里是我可以开始的一种方法。这仍然需要人类来确定可以安全移除的内容。 您不应使用此方法自动删除软件包。 这仅用于教育用途。

构建所有已安装 RPM 的列表。

rpm -qa | sort -n > /dev/shm/all.txt
Run Code Online (Sandbox Code Playgroud)

建立最近访问的文件列表并保存计数。 我们即将迎来新的一年,所以你可能想看看去年。

YEAR=`date -d "one year ago" '+%Y'`
# YEAR=2014
OFS="$IFS";IFS=$'\n';stat --printf="%y %n\n" $(ls -tr $(find /bin /boot /etc /lib /lib64 /sbin /usr /var -type f ! -name "*~" ! -name "*.gz" ! -name "*.tar")) | grep ^${YEAR} | awk {'print $NF'} > /dev/shm/recent.txt;IFS="$OFS";
FILECOUNT=`egrep -c ^.+ /dev/shm/recent.txt`
Run Code Online (Sandbox Code Playgroud)

将我们的 RPM 数据库复制到 ram 磁盘,这样我们就不会滥用服务器。确保您至少有 100 MB 左右的可用空间。例如 df -Ph /dev/shm

mkdir --mode=0700 /dev/shm/rpmdb
rsync -a /var/lib/rpm/. /dev/shm/rpmdb/.
Run Code Online (Sandbox Code Playgroud)

找到与我们的 recent.txt 列表相关的 RPM。这将需要一段时间。我敢打赌有人会找到更有效、更快和更聪明的方法来完成这一步。我会在屏幕会话中执行此操作。

renice 19 -p $$ > /dev/null 2>&1
printf "${FILECOUNT} files to iterate through."
> /dev/shm/recent_packages.txt
for file in `cat /dev/shm/recent.txt`
do
rpm --dbpath /dev/shm/rpmdb -q --whatprovides ${file} >> /dev/shm/recent_packages.txt 2>/dev/null
# optional status indicator.
printf "."
done
Run Code Online (Sandbox Code Playgroud)

从我们的列表中删除不属于 RPM 包的文件。

grep -v "not owned by" /dev/shm/recent_packages.txt | sort -n | uniq > /dev/shm/recent_sorted.txt
Run Code Online (Sandbox Code Playgroud)

区分输出。同样,这本身并不完全有用。您需要确定未访问这些包中的文件的原因。

diff -u /dev/shm/recent_sorted.txt /dev/shm/all.txt | grep '^+'
Run Code Online (Sandbox Code Playgroud)

您可以使用rpm -ql package列出 RPM 的内容。这是我的其中一个 VM 上的输出。如您所见,这在我的情况下并不完全有用。

+++ /dev/shm/all.txt    2014-12-31 20:50:06.521227281 +0000
+basesystem-10.0-4.el6.noarch
+dhcp-common-4.1.1-43.P1.el6.centos.x86_64
+filesystem-2.4.30-3.el6.x86_64
+rootfiles-8.1-6.1.el6.noarch
Run Code Online (Sandbox Code Playgroud)

我需要保留文件系统和基本系统,尽管这些文件已经有一段时间没有被访问过。 注意:在某些时候我启用了 noatime

我删除了 dhcp-common 及其关联的 dhclient 包,因为在我的特定用例中我永远不需要 DHCP。我意识到这种方法并不完全有效,但它应该为您提供服务器的每个独特角色的起点。新年快乐!