# apt

> APT - Advanced Packaging Tool

### apt 包管理工具简介展开目录

Advanced Packaging Tool（apt）是 Linux 下的一款安装包管理工具，是一个客户 / 服务器系统。

最初只有.tar.gz 的打包文件，用户必须编译每个他想在 GNU/Linux 上运行的软件。用户们普遍认为系统很有必要提供一种方法来管理这些安装在机器上的软件包，当 Debian 诞生时，这样一个管理工具也就应运而生，它被命名为 dpkg。从而著名的 “package” 概念第一次出现在 GNU/Linux 系统中，稍后 Red Hat 才决定开发自己的 “rpm” 包管理系统。

很快一个新的问题难倒了 GNU/Linux 制作者，他们需要一个快速、实用、高效的方法来安装软件包，当软件包更新时，这个工具应该能自动管理关联文件和维护已有配置文件。Debian 再次率先解决了这个问题，APT (Advanced Packaging Tool）作为 dpkg 的前端诞生了。APT 后来还被 Conectiva 改造用来管理 rpm，并被其它 Linux 发行版本采用为它们的软件包管理工具。

APT 由几个名字以 `apt-` 打头的程序组成。apt-get、apt-cache 和 apt-cdrom 是处理软件包的命令行工具。

Linux 命令 `apt`，也是其它用户前台程序的后端，如 dselect 和 aptitude。

### apt-get 工作原理展开目录

#### 关于 /etc/apt/sources.list展开目录

**/etc/apt/sources.list 作用展开目录**

Ubuntu 采用集中式的软件仓库机制，将各式各样的软件包分门别类地存放在软件仓库中，进行有效地组织和管理。然后，将软件仓库置于许许多多的镜像服务器中，并保持基本一致。

这样，所有的 Ubuntu 用户随时都能获得最新版本的安装软件包。因此，对于用户，这些镜像服务器就是他们的软件源（Reposity）。

然而，由于每位用户所处的网络环境不同，不可能随意地访问各镜像站点。为了能够有选择地访问，在 Ubuntu 系统中，使用软件源配置文件 /etc/apt/sources.list 列出最合适访问的镜像站点地址。

**/etc/apt/sources.list 格式展开目录**

以下面这个文件中的内容为例子：

```
deb http://mirrors.163.com/debian/ wheezy main non-free contrib
deb http://mirrors.163.com/debian/ wheezy-proposed-updates main non-free contrib
deb-src http://mirrors.163.com/debian/ wheezy main non-free contrib
deb-src http://mirrors.163.com/debian/ wheezy-proposed-updates main non-free contrib
```

其中可以把每一行分为四个部分，当你在线更新某个软件时，debian 就是遵照这四个选项（准确的说是后三项）的指示找到软件来给你安装的：

```
deb    ###   URI地址                         ###  版本代号   ###  限定词
deb    ###   http://mirrors.163.com/debian/ ###  wheezy    ###   main non-free contrib
```

1. 第一部分（Archive type）：获取的软件包类型\
   deb 或 deb-src 分别表示直接通过.deb 文件或源文件的方式进行安装
2. 第二部分：仓库地址（Repository URL）软件包所在仓库的地址，即 URI
3. 第三部分：发行版（Distribution）

* 发行版有两种分类方法：一类是发行版的具体代号，如 xenial, trusty, precise 等；\
  还有一类则是发行版的发行类型，如 oldstable, stable, testing 和 unstable。另外，在发行版后还可能有进一步的指定，如 xenial-updates, trusty-security, stable-backports 等。

参看 [http://mirrors.163.com/debian/dists/](http://mirrors.163.com/debian/dists/) 网页里面的内容:\
![1.jpg](https://attacker.cc/usr/uploads/2018/03/1609584403.jpg)

* oldstable 顾名思义，就是以前的稳定发行版了，在本例中 oldstable 就是 Debian6.0.8 目录的一个链接，两者内容完全一致。
* stable 是指现在的稳定发行版，对于每个 debian 来说，每个稳定发行版都会有一个代号，
  * 如 debian 6 叫做 squeeze，debian 7 叫做 wheezy，由于在笔者写本文的时候稳定版是 debian7，所以 stable 就是 wheezy 的一个链接。
* testing 指目前还暂时处于测试阶段的 debian 发行版，如 wheezy 往下发展就是 jessie 了，所以 testing 代指的就是 jessie 目录，它是 jessie 的一个链接。
* unstable 那就是不稳定版本了，但在这个目录清单里我们并没有看到 unstable 目录，其实它还有一个代号：sid，我们知道 debian 的发行版本名称大都来自玩具总动员中的角色名称，而 sid 就是那个专门破坏玩具的邻居家坏小孩，所以就把 unstable 这个不稳定的软件目录起名为 sid 了，这里面的软件一般都是最新的，稳定性、安全稳定值得商榷，如果你想做试验小白鼠，大可使用这里的软件。经过一段时间的测试，这里面的软件可能会进入下一个阶段 testing 目录从而出现在下一个 debian 发行版中，要么就夭折被直接抛弃了。

1. 第四部分：软件包分类 (Component)\
   跟在发行版之后的就是软件包的具体分类了，可以有一个或**多个**。

**Debian**

| 分类名称     | 类型含义                                                                  |
| -------- | --------------------------------------------------------------------- |
| main     | 包含符合 DFSG 指导原则的自由软件包，而且这些软件包不依赖不符合该指导原则的软件包。 这些软件包被视为 Debian 发型版的一部分。 |
| contrib  | 包含符合 DFSG 指导原则的自由软件包，不过这些软件包依赖不在 main 分类中的软件包。                        |
| non-free | 包含不符合 DFSG 指导原则的非自由软件包。                                               |

**Ubuntu**

| 分类名称       | 类型含义          |
| ---------- | ------------- |
| main       | 官方支持的自由软件     |
| restricted | 官方支持的非完全自由的软件 |
| universe   | 社区维护的自由软件     |
| multiverse | 非自由软件         |

#### apt-get update 工作原理展开目录

无论用户使用哪些手段配置 APT 软件源，只是修改了配置文件 `/etc/apt/sources.list`，目的只是告知软件源镜像站点的地址。但那些所指向的镜像站点所具有的软件资源并不清楚，需要将这些资源列个清单，以便本地主机知晓可以申请哪些资源。

用户可以使用 `apt-get update` 命令刷新软件源，建立更新软件包列表。

在 Ubuntu Linux 中，`apt-get update` 命令会扫描每一个软件源服务器，并为该服务器所具有软件包资源建立索引文件，存放在本地的 `/var/lib/apt/lists/` 目录中。

使用 apt-get 执行安装、更新操作时，都将依据这些索引文件，向软件源服务器申请资源。

因此，在计算机设备空闲时，经常使用该命令刷新软件源，是一个好的习惯。

#### apt-get install 工作流程展开目录

1. 扫描本地存放的软件包更新列表（由 “apt-get update” 命令刷新更新列表，也就是 /var/lib/apt/lists/），找到最新版本的软件包
2. 第二步，进行软件包依赖关系检查，找到支持该软件正常运行的所有软件包
3. 第三步，从软件源所指的镜像站点中，下载相关软件包
4. 第四步，解压软件包，并自动完成应用程序的安装和配置。

### 常见使用方式展开目录

```bash
apt-cache search package 搜索包
apt-cache show package 获取包的相关信息，如说明、大小、版本等
apt-get install package 安装包
apt-get install package - - reinstall 重新安装包
apt-get -f install 修复安装"-f = ——fix-missing"
apt-get remove package 删除包
apt-get remove package - - purge 删除包，包括删除配置文件等
apt-get update 更新源
apt-get upgrade 更新已安装的包
apt-get dist-upgrade 升级系统
apt-get dselect-upgrade 使用 dselect 升级
apt-cache depends package 了解使用依赖
apt-cache rdepends package 是查看该包被哪些包依赖
apt-get build-dep package 安装相关的编译环境
apt-get source package 下载该包的源代码
apt-get clean && apt-get autoclean 清理无用的包
apt-get check 检查是否有损坏的依赖
```

### Troubleshooting & Suggestions展开目录

1. 一般不建议混用 stable, testing 和 unstable 的源。\
   因为很多软件之间都有不同程度的相依性，强行的结果会造成更多软件相依、相斥问题的产生，最终可能影响系统稳定与整个软件升级制度的正常运作。

### 参考链接展开目录

1. [ubuntu APT-GET 工作原理](https://www.cnblogs.com/cyl2008/p/6417443.html)
2. [debian 软件源 source.list 文件格式说明](https://www.cnblogs.com/beanmoon/p/3387652.html)
3. [/etc/apt/sources.list 详解](https://zzz.buzz/zh/2016/03/09/etc-apt-sources-list/)

软件安装方法历程图

![](https://notes.xiechengqi.top/Linux/images/%E8%BD%AF%E4%BB%B6%E5%AE%89%E8%A3%85%E6%96%B9%E6%B3%95%E5%8E%86%E7%A8%8B.jpg)

`/etc/apt/sources.list` 只会告知系统可以访问的镜像站点地址，这时每当系统执行一次 `sudo apt install xxx` 都要链接镜像站检索出对应的软件地址，这样是很浪费时间的，所以在本地 `/var/lib/apt/lists/` 会缓存一份镜像站里的所有软件源信息，这样每次执行 `sudo apt install xxx` 直接在本地缓冲里检索，在连接网络下载文件。所以 `sudo apt install` 会先访问 `/var/lib/apt/lists/`；而且 `sudo apt update` 更新的是 `/var/lib/apt/lists/` 里的软件源

每当执行命令进行软件的安装或着更新，或者软件源的更新时，apt 会访问 `/etc/apt/sources.list` 内的地址，并在该网站中找到对应系统的包信息例如我的操作系统是 ubuntu，网站是 `deb http://mirrors.163.com/ubuntu/ precise main restricted universe multiverse` 网易的，那么当我们执行安装的命令时，他就会对应的访问 `http://mirrors.163.com/ubuntu/dists/lucid/main/binary-i386/` 的 `packages.gz`，这个文件是服务器上软件包及其依赖关系的清单，并且用 `gzip` 压缩过了。`apt-get update`使用这个清单来确定能够获得哪些补充的软件包且他的内容会被保存在 `/var/lib/apt/lists` 内，通过访问这个 lists 确定该软件是否已安装，是否是最新版本，依赖关系是否满足，从而确定要更新内容，并进行更新，其安装过程主要是由 dpkg 来完成

### 一、 背景知识 <a href="#yi-bei-jing-zhi-shi" id="yi-bei-jing-zhi-shi"></a>

#### 1. PPA 源 - Personal Package Archives - 个人软件包集 <a href="#id-1ppa-yuan-personalpackagearchives-ge-ren-ruan-jian-bao-ji" id="id-1ppa-yuan-personalpackagearchives-ge-ren-ruan-jian-bao-ji"></a>

> 源和软件仓库实际上是一个意思，厂商将编译后的二进制文件和软件信息存放至服务器，用户需要安装软件时，包管理器自动分析本机和容器（repository）内的信息，下载需要的包并自动安装，安装后将新安装的软件信息存放至本地

*   添加、删除 PPA 软件源

    ```
    # 添加 PPA 软件源的命令
    $ sudo add-apt-repository ppa:user/ppa-name
    # 删除 PPA 软件源的命令
    $ sudo add-apt-repository --remove ppa:user/ppa-name
    ```

    例如，我们想要添加一个 Wireshark 软件的 PPA 源，我们可以根据它官网上提供的命令来进行添加，如下图所示：

当我们添加完 PPA 源之后，系统就会在 `/etc/apt/sources.list.d/` 文件夹里创建了两个文件，一个 `.list` 文件和一个带有 `.save` 后缀的备份文件：

```
$ cd /etc/apt/sources.list.d
$ ls | grep wireshark
wireshark-dev-stable-trusty.list
wireshark-dev-stable-trusty.list.save
```

我们再来打开一下 `wireshark-dev-stable-trusty.list` 文件看看里面的内容是什么：

```
deb http://ppa.launchpad.net/wireshark-dev/stable/ubuntu trusty main
# deb-src http://ppa.launchpad.net/wireshark-dev/stable/ubuntu trusty main
```

原来文件里就是添加了一个跟软件源一模一样的东西，他们的作用殊途同归啊。我想这其实是 Ubuntu 为了分辨官方的源和第三方的源才设计成在 `sources.list` 和 `sources.list.d/` 这两个地方中存储软件源信息。因为第三方的源毕竟不太可信，如果随便更新的话可是会出事情的。

#### 2. `deb http://site.example.com/debian distribution component` 格式详解 <a href="#id-2debhttpsiteexamplecomdebiandistributioncomponent-ge-shi-xiang-jie" id="id-2debhttpsiteexamplecomdebiandistributioncomponent-ge-shi-xiang-jie"></a>

```
deb http://site.example.com/debian distribution component1 component2 component3
deb-src http://site.example.com/debian distribution component1 component2 component3
# 例如
deb http://mirrors.aliyun.com/ubuntu/ bionic main restricted
deb-src http://mirrors.aliyun.com/ubuntu/ bionic restricted universe multiverse main
```

1. 档案类型 - Archive type
2. 条目的第一个词 deb 或是 deb-src 表明了所获取的软件包档案类型
   * deb - 档案类型为二进制预编译软件包，一般我们所用的档案类型
   * deb-src - 档案类型为用于编译二进制软件包的源代码

> 每行的第一个单词 deb 或 deb-src，描述了文件类型，目录中包含的是二进制软件包（ deb ），即我们通常使用的已编译好的软件包；或包含的是源码包（ deb-src ），源码包包含源程序编码、Debian 管理文件（ .dsc ）和 “Debian 化” 该程序所做更改的记录文件 diff.gz

1. 仓库地址 - Repository URL
2. 条目的第二个词则是软件包所在仓库的地址，我们可以更换仓库地址为其他地理位置更靠近自己的镜像来提高下载速度
   * Ubuntu 软件源的源列表：[国内开源镜像站点汇总](https://segmentfault.com/a/1190000000375848)
3. 仓库地址可以是多种类型：http、ftp、file（ 本地文件，例如：一个加载了 ISO9600 文件系统的目录 ） 或 ssh
4. 发行版 - Distribution
5. 跟在仓库地址后的是发行版。发行版有两种分类方法
   * 一类是发行版的具体代号，如 xenial,trusty, precise 等
   * 另一类则是发行版的发行类型，如 oldstable, stable, testing 和 unstable
6. 另外，在发行版后还可能有进一步的指定，如 xenial-updates, trusty-security, stable-backports 等

> * 可以通过命令 `lsb_release -cs`,查看当前操作系统代号, 例如 Ubuntu 16.04 LTS 代号为 xenial, Ubuntu 18.04 LTS 代号为 bionic

```
$ lsb_release -ca
No LSB modules are available.
Distributor ID:    Ubuntu
Description:    Ubuntu 18.04.3 LTS
Release:    18.04
Codename:    bionic
```

1. 软件包分类 - Component
2. 跟在发行版之后的就是软件包的具体分类了，可以有一个或多个。不同的 Linux 发行版对软件有着不同的分类

**Debian**

* main
  * 包含符合 DFSG 指导原则的自由软件包，而且这些软件包不依赖不符合该指导原则的软件包。这些软件包被视为 Debian 发型版的一部分
* contrib
  * 包含符合 DFSG 指导原则的自由软件包，不过这些软件包依赖不在 main 分类中的软件包
* non-free
  * 包含不符合 DFSG 指导原则的非自由软件包

**Ubuntu**

* main
  * 官方支持的自由软件
* restricted
  * 官方支持的非完全自由的软件
* universe
  * 社区维护的自由软件
* multiverse
  * 非自由软件

| Ubuntu | 自由软件     | 非自由软件      |
| ------ | -------- | ---------- |
| 官方支持   | Main     | Restricted |
| 非官方支持  | Universe | Multiverse |

### 二、 apt 基本命令 <a href="#er-apt-ji-ben-ming-ling" id="er-apt-ji-ben-ming-ling"></a>

* **`apt [选项] 命令`**
* **`[选项]`**
  * `list` - 根据名称列出软件包
  * `search` - 搜索软件包描述
  * `show` - 显示软件包细节
  * `install` - 安装软件包
  * `remove` - 移除软件包
  * `autoremove` - 卸载所有自动安装且不再使用的软件
  * `update` - 根据 `/etc/apt/sources.list` 更新 `/var/lib/apt/lists` 软件包列表
  * `upgrade` - 根据 `/var/lib/apt/lists` 安装/升级 软件来更新系统
  * `full-upgrade` - 通过 卸载/安装/升级 来更新系统
  * `edit-sources` - 编辑软件源信息文件

**`添加 PPA 软件源并安装`**

```
$ sudo add-apt-repository <PPA_info>            # 此命令将 PPA 仓库添加到列表中
$ sudo apt-get update     # 此命令更新可以在当前系统上安装的软件包列表
$ sudo apt-get install <package_in_PPA>       # 此命令安装软件包

# 例如
$ sudo add-apt-repository ppa:dr-akulavich/lighttable
$ sudo apt-get update
$ sudo apt-get install lighttable-installer
```

**`强制重装已安装的软件`**

```
 $ sudo apt-get --reinstall install <package-name>
 # 会先删除软件，再安装
```

**`sudo apt install \<package-name\> 新增文件位置`**

* 主要分散到以下四个目录
  * `/usr/bin` - 二进制文件
  * `/usr/lib` - 动态函数库文件
  * `/usr/share/doc` - 使用手册
  * `/usr/share/man` - man page
* 所以在多用户情况下使用 `sudo apt install <package-name>` 安装软件，会造成软件存放散乱，寻找软件配置文件麻烦；但好处是 apt 安装软件系统会自动注册环境变量，且是全局的
* 当自己使用源码安装软件通常把源码包放在 `/usr/local`

**`sudo apt update 具体执行动作`**

* 执行 `sudo apt update`
* 链接 `/etc/apt/sources.list` 里的软件源的镜像站，自动检索对比镜像站里的所有软件源与本地的 `/var/lib/apt/lists/` 目录，若发现有更新，立即在 `/var/lib/apt/lists/` 目录里跟新
* 更新完毕

**`强制更新`**

```
sudo rm -rf /var/lib/apt/lists/*
sudo apt-get update
```

### 三、 `sudo apt autoremove` <a href="#id-3-sudo-apt-autoremove" id="id-3-sudo-apt-autoremove"></a>

`autoclean` 是另一种方法，用于清除下载的包文件的本地存储库，clean 和之间的区别在于autoclean后者仅删除无法再从其源下载的包文件，并且很可能无用

### 四、 `/etc/apt/` 目录详解 <a href="#id-4etcapt-mu-lu-xiang-jie" id="id-4etcapt-mu-lu-xiang-jie"></a>

![](https://notes.xiechengqi.top/Linux/images/etc-apt%E7%9B%AE%E5%BD%95.jpg)\
/etc/apt 目录详解图

#### `/etc/apt/sources.list` && `/etc/apt/sources.list.d/` <a href="#etcaptsourceslist--etcaptsourceslistd" id="etcaptsourceslist--etcaptsourceslistd"></a>

**/etc/apt/sources.list内容组成**

![](https://notes.xiechengqi.top/Linux/images/etcaptsources.list.jpg)\
/etc/apt/sources.list 文件

* 当使用`sudo apt install xxx`安装软件时，系统会自动在配置的镜像软件源列表（ /var/lib/apt/lists/ )寻找，找到后自动添加进来

**/etc/apt/sources.list.d/内容组成**

![](https://notes.xiechengqi.top/Linux/images/sources.list.d.jpg)\
/etc/apt/sources.list.d/ 文件夹

* `/etc/apt/sources.list.d/`多是由第三方软件源文件组成，比如使用`sudo dpkg -i xxx.deb`安装或通过添加 PPA 软件第三方源`sudo add-apt-repository ppa:user/ppa-name`安装，而这些文件主要有这么三种：

```
xxx.list
xxx.list.distUpgrade
xxx.list.save
```

> 1.  xxx.list - 记录第三方软件的软件源信息
>
>     ```
>     ### THIS FILE IS AUTOMATICALLY CONFIGURED ###
>     # You may comment out this entry, but any other modifications may be lost.
>     # deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main # 已禁止升级到 bionic
>     ```
> 2. xxx.list.save - 是`xxx.list.save`的备份，内容相同
> 3. xxx.list.disUpgrade - 网上没找到，未知待续

```
### THIS FILE IS AUTOMATICALLY CONFIGURED ###
# You may comment out this entry, but any other modifications may be lost.
deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main
```

#### `/etc/apt/apt.conf` && `/etc/apt/apt.conf.d/` <a href="#etcaptaptconf--etcaptaptconfd" id="etcaptaptconf--etcaptaptconfd"></a>

/etc/apt/apt.conf:APT配置文件。

/etc/apt/apt.conf.d/:APT配置文件片段。

#### `/etc/apt/preferences` <a href="#etcaptpreferences" id="etcaptpreferences"></a>

版本首选项文件。您可以在此处指定“ 固定 ”，即从单独的源或不同版本的分发中获取某些包的首选项。

### 五、 `/var/cache/apt/` <a href="#id-5-varcacheapt" id="id-5-varcacheapt"></a>

#### `/var/cache/apt/archives/` <a href="#varcacheaptarchives" id="varcacheaptarchives"></a>

检索到的包文件的存储区域

`$ sudo apt clean`清空此目录

APT缓存文件，目录是在用 apt-get install 安装软件时，软件包的临时存放路径

#### `/var/cache/apt/archives/partial/` <a href="#varcacheaptarchivespartial" id="varcacheaptarchivespartial"></a>

传输中的包文件的存储区域。

#### `/var/lib/apt/lists/` <a href="#varlibaptlists" id="varlibaptlists"></a>

sources.list中指定的每个包资源的状态信息的存储区域

#### `/var/ lib/apt/lists/partial/` <a href="#var-libaptlistspartial" id="var-libaptlistspartial"></a>

传输中的状态信息的存储区域。

#### `/var/lib/dpkg/available` <a href="#varlibdpkgavailable" id="varlibdpkgavailable"></a>

文件的内容是软件包的描述信息，该软件包括当前系统所使用的安装源中的所有软件包，其中包括当前系统中已安装的和未安装的软件包
