包管理器到底管理了什么?
2023-2-11 23:57:35 Author: NOP Team(查看原文) 阅读量:30 收藏

为什么需要包管理器

如果读过《程序员的自我修养》这本书,肯定知道软件包的发展历程,现在的软件包绝大多数都是动态链接,存在依赖的。因此,安装一个软件包,还需要解决依赖问题,依赖的软件包可能还会依赖其他依赖,因此这是一个复杂的过程

删除软件包的时候也是一样,而且被删除的软件包依赖的软件包可能也被其他软件包依赖着,删除一个软件包及其依赖也是一个复杂的过程

因此需要包管理器这么个程序来对此进行管理

传统包管理器

说到管理,表面上主要就是增删改查,实际上是数据库信息管理。除了dpkg这类不顾依赖的,其他包管理工具功能上大差不差,

这里以 APT 包管理工具为例

1) 更新索引

# 更新索引
sudo apt update 

更新索引可以从软件服务器更新最新软件包索引信息,以供后续搜索以及

2) 搜索软件包

可以根据软件包名称或者功能描述关键字进行搜索

sudo apt search "web scanner"

查看软件包信息

sudo apt show nmap 

通过这个命令可以展示出nmap软件包的基本信息,例如包名称、版本、依赖、大小、描述等

查看软件源代码信息

sudo apt showsrc nmap

3) 安装

相对于下载源码进行编译,APT这类工具将安装简化成几条指令

# 安装 nmap 软件包
sudo apt install nmap

APT 是如何实现这种封装的呢?

首先我得知道从哪里下载吧,所以就有了更新源的概念

Ubuntu 系列的系统更新源信息存储位置为

  • /etc/apt/sources.list

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

/etc/apt/sources.list   是系统官方定义的软件更新源

/etc/apt/sources.list.d/ 目录存储的是第三方软件的更新源

格式上基本一致

软件包/软件源码 软件包服务器地址 发行版本-软件包分类 软件包分类目录
deb http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted universe multiverse
  • deb 表示软件包源
  • deb-src 表示软件源码源,如果想要下载软件包源代码就需要添加 deb-src 的源
  • 软件包服务器地址我使用的是阿里云的
  • bionic-security 是发行版本-软件包类型,这里表示 bionic 发行版的安全类软件包
  • main restricted universe multiverse  表示四类不同支持的软件目录
    • main 官方支持的自由软件
    • restricted  官方支持的非完全自由的软件,也就是不开源的软件包
    • universe 社区维护的自由软件
    • multiverse 非自由软件,且官方不提供支持和安全更新

只下载deb包

sudo apt download nmap 

此时 Nmap 程序的 deb 包就被我们下载到当前目录了,后续可以通过 dpkg 进行安装

只下载软件源代码

sudo apt source nmap 

通过浏览器获取 deb 包和源代码

以阿里云的镜像网站为例

http://mirrors.aliyun.com/ubuntu/

以 main 为例

选择以 nmap为例,选择 n 开头的

这样就找到 nmap 的 deb 安装包和源代码了

软件包通常被下载到哪里

通过 sudo apt install 下载并安装的软件包下载到了哪里呢?

更新或安装结束后,下载的软件包会被自动清除

软件包被安装到哪里

这个问题我个人是比较关注的,因为Linux 默认包管理器会将一个软件包分解成很多文件,放在其该有的位置,例如

  • /usr/share  说明文档

  • /usr/bin 可执行文件

  • /etc  配置文件

  • /usr/lib  lib文件

但是其实这个事不是由用户来决定的,甚至不是系统决定的,是由包的维护者决定的

以 Proxychains 这款程序来举例

首先正常使用 apt 进行安装

安装 proxychains 后,使用 dpkg -L 来进行查看该软件包各种文件的位置

现在我们使用 apt purge 卸载 proxychains,之后通过下载 deb 包后尝试修改相关文件位置后再打包后安装,对比一下

下载 deb 软件包并解包

查看包内容

看到这里大家应该都理解了,其实就是包管理器把包里的内容拷贝到相关位置,并解决依赖问题

现在我们尝试在 extract 文件夹中新建 opt/proxychains-test目录,并放置 proxychains 可执行文件,删除默认的 /usr/bin/proxychains

现在重新打包

dpkg-deb -b extract build/

安装新的 deb 包

sudo dpkg -i build/proxychains_3.1-7_all.deb

查看 proxychains 软件包相关文件

sudo dpkg -L proxychains

测试功能是否可以正确执行

由于/opt/proxychains-test 不在当前的环境变量中,所以肯定无法直接执行,APT 也没有识别到我们安装了这个程序

通过绝对路径执行是可以成功的,现在我们配置一下 /etc/proxychains.conf测试一下功能

如果我们更改了配置文件的位置为 /tmp/proxychains/proxychains.conf 程序还可以正常执行吗?

卸载 proxychains

重新解包、修改、打包

结果在打包的时候就出错了,这说明配置文件等是由一些元信息在记录着的

记录配置文件位置的文件就是 extract/DEBIAN/conffiles

尝试修改该文件内容为 /tmp/proxychains/proxychains.conf

成功打包,安装测试功能

经过测试发现,虽然安装成功了,但是在使用过程中, proxychains 还是会去找 /etc/proxychains.conf 这个配置文件

如何确定某个文件属于哪个软件包

dpkg -S xxxx

4) 卸载

sudo apt remove nmap

sudo apt purge nmap

remove 会删除软件程序以及帮助文档等,但是不会删除配置文件

purge 会删除配置文件

但是purge和remove 都不会删除软件程序在用户目录下创建的配置文件

以 fish 为例

~/.local/share/fish/ 是 fish 的配置文件夹,现在我们分别尝试用remove 和 purge 来进行卸载 fish

remove 和 purge 都没能删除软件包在用户目录下创建的配置文件

5) 清理空间

# 删除下载过的所有软件包的安装包
sudo apt clean

# 删除已经过期的软件包的安装包
sudo apt autoclean

# 删除未使用的依赖项,主要是由软件包卸载后,没有其他软件包依赖这些项,于是处于未使用状态
sudo apt autoremove

软件遗留在用户目录的配置项不在这三者的清理范围内

独立软件包管理器

包管理也是一直在进步的,准确地说可能是探索,APT、DNF 等包管理器在依赖解决方式上让部分用户体验不够完美,大家开始创造新的依赖解决方案

总体的思想就是将程序和全都封装起来,这样依赖不再共享,同一个依赖包可以包含不同版本

最关键的是,开发者不再需要针对各种包管理器进行单独打包发布了,于是出现了以下几种有代表性的独立包管理器;同时通过对这些软件包做虚拟化或者沙盒化处理,在安全性方面更加可控

  • snap
  • flatpak
  • AppImage
  • 玲珑
  • nix

1) Snap

https://cn.ubuntu.com/blog/what-is-snap-application

snap 是由开发Canonical 公司开发的,也就是 Ubuntu 的开发商,开发 snap 的目的就是想要做一个跨平台的解决方案,包括桌面、服务器、iot、甚至是手机,同时兼顾安全性

现在基本上主流的 Linux 系统上都可以安装 snap 包管理器,甚至曾经Canonical 官方还在 snap 推广上做过一些较为激进的举动和决定

snap 的使用方法与 apt 差不多,只不过软件包格式为 .snap ,某些指令略有不同

搜索程序

snap 目前只有官方源,所以就不需要配置源了

sudo snap find nmap

查看程序信息

sudo snap info nmap

安装程序

sudo snap install nmap 

更新程序

sudo snap refresh nmap

回滚到上一个版本

sudo snap revert nmap 

由于我这里直接安装的最新版,所以就没有可回滚的版本了

查看已经安装的 snap

sudo snap list

卸载程序

sudo snap remove nmap

snap 的文件存储

通过环境变量可以发现,直接与 snap 相关的目录为 /snap/bin

通过查看 /snap/README 可以看到该目录的介绍

/snap/ 目录是已安装的快照包中的文件和文件夹显示在系统上的位置

/snap/bin 这个目录存储指向实际的snap软件包的链接文件

/snap/<snapname>/<revision> 挂载点信息

这里 snapname 就是 nmap ,其中 revision 为 2944

/snap/<snapname>/current  表示当前版本的 revision ,由于 snap 具有版本回退功能,所以我猜测这个文件应该是为了版本记录以及回退准备的

既然上面说到挂在点,我们可以筛选一下挂载信息,看看是否有对应关系

sudo mount | grep nmap

可以看到 /snap/nmap/2944 这个目录其实就是 /var/lib/snapd/snaps/nmap_2944.snap 这个设备(文件)的挂载

sudo lsblk -a

这就是 snap 的工作模式, .snap 的快照文件放在 /var/lib/snapd/snaps/ 下,之后通过块文件挂载的方式挂载到 /snap/<snapname>/<revision>  目录下

用户使用 snap 程序产生的数据存放在 ~/snap 目录下,格式与 /snap 下的基本一致

程序目录控制

snap 将程序及其依赖打包放在了一起,同时通过一个叫 connections 的东西给程序分配权限,其中涉及到程序可以访问的路径,这件事对安全人员和运维人员具有不同的意义,现在通过 tree 这个程序来探索一下这件事

安装 tree
sudo snap install tree

查看 tree 这个软件包的 connections
sudo snap connections tree

可以看到,tree 可以访问的目录有 /home 和可移动设备,目前 /home 处存在插槽(slot),可移动设备处无插槽,所以tree可以访问 /home 目录,访问不了其他目录,测试一下

可以看出

  • tree 可以访问 /home/ 目录
  • tree 无法访问 /usr/
  • tree 可以访问 /home/目录下的目录以及文件
  • tree 无法访问 ~/snap目录下其他 snap 程序的目录

这样限制了单一程序的目录访问,在一定程度上加强了安全性,但是易用性有所降低

程序权限控制

snap 挺有意思,将程序获取某种系统资源设计为插槽(Slot)与插头(Plug)的形式

所谓插槽就是系统提供的一些资源,例如文件资源,音频播放,摄像头,网络接口等,插头也是一样,只不过需要将插头和插槽连接起来组合成一个接口(interface)才能让程序获得这项资源

接口如何使用插头和插槽

一般情况下,一个程序包需要哪些接口都是经过审核的,可以通过以下命令查看

sudo snap connections nmap

nmap 有四个接口,其中三个插头插在了插槽上使 nmap 具有 home 目录的访问权限,可以使用网络并且做网络绑定

查看所有的插槽

snap connections --all | cut -d " " -f 1 | sort | uniq

现在我想将 nmap 的最后一个插头插上

sudo snap connect nmap:network-control :network-control

注意插头和插槽前后名称要一致

如果我想将一个不存在的插头插在系统插槽上,会怎么样呢?

以手动赋予 nmap 音频录制为例

sudo snap connect nmap:audio-record :audio-record

可以看到,操作不存在的插头会执行失败

断开一个接口也很简单

sudo snap disconnect nmap:network-control :network-control

程序配置项

对于需要进行配置的软件包, snap 也给予了支持,需要先安装这个软件包后才可以获取、设置、取消设置部分配置项

以官网的 nextcloud 为例,这是一个文件管理与共享工具,类似百度网盘

使用 snap 安装 nextcloud

sudo snap install nextcloud

获取 nextcloud 配置信息

sudo snap get nextcloud

配置以 key 和 value 的形式显示,可以看到 mode 的值为 production ,表明当前处于生产模式中,其他选项,例如 http 对应值为 {...} ,这表明配置不止一项,下面还有子配置

以获取 nextcloud 的 ports 配置项为例

sudo snap get nextcloud ports

根据经验可以知道,这是在配置 http 和 https 的端口号

设置配置项

sudo snap set nextcloud ports.https=8443

这样就将 https 的端口设置为了 8443

重置设置项

sudo snap unset nextcloud ports.https

unset 后又回到了默认的情况

这样的话,配置起来仿佛更容易了一些,因为不用到处去找配置文件位置之类的了

当然了,部分用户更熟悉 json 格式来展示,可以使用 -d

sudo snap get -d nextcloud

快照功能

这点我觉得很好,因为软件包是独立的,可以对软件包进行快照打包,恢复等

还有一些服务,系统配置,资源限制等,大家可以阅读参考文档里的链接进行了解

2) Flatpak

flatpak 也是同样的想法,让开发者只用这种框架进行打包,之后在所有linux上都可以运行,所以 flatpak 的形式和 snap 也差不多,也构建了官方源,还支持第三方源

flatpak 官方将传统软件包的弊端和 flatpak 的优势、劣势等都写在了产品介绍页

https://docs.flatpak.org/zh_CN/latest/introduction.html

PS:flatpak 只支持桌面程序打包

在 Ubuntu 22.10 中默认没有安装 flatpak ,所以需要先安装

安装  flatpak

sudo apt install flatpak

添加软件包源

flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo

flatpak是支持第三方源的,这里以官方源为例

重启电脑

这个是官方描述的

安装软件包

以安装 sublime 为例

访问 https://flathub.org/ 搜索sublime

直接点击 INSTALL 会下载安装包描述文件,可以通过安装包描述文件进行安装

也可以根据页面下方的命令行进行安装和运行

安装sublime
flatpak install flathub com.sublimetext.three

运行 sublime 
flatpak run com.sublimetext.three

安装后程序可以直接通过点击图标运行,打开sublime,sublime提示升级,但是点击升级按钮就直接跳转到sublime网站了,而不是 flatpak 的仓库

升级软件包

单个软件包升级需要先获取 Application ID

flatpak list

升级 sublime

flatpak update com.sublimetext.three

升级全部程序

flatpak update

卸载软件包

flatpak uninstall com.sublimetext.three

flatpak 似乎在资源访问、权限控制等方面更倾向于交给开发者打包时决定

因为在我寻找官方文档中对于程序权限控制问题时,只找到了针对开发者的部分,告诉开发者如何配置权限和资源访问

当然了,也提到了flatpak 本身具备各种权限控制的命令参数,也规划了类似 snap 的系统资源分类,也有类似 snap 插头概念的接口,官方提到了应用程序使用部分权限时会提示用户,但是没有找到用户如何主动使用

flatpak 也支持一些类似回滚版本之类的操作,具体可以查看参考文档中的链接

3) AppImage

让 Linux 应用随处运行

"作为一名用户,我在从原作者处下载到应用后,我希望能直接在Linux桌面上运行它,就像运行一个Windows或者Mac应用程序一样。"

"作为一名应用开发者,我想为Linux桌面系统提供软件包的同时,不需要将其分发到每一个发行版中,也不必为不同的发行版编译多个版本。"

https://appimage.org/

软件库

https://www.appimagehub.com/

使用软件包

AppImage 软件包就不叫安装了,可以说是使用,因为就一个 xxx.AppImage 文件就够了,下载,赋予权限,运行

以 pycharm 为例

可惜 pycham 运行失败了,下载 tg 程序试了一下,发现也是这个报错,查询资料后发现需要安装一个依赖 linfuse2

测试文件权限

以 sudo 启动后, pycharm 可以访问任意目录

tg 也可以正常启动

使用体验

AppImage 号称是一个文件等于一个程序,但是在程序打包的时候需要开发作者根据自己的经验以及官方总结的清单自己决定哪些依赖是要包含进入软件包的,这也是 AppImage 声称的特色,这样可以直接让开发者直接打包,扁平化的进行功能更新以及bug 修复等,由此引来的问题就是软件包没有审核者,质量很难保证

作为用户对AppImage 格式程序的目录控制和权限控制似乎没有一个比较简单的方法,同时也不知道这种格式是否可以作用于无图形化界面的程序和有守护进程的服务类程序

软件更新

AppImage 格式的程序就是一个软件包,并没有办法利用其他工具进行更新,只能是用户去软件仓库自己查看是否存在更新

AppImage 的定位更像是 Windows 上的便携版软件,它可以将一些非 AppImage 格式且非开源的程序打包成AppImage 格式,至于用起来的效果,就看程序本身情况了

4) 玲珑

玲珑是一种新型的独立包管理工具集,致力于治理Linux系统下传统软件包格式复杂、交叉的依赖关系导致的各种兼容性问题,以及过于松散的权限管控导致的安全风险。

玲珑是国内 deepin 那个公司开发的一种包管理器,从功能上看与 flatpak 差不多,但是目前还没有大范围部署,毕竟玲珑发布也没有太久

玲珑有中文文档,大家可以直接去下面的链接中查看

https://linglong.dev/

希望玲珑能在这个领域遍地开花

也希望 deepin 能在无歧视的环境下茁壮成长

5) nix

Nix 是一个纯粹的功能包管理器。这意味着它将包视为纯函数式编程语言(如 Haskell)中的值——它们由没有副作用的函数构建,并且在构建后永远不会改变。Nix 将包存储在 Nix store 中。

nix 官方还发布了一个以 nix 为包管理器的 Linux 发行版 NixOS

https://nixos.org/

直接看 nix 官方的演示视频并不是很容易理解 nix 的理念, nix 是如何管理依赖,解决依赖地狱问题的呢?

依赖方面容易产生问题的几个原因

  • 开发者写依赖关系的时候,遗漏了部分依赖。开发者电脑依赖比较全,很容易导致梳理依赖关系的时候落下
  • 应用程序升级了,连带着依赖也升级了,但是升级后发现新版本无法满足预期要求,想要降级,此时缺少低版本的依赖文件

nix 将所有的依赖文件不再放置在 Linux 默认的位置,而是另起炉灶,放在 nix 自定义的一个目录中,这个目录不在环境变量中。这样开发者需要通过绝对路径或者相对路径进行引用,这样在最终打包的时候就不会有所遗漏

nix 管理下,程序升级后,原有的依赖并不会删除,而是会继续留在原来的位置,同时安装新版本的依赖,同时 nix 提供了垃圾回收器,执行垃圾回收器后,会清除那些没有被任何软件包依赖的依赖包

也就是说 nix 是支持在系统中存在不同版本的同一个软件包的

nix 支持单用户(root)以及多用户模式,多用户模式下每个用户都可以在非 root

权限下安装软件包,互不影响

安装 nix

sudo bash <(curl -L https://nixos.org/nix/install)

nix 支持 Linux 和 MacOS ,我这里直接使用 NixOS

订阅频道

nix-channel --add https://nixos.org/channels/nixpkgs-unstable
nix-channel --update

如果使用的是 NixOS ,则不需要订阅频道,自动会订阅

搜索软件包

https://search.nixos.org/

也可以使用命令

nix-env -qaP nmap 

安装软件包

nix-env -i nmap

更新软件包

nix-channel --update nixpkgs
nix-env -u nmap

软件包回滚

nix-env --rollback

卸载软件包

nix-env -e nmap

垃圾回收器

nix-collect-garbage -d

实际上,在升级和卸载软件包的时候,nix 并未真正删除包,只是修改了相关指向而已,执行垃圾回收器未被依赖的包被删除

测试软件包

这个功能有点东西,可以在不安装软件包的时候测试软件包

nix-shell -p nmap

Nix 还支持将软件包在多台机器间共享,可以通过 HTTP、SSH 等协议来完成,用以加快软件包安装速度

Nix 表达式

上面我们提到了 channel ,这个频道就有点像 APT 的更新源一样,channel 里存储的是 nix 表达式,这个表达式是由 Nix language 来编写的,就是要求源代码如何进行编译,例如程序需要的依赖之类的信息

Nix 有一种算法,根据这些依赖计算出 hash 值,作为程序安装后的目录名称的一部分,所以当程序升级或依赖升级后,hash 值就会变化,这样升级后的程序就会生成一个新的目录,旧的目录也不自动删除,以方便用户回滚

Nix 官方提供了一堆现成的 Nix 表达式,方便开发者直接使用。使用表达式构建的程序是各方面非常严谨准确的,最关键是非常容易复现,因此可以用来方便地部署开发环境、测试环境等

详细参考

https://nixos.org/manual/nix/stable/language/index.html

Nix 包管理器很强大,推荐大家研究研究

总结

此文章主要目的是了解各种包管理器的原理,并不是完整的功能测试,所以主要介绍了包管理核心特点,大家可以对感兴趣的包管理器做深入了解,具体可以参考下面的链接

参考文章

https://www.cnblogs.com/cxsy/p/8093879.html

https://cn.ubuntu.com/blog/what-is-snap-application

https://snapcraft.io/docs/getting-started

https://snapcraft.io/docs/system-snap-directory

https://flatpak.org/setup/

https://docs.flatpak.org/zh_CN/latest/introduction.html

https://appimage.org/

https://linglong.dev/guide/start/install.html

https://nixos.org/manual/

往期文章


文章来源: http://mp.weixin.qq.com/s?__biz=MzU1NDkwMzAyMg==&mid=2247492389&idx=1&sn=04cc40175a8f16a77663c0981f117d19&chksm=fbded7a4cca95eb28d324129335db5d6b08d68056d42bbc24cd41c2fb16b791c7b88e7d6d09a#rd
如有侵权请联系:admin#unsafe.sh