假设我有一个基本的 shell 脚本 foo.sh:
#!/bin/sh
while [ 1 ]
do
echo "looping"
sleep 1
done
我想将其作为命令提出:/snap/bin/myapp.foo
我有 snapcraft.yaml:
apps:
foo:
command: opt/foo/bin/foo.sh
parts:
foo:
source: .
plugin: dump
organize:
foo.sh: opt/foo/bin/foo.sh
这会产生一个文件/snap/bin/myapp.foo
,但它是指向 /usr/bin/snap 的链接。运行该命令时,我遇到了分段错误。
为此设置 snapcraft.yaml 的正确方法是什么?我想知道我是否必须打包sh
到 Snap 中?或者 shell 脚本是否不适用于 snap?
答案1
好吧,有两件东西缺失了。
1) 在命令部分下,应使用 $SNAP 环境变量。您创建的所有部分将在运行时相对于该环境变量进行存储。
2) 不要直接调用 shell 脚本,而是指定解释器(本例中为“sh”)。如果没有这个,脚本就会失败。
apps:
foo:
command: sh $SNAP/opt/foo/bin/foo.sh
parts:
foo:
source: .
plugin: dump
organize:
foo.sh: opt/foo/bin/foo.sh
附录 1:事实证明,对我的使用来说真正重要的因素是在 Ubuntu 18 中,Snap 与 Ubuntu 16 中的 libc 版本绑定。这导致 Snap 需要将 Ubuntu 18 的 libc6 吸收到我的 Snap 中,这反过来会与 bash 和 dash/sh 等产生冲突。
如果您尝试运行 shell 脚本并看到段错误,则可能与此有关。进程尝试调用 shell 脚本,读取顶部的“shebang”(“#!/bin/bash”),当它运行 /bin/bash 时,会发生 libc 冲突。
附录 2:对于父进程启动 shell 脚本的情况,请注意顶部的“shebang”语句可能无效。例如,“#!/bin/sh”将无法正确解析,因为实际路径将是“$SNAP/bin/sh”,它将解析为“/snap/project-name/project-revision/bin/sh”之类的内容。
为了解决这个问题,请确保将 PATH 环境传递给程序,并将 $SNAP 前缀到每个相关路径。然后调整父程序以使用解释器调用脚本,例如“bash child.sh”与“child.sh”。