Flatpak 从命令行用起来太糟了
摘要
这篇博客文章批评了 Linux 上 Flatpak 糟糕的命令行体验,指出虽然它让 GUI 应用跨发行版分发变得容易,但以 Flatpak 形式运行 CLI 工具却非常别扭,开发者也因此大多不愿为 Flatpak 打包命令行工具。
<p><a href="https://lobste.rs/s/lnmgaw/flatpak_from_cli_sucks">评论</a></p>
查看缓存全文
缓存时间: 2026/10/04 17:02
# 在命令行中使用 Flatpak 太难用了 - kowalski7cc
Source: https://kowalski7cc.xyz/blog/flatpak-from-the-cli-sucks/
Sticker by Puzzoz (https://kowalski7cc.xyz/static/1443566f8359cd4bfc867ec74a929d95/cb136/cover.png)Sticker by Puzzoz## 包管理,从头说起
Linux 早在竞争对手之前就拥有的一项功能,是从在线仓库下载应用程序的能力——这些仓库后来被称为"应用商店"。在此之前,你需要下载应用程序的二进制文件和库,或者自行从源代码编译,并确保已经安装了编译所需的所有依赖。为了解决这个问题,"APT" 和 "DNF" 这样的包管理器被开发出来。表面上看,这个任务似乎很简单:下载、安装、更新和卸载应用程序。然而在底层,包管理器必须处理复杂的操作:连同所有必需的库一起下载所请求的应用程序,检查依赖是否可用,解决冲突,将文件解压到磁盘上,并运行任何可选的安装后脚本。程序安装完成后,可以通过点击新出现的图标来运行;如果程序被放在 `/bin/` 或系统 `$PATH` 变量中的其他路径下,则直接输入可执行文件的名称即可运行。
选择格式太多了!有时有太多格式可供选择! - Sticker by Puzzoz (https://kowalski7cc.xyz/static/4dc249c85bc0fb299908f5c51e37a572/7d769/packages-formats.png)有时有太多格式可供选择! \- Sticker by Puzzoz
随着时间推移,包管理器出现了新的需求:发行版无关的支持,以及通过应用程序沙箱化来增强安全性。由于每个发行版家族都有自己的包管理器,开发者很快意识到为多个发行版维护软件包非常耗时,而发行版维护者更不可能为每个可用的应用程序都进行打包。此外,随着安全威胁的增加,有必要将不受信任的应用程序与系统隔离,包括那些可能被恶意软件利用的合法软件。对文档、外设和系统其他方面的访问需要被限制,仅在获得用户明确许可后才能临时使用。
采用这种新方法的包管理器之一就是 Flatpak。Flatpak 试图通过彻底改变打包和分发模型来解决这两个问题。它允许开发者以分层格式发布应用程序,包含所有必要的依赖,在所有发行版上都能运行,并在沙箱中运行。Flatpak 提供两种权限:在清单中声明的静态权限,以及在运行时通过 D-Bus 暴露的门户请求的动态权限。
这种格式很快成为了主流、默认方式,甚至在一些发行版中成为了通过软件商店安装图形应用程序的唯一方式。然而,命令行应用程序却被落下了,而且这是有原因的。当然,存在一些纯 CLI 工具,例如 flatpak-builder(用于构建新 Flatpak 的工具),但开发者往往不愿意为其打包。而且,正如我们将看到的,它们在命令行中的使用……相当困难!如果我们通过发行版的仓库以经典软件包的方式安装 Flatpak Builder,我们会使用 `flatpak-builder build-folder manifest.yaml` 来启动它。但是,当它本身作为 Flatpak 安装时,命令就变成了 `flatpak run org.flatpak.Builder build-folder manifest.yaml`。这不仅让命令变长,需要完整的"应用 ID"(由"唯一的三部分标识符"组成,能同时定位开发者和应用程序),而且还必须禁用文件系统沙箱!
与此同时,`flatpak run` 新增了 `--file-forwarding` 选项,它可以将命令行中指定的文件(在 `@@` 分隔符之间的参数中表达)映射到沙箱内部,使其对应用程序可用。然而,这种方法仍然有一个问题。添加所需的选项并将文件路径用 `@@` 包围,对命令长度毫无帮助,但更重要的是,它不适用于目录或你可能想要创建的不存在的文件(例如在转换图片时,第二个文件路径将是输出文件)。
## Windows 10 与通用 Windows 平台
其他操作系统也遇到了完全相同的应用分发和沙箱化问题。Windows 采取了一种激进的方式:与其改进经典的 Win32 桌面栈,它创建了一个全新的平台。尽管这项技术最初相当不成熟,但它为通过 Windows Store 分发 "APPX" 软件以及通过 AppContainer 进行沙箱化奠定了基础。
很快,开发者意识到从 Win32 迁移会带来巨大的工作量,试图将应用程序移植到新平台——而且由于 UWP 的技术限制,并非总是可行的。因此,在 Windows 的后续更新中,引入了桌面桥(Desktop Bridge)。
桌面桥是一项 Windows 技术,可将桌面应用打包为现代格式 (https://kowalski7cc.xyz/static/6bfdde8690317aad7d9db48f9a68bbce/7abe2/desktop-bridge.png)桌面桥是一项 Windows 技术,可将桌面应用打包为现代格式
在新功能中,许多都围绕着以 "APPX" 格式打包现有的 Win32 桌面应用程序,同时还加入了一系列改进,使 UWP 和 Win32 应用都能更轻松地从命令行运行。
当然,并非每个应用都支持此功能,因为它要求开发者通过添加 `uap3:AppExecutionAlias` 扩展来更新应用清单,并指定沙箱外部导出的可执行文件的名称。这会在 `%LOCALAPPDATA%\Microsoft\WindowsApps` 中创建一个特殊的 0 字节执行别名,该目录已包含在用户的 PATH 变量中。该文件依赖于一个标记为 `IO_REPARSE_TAG_APPEXECLINK` 的 NTFS 重解析点。执行时,Windows 会读取此重解析数据,并在其指定的应用程序容器内,从受限的 `C:\Program Files\WindowsApps` 目录启动实际的二进制文件。一个应用程序可以导出多个别名,且别名名称不必与容器内的可执行文件名匹配。
由于这些别名位于用户 PATH 变量所包含的目录中,它们有时会导致冲突。一个典型的例子是在 CMD 中输入 python,却意外打开了 Microsoft Store,而不是启动你从 python 官网手动安装的 Python 版本。
为了解决这个问题,系统提供了一个简单的界面,用于查看已安装应用程序导出的所有别名,以及禁用它们的开关。当某个别名被关闭时,Windows 只是从 `%LOCALAPPDATA%\Microsoft\WindowsApps` 目录中删除该 0 字节重解析点。文件被删除后,shell 会继续在用户 PATH 的其余部分中搜索。
Windows 有一个设置页面,用户可以在其中开关各个别名 (https://kowalski7cc.xyz/static/f209337fbfadc46b1667cd005a054955/2559a/windows-aliases-settings.png)Windows 有一个设置页面,用户可以在其中开关各个别名
## Flatpak 的一个解决方案
Flatpak 的开发可以借鉴 Windows 的方法。建议的解决方案由多个小改动组成。第一项是在 Flatpak 清单中添加一个 `export-commands` 键,将内部可执行文件路径映射到导出的命令别名。这种方法允许开发者在软件包内创建具有复杂名称的包装文件,并以简单的名称导出它们。
```
app-id: uk.org.greenend.chiark.sgtatham.putty
runtime: org.freedesktop.Platform
runtime-version: '26.08'
sdk: org.freedesktop.Sdk
rename-desktop-file: putty.desktop
rename-icon: putty
command: putty
export-commands:
putty: putty
puttygen: puttygen
psftp: psftp
pageant: pageant
pscp: pscp
...
```
Flatpak builder 可以接收这个新部分,并在应用程序的 `metadata` 文件中构建出以下部分:
```
[Commands]
putty=putty
puttygen=puttygen
psftp=psftp
pageant=pageant
pscp=pscp
```
安装后,除了在当前请求权限界面上显示支持的别名之外,Flatpak 还可以生成一组包装脚本(类似于已经存在于 `/var/lib/flatpak/exports/bin/` 中的那些),并进行几处关键改动:这些包装脚本会自动为每个导出的内部二进制文件附加 `--command` 标志,使用指定的别名名称保存包装脚本,并通过检测现有的文件参数并将它们包裹在 `@@` 分隔符中,提供对 `--file-forwarding` 的内置支持。
```
#!/bin/sh
for arg do
shift
if [ -e "$arg" ]; then
set -- "$@" "@@" "$(readlink -f "$arg")" "@@"
else
set -- "$@" "$arg"
fi
done
exec /usr/bin/flatpak run --branch=master --arch=x86_64 --command="putty" --file-forwarding uk.org.greenend.chiark.sgtatham.putty "$@"
```
随后,Flatpak 命令可以扩展以包含启用或禁用特定别名的子命令,或配置新应用程序是否默认自动导出别名。图形化管理工具,例如系统设置或 Flatseal,可以集成一个专用的控制面板,类似于 Windows 中的那个,以简化用户的别名管理。
类似别名管理体验在桌面 Linux 发行版中的一个示例 (https://kowalski7cc.xyz/static/f283cd0cb5b7376ec52db7c5cacc57f8/d02e2/flatpak-exporter-gui.png)类似别名管理体验在桌面 Linux 发行版中的一个示例
## 桌面与命令行的统一前进之路
随着桌面 Linux 持续获得主流关注,图形界面应用程序与命令行工具之间的差异变得越来越重要。虽然 Flatpak 为解决图形软件的碎片化和安全挑战奠定了基础,但要将沙箱化和发行版无关分发的相同原则扩展到命令行工具,需要实现方式的改变。
## 资源
- https://learn.microsoft.com/windows/apps/desktop/modernize/desktop-to-uwp-extensions
- https://learn.microsoft.com/it-it/windows/win32/secauthz/appcontainer-for-legacy-applications-
- https://learn.microsoft.com/en-us/windows/win32/fileio/reparse-point-tags
- https://gist.github.com/ssokolow/db565fd8a82d6002baada946adb81f68
- https://man7.org/linux/man-pages/man1/flatpak-run.1.html
相似文章
对Flatpak不安全说法的回应
一篇反驳Flatpak安全模型的博客文章,针对其是“安全噩梦”的说法进行辩护,内容涉及其容器化历史、隔离机制、门户系统以及权限模型。
KDE Linux 使用体验
作者 AksDev 分享了一年日常使用 KDE Linux 的体验,强调其原子设计在开发中的优势,但指出 Flatpak 问题,最终切换回 Fedora KDE。
Flatpak 将依赖 systemd
Flatpak 的下一个重要版本可能将依赖 systemd,以将权限管理移至服务层,这可能会破坏与不使用 systemd 的发行版的兼容性。
介绍 Toolpak
介绍 Toolpak,一个旨在解决基于镜像操作系统中开发者工具和依赖管理缺口的工具,并与现有方法如 Flatpak 和 Toolbox 进行比较。
A critical look at the UX of various linux desktops
本文基于Linus TechTips视频,批评Linux桌面环境的用户体验问题,以网络驱动器挂载和GNOME Disks工具为例,指出其“技术上正确”却难用,呼吁社区进行自我反思和改善。