跳转至

包管理系统

APT(Advanced Package Tool) 是 Debian 发行版最常用的包管理工具。其可以执行安装,卸载,更新,系统更新,校验与修复这些常见功能。

apt与dpkg

Debian 是一个基于二进制(而非源码)的发行版,其软件包格式为 .deb,这代表这是一个二进制包。

Debian 的初等包管理器是 dpkg,其负责管理包的安装,删除,查询,替换,校验。

dpkg 一般不会被直接使用。而是作为 apt 以及其他一些高等包管理器的后端使用

Debian 自带的高等包管理器是 APT,负责进行依赖解析与安装包下载,并且以最优的顺序调用 dpkg,其没有直接安装 .deb 包的能力。

Debian 下还有很多包管理软件,如 Synaptics、Aptitude,这里不一一详细展开。

常用操作

安装软件包

如果我们需要安装一个名称为 name 的包

1) 在手动下载 .deb 包后,使用 dpkg 直接安装 .deb 包:

dpkg -i <name_version.deb>

Obviously, i refers to install.

2) 使用 apt 安装软件包:

apt install <name>

如果 name 有未在系统上安装的依赖的话,那么第一个命令会失败(除非使用 --force 选项),第二个命令会下载对应的安装包及其依赖,并且进行安装。

卸载软件包

如果我们需要卸载一个名称为 name 的包

1) 使用 dpkg 直接卸载:

dpkg -r <name>

Obviously, r refers to remove.

2) 使用 apt 卸载:

apt remove <name>

Note

要是我安装了一个有很多依赖的包,那么我们卸载它时依赖不会同时被卸载。这样依赖会一直占据我们电脑里面的空间。而手动卸载依赖并不直观,还可能破坏其他包的依赖。那该咋办?

包和依赖的空间管理

针对这个问题,我们介绍apt的一个特性:

  1. 包和依赖的关系
    • 当你使用 APT 安装一个软件包时,这个包可能依赖其他包才能正常运行。APT 会自动下载并安装这些依赖包。然而,如果你之后卸载了这个软件包,APT 默认不会自动卸载它的依赖项,这些依赖项就会一直占据存储空间。
  2. Manual(手动)和 Automatic(自动)标记
    • Manual(手动):当你直接用 APT 安装一个包时,这个包会被标记为 manual,意思是你明确想要安装这个包。
    • Automatic(自动):当 APT 自动安装一个依赖包时,这个包会被标记为 automatic,意思是它只是作为依赖被安装的,而不是你直接需要的包。
  3. 为什么标记为 Automatic 的包可以被清理
    • 如果一个自动安装的依赖包没有被任何手动安装的包(或者这些手动安装的包的其他依赖项)需要,那么它就变得不再必要,可能只是在占用空间。
  4. apt autoremove 命令
    • apt autoremove 命令会自动卸载所有不再被任何手动安装的包依赖的自动安装包。这些包在系统中没有直接用途,卸载它们可以释放存储空间。

总结

  • 当你安装一个包时,它和它的依赖项会分别标记为 manual 和 automatic。
  • 随着时间的推移,某些自动安装的依赖项可能不再需要,apt autoremove 可以帮助你清理这些不再需要的自动安装的包,释放系统存储空间。这种标记机制可以帮助你自动管理系统中的依赖包,并避免不必要的空间浪费。
Bash
1
2
3
4
5
6
7
8
9
huluobo@ubuntu:/Users/huluobo$ apt autoremove
E: Could not open lock file /var/lib/dpkg/lock-frontend - open (13: Permission denied)
E: Unable to acquire the dpkg frontend lock (/var/lib/dpkg/lock-frontend), are you root?

huluobo@ubuntu:/Users/huluobo$ sudo apt autoremove
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
0 upgraded, 0 newly installed, 0 to remove and 287 not upgraded.

上述实例说明:

  1. 权限问题已通过使用 sudo 解决。
  2. 当前没有不需要的自动安装包可供删除,系统已经是清理状态。如果你想进一步管理或更新系统,可以考虑运行 sudo apt upgrade 来升级那些未升级的包。

当我sudo apt upgrade时,再进行autoremove时,会提示:

Bash
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
huluobo@ubuntu:/Users/huluobo$ sudo apt autoremove
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following packages will be REMOVED:
  libgsasl7 libldap-2.5-0 libmailutils8 libpython3.10 libsigsegv2
0 upgraded, 0 newly installed, 5 to remove and 1 not upgraded.
After this operation, 8792 kB disk space will be freed.
Do you want to continue? [Y/n] y
(Reading database ... 159564 files and directories currently installed.)
Removing libmailutils8:arm64 (1:3.14-1) ...
Removing libgsasl7:arm64 (1.10.0-5) ...
Removing libldap-2.5-0:arm64 (2.5.16+dfsg-0ubuntu0.22.04.1) ...
Removing libpython3.10:arm64 (3.10.12-1~22.04.2) ...
Removing libsigsegv2:arm64 (2.14-1ubuntu1) ...
Processing triggers for libc-bin (2.37-0ubuntu2.2) ...

说明在升级后,有很多原本的依赖包并不再被需要了,因此它们就会被autoremove自动清除 :)

推荐与建议

安装软件包时,APT 在默认配置下会安装推荐(Recommended)的包。还会提示你可以安装建议(Suggested)的包以拓展原包的功能。

比如:apt 包的推荐有 ca-certificates,建议包有 aptitude、synaptic、gnupg、powermgmt-base 和 dpkg-dev。那么安装这个包时,会默认安装 ca-certificates,结束后会给出后面的包的提示。

为了精简安装的软件包,可以使用 --no-install-recommends 的选项,以跳过推荐的软件包。还可以在配置文件中添加 Apt::Install-Recommends "false" 以使默认配置不会安装推荐的包。

当这类包被安装的时候,它们的类型为 automatic,也就是说在默认情况下, 如果没有软件推荐或者建议它们,它们会被 apt autoremove 卸载。

使用 apt-mark (automatic|manual) <name> 修改包的状态。

查找包

apt search <name> 可以进行包的查找

1) 查找已安装并包含 "gcc" 的软件包

Bash
1
apt search ~i ~ngcc

解释

  • ~i:表示只查找已安装的包。
  • ~n:后跟 "gcc",表示查找包名中包含 "gcc" 的软件包。

结果:返回所有已安装的包,这些包的名称中包含 "gcc"。

2) 查找名称完全匹配 "gcc" 的已安装包

Bash
1
apt search ~i ?exact-name(gcc)

解释

  • ~i:表示只查找已安装的包。
  • ?exact-name(gcc):表示查找名称完全等于 "gcc" 的包。

结果:返回已安装的软件包中名称完全等于 "gcc" 的包。

  1. 查找可以升级的包
Bash
1
apt search ~U

解释

  • ~U:表示查找所有可以升级的包。

结果:列出所有当前系统中有可用更新的包。

4) 查找所有需要被自动移除的已安装包

Bash
1
apt search ~g

解释

  • ~g:表示查找那些标记为需要被 apt autoremove 移除的已安装包。

结果

  • 返回所有被标记为不再需要且可以通过 apt autoremove 命令移除的包。
  • 这个步骤建议在运行 apt autoremove 之前进行检查。

5) 查找已安装并且包名包含 "lib" 或者可以升级的包

Bash
1
apt search ~i ~nlib | ~U

解释

  • ~i:表示只查找已安装的包。
  • ~nlib:表示查找包名中包含 "lib" 的软件包。
  • |:表示 or 操作符,查找符合任意一个条件的包。
  • ~U:表示查找可以升级的包。

结果:返回已安装的包中包名包含 "lib" 的包,或者所有可以升级的包。

6) 查找已安装但包名不包含 "lib" 的包

Bash
1
apt search ~i !~nlib

解释

  • ~i:表示只查找已安装的包。
  • !:表示取反操作,即查找不满足条件的包。
  • ~nlib:表示包名中包含 "lib" 的包。

结果:返回所有已安装的包中,包名不包含 "lib" 的包。

常见的 apt-patterns 单位
  • 空格分隔 若干个 apt-patterns。
  • | 分隔若干个 apt-pattern。
  • ! 表示取反的简写。
  • ~g 为需要被 autoremove 的已安装包。在进行 autoremove 之前建议进行一次检查。
  • ~i 为已经安装的包。
  • ~U 可以升级的包。
  • ~nREGEX 包名称满足正则表达式的包。

apt 基本目录结构

apt 的工作依赖于一些文件,理解这些文件(与目录)的作用有助于更好的理解其工作原理

cd etc/apt

声明 apt 的软件源

/etc/apt/sources.list/etc/apt/sources.list.d/

这些文件声明 apt 的软件源,在进行 apt update 这类操作时,会从这些软件源下载 metadata 并且进行缓存。

这些 metadata 包括软件源里所有包的基本信息,例如包名称,每个包的依赖,推荐与建议包,开发者与维护者等等。

Bash
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
huluobo@ubuntu:/etc/apt$ ls
 apt.conf.d   auth.conf.d   keyrings   preferences.d   sources.list   sources.list.d   trusted.gpg.d
huluobo@ubuntu:/etc/apt$ cat sources.list
───────┬───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
        File: sources.list
───────┼───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
   1    deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports lunar main restricted universe multiverse
   2    deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports lunar-updates main restricted universe multiverse
   3    deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports lunar-security main restricted universe multiverse
   4    deb [arch=amd64] http://archive.ubuntu.com/ubuntu lunar main restricted universe multiverse
   5    deb [arch=amd64] http://archive.ubuntu.com/ubuntu lunar-updates main restricted universe multiverse
   6    deb [arch=amd64] http://archive.ubuntu.com/ubuntu lunar-security main restricted universe multiverse
───────┴───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
huluobo@ubuntu:/etc/apt$ cd sources.list.d
huluobo@ubuntu:/etc/apt/sources.list.d$ ls
 wireshark-dev-ubuntu-stable-jammy.list
huluobo@ubuntu:/etc/apt/sources.list.d$ cat wireshark-dev-ubuntu-stable-jammy.list
───────┬───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
        File: wireshark-dev-ubuntu-stable-jammy.list
───────┼───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
   1    deb https://ppa.launchpadcontent.net/wireshark-dev/stable/ubuntu/ jammy main
   2    # deb-src https://ppa.launchpadcontent.net/wireshark-dev/stable/ubuntu/ jammy main

apt的配置文件

/etc/apt/apt.conf/etc/apt/apt.conf.d/

这些文件是 apt(以及其拓展)使用的配置文件。

对于 apt.conf.d 里面的文件,其优先级由字典序决定。

一般在文件前添加数字代表优先级,数字更大者读取越靠后,因而优先级更高。(apt.conf 最后被读取,拥有最高的优先级)

apt.conf.d 目录中的文件设定为“数字更大者读取越靠后,因而优先级更高”的设计背后,有以下几点原因:

覆盖性配置

这里解释的是,为什么 “读取越靠后者优先级更高” 这个观点

配置文件的读取顺序决定了设置的优先级。如果先读取的配置文件中的某些设置在后续的配置文件中被再次定义,那么后读取的文件会覆盖前面的设置。通过让数字更大的文件被最后读取,可以确保这些文件中的设置能够覆盖之前的配置,从而实现预期的效果。

这种命名和优先级分配方式是一种通用的习惯用法,也在其他 Linux 配置目录中被广泛使用(如 /etc/rc.d/etc/cron.d 等)。这种标准化的做法简化了系统管理,使得管理员可以轻松理解和管理不同的配置文件。

/var/lib/

metadata 的储存位置

/var/lib/apt/lists

我们之前提到的 metadata 的储存位置。需要注意的是,metadata 不止和软件源包含什么有关。

我们可以使用 apt-cache 工具查询相关信息 (metadata-info)

???+ note"回顾apt清单"

Text Only
1
2
3
4
5
如果记不得apt内的清单文件,可以直接用下述指令回顾一下apt清单:

```sh
apt list
```

使用 apt-cache 查看软件包相关 metadata

Bash
1
apt-cache show <name>

形如这个例子,我们可以看一下metadeta的数据格式

Bash
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
huluobo@ubuntu:/etc/apt$ apt-cache show zynaddsubfx/lunar
Package: zynaddsubfx
Architecture: arm64
Version: 3.0.6-5
Priority: extra
Section: universe/sound
Origin: Ubuntu
Maintainer: Ubuntu Developers <[email protected]>
Original-Maintainer: Debian Multimedia Maintainers <[email protected]>
Bugs: https://bugs.launchpad.net/ubuntu/+filebug
Installed-Size: 3976
Depends: zynaddsubfx-data, libasound2 (>= 1.0.16), libc6 (>= 2.34), libfftw3-single3 (>= 3.3.5), libfltk1.3 (>= 1.3.4), libgcc-s1 (>= 3.3.1), libjack-jackd2-0 (>= 1.9.10+20150825) | libjack-0.125, liblo7 (>= 0.26~repack), libmxml1 (>= 3.3.1), libstdc++6 (>= 12.2.0-9ubuntu1), zlib1g (>= 1:1.1.4)
Filename: pool/universe/z/zynaddsubfx/zynaddsubfx_3.0.6-5_arm64.deb
Size: 1207896
MD5sum: 268b6f1d83b0b45b82c4ddcedac96ee9
SHA1: ba2331a747e159d67f2ecc8e68dc510cdbdf59a4
SHA256: e4a0bdaee5eb0616057992f2b536f93413fed6dff96f8e30e33d1aceb8578246
SHA512: deae408e534645afdabb078d655e91ebfd634757230fe741dc11e92bb69c0a16e423f40e82817cec3b9e5e5386c5c748e55ceb7473c36f915b06881bef8212db
Homepage: https://zynaddsubfx.sourceforge.io
Description-en: Realtime software synthesizer for Linux
 A real-time software synthesizer for Linux and Windows with many
 features, including polyphony, multi-timbral and microtonal
 capabilities. It includes randomness of some parameters, which
 makes warm sounds, like analogue synthesizers.
 It has system/insertion effects too, and much more.
Description-md5: 1db3b1a52de6b1c8b7af5c53feb77591
Task: ubuntustudio-audio

使用 apt-cache 查看软件包的依赖和反向依赖

Bash
1
2
apt-cache depends <name>
apt-cache rdepends <name>
Note

1) 依赖(Dependencies)

依赖是指某个软件包在运行或安装时所需要的其他软件包。如果一个软件包需要其他包来提供某些功能或库,那么这些包就是它的依赖项。没有这些依赖项,该软件包可能无法正常工作或根本无法安装。

举例:假设有一个软件包 A,它需要包 B 和 C 提供的功能才能正常运行。在这种情况下,包 B 和 C 是包 A 的依赖项。

2) 反向依赖(Reverse Dependencies)

反向依赖是指那些依赖于某个特定软件包的其他软件包。换句话说,如果某个软件包 B 是另一个软件包 A 的依赖项,那么 A 就是 B 的反向依赖。

举例:如果包 B 是包 A 的依赖项,那么包 A 就是包 B 的反向依赖。

依赖与反向依赖的重要性

  • 依赖:安装一个软件包时,包管理器会自动解析其依赖关系,确保所有依赖项都被正确安装,从而保证该软件包能正常工作。
  • 反向依赖:在卸载一个软件包时,了解它的反向依赖非常重要。如果其他软件包依赖于你想卸载的包,你可能需要谨慎处理,以免影响系统中的其他软件或功能。

形如这个例子,我们可以理解依赖与反向依赖

Bash
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
huluobo@ubuntu:/etc/apt$ apt-cache depends zynaddsubfx/lunar
zynaddsubfx
  Depends: zynaddsubfx-data
  Depends: libasound2
  Depends: libc6
  Depends: libfftw3-single3
  Depends: libfltk1.3
  Depends: libgcc-s1
 |Depends: libjack-jackd2-0
  Depends: <libjack-0.125>
    libjack-jackd2-0
    libjack0
  Depends: liblo7
  Depends: libmxml1
  Depends: libstdc++6
  Depends: zlib1g

huluobo@ubuntu:/etc/apt$ apt-cache rdepends zynaddsubfx/lunar
zynaddsubfx
Reverse Depends:
  multimedia-soundsynthesis
  zynaddsubfx-data

alt text

检查未被满足的依赖,用来修复一些依赖地狱问题

Bash
1
apt-cache unmet

dpkg 数据库

/var/lib/dpkg/available

dpkg 的 数据库,结构与 apt 相似,在现在随着 dpkg 本身的使用逐渐减少,已经基本停止使用。

dpkg 状态列表

/var/lib/dpkg/status

dpkg 的 状态列表,相较于纯粹的 metadata,其添加了优先级和状态,去除了校验值。

一般这里包含安装结束的包与部分安装的包。

所有包的管理相关信息

/var/lib/dpkg/info

所有包的管理相关信息,例如包内文件的 md5sum 值,库包的符号列表,安装和卸载时需要的额外操作等等。

记录已安装包的类型

/var/lib/apt/extended_states

记录已经安装的包的类型:自动安装或者手动安装的。

一般而言列表中的包都是自动安装的。

在进行 apt autoremove 时用于判定是否要卸载,如果一个包没有被其他手动安装的包(直接或间接)依赖并且是自动安装的,那么其会被移除。

通过 apt-mark auto <name>apt-mark manual <name> 进行修改。

Bash
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
Package: systemd-hwe-hwdb
   2    Architecture: arm64
   3    Auto-Installed: 1
   4      5    Package: language-pack-en-base
   6    Architecture: arm64
   7    Auto-Installed: 1
   8      9    Package: libxmuu1
  10    Architecture: arm64
  11    Auto-Installed: 1

  ......

apt 优先级配置文件

/etc/apt/preferences/etc/apt/preferences.d/

apt 优先级的配置文件

apt 在遇到相同软件包时,会选择优先级最高的安装包进行安装。在拥有相同优先级的情况下,会选择最高版本安装。

使用源码重编译包

软件源

软件包构建