当我从 Windows 转到 Linux 时,我很幸运地拥有了软件包管理器。大多数时候,我的发行版(目前是 Debian 12)的官方存储库都会有我需要的软件包。但有时却没有,这意味着如果我想安装某些应用程序,我必须在不通过软件包管理器的情况下进行安装;也许可以通过克隆 GitHub 存储库并从源代码构建,或者使用wget
或curl
从开发人员那里获取专用的安装程序。
这样做安全吗?我不是在问这些软件包的可信度。而是,如果我这样做,会破坏软件包管理系统吗?例如,当我使用发行版的软件包管理器执行系统范围的更新时,以这种方式安装的软件包会被更新吗?我可以使用软件包管理器卸载它们吗?
这是一个具体的例子。假设我想安装 Rust。Rust 官方网站建议 Linux 用户运行以下命令。
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
换句话说,rustup.rs
从网站下载文件,然后运行它来安装 Rust。这个例子对我来说更加令人困惑,因为 Debian确实在存储库中提供rustup
了软件包。那么我应该使用 Debian 软件包,还是应该按照网站上的说明操作?
这是另一个例子。假设我想安装 Minecraft,但 Debian 存储库中没有。因此我必须访问 Minecraft 网站,该网站允许我下载文件minecraft.deb
。如果我的猜测正确,那么我将使用apt
它来安装它。在这种情况下,包管理器会跟踪包吗?我是否可以卸载它,或者使用它来更新它apt
?
感谢您帮助我解决了这个困扰我很长时间的困惑。
一般来说,是的,它是安全的 — — 只要任何未使用包安装的内容都安装在
/usr/local
或中/opt
,并且不会将自身添加到全局系统配置文件中。我将首先回答您问题的最后一部分,因为它最简单。如果您下载一个
.deb
文件并安装它(apt install ./minecraft.deb
例如使用,这比 更好,dpkg -i minecraft.deb
因为它会为您处理依赖项),则包管理器将知道该包。这很好,因为这意味着包的依赖项不会被意外删除。您还可以使用 卸载包apt
。但是,以这种方式安装包并不一定保证您能够使用 更新它apt
;配置自己的存储库的包除外(例如许多 Google 包)。您始终可以通过下载新包并再次使用 来安装它来手动升级此类包apt install
。语言生态系统和相关工具(例如)
rustup
稍微复杂一些。为了方便起见rustup
,它以 Debian 软件包的形式提供,但仅限于 Debian 13 及更高版本(请参阅安装手册)rustup
;因此您无法apt install rustup
在 Debian 12 上按原样使用。大多数语言生态系统都了解发行版打包约束,并且可以与发行版中的软件包很好地配合使用。例如,您可以在 Debian 中安装最新版本的 Go 以及打包的 Go,一切都会正常工作。Java 也是如此,从 Debian 12 开始,只要您使用虚拟环境,Python 也是如此。唯一要绝对确保的是,您永远不会用
/usr/bin
不兼容的版本替换系统二进制文件( 中的二进制文件);这种情况在 Python 中尤其普遍,这里有很多用户替换 的问题/usr/bin/python3
。只要你不做这样的事情,你应该没事。包管理器通常不会跟踪安装在包管理器之外的软件。
尽可能使用发行版的包管理器。它可以简化更新和依赖项管理。
.deb
可以使用dpkg
或安装软件包apt
如何通过 dpkg -i 或 apt 安装 deb 文件?
sudo apt install package.deb
sudo dpkg -i package.deb
dpkg
是基于 Debian 的系统的低级包管理工具,可.deb
直接安装、删除和管理包。如果可能的话,尝试使用 Debian 存储库。
不要忘记,并非所有软件包都在 Debian 主贡献存储库中。
你必须修改你的
/etc/apt/sources.list
这是我的
sources.list
:进行更改后,运行
sudo apt-get update
或apt update
更新包列表。apt 和 apt-get 有什么区别?
您要知道,还有另一个名为 的包管理器
Synaptic
。它是一个可以提供用户友好界面的
graphical frontend
工具。apt
dpkg
用户可以搜索软件包、查看有关软件包的信息,并通过单击安装或删除软件包。
它显示依赖项和建议的包,让用户更好地控制包管理。
Synaptic 是 Debian 包管理系统的图形界面。
这个问题一般无法回答,因为我们不知道安装需要做什么,尤其是通过这样的命令安装某些东西时:
脚本可以做任何事情。它可以添加一个存储库并从该存储库安装某些东西(有很多
curl | sh
脚本可以这样做)。它可以显示为不同位置的不同脚本(这里可能没有,但可以)。该 minecraft deb 包可以添加一个存储库。如果他们添加一个存储库,然后添加一些与您想要从发行版的存储库中使用的其他包相冲突或冲突的包,这两种情况都可能破坏包管理系统(如果他们确实使用它,就curl | sh
脚本而言)。不仅仅是 deb 文件或随机脚本。以 root 身份安装任意 Python 包(脚本可能会这样做)会破坏包管理系统,这就是PEP-668出现的原因(导致发布诸如 Ubuntu 上的 pip 错误:外部管理环境 × 此环境是外部管理的和每次使用 pip 3 时如何解决“错误:外部管理环境”?之类的帖子)。该脚本可能正在编译和安装 OpenSSL 或某些核心库,并破坏您的包管理命令,仅仅是因为库的安装方式覆盖了系统库。
对于脚本
curl | sh
,我通常更喜欢自己查看脚本,提取与我和我正在使用的系统相关的部分,然后自己执行这些部分。在这种情况下,是的,该软件包将被 apt/dpkg 跟踪。您将能够卸载它。一些 deb 文件(值得注意的是 Google Chrome)确实在软件包安装过程中添加了 repos,然后您可以使用它
apt
来更新它们,但如果没有添加这样的 repos,您可能需要手动下载新的 deb 文件并再次安装它们。当您实际上“采用 Windows 方法”并下载和运行一些随机软件时,无法确定。有些软件表现良好,会将所有内容放在下面
/opt
或/usr/local
根据需要放置,以避免干扰系统包管理器。例如,来自https://go.dev的官方上游 Go 工具链 确实将所有内容放在类/usr/local
UNIX 系统下(实际上/usr/local/go
)。但并非所有软件都表现良好,很难确定。所有这些都有一些特殊的例外:
go install
) 安装,用 Go 编写的应用程序/工具通常是安全的。Go 工具链在主目录的子目录中管理这些应用程序/工具,它们本质上是 100% 独立的,因此几乎没有任何风险,除非它们写入系统中的任意文件。包装安全性比较
没有绝对安全或绝对不安全的事情。一切都是相对的。但相对而言,分发包通常更安全,原因有很多。这不应该阻止您在需要时安装非分发包。但如果某个程序既可以作为分发包使用,也可以从其他渠道获得,则应尽可能使用分发包。
我所说的“发行版软件包”是指 Debian、Ubuntu、Red Hat、SuSE、Arch、FreeBSD 等主流发行版直接发布的软件包。人力较少的发行版可能相对安全性较低。以发行版格式(例如 a
.deb
或.rpm
)手动下载的软件包不具备发行版软件包的安全性优势。从其他软件包源(例如 Ubuntu PPA)安装的软件包介于两者之间。透明度
分发包已签名并复制,安装程序会验证签名。因此,您知道自己得到的是什么。如果在给定版本中发现错误,您至少可以知道您是否拥有有错误的版本。
相反,当你使用 安装 时
curl https://example.com/run_me.sh | bash
,你无法知道你安装了什么。我至少见过一个概念验证(我不记得它是否是真正的攻击),如果你下载了 ,Web 服务器会返回一个干净的安装程序.sh
,但如果你运行 ,则会返回一个带有后门的安装程序curl … | bash
,这是通过检测安装程序脚本执行中暂停的时间来得出的。第三方软件包源介于两者之间:它们仅由其供应商签名,但有些(例如 Ubuntu PPA)由发行版托管,这至少可以防止未被发现的替换。
审查
发行版发布的软件会受到一些审查。审查并不多,而且绝对不能防止出现漏洞或后门。但这足以让发布长期未被发现的后门变得更加困难。这意味着该软件至少受到发行版信任的一个人的信任。
直接从供应商处获取软件可以省去一层审查,无论是从软件包源还是从网站下载获取。
安全更新可用性
当发现漏洞时,发行版会有人进行安全更新。这包括将安全修复移植到软件包的分发版本中。除了滚动发行版外,在给定版本的发行版中,您只会获得主要错误修复,因此您可以有理由相信修复后的版本不会有干扰您工作流程的新功能。
一些供应商遵循相同的原则,但其他的则不然。
安全更新自动性
对于通过软件包管理器获取的任何软件,只需一个命令(例如
apt update && apt upgrade
)即可应用所有安全更新。某些发行版或桌面环境会设置自动任务来应用安全更新,或提示您应用安全更新。对于通过其他渠道获得的软件,你必须记住去寻找更新。因此,你可能在很长时间内都无法察觉到软件存在漏洞。
包装自动化
大多数打包系统会跟踪哪个包拥有哪些文件。如果一个包试图覆盖另一个包的文件,它们会发出错误信号。卸载包时,它们会删除包的所有文件。这适用于使用打包系统的任何事物,无论包是谁制作的。
您无法从手动安装的软件中获得这些好处。
包装质量
发行版有最低软件包质量要求。例如,它们遵循目录结构约定。它们不会以任意方式破坏您的系统或用户帐户。当您卸载它们时,它们会自行清理。
第三方软件,无论是否以软件包形式提供,都可能达到或达不到这个质量。
集成质量
发行版不会对其发布的大多数软件进行太多测试。但至少它们会确保满足所有依赖关系 — 您不会最终得到软件 B 需要 A 版本 1.3,软件 C 需要 A 版本 1.4,而无法安装 A 的两个版本。具体而言,发行版的给定版本会针对给定的一组库版本编译所有程序。发行版会为您解决 DLL 难题。
如果您安装的软件不是来自发行版,则需要您自己承担责任。供应商可能已经或可能没有使用与您的系统类似的系统进行测试。两个不同的供应商对典型系统的期望可能完全不同。
这就是为什么现在很多供应商都在发布“设备”:他们不只是发布应用程序,而是发布应用程序及其依赖的所有库。有时他们甚至将应用程序放入容器中:flatpak、Docker 镜像、虚拟机……这解决了依赖性问题,但这也意味着容器中的库不会得到错误修复(尤其是安全修复),除非供应商将修复应用于他们自己的库副本。实际上,这种情况从未发生过,所以我们回到我上面提到的安全更新可用性问题。
关于语言生态系统
如果您是开发人员,那么在许多编程语言中,特定于语言的分发渠道(,,,,,...
pip
)是很难避免的。npm
rustup
hackage
opam
不幸的是,打包的状态相当糟糕。唯一的好处是它们可以处理版本依赖项。这些包管理器几乎不跟踪哪些文件属于谁。它们在卸载时可能无法清除所有内容。
这些生态系统通常会放弃 DLL 地狱,只会告诉您在每个构建树中安装所有内容的单独副本,或者至少每个项目(版本)安装一个副本。但是,如果您的项目需要库 A 和 B,而它们都需要库 C,但版本不同……那您就倒霉了。
因此,如果可以的话,你应该避免语言生态系统打包,但通常你做不到。你需要花一些精力来审查和维护你的供应链。