概述
软件包管理是 Linux 系统运维的基础。Debian 系使用 apt/dpkg,Red Hat 系使用 yum/dnf/rpm。理解两套包管理体系的原理和用法,掌握仓库管理、依赖解析、包构建、版本锁定和离线安装,是高效运维的前提。本文系统对比两大体系,并深入实践包构建和镜像源优化。
apt/dpkg 体系
体系架构
apt (高级前端)
│
├── apt-get → 包安装/卸载/更新
├── apt-cache → 包查询/搜索
└── apt → 综合命令(交互友好)
│
dpkg (底层工具)
│
├── dpkg → .deb 包安装/卸载
├── dpkg-deb → .deb 包操作
└── dpkg-query → 包查询
│
aptitude (替代前端,可选)
apt vs apt-get
# apt 是 apt-get 和 apt-cache 的综合,输出更友好
# 常用对照:
# 安装
$ apt install nginx # 新(推荐交互使用)
$ apt-get install nginx # 旧(推荐脚本使用)
# 搜索
$ apt search nginx
$ apt-cache search nginx
# 查看包信息
$ apt show nginx
$ apt-cache show nginx
# 更新索引
$ apt update
$ apt-get update
# 升级
$ apt upgrade # 升级已安装的包(不删除)
$ apt full-upgrade # 升级(可删除包以解决依赖)
$ apt-get dist-upgrade # 等同 full-upgrade
在脚本中建议使用
apt-get/apt-cache,因为其输出格式稳定;交互操作使用apt更友好。
基本操作
# 安装包
$ apt install nginx
$ apt install nginx=1.24.0-1ubuntu1 # 安装指定版本
$ apt install -y nginx # 自动确认
$ apt install --no-install-recommends nginx # 不安装推荐包
# 卸载
$ apt remove nginx # 卸载但保留配置
$ apt purge nginx # 卸载并删除配置
$ apt autoremove # 卸载不再需要的依赖
$ apt autoclean # 清理过期的 deb 文件
$ apt clean # 清理所有 deb 文件
# 更新
$ apt update # 更新包索引
$ apt upgrade # 升级所有包
$ apt full-upgrade # 升级(含依赖变更)
$ apt install --only-upgrade nginx # 只升级指定包
# 查询
$ apt list --installed # 已安装的包
$ apt list --upgradable # 可升级的包
$ apt show nginx # 包详情
$ apt search "web server" # 搜索
$ apt depends nginx # 查看依赖
$ apt rdepends nginx # 查看反向依赖
$ apt policy nginx # 查看版本和来源
dpkg 底层操作
# 安装 deb 包
$ dpkg -i package.deb # 安装
$ dpkg -i --force-depends package.deb # 忽略依赖安装(不推荐)
# 卸载
$ dpkg -r package # 卸载(保留配置)
$ dpkg -P package # 卸载(删除配置)
# 查询
$ dpkg -l # 列出所有已安装的包
$ dpkg -l nginx # 查看指定包状态
$ dpkg -L nginx # 查看包安装的文件
$ dpkg -S /usr/sbin/nginx # 查找文件属于哪个包
$ dpkg -s nginx # 查看包详情
$ dpkg -I package.deb # 查看 deb 包信息
$ dpkg -c package.deb # 查看 deb 包内容
# 解压(不安装)
$ dpkg -x package.deb /tmp/extract
$ dpkg -e package.deb /tmp/extract/DEBIAN # 提取控制文件
apt 包状态
$ dpkg -l nginx
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name Version Architecture Description
+++-==============-==============-============-=================================
ii nginx 1.24.0-1 amd64 high performance web server
| 字段 | 值 | 含义 |
|---|---|---|
| Desired | i | 应安装 |
| Status | i | 已安装 |
| Err | (none) | 无错误 |
混合状态 ii | 正常安装 | |
rc | 已卸载但配置保留 | |
hi | 已安装且被锁定 | |
un | 未安装 |
修复损坏的依赖
# 修复依赖
$ apt --fix-broken install
$ apt-get -f install
# 重新配置已安装的包
$ dpkg --configure -a
# 强制重装
$ apt install --reinstall nginx
$ dpkg --force-all -i package.deb # 最后手段
yum/dnf/rpm 体系
体系架构
dnf (yum 的继任者,Fedora/RHEL 8+)
│
├── dnf → 包安装/卸载/更新
├── dnf-config-manager → 仓库管理
└── dnf-utils → 实用工具(repoquery 等)
│
yum (RHEL 7 及以下)
│
rpm (底层工具)
│
├── rpm → .rpm 包安装/卸载
├── rpm2cpio → 解压 rpm
└── rpmbuild → 构建 rpm
yum vs dnf
# dnf 命令基本兼容 yum
# 主要改进:
# - 更快的依赖解析(libsolv)
# - 更好的内存使用
# - 模块化支持
# - 更清晰的错误信息
# 常用命令(yum/dnf 通用)
$ dnf install nginx
$ dnf remove nginx
$ dnf update nginx
$ dnf update # 更新所有包
$ dnf search nginx
$ dnf info nginx
$ dnf list installed
$ dnf list available
$ dnf history # 操作历史
$ dnf history undo 5 # 撤销第 5 次操作
基本操作
# 安装
$ dnf install nginx
$ dnf install nginx-1.24.0 # 指定版本
$ dnf install -y nginx # 自动确认
$ dnf install --nogpgcheck nginx # 跳过 GPG 检查(不推荐)
$ dnf reinstall nginx # 重装
# 卸载
$ dnf remove nginx # 卸载
$ dnf autoremove # 卸载不需要的依赖
$ dnf remove --noautoremove nginx # 不自动卸载依赖
# 更新
$ dnf check-update # 检查可更新的包
$ dnf update # 更新所有
$ dnf upgrade # 等同 update
$ dnf update --security # 只更新安全补丁
# 查询
$ dnf list nginx # 查看包
$ dnf info nginx # 包详情
$ dnf search "web server" # 搜索
$ dnf provides /usr/sbin/nginx # 查找文件属于哪个包
$ dnf repoquery --requires nginx # 查看依赖
$ dnf repoquery --whatrequires nginx # 反向依赖
$ dnf history # 操作历史
$ dnf grouplist # 包组列表
$ dnf groupinstall "Development Tools" # 安装包组
rpm 底层操作
# 安装
$ rpm -ivh package.rpm # 安装
$ rpm -Uvh package.rpm # 升级安装
$ rpm -Fvh package.rpm # 只升级已安装的
$ rpm -ivh --nodeps package.rpm # 忽略依赖(不推荐)
$ rpm -ivh --force package.rpm # 强制重装
# 卸载
$ rpm -e package # 卸载
$ rpm -e --nodeps package # 忽略依赖卸载(危险)
# 查询
$ rpm -qa # 列出所有已安装的包
$ rpm -q nginx # 查看是否安装
$ rpm -qi nginx # 包详情
$ rpm -ql nginx # 包安装的文件
$ rpm -qc nginx # 配置文件
$ rpm -qd nginx # 文档文件
$ rpm -qf /usr/sbin/nginx # 文件属于哪个包
$ rpm -qR nginx # 依赖关系
$ rpm -q --whatrequires nginx # 反向依赖
$ rpm -q --changelog nginx # 变更日志
# 验证
$ rpm -V nginx # 验证文件完整性
$ rpm -Va # 验证所有包
# S=大小变化 M=权限变化 5=MD5变化 T=时间变化
rpm 包状态验证
$ rpm -V nginx
S.5....T. c /etc/nginx/nginx.conf
# 字段含义:
# S - 文件大小改变
# 5 - MD5 校验和改变
# L - 符号链接改变
# T - 修改时间改变
# D - 设备改变
# U - 用户改变
# G - 组改变
# M - 权限改变
# . - 该属性未改变
# 第二列:
# c - 配置文件
# d - 文档文件
# g - 幽灵文件(不应存在)
# l - 许可证文件
# r - readme 文件
# (空) - 普通文件
仓库管理
apt 仓库管理
# 查看已配置的仓库
$ apt policy
$ cat /etc/apt/sources.list
$ ls /etc/apt/sources.list.d/
# 添加仓库(传统方式)
$ echo "deb http://archive.ubuntu.com/ubuntu noble main restricted universe multiverse" >> /etc/apt/sources.list
# 添加 PPA
$ add-apt-repository ppa:nginx/stable
$ apt update
# 添加仓库(推荐方式)
# /etc/apt/sources.list.d/nginx.list
deb [arch=amd64 signed-by=/etc/apt/keyrings/nginx.gpg] https://nginx.org/packages/ubuntu noble nginx
# 导入 GPG 密钥
$ curl -fsSL https://nginx.org/keys/nginx_signing.key | gpg --dearmor -o /etc/apt/keyrings/nginx.gpg
# 禁用仓库
# 在行首加 #
# 或使用 apt preferences
# 更新索引
$ apt update
apt 仓库优先级
# /etc/apt/preferences.d/nginx
Package: nginx
Pin: release o=nginx
Pin-Priority: 1001
# 优先级说明:
# 1001+ - 降级也允许安装
# 990 - 默认(已安装的优先)
# 500 - 标准优先级
# 100 - 非官方源
# <0 - 拒绝安装
# 查看优先级
$ apt policy nginx
dnf/yum 仓库管理
# 查看已配置的仓库
$ dnf repolist
$ dnf repolist --all
# 仓库配置文件
$ ls /etc/yum.repos.d/
# /etc/yum.repos.d/nginx.repo
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
# 启用/禁用仓库
$ dnf config-manager --enable nginx-stable
$ dnf config-manager --disable nginx-stable
# 临时启用仓库
$ dnf --enablerepo=nginx-stable install nginx
# 添加仓库
$ dnf config-manager --add-repo https://nginx.org/packages/centos/nginx.repo
# 导入 GPG 密钥
$ rpm --import https://nginx.org/keys/nginx_signing.key
dnf 模块化
# 查看可用模块
$ dnf module list
# Node.js 模块示例
$ dnf module list nodejs
Name Stream Profiles Summary
nodejs 18 common [d], development, minimal Javascript runtime
nodejs 20 common [d], development, minimal Javascript runtime
# 启用模块流
$ dnf module enable nodejs:20
# 安装模块
$ dnf module install nodejs:20/common
# 切换模块流
$ dnf module reset nodejs
$ dnf module enable nodejs:18
$ dnf module install nodejs:18
依赖解析
apt 依赖解析
# 查看依赖
$ apt depends nginx
$ apt-cache depends nginx
# 查看反向依赖
$ apt rdepends nginx
$ apt-cache rdepends nginx
# 查看依赖树
$ apt-cache depends --recurse nginx | head -50
# 查看某个包为何被安装
$ apt why nginx
# nginx <depends> nginx-core
# nginx-core <depends> nginx
# 查看包的推荐和建议
$ apt show nginx | grep -E "Depends|Recommends|Suggests"
dnf 依赖解析
# 查看依赖
$ dnf repoquery --requires nginx
$ dnf repoquery --requires --recursive nginx
# 反向依赖
$ dnf repoquery --whatrequires nginx
# 查看包提供的功能
$ dnf repoquery --provides nginx
# 查看包的文件
$ dnf repoquery --list nginx
# 依赖树
$ dnf repoquery --requires --resolve --recursive nginx
依赖冲突处理
# apt: 模拟安装查看冲突
$ apt install -s nginx
# dnf: 使用 --best 显示最佳可用版本
$ dnf install --best nginx
# dnf: 使用 --allowerasing 允许删除冲突包
$ dnf install --allowerasing nginx
# 查看冲突详情
$ dnf install nginx --assumeno # 模拟,回答 no
包构建
构建 deb 包
目录结构
mypackage/
├── DEBIAN/
│ ├── control # 包信息(必须)
│ ├── postinst # 安装后脚本
│ ├── prerm # 卸载前脚本
│ ├── postrm # 卸载后脚本
│ ├── preinst # 安装前脚本
│ ├── conffiles # 配置文件列表
│ ├── md5sums # 文件校验和(自动生成)
│ └── triggers # 触发器
├── usr/
│ ├── bin/
│ │ └── myapp # 可执行文件
│ ├── lib/
│ │ └── myapp/
│ │ └── config.yaml
│ └── share/
│ └── man/
│ └── man1/
│ └── myapp.1
└── etc/
└── myapp/
└── config.conf
control 文件
# mypackage/DEBIAN/control
Package: myapp
Version: 1.0.0
Architecture: amd64
Maintainer: Admin <admin@sre.wang>
Installed-Size: 1024
Depends: libc6 (>= 2.34), libssl3
Recommends: logrotate
Suggests: myapp-doc
Conflicts: oldapp
Replaces: oldapp
Section: utils
Priority: optional
Description: My Application
A custom application for server management.
.
Features:
- Feature 1
- Feature 2
维护脚本
#!/bin/bash
# mypackage/DEBIAN/postinst
set -e
case "$1" in
configure)
# 创建用户
if ! id myapp &>/dev/null; then
useradd --system --no-create-home --shell /usr/sbin/nologin myapp
fi
# 设置权限
chown myapp:myapp /var/lib/myapp
chmod 750 /var/lib/myapp
# 启用服务
systemctl enable myapp.service
systemctl start myapp.service
echo "myapp installed successfully"
;;
abort-upgrade|abort-remove|abort-deconfigure)
;;
*)
echo "postinst called with unknown argument \`$1'" >&2
exit 1
;;
esac
exit 0
构建
# 确保 control 文件权限正确
$ chmod 755 mypackage/DEBIAN/postinst
$ chmod 755 mypackage/DEBIAN/prerm
# 生成 md5sums
$ cd mypackage
$ find . -type f ! -path './DEBIAN/*' -exec md5sum {} \; | sed 's/\.\///' > DEBIAN/md5sums
# 构建 deb 包
$ dpkg-deb --build mypackage
# 或
$ dpkg -b mypackage myapp_1.0.0_amd64.deb
# 验证
$ dpkg-deb --info myapp_1.0.0_amd64.deb
$ dpkg-deb --contents myapp_1.0.0_amd64.deb
# 使用 lintian 检查
$ lintian myapp_1.0.0_amd64.deb
使用 debhelper 构建(进阶)
# 安装构建工具
$ apt install debhelper dh-make devscripts
# 初始化包
$ dh_make --createorig -p myapp_1.0.0
# 编辑 debian/ 目录下的文件
# debian/control
# debian/rules
# debian/changelog
# 构建
$ dpkg-buildpackage -us -uc -b
构建 rpm 包
spec 文件
# myapp.spec
Name: myapp
Version: 1.0.0
Release: 1%{?dist}
Summary: My Application
License: MIT
URL: https://sre.wang
Source0: %{name}-%{version}.tar.gz
BuildRequires: gcc
BuildRequires: make
Requires: openssl
Requires(post): systemd
Requires(preun): systemd
Requires(postun): systemd
%description
A custom application for server management.
%prep
%setup -q
%build
make %{?_smp_mflags}
%install
make install DESTDIR=%{buildroot}
install -D -m 644 config/myapp.service %{buildroot}%{_unitdir}/myapp.service
install -D -m 644 config/myapp.conf %{buildroot}%{_sysconfdir}/myapp/myapp.conf
%files
%{_bindir}/myapp
%{_unitdir}/myapp.service
%dir %{_sysconfdir}/myapp
%config(noreplace) %{_sysconfdir}/myapp/myapp.conf
%doc README.md
%license LICENSE
%post
%systemd_post myapp.service
%preun
%systemd_preun myapp.service
%postun
%systemd_postun_with_restart myapp.service
%changelog
* Wed Jul 10 2026 Admin <admin@sre.wang> - 1.0.0-1
- Initial release
构建
# 1. 准备构建环境
$ dnf install rpmdevtools rpmbuild
$ rpmdev-setuptree
# 2. 目录结构
~/rpmbuild/
├── BUILD/
├── RPMS/
├── SOURCES/
│ └── myapp-1.0.0.tar.gz
├── SPECS/
│ └── myapp.spec
└── SRPMS/
# 3. 放置源码
$ cp myapp-1.0.0.tar.gz ~/rpmbuild/SOURCES/
$ cp myapp.spec ~/rpmbuild/SPECS/
# 4. 构建
$ rpmbuild -ba ~/rpmbuild/SPECS/myapp.spec
# -ba: 构建 src.rpm 和 binary rpm
# -bb: 只构建 binary rpm
# -bs: 只构建 src.rpm
# 5. 查看
$ ls ~/rpmbuild/RPMS/x86_64/
myapp-1.0.0-1.el9.x86_64.rpm
# 6. 验证
$ rpm -qpi ~/rpmbuild/RPMS/x86_64/myapp-1.0.0-1.el9.x86_64.rpm
$ rpm -qpl ~/rpmbuild/RPMS/x86_64/myapp-1.0.0-1.el9.x86_64.rpm
deb vs rpm 包构建对比
| 特性 | deb | rpm |
|---|---|---|
| 控制文件 | DEBIAN/control | spec 文件 |
| 脚本位置 | DEBIAN/ 目录 | spec 文件内 |
| 依赖声明 | Depends/Recommends | Requires |
| 配置文件标记 | conffiles | %config(noreplace) |
| 构建工具 | dpkg-deb / debhelper | rpmbuild |
| 源码包 | .dsc + .orig.tar.gz | .src.rpm |
| 变更日志 | debian/changelog | %changelog |
版本锁定
apt 版本锁定
# 方法 1: apt-mark hold
$ apt-mark hold nginx
$ apt-mark showhold
$ apt-mark unhold nginx
# 方法 2: dpkg --set-selection
$ echo "nginx hold" | dpkg --set-selections
$ dpkg --get-selections | grep hold
# 方法 3: apt preferences(更精细)
# /etc/apt/preferences.d/hold-nginx
Package: nginx
Pin: release *
Pin-Priority: -1
# 优先级 < 0 拒绝安装/升级
# 锁定特定版本
# /etc/apt/preferences.d/pin-nginx
Package: nginx
Pin: version 1.24.0*
Pin-Priority: 1001
dnf/yum 版本锁定
# 方法 1: versionlock 插件
$ dnf install python3-dnf-plugin-versionlock
$ dnf versionlock add nginx
$ dnf versionlock list
$ dnf versionlock delete nginx
$ dnf versionlock clear
# 方法 2: 在 repo 中排除
# /etc/yum.repos.d/centos.repo
[baseos]
exclude=nginx kernel*
# 方法 3: dnf 配置
# /etc/dnf/dnf.conf
exclude=nginx
离线安装
方法 1: 下载 deb 包及依赖
# 下载包及所有依赖
$ apt download nginx
$ apt-get install --download-only -o Dir::Cache=/tmp/packages nginx
# 或
$ apt install --reinstall --download-only nginx
# 更好的方式:使用 apt-rdepends
$ apt install apt-rdepends
$ apt-rdepends nginx | grep -v "^ " | awk '{print $1}' | xargs apt download
# 使用 dpkg-offline
$ apt install dpkg-offline
$ dpkg-offline /path/to/iso nginx
# 安装离线包
$ dpkg -i /tmp/packages/*.deb
$ apt --fix-broken install # 修复依赖(如果需要)
方法 2: 下载 rpm 包及依赖
# 下载包及依赖
$ dnf install --downloadonly --downloaddir=/tmp/packages nginx
# 使用 repotrack
$ dnf install dnf-utils
$ repotrack nginx -p /tmp/packages
# 安装离线包
$ rpm -Uvh /tmp/packages/*.rpm
# 或
$ dnf localinstall /tmp/packages/*.rpm
方法 3: 创建本地仓库
# apt 本地仓库
$ apt install dpkg-dev
$ mkdir -p /opt/local-repo
$ cp *.deb /opt/local-repo/
$ cd /opt/local-repo && dpkg-scanpackages . /dev/null | gzip -9c > Packages.gz
# 配置仓库
# /etc/apt/sources.list.d/local.list
deb [trusted=yes] file:///opt/local-repo ./
$ apt update
$ apt install myapp
# dnf 本地仓库
$ dnf install createrepo
$ mkdir -p /opt/local-repo
$ cp *.rpm /opt/local-repo/
$ createrepo /opt/local-repo
# 配置仓库
# /etc/yum.repos.d/local.repo
[local]
name=Local Repository
baseurl=file:///opt/local-repo
gpgcheck=0
enabled=1
$ dnf install myapp
方法 4: 使用快照/镜像
# apt-mirror: 完整镜像
$ apt install apt-mirror
# /etc/apt/mirror.list
deb http://archive.ubuntu.com/ubuntu noble main restricted universe multiverse
deb http://archive.ubuntu.com/ubuntu noble-updates main restricted universe multiverse
deb http://archive.ubuntu.com/ubuntu noble-security main restricted universe multiverse
$ apt-mirror
# 下载到 /var/spool/apt-mirror/
# reposync: 镜像 dnf 仓库
$ dnf install dnf-utils
$ reposync --repoid=baseos --download_path=/opt/mirror
$ createrepo /opt/mirror/baseos
镜像源优化
选择最快的镜像
# apt: netselect-apt
$ apt install netselect-apt
$ netselect-apt noble
# 自动选择最快的 Ubuntu 镜像
# 或手动测试
$ time curl -sI http://archive.ubuntu.com/ubuntu/ > /dev/null
$ time curl -sI http://mirrors.aliyun.com/ubuntu/ > /dev/null
$ time curl -sI http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ > /dev/null
# dnf: fastestmirror 插件
# /etc/dnf/dnf.conf
fastestmirror=True
$ dnf clean all
$ dnf makecache
配置国内镜像
# Ubuntu/Debian 镜像源
# /etc/apt/sources.list
deb https://mirrors.aliyun.com/ubuntu/ noble main restricted universe multiverse
deb https://mirrors.aliyun.com/ubuntu/ noble-updates main restricted universe multiverse
deb https://mirrors.aliyun.com/ubuntu/ noble-security main restricted universe multiverse
# 或清华源
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ noble main restricted universe multiverse
# Debian
deb https://mirrors.aliyun.com/debian/ bookworm main contrib non-free non-free-firmware
deb https://mirrors.aliyun.com/debian/ bookworm-updates main contrib non-free non-free-firmware
deb https://mirrors.aliyun.com/debian-security/ bookworm-security main contrib non-free non-free-firmware
# RHEL/CentOS 镜像源
# /etc/yum.repos.d/CentOS-Base.repo
[baseos]
name=CentOS Stream $releasever - BaseOS
baseurl=https://mirrors.aliyun.com/centos-stream/$releasever-stream/BaseOS/$basearch/os/
gpgcheck=1
enabled=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
[appstream]
name=CentOS Stream $releasever - AppStream
baseurl=https://mirrors.aliyun.com/centos-stream/$releasever-stream/AppStream/$basearch/os/
gpgcheck=1
enabled=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
# AlmaLinux/Rocky Linux
# 通常已有国内镜像,参考官方文档
镜像缓存优化
# apt: 配置缓存
# /etc/apt/apt.conf.d/99-cache
Dir::Cache "/var/cache/apt";
Dir::Cache::archives "archives";
APT::Install-Recommends "false"; # 减少不必要的包
APT::Install-Suggests "false";
APT::Get::Install-Suggests "false";
# 清理缓存
$ apt clean # 清理所有下载的 deb
$ apt autoclean # 只清理过期的 deb
$ apt autoremove # 清理不需要的依赖
# dnf: 配置缓存
# /etc/dnf/dnf.conf
keepcache=True # 保留下载的 rpm
cachedir=/var/cache/dnf
$ dnf clean all # 清理缓存
$ dnf makecache # 重建缓存
使用代理
# apt 代理
# /etc/apt/apt.conf.d/99proxy
Acquire::http::Proxy "http://proxy.sre.wang:8080";
Acquire::https::Proxy "http://proxy.sre.wang:8080";
# 或环境变量
$ export http_proxy=http://proxy.sre.wang:8080
$ export https_proxy=http://proxy.sre.wang:8080
$ apt update
# dnf 代理
# /etc/dnf/dnf.conf
proxy=http://proxy.sre.wang:8080
proxy_username=user
proxy_password=pass
包管理安全
GPG 密钥管理
# apt: GPG 密钥
# 导入密钥(新方式)
$ install -d /etc/apt/keyrings
$ curl -fsSL https://nginx.org/keys/nginx_signing.key | gpg --dearmor -o /etc/apt/keyrings/nginx.gpg
# 导入密钥(旧方式,不推荐)
$ apt-key add nginx_signing.key
# 查看已导入的密钥
$ apt-key list
# 删除密钥
$ apt-key del ABC12345
$ rm /etc/apt/keyrings/nginx.gpg
# dnf: GPG 密钥
$ rpm --import https://nginx.org/keys/nginx_signing.key
# 查看已导入的密钥
$ rpm -qa gpg-pubkey --qf '%{NAME}-%{VERSION}-%{RELEASE}\t%{SUMMARY}\n'
# 删除密钥
$ rpm -e gpg-pubkey-abc12345
验证包完整性
# apt: 验证
$ apt install --allow-unauthenticated nginx # 禁用验证(不推荐)
$ apt install nginx # 默认验证
# dpkg 验证
$ debsums nginx # 验证已安装包的文件
$ debsums -c nginx # 只检查变化的文件
# dnf: 验证
$ dnf install --nogpgcheck nginx # 禁用验证(不推荐)
# rpm 验证
$ rpm -K package.rpm # 验证签名
$ rpm --checksig package.rpm
# 验证所有已安装包
$ rpm -Va | grep -E "S\.5" | head -20
# 检查文件是否被篡改
实战案例
案例 1:自动化包安装脚本
#!/bin/bash
# install-packages.sh - 跨发行版包安装
set -e
# 检测包管理器
if command -v apt &>/dev/null; then
PKG_MGR="apt"
elif command -v dnf &>/dev/null; then
PKG_MGR="dnf"
elif command -v yum &>/dev/null; then
PKG_MGR="yum"
else
echo "Unsupported distribution"
exit 1
fi
# 包名映射(不同发行版包名可能不同)
declare -A PACKAGES=(
["nginx"]="nginx"
["redis"]="redis-server" # Debian 用 redis-server
["vim"]="vim"
["curl"]="curl"
["git"]="git"
)
# 安装函数
install_package() {
local name=$1
local apt_name=${2:-$1}
local dnf_name=${3:-$1}
case $PKG_MGR in
apt)
apt update && apt install -y "$apt_name"
;;
dnf|yum)
$PKG_MGR install -y "$dnf_name"
;;
esac
}
# 批量安装
for pkg in nginx redis vim curl git; do
echo "Installing $pkg..."
install_package "$pkg"
done
echo "All packages installed."
案例 2:构建自定义 Nginx 包
#!/bin/bash
# build-nginx-deb.sh - 构建 Nginx deb 包
set -e
VERSION="1.27.0"
NGINX_USER="www-data"
BUILD_DIR="/tmp/nginx-build"
PKG_DIR="$BUILD_DIR/nginx_$VERSION"
# 1. 准备构建环境
apt install -y build-essential libpcre3-dev zlib1g-dev libssl-dev dpkg-dev
# 2. 下载源码
mkdir -p $BUILD_DIR
cd $BUILD_DIR
wget http://nginx.org/download/nginx-$VERSION.tar.gz
tar xzf nginx-$VERSION.tar.gz
# 3. 编译
cd nginx-$VERSION
./configure \
--prefix=/usr/share/nginx \
--sbin-path=/usr/sbin/nginx \
--conf-path=/etc/nginx/nginx.conf \
--user=$NGINX_USER \
--group=$NGINX_USER \
--with-http_ssl_module \
--with-http_v2_module \
--with-http_stub_status_module
make -j$(nproc)
make install DESTDIR=$PKG_DIR
# 4. 创建 DEBIAN 目录
mkdir -p $PKG_DIR/DEBIAN
# 5. 创建 control 文件
cat > $PKG_DIR/DEBIAN/control << EOF
Package: nginx-custom
Version: $VERSION
Architecture: amd64
Maintainer: Admin <admin@sre.wang>
Depends: libc6, libpcre3, zlib1g, libssl3
Section: web
Priority: optional
Description: Custom Nginx $VERSION
Nginx built with custom configuration.
EOF
# 6. 创建 systemd service
mkdir -p $PKG_DIR/etc/systemd/system
cat > $PKG_DIR/etc/systemd/system/nginx.service << 'EOF'
[Unit]
Description=The NGINX HTTP and reverse proxy server
After=syslog.target network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target
[Service]
Type=forking
PIDFile=/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t
ExecStart=/usr/sbin/nginx
ExecReload=/usr/sbin/nginx -s reload
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true
[Install]
WantedBy=multi-user.target
EOF
# 7. 创建 postinst
cat > $PKG_DIR/DEBIAN/postinst << 'EOF'
#!/bin/bash
set -e
systemctl daemon-reload
systemctl enable nginx
systemctl start nginx
EOF
chmod 755 $PKG_DIR/DEBIAN/postinst
# 8. 生成 md5sums
cd $PKG_DIR
find . -type f ! -path './DEBIAN/*' -exec md5sum {} \; | sed 's/\.\///' > DEBIAN/md5sums
# 9. 构建
cd $BUILD_DIR
dpkg-deb --build $(basename $PKG_DIR)
echo "Package built: $BUILD_DIR/nginx_$VERSION.deb"
案例 3:安全更新自动化
#!/bin/bash
# auto-security-update.sh - 安全更新自动化
set -e
LOG="/var/log/security-update.log"
exec > >(tee -a $LOG) 2>&1
echo "=== Security Update $(date) ==="
if command -v apt &>/dev/null; then
# Debian/Ubuntu
apt update
# 只安装安全更新
apt list --upgradable 2>/dev/null | grep -i security
# 使用 unattended-upgrades
apt install -y unattended-upgrades
echo 'APT::Periodic::Update-Package-Lists "1";' > /etc/apt/apt.conf.d/20auto-upgrades
echo 'APT::Periodic::Unattended-Upgrade "1";' >> /etc/apt/apt.conf.d/20auto-upgrades
unattended-upgrade --dry-run -v
elif command -v dnf &>/dev/null; then
# RHEL/CentOS
dnf check-update --security
# 安装安全更新
dnf update --security -y
# 使用 dnf-automatic
dnf install -y dnf-automatic
sed -i 's/apply_updates = no/apply_updates = yes/' /etc/dnf/automatic.conf
sed -i 's/upgrade_type = default/upgrade_type = security/' /etc/dnf/automatic.conf
systemctl enable --now dnf-automatic.timer
fi
echo "Security update completed."
包管理速查表
| 操作 | apt/dpkg | dnf/yum/rpm |
|---|---|---|
| 安装 | apt install pkg | dnf install pkg |
| 卸载 | apt remove pkg | dnf remove pkg |
| 卸载+配置 | apt purge pkg | dnf remove pkg |
| 更新索引 | apt update | dnf makecache |
| 升级包 | apt upgrade pkg | dnf update pkg |
| 升级全部 | apt full-upgrade | dnf update |
| 搜索 | apt search keyword | dnf search keyword |
| 包信息 | apt show pkg | dnf info pkg |
| 已安装列表 | apt list --installed | dnf list installed |
| 查找文件 | dpkg -S file | rpm -qf file / dnf provides file |
| 包文件列表 | dpkg -L pkg | rpm -ql pkg |
| 安装本地包 | dpkg -i pkg.deb | dnf localinstall pkg.rpm |
| 查看依赖 | apt depends pkg | dnf repoquery --requires pkg |
| 反向依赖 | apt rdepends pkg | dnf repoquery --whatrequires pkg |
| 锁定版本 | apt-mark hold pkg | dnf versionlock add pkg |
| 操作历史 | cat /var/log/dpkg.log | dnf history |
| 清理缓存 | apt clean | dnf clean all |
总结
Linux 包管理是系统运维的基础技能,两大体系各有特点但概念相通。核心要点:
- apt/dpkg 和 dnf/rpm 是两套并行的体系:Debian 系用 apt,Red Hat 系用 dnf(yum 的继任者),底层分别用 dpkg 和 rpm。
- 优先使用高级前端:
apt/dnf处理依赖解析,dpkg/rpm只处理单个包。 - 仓库管理是运维核心:正确配置仓库源、GPG 密钥、优先级,是安全使用第三方软件的前提。
- 依赖解析理解
Depends/Requires:apt depends/dnf repoquery --requires查看依赖,apt why/dnf repoquery --whatrequires查看安装原因。 - 包构建要掌握目录结构和控制文件:deb 用
DEBIAN/control,rpm 用 spec 文件,维护脚本处理服务启停和权限设置。 - 版本锁定防止意外升级:
apt-mark hold/dnf versionlock锁定关键包,避免自动升级导致兼容性问题。 - 离线安装有多种方式:下载 deb/rpm 及依赖、创建本地仓库、使用 apt-mirror/reposync 镜像。
- 镜像源优化提升安装速度:使用国内镜像、配置缓存、选择最快镜像。
- 安全更新是运维基线:使用 unattended-upgrades/dnf-automatic 自动安装安全补丁。
- GPG 验证是安全基础:不要使用
--allow-unauthenticated/--nogpgcheck,确保包来源可信。
包管理的黄金法则:最小化安装,最大化控制。只安装需要的包,锁定关键包版本,定期清理不需要的依赖,保持系统干净可控。