Flatpak概念及其基础使用方法
图源:陌芋Marginal 🎆🎇🎆 108115520
为什么使用Flatpak?
- 问题:已经有了
apt、dnf等这种系统级的包管理器,为什么还要使用Flatpak?- Flatpak给软件提供相对独立的运行环境(沙箱),并提供权限控制功能,避免软件破坏或任意修改系统;
 - Flatpak很大程度上解决了软件的兼容性问题,让“新系统跑旧软件”或“旧系统跑新软件”成为可能;因此Flatpak可以在非滚动更新的发行版上安装 比系统源内版本更高的软件;
 - Flatpak支持诸多发行版,在不同的发行版上能够获得几乎相同的软件使用体验;
 - Flatpak允许同一个软件的不同版本在系统内共存;
 - Flatpak允许非root用户在单用户作用域内安装软件;
 
 - 问题:我在用Snap或者AppImage,它们和Flatpak有什么区别嘛?
- Flatpak性能中等,略优于Snap,略差于AppImage;
 - Flatpak、AppImage不需要服务(Service),而Snap需要Snapd;
 - Flatpak、Snap提供权限控制功能,而AppImage不提供;
 - Flatpak、Snap统一提供所有软件包的更新,而AppImage需要打包者自行适配应用内更新或利用第三方工具更新;
 - Flatpak、Snap在发行版的预装情况方面有区别:
- Flatpak预装在这些发行版中:
- Fedora (Workstation/Silverblue/Kinoite)
 - Manjaro
 - Endless OS
 - Linux Mint
 - Rocky Linux (GNOME)
 - AlmaLinux (GNOME)
 - CentOS (GNOME)
 - EuroLinux (GNOME)
 - Pop!_OS
 - elementary OS
 - Clear Linux (Desktop)
 - PureOS
 - Zorin OS
 - MX Linux
 - KDE neon
 - ……
 
 - 而Snap预装在这些发行版中:
- Ubuntu系列 (Ubuntu Desktop, Ubuntu Server, KUbuntu, XUbuntu……)
 - KDE neon
 - Manjaro
 - Solus
 - Zorin OS
 - ……
 
 
 - Flatpak预装在这些发行版中:
 - Flatpak和Snap均得到了两个软件中心(GNOME Software Center、KDE Plasma Discover)的支持,而Appimage需要使用第三方软件中心(如prateekmedia/appimagepool、app-outlet/app-outlet(同样支持Flatpak))
 
 
什么时候不用Flatpak?
- 软件与系统结合非常紧密、不适合在沙箱中运行时不应该使用Flatpak
- 或者说,这种情况下软件很难打包成Flatpak
 - 例如:GParted、Wireshark、Virt-Manager
 - 应当考虑系统软件包管理器(
apt、dnf等) 
 - 需要软件的便携性时不应该使用Flatpak
- 应当考虑将程序打包成单个文件的AppImage
 
 - 命令行软件不应该使用Flatpak
- Flatpak有计划支持命令行程序,但目前体验不佳
- Flatpak不会自动创建软件包内程序文件的链接和别名,例如不能直接执行
go只能执行flatpak run --command=/usr/lib/sdk/golang/bin/go org.freedesktop.Sdk//21.08 
 - Flatpak不会自动创建软件包内程序文件的链接和别名,例如不能直接执行
 - 例如:Golang,Gcc,Docker,Minikube
 - 应当考虑Snap或系统软件包管理器
 
 - Flatpak有计划支持命令行程序,但目前体验不佳
 - 运行内存(RAM)或存储空间(Storage)极为有限的时候不应该使用Flatpak
- 应当考虑系统软件包管理器;
 
 
App和Runtime
Flatpak 分为两种软件包:
- Application(App):应用本体;
 - Runtime:应用所需的运行时;
 
“运行时”均是支持GUI显示的基本运行时(“没它打不开”),与桌面环境相关,一个“应用本体”只依赖一个“运行时”。
“运行时”目前主要有以下四种:
- FreeDesktop:最基础的运行时,提供D-Bus、GTK3、X11、Wayland等
org.freedesktop.Platformorg.freedesktop.Sdk
 - GNOME:GNOME=FreeDesktop+GNOME_Specific;提供Gjs、GStreamer、GVFS等;
org.gnome.Platformorg.gnome.Sdk
 - KDE:KDE=FreeDesktop+KDE_Specific;提供Qt等;
org.kde.Platformorg.kde.Sdk
 - elementary:elementary=GNOME+elementary_Specific;提供elementaryOS专属的图标、Granite等;
io.elementary.Platformio.elementary.Sdk
 
ID
每个App或Runtime都有一个ID,类似Andorid下App的包名,例如:
- (App) Blender: 
org.blender.Blender - (Runtime) Gnome Platform:
org.gnome.Platform 
加入架构和版本号,就构成了 ID三元组:
org.blender.Blender/x86_64/stableorg.gnome.Platform/x86_64/43
加入软件包类型,就构成了 该App对应的Flatpak ostree分支名:
app/org.blender.Blender/x86_64/stableruntime/org.gnome.Platform/x86_64/43
App和Extension
另一种对软件包的分类是:
- Application(App):(主要)应用,即可直接打开或运行的应用,例如:VLC、Blender;
 - Extension:应用的扩展,有多种情况:
- 支持特定应用正常运行的其他软件或库(“没它用不了”),如:Wine、FFMpeg、Mesa;
 - 特定应用所需的程序包(“没它用不好”),如:TeX环境、Rust语言(编译器)、Go语言(编译器);
 - 软件自身的一部分,如:Blender的语言文件;
 
 
对应第一种分类时,App和Runtime都可以有Extension。Extension有自己的ID,命名规则是在App或Runtime的包名后加上Extension名:
- App的Extension,例如:
org.blender.Blender.Codecs 
应用安装时,应用依赖的运行时和扩展也会被安装;
安装范围
Flatpak 有两种安装范围:
- System:系统级安装,需要root权限,安装的应用 系统上所有的用户均可见;
 - User:用户级安装,安装的应用 仅当前用户(触发安装的用户)可见;
 
软件包的源
与其他的包管理器(系统级或Snap)一样,Flatpak也有“软件源”的概念(即“软件包源”)。
Flatpak的软件包源是一个OSTree Repo,Flatpak包按照软件包类型、ID、架构与版本存储在对应的OSTree分支中;而软件包的各种信息和描述(元数据,MetaData)则存放在特定的分支中以供软件中心调取;
每个Flatpak 的OSTree Repo就是一个文件夹;一般使用HTTPd/NGINX/Caddy做HTTP服务器分发该文件夹下的文件,而Flatpak及各软件中心使用HTTP协议访问和下载OSTree Repo内的文件。
.flatpakref
.flatpakref文件描述了单个软件包的信息和获取方式,文件结构大致如下:
1  | [Faltpak Ref]  | 
示例:
1  | [Flatpak Ref]  | 
.flatpackref文件可直接用于安装软件包的命令中,也可直接使用软件中心打开;
.flatpakrepo
.flatpakrepo文件描述了单个软件包源的信息,文件结构大致如下:
1  | [Flatpak Repo]  | 
示例:
1  | [Flatpak Repo]  | 
.flatpakrepo文件可用于flatpak remote-add命令添加软件源,也可以直接使用软件中心打开;
列出已安装的软件包
只列出App:
1  | flatpak list  | 
也可以:
1  | flatpak list --app  | 
只列出Runtime:
1  | flatpak list --runtime  | 
列出System App:
1  | flatpak list --system  | 
列出User Runtime:
1  | flatpak list --user --runtime  | 
卸载软件包
卸载特定软件包:
1  | flatpak uninstall <ID>  | 
卸载所有无用(useless)的运行时和扩展(相当于 apt-get autoremove):
1  | flatpak uninstall --unused  | 
升级软件包
升级所有已安装软件包:
1  | flatpak update  | 
升级所有User范围内的软件包:
1  | flatpak update --user  | 
升级某个特定的软件包:
1  | flatpak update <ID>  | 
搜索软件包
类似apt search:
1  | flatpak search <keyword>  | 
关键字可以是ID内出现的字符串(与ID相关),也可能是软件包描述内出现的字符串(与描述有关);
在某一个源内搜索软件包:
1  | # 找带关键字的所有软件包 -> grep过滤出特定的源  | 
安装软件包
在不知道软件包的ID时,可以直接使用关键字,flatpak会查找所有匹配的项并询问要安装哪个:
1  | flatpak install <keyword>  | 
知道软件包的ID时,可根据ID直接安装:
1  | flatpak install <ID>  | 
知道软件包源和软件包ID时,可安装指定源内的某软件包:
1  | flatpak install <repo_name> <ID>  | 
- 控制安装软件的范围:加
--system或--user - 控制安装软件的版本(即安装某个旧版本而不是最新版):使用ID三元组
- flatpak可自动检测当前系统的架构,三元组可简写为二元组,例如:
org.blender.Blender/x86_64/stable->org.blender.Blender//stable 
 - flatpak可自动检测当前系统的架构,三元组可简写为二元组,例如:
 
有些情况下,软件包所在的软件包源(Repo)系统中并没有添加(比如第三方源,或者本地源),此时若软件包提供者提供了flatpakref文件,软件包可以在不添加源的情况下安装;
1  | flatpak install <flatpakref_url>  | 
修复软件包
软件包的文件丢失或出错,可以联网快速修复:
1  | flatpak repair  | 
修复操作包括校验安装的所有软件包、重新下载安装文件缺失或出错的软件包、删除没被任何ostree commit引用的文件,等。
可以使用--system和--user指定修复的范围。
查询flatpak操作历史
会列出flatpak的拉取(pull)、部署(depoly)、卸载(uninstall)等动作的历史记录;
1  | flatpak history  | 
查询软件包的详细信息
需要是已安装的软件包的ID;
1  | flatpak info <ID>  | 
会给出类似下面的输出(LANG=en-US.UTF-8):
1  | Blender - Free and open source 3D creation suite  | 
查询哪些软件包正在运行
需要以和运行软件时相同的用户身份进行查询(查询userA正在运行的软件包就su userA);
类似
docker ps
1  | flatpak ps  | 
有时只需要软件包ID或者是只需要实例ID,可以使用参数--columns=<column_name>进行输出限定;column_name是输出列的英文名称;
1  | # 只看实例ID列  | 
强制退出正在运行的软件包
与kill不同,不能用于发送信号,只能用于强制停止软件包运行;
类似
docker stop
1  | flatpak kill <ID>  | 
使用命令行运行软件包
有时需要对软件包进行这些操作:
- 查看软件包对stdout的输出(log等);
 - 给软件包增加启动参数(例如给Discord软件包增加
--proxy-server=<url>使Discord通过代理连接服务器); - 修改、增加或删除软件包中的环境变量;
 - 强制使软件包使用某个运行时;
 - 修改软件包的入口点(使用自定义的软件包启动命令);
 - 临时赋予软件包某些权限,如允许访问某些文件系统(路径等)、允许访问特定设备(共享内存等)……
 
类似
docker run
直接运行:
1  | flatpak run <ID>  | 
增加启动参数:
1  | flatpak run <ID> <params>  | 
其他常用的命令参数,参数需要放到软件包ID的前面:
- 环境变量
- 修改或增加:
--env=<var_name>=<var_value> - 删除:
--unset-env=<var_name> 
 - 修改或增加:
 - 入口点
- 修改运行软件包时执行什么命令:
--command=<command> 
 - 修改运行软件包时执行什么命令:
 - 强制指定运行时(需要ID或ID三元组)
--runtime=<ID>
 - 临时修改权限相关设置
- 文件系统:
--filesystem,--nofilesystem - 规则:
--add-policy,--remove-policy - 设备:
--device,--nodevice - Socket:
--socket,--nosocket - ……
 
 - 文件系统:
 - 其他选项可参照官方文档了解
 
进入正在运行的软件包的环境
flatpak的软件包运行在相对独立的环境中(类似于容器),因此只能通过命令进入正在运行中的软件包的环境;需要正在运行中的软件包的实例ID;
类似
docker exec
1  | flatpak enter <instance_id> <command>  | 
软件包的权限
要查看某个软件包获取了哪些权限:
1  | flatpak permission-show <ID>  | 
修改软件包的权限:不推荐直接使用命令行修改,可以使用软件包 Flatseal
若软件包出现权限问题,可尝试重置软件包权限解决:
1  | flatpak permission-reset <ID>  | 
软件包源
与直接编辑配置文件增加/删除软件源不同,软件包源是通过flatpak命令行增删和管理的;
查看当前已有的源:
1  | # 会显示源的名称(Repo name)和源的选项(Options)  | 
删除某个源:
1  | flatpak remote-delete <repo_name>  | 
添加某个源:软件包源的维护者会提供源的描述文件(.flatpakrepo),而添加源时需要这个描述文件的位置;
1  | flatpak remote-add <repo_name> <flatpakrepo_url>  | 
其他常用的命令参数
- 指定作用域:
--user,--system - 关闭GPG签名校验,测试时非常好用:
--no-gpg-verify - 本地导入源的GPG密钥:
--gpg-import=<gpg_file_url> - ……
 - 其他选项可参照官方文档了解
 
添加源时没有使用命令行参数设置选项,可在以后使用命令行修改;
1  | flatpak remote-modify <repo_name>  | 
软件包源内的软件包
查看某个软件包源内包含的所有软件包:
1  | flatpak remote-ls <repo_name>  | 
查看某软件包源内某个软件包的具体信息:
1  | flatpak remote-info <repo_name> <ID>  | 
