压缩打包与包管理

前半部分是打包、压缩和同步文件——tar 的几十个参数其实只需要记住五六个组合;后半部分把 apt、dnf、pacman 的常用操作放在一张对照表里,在哪种发行版上都不会卡住。

共 31 条命令 · 最近更新

tar:打包与解包

tar 的参数可以不带横杠(tar czf 也合法)。记住五个字母:c 创建、x 解包、t 列出、z 走 gzip、f 指定文件名——f 必须紧跟文件名,放最后最安全。

tar -czf

创建 gzip 压缩的 tar 包,最通用的打包方式。-v 显示进度,-C 先切换目录再打包(避免包内出现多余的路径层级),--exclude 排除路径。

tar -czf backup.tar.gz /var/www
tar -czvf site.tar.gz -C /var/www site
tar -czf app.tar.gz --exclude='*.log' --exclude='node_modules' /srv/app

打包时尽量用 -C 进到目标目录再打包,避免解开时把文件散到当前目录或者带上 /var/www 这样的绝对路径。

tar -xzf

改文件

解压 gzip 压缩的 tar 包,并自动还原目录结构。-C 指定解压到的目录,--strip-components=N 去掉包内前 N 层目录,-v 显示进度。

tar -xzf app.tar.gz -C /srv/
tar -xzf pkg.tar.gz --strip-components=1 -C /srv/app
tar -tzf app.tar.gz | head -20

解压前先用 -t 看一眼包内结构,是避免「解出来一堆文件摊在当前目录」的最简单办法。

其它压缩格式的 tar

tar 本身只管打包,压缩交给后面的程序:z 是 gzip、j 是 bzip2、J 是 xz、--zstd 是 zstd。新版本 GNU tar 也能用 -a 让文件名自动决定压缩方式。

tar -cjf data.tar.bz2 /data
tar -cJf data.tar.xz /data
tar --zstd -cf data.tar.zst /data
tar -caf data.tar.zst /data

压缩率大致是 zstd < gzip < bzip2 < xz,速度大致反过来。日常备份用 gzip 或 zstd(快),冷归档用 xz(小)。

gz / xz / zstd 单文件压缩

gzip、xz、zstd 直接压缩单个文件并默认替换原文件;-k 保留原文件,-d 解压,-9 最高压缩等级,-T0(xz / zstd)用满所有 CPU 核并行压缩。

gzip -k access.log
xz -9 -T0 -k bigfile.iso
zstd -19 -T0 -k dump.sql
zstd -d dump.sql.zst

zstd 在压缩率接近 xz 的情况下快好几倍,且支持多线程,现在已经是很值得默认使用的选择。

zip / unzip

zip 格式在和 Windows、macOS 交换文件时最省事。-r 递归打包目录,-9 最高压缩率,-x 排除;unzip -l 先列内容,-d 指定解压目录,-o 覆盖不询问。

zip -r site.zip site -x '*.git*'
unzip -l site.zip
unzip -o site.zip -d /tmp/site

解压 Windows 传来的中文文件名压缩包出现乱码时,用 unzip -O cp936 site.zip(需要 unzip 支持 -O,部分构建不带)。

7z

p7zip 提供的高压缩率工具,支持多种格式。a 添加、x 解压(保留路径)、e 解压(不保留路径)、l 列表、t 测试。-p 指定密码。

7z a -t7z -mx=9 backup.7z /data
7z l backup.7z | head
7z x backup.7z -o/tmp/out

rsync

增量同步文件,只传变化的部分,是备份和发布最常用的工具。-a 归档(等于 -rlptgoD),-v 详细,-z 传输压缩,-P 显示进度并支持续传,--delete 删除目标端多余文件,--exclude 排除,--dry-run 只演练不实际执行。

rsync -avP /data/ /backup/data/
rsync -avz --delete --exclude '.git' /srv/app/ deploy@web1:/srv/app/
rsync -avn --delete /data/ /backup/data/
rsync -av -e 'ssh -p 2222' /data/ host:/data/

源路径末尾有斜杠表示「同步目录里的内容」,没有斜杠表示「同步这个目录本身」——这一条差异造成的文件层级错位非常常见。

rsync 的 --delete 与限速

危险

--delete 让目标端与源端严格一致(会删掉目标端多出来的文件),--bwlimit 限制带宽(单位 KB/s),--exclude-from 从文件读排除规则,-h 人类可读,--info=progress2 显示整体进度。

rsync -av --delete --bwlimit=5000 /data/ /backup/data/
rsync -av --exclude-from=/etc/rsync.exclude /www/ /backup/www/
rsync -av --info=progress2 /data/ /backup/data/

带 --delete 的命令一定要先加 -n(--dry-run)看一遍它会删什么,尤其在源端挂载失败变成空目录的时候——那会删光整个目标端。

scp / sftp

scp 在主机之间复制文件(-r 递归,-P 指定端口,注意是大写 P);sftp 提供交互式传输和断点续传,适合传大文件。

scp -P 2222 app.tar.gz deploy@web1:/tmp/
scp -r deploy@web1:/var/log/app /tmp/logs
sftp deploy@web1

新版 OpenSSH 的 scp 底层改用 SFTP 协议,通配符语义和老的 scp(基于 SCP 协议)略有不同;大量小文件传输还是 rsync 更合适。

sha256sum / gpg 校验

下载完安装包先校验再使用。sha256sum -c 校验清单文件,gpg --verify 校验签名(更严格,能防篡改)。

sha256sum -c SHA256SUMS
gpg --verify app.tar.gz.asc app.tar.gz

包管理三巨头对照

三套工具的语义其实一一对应,先把这张表看一遍,再去看具体命令就很快了。

apt / dnf / pacman 常用操作对照
操作Debian / Ubuntu(apt)RHEL / Fedora(dnf)Arch(pacman)
刷新索引apt updatednf check-updatepacman -Sy
安装包apt install nginxdnf install nginxpacman -S nginx
删除包apt remove nginx
(--purge 连配置一起删)
dnf remove nginxpacman -Rns nginx
升级全部apt upgrade
(full-upgrade 允许删包)
dnf upgradepacman -Syu
搜索apt search 关键词dnf search 关键词pacman -Ss 关键词
查看包信息apt show nginxdnf info nginxpacman -Si nginx
这个文件属于哪个包dpkg -S /usr/sbin/nginxrpm -qf /usr/sbin/nginxpacman -Qo /usr/bin/nginx
包安装了哪些文件dpkg -L nginxrpm -ql nginxpacman -Ql nginx
列出已安装apt list --installeddnf list installedpacman -Q
清理缓存apt clean / apt autocleandnf clean allpacman -Sc
谁提供了这个命令apt-file search bin/foo
(需先安装 apt-file)
dnf provides '*/bin/foo'pkgfile foo
(需先安装 pkgfile)
操作历史 / 回滚less /var/log/apt/history.logdnf history / dnf history undo Nless /var/log/pacman.log

apt / dpkg(Debian、Ubuntu)

apt 是前端,dpkg 是底层。日常用 apt,需要查文件归属或装本地 deb 包时才用 dpkg。

apt update / upgrade

update 只刷新软件包索引,不安装任何东西;upgrade 按索引升级已安装的包但不会删除现有包;full-upgrade 允许为满足依赖而安装或删除包(内核升级通常需要它)。

sudo apt update
sudo apt upgrade -y
sudo apt full-upgrade
sudo apt list --upgradable

生产环境升级前先 apt list --upgradable 看清楚要升什么;内核和安全相关的升级最好安排在维护窗口里。

apt install / remove / purge

install 安装(可一次装多个),remove 卸载但保留配置,purge 连配置文件一起删,autoremove 清理不再被依赖的孤立包。--no-install-recommends 只装必需依赖。

sudo apt install -y nginx curl git
sudo apt install --no-install-recommends nginx
sudo apt remove nginx
sudo apt purge nginx && sudo apt autoremove --purge

purge 之后再重装会回到默认配置;如果只是想要干净重装,先备份 /etc/nginx 之类的配置目录。

apt search / show / policy

search 按名称和描述搜索,show 看包的版本、依赖、体积和描述,policy 显示候选版本以及它来自哪个源——排查「为什么装到的是旧版本」时最关键。

apt search nginx | head -20
apt show nginx
apt-cache policy nginx
apt list --installed | grep nginx

同一个包在多个源里存在时,apt 按优先级挑选;policy 输出的优先级数字和来源能直接解释版本差异。

dpkg 查询

-l 列出已安装(-l 模式),-L 列出某包安装的文件,-S 反查文件属于哪个包,-s 查看包状态,-i 安装本地 deb 文件。

dpkg -l | grep nginx
dpkg -L nginx | head -20
dpkg -S /usr/sbin/nginx
sudo dpkg -i ./app_1.0_amd64.deb

dpkg -i 不会自动解决依赖,装完报依赖错误时跑 sudo apt -f install 让它补齐。

添加第三方源

add-apt-repository 添加 PPA 或第三方源(Ubuntu 需要 software-properties-common)。现代做法是把源的 keyring 放进 /etc/apt/keyrings,而不是用已废弃的 apt-key。

sudo add-apt-repository ppa:ondrej/php
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://example.com/key.gpg | sudo gpg --dearmor -o /etc/apt/keyrings/example.gpg
echo 'deb [signed-by=/etc/apt/keyrings/example.gpg] https://example.com/apt stable main' | sudo tee /etc/apt/sources.list.d/example.list

apt-key 已经废弃,现在的正确做法是 signed-by 指向 keyring 文件,这样密钥只对该源生效。

apt-mark hold / unhold

把某个包标记为「保持当前版本」,升级时不再动它。排查「某个包为什么一直不升级」时先看 apt-mark showhold。

sudo apt-mark hold nginx
apt-mark showhold
sudo apt-mark unhold nginx

dnf / yum(RHEL、CentOS、Fedora)

yum 在 RHEL 8 之后已经是 dnf 的软链接;新系统直接用 dnf。

dnf install / remove / upgrade

install 安装,remove 卸载(会连带删除依赖它的包,执行前 dnf 会列出将要删除的清单),upgrade 升级全部,--refresh 强制刷新元数据。

sudo dnf install -y nginx
sudo dnf remove nginx
sudo dnf upgrade --refresh
sudo dnf check-update

dnf remove 会级联删除依赖被删包的其它软件,输出里的清单一定要看一眼再确认。

dnf search / info / provides

search 搜索,info 查看详情,provides 查找哪个包提供了某个文件或命令(写 '*/bin/foo' 这种通配形式更准),list 列出可用或已安装的包。

dnf search nginx
dnf info nginx
dnf provides '*/sbin/nginx'
dnf list installed | grep nginx

dnf history / undo

dnf 会记录每一次事务。history 列出历史,history info N 看某次详情,history undo N 回滚该次操作(依赖关系复杂时可能无法回滚)。

dnf history
sudo dnf history info 42
sudo dnf history undo 42

undo 是尽力而为:如果系统状态在之后再变过,回滚可能失败或需要手动处理冲突。

rpm 查询

-qa 列出全部已安装包,-ql 列出某包的文件,-qf 反查文件归属,-qi 查看包信息,-q --changelog 看更新日志,-V 校验文件是否被改动过。

rpm -qa | grep nginx
rpm -ql nginx | head -20
rpm -qf /usr/sbin/nginx
rpm -V nginx

rpm -V 输出里的标记含义:S 大小变化、M 权限或类型变化、5 校验和不一致、T 时间戳变化。文件名前面带 c 表示它是配置文件。

添加仓库 / dnf config-manager

dnf config-manager --add-repo 添加第三方仓库(新版用 --add-repo=URL),--set-enabled / --set-disabled 启停仓库,repoquery -l 在不安装的情况下列出包内容。

sudo dnf config-manager --add-repo=https://example.com/repo.repo
sudo dnf config-manager --set-enabled epel
dnf repolist --all
dnf repoquery -l nginx | head

dnf module

RHEL 8+ 用模块流管理同一软件的多个版本(比如 PHP 8.1 / 8.2 / 8.3)。module list 查看,module enable / install 指定流,module reset 回到默认。

dnf module list php
sudo dnf module reset php
sudo dnf module enable php:8.2

切换模块流通常需要先 reset 再 enable,直接 enable 别的流会报冲突;切换后建议把相关包重装一遍。

pacman(Arch、Manjaro)

pacman 的参数是「大写操作 + 小写修饰」的组合:-S 同步安装、-R 删除、-Q 查询、-y 刷新、-u 升级。

pacman -S / -Syu

-S 安装,-Sy 只刷新索引,-Su 升级已安装的包,-Syu 是「刷新索引并升级全部」,这是 Arch 的标准升级命令。--noconfirm 跳过确认,--needed 已是最新就不重装。

sudo pacman -Syu
sudo pacman -S nginx vim git
sudo pacman -S --needed base-devel
sudo pacman -Ss nginx

Arch 不支持部分升级:不要长期只跑 -Sy 而不升级,也不要在同一个系统里长时间不升级后一次性大升级(官方建议看到更新就升)。

pacman -R / -Rns

-R 只删包,-Rs 连不再需要的依赖一起删,-Rn 连配置备份文件一起删,-Rns 是「彻底删干净」的推荐组合。

sudo pacman -R nginx
sudo pacman -Rns nginx
pacman -Qdt          # 列出孤立依赖
sudo pacman -Rns $(pacman -Qdtq)

pacman -Qdt 会列出曾经作为依赖安装、现在没人需要的包;一次性删掉它们能保持系统干净。

pacman -Q 查询

-Q 列出已安装,-Qs 在已安装里搜索,-Qi 查看包信息,-Ql 列出包内文件,-Qo 反查文件归属,-Qe 只看显式安装的包,-Qm 只看来自 AUR 的包。

pacman -Qs nginx
pacman -Qo /usr/bin/nginx
pacman -Ql nginx | head -20
pacman -Qm

pacman 缓存与文件数据库

pacman -Sc 清理旧版本的包缓存(-Scc 清空全部),pacman -Fy 更新文件数据库,pacman -F 查找文件属于哪个(未安装的)包。

sudo pacman -Sc
sudo pacman -Fy
pacman -F nginx.conf

缓存目录是 /var/cache/pacman/pkg;保留几个旧版本可以在升级出问题时降级(pacman -U 旧包文件),所以不要总是清空。

yay / paru(AUR)

AUR 是社区维护的软件包构建脚本仓库,需要用 AUR helper 来使用。yay -S 安装,-Ss 搜索,-Syu 同时升级官方源与 AUR 包。

yay -Ss 关键词
yay -S package-name
yay -Syu

AUR 里的包由社区维护,安装前最好看一眼 PKGBUILD 的内容——它是会在你机器上执行的构建脚本。

zypper(openSUSE)

openSUSE 系的包管理器,操作语义同样能对应上:refresh 刷新、install / remove 装卸、update 升级、search 搜索、info 详情、what-provides 反查文件、dup 是发行版级升级。

sudo zypper refresh
sudo zypper install nginx
zypper search --installed-only nginx
zypper what-provides /usr/sbin/nginx

源码安装与容器镜像

包管理器里没有的软件,才考虑源码编译;能进容器就别往宿主机里装。

configure / make / make install

经典三步。./configure --prefix=/usr/local/xxx 检查依赖并生成 Makefile,make 编译,sudo make install 安装。--prefix 一定要指定,装到 /usr/local 之外的地方便于以后卸载。

./configure --prefix=/usr/local/myapp --with-openssl
make -j$(nproc)
sudo make install
sudo make uninstall    # 只有 Makefile 支持时才有效

make install 不会登记到包管理器数据库里,以后升级或卸载都要手动处理。更推荐用 checkinstall 打成系统包,或者直接做成容器镜像。

编译依赖(-dev / -devel)

编译时报 fatal error: xxx.h: No such file or directory,缺的是开发包:Debian 上是 libssl-dev,RHEL 上是 openssl-devel。用 pkg-config 查询编译参数。

sudo apt install build-essential libssl-dev
sudo dnf install gcc make openssl-devel
pkg-config --cflags --libs openssl

报错信息里的头文件名和需要的开发包名通常不完全一样,用 apt-file search 或 dnf provides '*/xxx.h' 反查最可靠。

容器镜像相关命令

docker / podman 的基本操作:拉取镜像、运行、进容器、看日志。把服务跑在容器里可以避免污染宿主机,也不需要为它单独维护包。

docker pull nginx:1.27-alpine
docker run -d --name web -p 8080:80 -v /srv/site:/usr/share/nginx/html:ro nginx:1.27-alpine
docker exec -it web sh
docker logs -f --tail 100 web

podman 的命令与 docker 基本一致,但默认无守护进程、支持 rootless,服务器上更推荐。