如何让Snaps访问/somedir

我只是刚开始尝试使用 Snap。我已经安装了 VLC 并想尝试使用它。我的所有媒体文件都安装在 /store 下,这是一个 NFS 挂载点。而 Snaps 不允许访问那个目录。

经过搜索,我了解到我可以通过 :home 接口访问 /home/peter 下的文件,以及通过 :removable-media 接口访问 /media 目录下的文件。

但是我实际上喜欢 /store,不想将其改为 /media/store/home/peter/store 或其他任何非 /store 的名称。

有没有办法让 Snap 允许我的 Snaps(或者也许只是 VLC)访问 /store,这样 Snap 就符合我的命名约定了?或者我被迫转换为 Snap 的偏好设置?

这似乎非常死板,我希望我漏掉了某些东西。


2你可以尝试移除 snap(sudo snap remove vlc),然后使用经典选项重新安装。可能会有帮助,也可能不会。(sudo snap install vlc --classic - doug
5谢谢。我尝试了--classic--devmode,但都没有起作用。但是我还想明确地给予对/store的访问权限,而不是像/supersecret那样开放一切。 - Peter V. Mørch
5有关于Snap的任何票据/错误/功能请求吗?我也想要那个功能! - kravemir
1这不是最初的问题,但如果有其他人和我一样,想知道如何给予/snap下的/media访问权限(例如,使用Darktable时没有该权限基本上无法使用),你可以通过snap-store界面或在命令行中为你的snap应用程序添加removable-media 'plug'来实现。这里有一些文档:https://snapcraft.io/docs/interface-management - Daniel Murray
1@kravemir: 请查看Launchpad问题1643706 - Peter V. Mørch
7在处理这类问题之后,我有一个很大的建议:摒弃Snap。Snap真的不应该决定我作为机器和操作系统的所有者和管理员可以或不可以使用哪些目录。对我来说,这就像限制grep功能,不允许搜索某些词一样,真的对Snap感到失望。 - tonio
简而言之:你不能。设计糟糕,不注重用户体验。 - Alfonso Nishikawa
6个回答

惊讶地,它真的看起来像是硬编码了 /homemount-support.c 包含:
    const struct sc_mount mounts[] = {
        {"/dev"},   // because it contains devices on host OS
        {"/etc"},   // because that's where /etc/resolv.conf lives, perhaps a bad idea
        {"/home"},  // to support /home/*/snap and home interface
    ...

哇。这让我感到惊讶。但是就是这样。
编辑:另请参阅Launchpad问题1643706

7嘿,我是snapd开发者,负责那段代码。令你惊讶的是,这实际上是正确的做法。我们无法复制主机文件系统及其可能包含的任何随机目录。虽然你可以使用/store,但其他人可能会使用/stash或/whatever,通常无法使其正常工作。我的建议是将媒体简单地挂载到你所需的位置,可以是/home/...或/media。这样它将纳入管理该数据的现有系统,并且应该能够正常工作。 - Zygmunt Krynicki
如果snap已连接可移动介面,@ZygmuntKrynicki或在/mnt下。 - jarno
37@ZygmuntKrynicki 我也感到惊讶。默认挂载点应该通过配置文件进行配置,而不是强制执行。 - markhor
39@ZygmuntKrynicki 感谢你的光临并解释代码的意图。我非常尊重地完全不同意你的观点。硬编码路径是非常糟糕的做法,即使以安全为名也无法有意义地证明其合理性。这只是基本的不灵活性。 - Stéphane Gourichon
8@ZygmuntKrynicki没有人要求复制任意路径。然而,对于特定情况的一般解决方案似乎应该是配置而不是硬编码,是吧? - 0xC0000022L
7@ZygmuntKrynicki:对于将加密卷挂载在像/veracrypt这样的路径上的人来说怎么办?白名单路径是不是根本不可能? - Dan Dascalescu
10@ZygmuntKrynicki — 自从至少在1980年代初(或许更早)以来,硬编码已经被废弃了,有很好的理由。请您考虑使用配置文件。这对我们中的一些人造成了严重问题。 - Paddy Landau
好问题,但说实话,这个答案并不是它的答案。看起来SNAP正在以最佳方式进行安全性保密。 - Thomas
2想法:让这个工作与Docker类似,您可以明确地将卷或文件夹提供给容器。当我运行snap时,我可以执行snap --allow-write /foo/Movies,或者任何我想做的事情。 - Hugh Perkins
2为什么我要让一个快照能够读写我的整个主文件夹呢?限制权限有什么意义,然后又给它访问所有我的数据的权限!:O - Hugh Perkins
我觉得有机会让某人创造出一个能够读取和运行快照的东西,但对权限有更好的控制。当然,迟早Snap团队可能会将这个想法融入到他们自己的工作中。但考虑到我们目前看到的对改变的抵制,你在他们采取行动之前可能已经占据了50%以上的用户市场份额。 - Hugh Perkins
2@HughPerkins:你的评论不需要括号。这是对硬编码论点荒谬性的又一个例证。 - Peter V. Mørch
他们这样做真是太愚蠢了。完全没有理由去为硬编码进行辩护。 - Alfonso Nishikawa
虽然这篇帖子是正确的,但并不是答案。请向下滚动至https://askubuntu.com/users/184404/kat-amsterdam 以获取解释和解决方案。 - user3054986
@ZygmuntKrynicki 我把我的照片光盘挂载在/photos上,我希望它们就在那里(这不仅仅是出于个人偏好,还是为了与我的妻子共享这个目录)。所以现在我无法保存通过WhatsApp收到的照片,因为有人随意决定哪些目录是可以的,哪些目录是不可以的。 不确定是谁发明了保护/some/random/dirs的概念,同时又给予/home完全访问权限,但我们有一个完美运作的Unix权限系统,让我们能够清楚地指定权限。想要更严格一些?好的,让我授予某个组或用户权限,以标记哪些快照可以执行什么操作。 - undefined

只需像不是快照一样运行该应用程序 \o/
所以例如 chromium
  1. 使用菜单编辑器,例如“主菜单”,添加一个自定义的Chromium“菜单项”(这是Ubuntu在按下super+a时查找应用程序的方式):
  2. 设置名称,例如:Chromium Unsnapped
  3. 设置命令:/snap/chromium/current/usr/lib/chromium-browser/chrome --user-data-dir=~/ChrUnsnapped --class="ChrUnsnapped" %U
  4. 设置图标,例如下载一个复古的Chromium标志
  5. 保存/关闭
  6. super+a(或在左下角显示应用程序图标),找到您的新项目,右键单击将其添加到收藏夹 enter image description here

<抱怨>

我对Snap真的很沮丧,我无法像过去15年那样配置我的个人/stf目录。谢天谢地有这个hack,看来我将不得不为每个该死的Snap应用程序都这样做 :'(。

是的,我知道这很糟糕,但在有白名单配置之前,这似乎是恢复正常的唯一方法。我真的不想把我的东西放在/home、/mnt、/media,请不要讨厌你的用户。

</抱怨>


1我不明白你做了什么。这个设置有什么区别呢?比如说,你能用Chromium打开/tmp目录下的文件吗? - leogama
是的,我可以使用未损坏的Chromium访问我的真实/tmp目录。你可以尝试在命令行上手动运行命令/snap/chromium/current/usr/lib/chromium-browser/chrome --user-data-dir=~/ChrUnsnapped --class="ChrUnsnapped" %U。其余的只是为了创建一个启动图标。 - AmanicA
4好的,只是为了澄清一下:选择这个路径,我们是明确地绕过Snap confinement,以标准用户权限运行应用。它不会在~/snap/appname/{common,current}/中读写文件(设置、缓存等),而是在其默认位置$HOME内进行。这样做没有问题 - 我用它来创建Chrome SSB - 但是你需要理解自己在做什么。 - leogama
2我猜这个方法在新版本的Snap上不起作用,因为它只是将二进制文件符号链接到/usr/bin/snap本身。 - rogerdpack
太棒了,至少有一种方法可以运行 Snap 应用程序... - LetynSOFT

所以,有两件事。
第一:Linux和Unix有一个文件系统层次结构标准,Ubuntu和Snaps遵循这个标准。 https://en.wikipedia.org/wiki/Filesystem_Hierarchy_Standard 第二:如果选择偏离自1979年以来一直存在的全球标准,那完全可以,但是请将非标准目录绑定挂载,以便snap能够找到它。
mount --bind /nonstandard_mountpoint /media/$USER/directory

或者

mount --bind /nonstandard_mountpoint /home/$USER/directory

然后你可以继续使用你的非标准挂载点,同时所有的快照都能找到你的非标准挂载点数据。
甚至可以通过将其添加到你的FSTab中使这个挂载点变为永久挂载。
sudo nano /etc/fstab

追加这行
/source /destination none defaults,bind 0 0

保存并退出
CTRL+X y

这是一个例子: 音乐文件存储在 /srv/dsmusic
首先,在 /home/$USER/Music 目录下创建一个名为 dsmusic 的文件夹。
mkdir /home/$USER/Music/dsmusic

然后将/srv/ds音乐绑定到该目录
sudo mount --bind /srv/dsmusic /home/$USER/Music/dsmusic

然后,你所有的快照音乐程序都会自动地找到音乐文件。
继续音乐示例:
sudo nano /etc/fstab

追加这行
/srv/dsmusic    /home/username/Music/dsmusic    none    defaults,bind    0 0

** 卸载中 **

如果您想要卸载,可以像普通挂载点一样使用常规的umount命令。

sudo umount /home/$USER/Music/dsmusic

更多信息请参见: https://unix.stackexchange.com/questions/198590/what-is-a-bind-mount

SystemD

** 请注意,使用 SystemD 而不是使用 fstab 进行此操作有一种更现代的方法。

要在 SystemD 中创建绑定挂载点,您需要创建一个 .mount 文件,并将非标准挂载点的路径用 -(减号)分隔而不是正斜杠(/)。

sudo systemctl edit --full --force path-nonstandard.mount

过去以下并编辑挂载点
[Unit]
DefaultDependencies=no
Conflicts=umount.target
Before=local-fs.target umount.target

[Mount]
    What=/some/old/dir
    Where=/the/new/dir
    Type=none
    Options=bind

[Install]
WantedBy=local-fs.target

如果nano是默认编辑器 CTRL+X y(用于nano) :wq(用于vim)

启用systemD文件

sudo systemctl enable path-nonstandard.mount

然后重新加载SystemD守护程序。
sudo systemctl daemon-reload

然后用以下方式启动您的安装。
sudo systemctl start path-nonstandard.mount

如果你需要再次修改它,只需
sudo systemctl edit --full path-nonstandard.mount

例子: 再次以音乐为例:

sudo systemctl edit --full --force srv-dsmusic.mount

这将打开一个空白编辑器,并在正确的系统文件夹中创建一个新的.mount文件,然后添加相应的行。
对于同一硬件上的本地挂载点:
[Unit]
DefaultDependencies=no
Conflicts=umount.target
Before=local-fs.target umount.target

[Mount]
    What=/srv/dsmusic
    Where=/home/username/Music/dsmusic
    Type=none
    Options=bind

[Install]
WantedBy=local-fs.target

请注意,如果您的非标准挂载点是NAS或其他远程设备,您需要使用remote-fs.target而不是local-fs.target。
对于不同硬件(如NAS)上的远程挂载点。
[Unit]
DefaultDependencies=no
Conflicts=umount.target
Before=remote-fs.target umount.target

[Mount]
    What=/srv/dsmusic
    Where=/home/username/Music/dsmusic
    Type=none
    Options=bind

[Install]
WantedBy=remote-fs.target

然后退出编辑器 CTRL+X y(对于nano) :wq(对于vim)
启用systemD文件
sudo systemctl enable srv-dsmusic.mount

然后重新加载systemD守护程序。
sudo systemctl daemon-reload

然后开始你的新挂载点
sudo systemctl start srv-dsmusic.mount

卸载绑定挂载只需执行以下操作
sudo systemctl stop srv-dsmusic.mount

您现在可以在/srv/dsmusic找到您数据的镜像,snap也可以在/home/$USER/Music/dsmusic找到相同的数据。
更多信息请参阅:https://utcc.utoronto.ca/~cks/space/blog/linux/SystemdBindMountUnitshttps://www.freedesktop.org/software/systemd/man/systemd.mount.html

3我有一个疑问,也许你可以在回答中解答一下:如果/mnt是用于临时挂载,而/media是用于可移动介质,那么对于不属于系统安装的额外硬盘来说,标准的挂载位置是什么呢?特别是当用户的主目录被加密并且在登录之前没有挂载的情况下。 - Emilio
这应该是被接受的答案。SNAP的限制是有意为之的,它旨在强制采用FHS。然而,它并不阻止用户从其用户文件夹访问外部目录,只要源和目标被绑定挂载,就像你解释的那样。做得好。 - Yuri Sucupira
1在@Emilio的评论上进行扩展,请参阅在“/”中应该将额外的永久磁盘挂载在何处? - davidvandebunte
2Snap非常用户友好,毫无疑问。 - Alfonso Nishikawa
2我认为这个回答完全没有抓住重点。它应该是用户可配置的。例如,我可能希望让LibreOffice访问/mnt/super-secret-project,但不允许VLC。然而,这也是不可能的。 - Peter V. Mørch
1一般来说,通过/etc/fstab配置挂载点是管理挂载的首选方法。对于工具,应优先编写挂载单元而不是编辑/etc/fstab。 - sourcejedi
首先,Linux拥有一个我们愉快地使用、理解并且具备丰富工具的权限系统。然而,某人决定自己比我们更清楚我们想要将文件保存在哪里以及哪些文件需要更多的保护,并将其硬编码进去。因此,当我尝试保存文件时,出现了一个神秘的文件保存窗口,我的主目录默默地跳过了符号链接,大多数书签也无法正常工作。抱歉发牢骚,但我又浪费了一个小时。我打算移除所有的Snaps并安装Debs或Flatpaks。 - undefined

所以,对于我上面的简短回答,没有一种通用、安全且可靠的方法来实现。我知道每个人都喜欢自定义他们的文件系统,但这也有一些代价,这就是其中之一。
最终,通过XDG门户的工作,某些应用程序(尤其是图形应用程序)可以在任意位置访问文件,前提是这些应用程序使用了最近引入的GTK API之一。当在限制环境下运行时,它会与一个受信任的助手进行通信,弹出一个看起来像文件选择器的受信任的用户界面,与一个特殊的FUSE文件系统进行交互,将文件(无论位置如何)作为/run/...中的一个特殊对象展示给应用程序,从而使得事情可能顺利进行。
这个设计适用于文件选择器友好的应用程序,比如媒体播放器或文字编辑器。不过,你在/codez目录下托管的Linux树可能效果不太好。

15嗨Zygmunt,谢谢你的回答。我感到非常惊讶。你说:“我知道每个人都喜欢自定义他们的文件系统,但这是有代价的,而这就是其中之一。”所以,我理解对了:你意识到了,但选择忽视这是一个普遍的需求吗?在过去的15年里,我没有意识到还有其他的代价与这种命名约定相关。 - Peter V. Mørch
25有没有任何理由不能在/etc/snapd.conf/etc/snapd/conf.d/vlc.conf中添加类似于extradirs=/store:/other/location的行。就像其他许多Linux应用程序一样。这对于Docker等应用程序来说似乎工作得很好。这就好像Apache硬编码了DocumentRoot /var/www一样。 - Peter V. Mørch
6我真的很感激你抽出时间在这里写,Zygmunt。谢谢。 - Peter V. Mørch
3这并不容易。主要问题不是apparmor,而是在运行时应用程序在一个不同的根文件系统中运行。从该进程的角度来看,/store不存在 - 不是它没有被挂载,而是根本就不是一个目录。snap-confine所做的是将一些路径从主机系统带入应用程序的挂载命名空间中。由于snaps中的根文件系统是只读的,我们无法轻松地注入新的挂载点(例如/store)。 - Zygmunt Krynicki
@PeterV.Mørch你可以将那些文件挂载或移动到/mnt下,确保可移动介面已连接到Snap,并在原始位置创建符号链接(如果需要)。 - jarno
9@jarno: 请阅读原帖:“我实际上喜欢/store”。我知道我可以将文件移动或重新挂载到snap喜欢的位置,_但我不想这样做_。 - Peter V. Mørch
1哎呀?这对我没用。如果我把文件放在/mnt/ost.txt,然后运行snap gedit,它可以正常打开。但是如果我把文件移动到/media/ost.txt(这似乎与文档相矛盾),就无法打开了。但是将/mnt/ost.txt创建为指向/ost.txt的软链接也不起作用。(如果起作用的话,这也将是一个巨大的安全问题) - Peter V. Mørch
@PeterV.Mørch 哦,对我在18.04版本中也没有起作用。但是可以使用/media/$USER下的文件。顺便说一句,我没有收到任何通知,因为你没有提到我。 - jarno
@jarno:正如我在原帖中所写的:“但实际上,我喜欢/store,并且不想将其更改为/media/store或/home/peter/store或任何其他不是/store的路径。” - Peter V. Mørch
@PeterV.Mørch 抱歉,我不记得为什么我认为符号链接目录会起作用。 - jarno
7@Zygmunt Krynicki - 鉴于“每个人都喜欢自定义他们的文件系统”,这显示了使用snap模块是多么不可取。作为系统管理员,我完全看不出任何优势来利用snap模块,除非是一些非常专门的实用工具。对于诸如媒体查看器、文件浏览器等通用程序而言,使用snap需要对现有系统进行大规模重新配置和大量冗余文件复制。除了能够使用一些Ubuntu现在强制我们安装的snap模块之外,没有任何积极的优势。 - HippoMan
1我甚至没有定制我的文件系统,我只是喜欢在临时工作中使用/dev/shm,因为我不想把它保存到固态硬盘上。 - Michael
2我还是不明白为什么我可以使用docker run-v选项在任何来自互联网的Docker镜像上挂载任意目录,但对于Snaps来说却不可能。它们都是相同的底层技术和相同的问题,这里有什么区别呢? - pkubik
@PeterV.Mørch 我同意你的观点:应该有一个简单的应用程序来配置快照,你可以在其中查看你的快照并配置更多位置。简单而整洁。 - Alfonso Nishikawa
这是否意味着一个快照应用程序无法永远访问存储在ZFS上的文件(遵循ZFS命名约定,不使用/media或/mnt作为挂载点),并且这些文件太大无法复制到RAM或托管/home的机器的小型引导磁盘上?为什么在这个限制中技术上需要排除符号链接(以及根据https://askubuntu.com/a/1096079/54298所述的绑定挂载)? - undefined

将目标目录挂载到/home/*/snap/被提及为一种选择;对我来说,简单的绑定挂载、硬链接或符号链接都不起作用,无论是将目标文件还是目录的符号链接到建议的snap目录中,或者其任何子目录。这个限制可能是因为目标文件存在于/home/*/目录之外,我没有测试在/home/*/前缀通配符内挂载/硬链接/符号链接到文件。

然而,有一个解决办法:将完整的文件复制到/home/<myuser>/snap/<appname>/<somenewdirectory>对我有效。对我来说,保持完整数据集的副本仍然不可行,但有很多工具可以帮助应对这样的约束; 如果您的数据集很小甚至是原子的,可以在使用snap之前手动递归复制,并在之后将修改过的文件复制回去。

以下是一些可能对您有所帮助的文件复制工具:

  • cp --verbose --archive --recursive /somedir ~/snap/somedir,并且源目录和目标目录可以互换
  • tar -C / -c somedir | tar -C ~/snap/ -xv 是一个基于tar的文件复制示例
  • rsync --archive /somedir ~/snap/somedir,rsync非常流行,并且有许多包装器/扩展

  • 任何基于文件的备份工具(图形化示例:grsync)应该是可用的,因为整个目标是根据需要前后复制数据集

  • 可能可以使用git克隆,但是默认情况下本地克隆使用硬链接,所以如果你正在使用git来管理对快照的文件系统IO,请注意在克隆时禁用硬链接,否则该git克隆可能无法访问。


6这在一个常见的使用情况下是行不通的,比如NFS挂载的多TB级别的NAS驱动器。 - Peter V. Mørch
2将文件复制到某些快照安装中也会破坏像Veracrypt这样的安全驱动器的目的。 - Dan Dascalescu
8@ThorSummoner - 现在不得不使用这些复制工具只是为了使用基于snap的程序,对用户和系统管理员来说是一种巨大的时间、精力和硬件资源的浪费。事实上,Ubuntu不再允许我们下载非snap版本的某些程序,这迫使我们要做额外的工作。对终端用户或系统管理员来说,并没有任何优势来执行这些繁琐的任务。从这个意义上说,snap是自我打败的,因为它鼓励用户和管理员使用它,并切换到不需要它的发行版。 - HippoMan
6sudo snap remove --purge <app> && sudo apt install <app> - Matthieu
2@Matthieu 应该是被接受的解决方案!虽然我很确定这在Ubuntu上不起作用,因为Canonical强制使用apt配置文件来触发切换,以便无论如何都安装snap版本的<app>。现在我建议用户从Debian仓库安装,或者也许使用不断发展的nix软件包管理器。编辑:糟糕,没有看到HippoMan在上面解释了同样的事情的评论 - mikerover
最近我遇到了一个情况,通过snap connect系列命令,可以让两个快照进行“允许通信”。我不知道这是否扩大了使用范围,也许可以将一个目录与一个快照“连接”起来。如果有人了解更多信息,请告诉我们 :) - ThorSummoner
有一些文件是无法复制的,比如Unix套接字。当我试图使用Snap Workbench连接到通过Unix套接字暴露的MySQL服务器时,我发现这非常令人沮丧(我没有找到任何解决方法,只能继续使用MySQL命令行工具)。 - ThorSummoner
1现在是2021年,使用mount --bind命令,并且目标位置对Snap应用可读,在我的情况下有效。我正在使用Ubuntu桌面版20.04上的snapd版本2.48.3。 - leogama

如果你变得绝望,还有一些其他选择:
  1. 使用unsnap实用程序 - 这是一个有点先进/尖端的工具,但在Ubuntu上可以完成。
  2. 使用flatpak-remix - 如果你正在进行新安装,这可能会很有用,但请注意它不是官方版本的哦 :'(
  3. 尝试linux-mintdebianPop!_OS - 如果你想尝试其他发行版,就像其他人为了摆脱snaps而做的那样。