Snap 的哲学

来源:互联网 发布:编程入门培训 编辑:程序博客网 时间:2024/05/21 14:56

如果你是初次接触 snap 这种包格式,并且好奇它和其它传统包格式的区别;如果你想知道如何架构你的应用程序包并从原型开始迭代直到其工作,那么这篇文章就是专门为你准备的。

Snap 包是什么?

Snap 包:

  • 是一个 SquashFS 文件系统,其中包含有应用程序的代码和一个含有特定元数据的 snap.yaml 文件。它是一个只读的文件系统,一旦安装,还会有一个可写的区域。

  • 是自包含的。它捆绑了大多数运行时需要的库,并且可以在不影响系统其他部分的情况下更新和回退。

  • 通过安全机制受限于 OS 和其他应用程序,但是可以通过由用户和操作系统默认值控制的细粒度策略与其他 snap 包交换数据和功能。

Snap 的哲学

可重定位的代码

构建 snap 包时我们首先需要理解一个重要概念 —— 那就是你的应用程序是 可重定位的。Snap 包不再依赖诸如 /etc 之类的绝对路径,而是从应用程序的子文件夹中读取相应的资源(assets)、配置和钩子(hooks)。应用程序的一种常见方法是先读取一些本地文件夹,然后通过一个相对路径找到可执行文件,最后再返回全局的那个。

这可以让应用程序能够在你的开发目录中工作,从而使测试人员只用从你的 VCS 下载它就可以以测试一个新特性,而不依赖于任何全局的安装。这同时也使得 写-调试-修复 循环变得更加容易。

注意,你也可以使用环境变量来改变应用程序正在使用的路径。
然后,只需基于 $SNAP$SNAP_DATA$SNAP_USER_DATA 在包装器脚本(snap 包中的命令会指向这些脚本)中设置这些环境变量,就可以知道到哪里去读写数据和资源。

加入你自己的依赖

另一个我们需要理解的概念是 —— 你可以控制应用程序所需的所有依赖项。这意味着应用程序不会再因系统的更新而损坏,因为每个 snap 包都包含了其运行时需要的所有的东西,并且会按照自己的步调来更新。

总而言之,你的 snap 包将只会看到 snap 包本身包含的库文件和第三方依赖以及 core snap 包 。后者主要提供一些系统库,如网络访问和设备节点等。所有依赖都将做为 snap 包的一部分,所以不要通过绝对路径来使用它们。Snapcraft 通过创建一个主包装器脚本,在 snap 文件夹下重定向库的加载目录,然后再回退到系统中的那个。包装器脚本的内容取决于你所使用的技术(通过重新定义 PYTHONPATHLD_LIBRARY_PATHGEM_HOMEPATH 等)。

Kazam_screenshot_00003.png-26.3kB

将数据写入用户路径

你并不能将 snap 包的数据写到每个用户可写的路径中。Snap 相关的数据被限制在很小的范围内。这是为了使回滚机制能够在不考虑代码版本的情况下恢复数据,确保数据和代码始终兼容。

因此,请使用 $SNAP_USER_DATA 指定的路径保存用户数据。如果某些全局配置需要让多个用户可读写,可以使用 $SNAP_DATA 。记住,只有 root 用户才有权限读写 $SNAP_DATA 所表示的路径。

你可以在包装器脚本中使用前面描述的环境变量,也可以直接 cd$SNAP_USER_DATA

命令 vs 版本化路径

前面提到的路径是版本化的。这意味着对于每次更新 snap 包时,这些内容都会被复制到一个新的目录。

有些数据是不需要进行版本管理并且占用空间较大的资源(即使回滚,也没有特定于某个版本的配置或者数据格式)。这种情况下,你可以使用 $ SNAP_USER_COMMON$SNAP_COMMON 两个环境变量,这和它们对应的 *_DATA 有类似的权限。

但是,就像它们的名字所暗示的,这里数据的任何改变都会影响 snap 包所有的版本(磁盘中只有一份数据的实例),因此这里不应该包含任何特定版本的信息。如果你希望保持向后兼容,我们不建议在该目录中保存配置(这可能会随着版本的变更而改变格式)和存储数据,即使是数据库文件。

你可以这样来思考:如果我将 snap 包恢复到以前的版本,它能够读取 COMMON 目录中的所有数据吗? 如果答案是否定的,就将其中的一些数据移动到对应的版本中。别担心,我们有一个很棒的垃圾回收机制,它只会 为 snap 包保留几个可工作的版本。

总是在开发模式下开始 snap 包的开发

选择合适的 confinement 是一个具有挑战性的话题。调整这个键值的时候,你必须确保你的代码是可重定位的,因为将所有的依赖都包含在一个只读的系统中很有可能会出现一些问题。

因此,你总应该在开发模式下开始 snap 包的开发:确保 snapcraft.yaml 文件中定义了 confinement: devmode,并且安装软件包的时候需要加上 –devmode 选项。然后不断迭代直到程序开始工作。完成后,打开系统日志文件(/var/log/syslog),你也许会看到一些带有 ALLOWED 标记的 apparmorseccomp 的警告。这意味着你有一些约束工作要做,你需要在 snap 中添加正确的接口插头(plugs)。

接下来,你就可以在非开发模式下安装你的软件包,然后根据 snappy-debug.security(来自 snappy-debug 包)反馈的结果增加需要的接口配置,使用这个模式进行迭代直到系统日志中不再有 DENIALS 提示并且已约束的 snap 包也能工作。

不要请求太多的权限

有些接口在安装时会自动连接,有些则不会。这意味着你使用的插头越少,就可能有更多的人愿意安装你的 snap 包。对于那些不能自动连接的接口,试着让它们成为可选的,并在代码中进行提示适当,以解释为什么最好开启这个特性,或者它为什么是必需的。

1419363825.jpg-77.9kB

原创粉丝点击