我的主目录位于/z/home/$USER
,而不是/home/$USER
,因此我可以将它放在 ZFS 上。
这让 Snap 软件包非常烦躁。当我尝试运行它们时,它们显示:
抱歉,目前不支持 /home 之外的主目录。请参阅https://forum.snapcraft.io/t/11209了解详情。
当我访问该 URL 时,我得到了一个解决方法,但没有足够详细的描述来实际实施:
如果用户的主目录不在 /home 中,Snapd 目前不支持运行 snap。此处讨论了这个问题这里。
一种解决方法是将 /home 之外的主目录绑定挂载到 /home 中。
链接的主题变成了讨论如何正确支持任意主目录的设计應該是,而且我目前还不清楚如何实现所描述的解决方法。我尝试绑定挂载/z/home/$USER
也出现在/home/$USER
,并告诉 Snap 这是我的主目录,但我想要运行的 Snap 包仍然坚持我的主目录不好并拒绝运行:
$ sudo mkdir /home/$USER
$ sudo chown ${USER}:${USER} /home/$USER
$ sudo mount --bind /z/home/$USER /home/$USER
$ HOME=/home/$USER any-snap-package
Sorry, home directories outside of /home are not currently supported.
See https://forum.snapcraft.io/t/11209 for details.
那么,究竟如何才能实现 Michael Vogt 在链接的 Snapcraft 论坛帖子中描述的解决方法呢?或者说该解决方法实际上不起作用?
答案1
似乎snap
直接从/etc/passwd
而不是任何其他来源获取有关您的主目录位置的信息。我能够找到的一个最有效的解决方法是使用 Docker 容器/etc/passwd
从snap
的角度替换 ,并将其替换为一个表示我的主目录是 的容器/home/$USER
。
我确信有一种更轻量的方法可以做到这一点(也许只是一个 chroot?),这将消除一些其他我需要一种解决方法来snap
在容器内工作,我还没有尝试过minetest
,但这是我编写的脚本,它可以运行 Snap,teatime
而我不必实际移动我的主目录。基本上,它在snapd
其中启动一个容器,所有保持状态的位置都snapd
从外部安装,但使用新安装的基本状态进行初始化snapd
(这就是它需要local-persist
Docker 卷驱动程序的原因)。然后它snap
在容器中运行,就像你一样,所有 X11 和 DBUS 管道都已连接好,以便teatime
可以显示其窗口和桌面通知。
#!/usr/bin/env bash
# teatime.sh: Run the teatime snap in a Docker container
# Requires local-persist driver installed in Docker: https://github.com/MatchbookLab/local-persist
# Installs it if not available.
set -ex
IMAGE_NAME="snapdock"
CONTAINER_NAME="snaphost"
STORAGE_ROOT="/var/lib/snapdock"
PASSWD_FILE="$HOME/etc/passwd.docker"
if [[ ! -f "${PASSWD_FILE}" ]] ; then
# The /etc/passwd that claims we have a normal home directory doesn't exist.
# We need to make it.
mkdir -p "$(dirname "${PASSWD_FILE}")"
cat "/etc/passwd" | sed "s_${HOME}_/home/${USER}_g" > "${PASSWD_FILE}"
fi
if ! (docker images "${IMAGE_NAME}" | grep "${IMAGE_NAME}" >/dev/null) ; then
# There's no image ready. We need to make one
WORKDIR="$(mktemp -d)"
cd "${WORKDIR}"
cat >Dockerfile <<EOF
FROM ubuntu:18.04
# Based on https://github.com/ogra1/snapd-docker/blob/master/build.sh
ENV container docker
ENV PATH "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin"
ENV LANG C.UTF-8
ENV LC_ALL C.UTF-8
RUN DEBIAN_FRONTEND=noninteractive apt-get -q -y update && \
DEBIAN_FRONTEND=noninteractive apt-get -q -y upgrade && \
DEBIAN_FRONTEND=noninteractive apt-get -q -y install \
fuse \
snapd \
snap-confine \
squashfuse \
sudo && \
apt-get clean && \
dpkg-divert --local --rename --add /sbin/udevadm && \
ln -s /bin/true /sbin/udevadm
VOLUME ["/sys/fs/cgroup"]
STOPSIGNAL SIGRTMIN+3
CMD ["/sbin/init"]
EOF
docker build . -t "${IMAGE_NAME}"
cd -
rm -Rf "${WORKDIR}"
fi
if ! which docker-volume-local-persist >/dev/null ; then
# We need the local-persist driver installed into Docker.
WORKDIR="$(mktemp -d)"
cd "${WORKDIR}"
curl -fsSL "https://raw.githubusercontent.com/MatchbookLab/local-persist/45c5c344d5dfd358c28d7148be48302d20456fac/scripts/install.sh" >install.sh
chmod +x install.sh
cat install.sh
sudo install.sh
cd -
rm -Rf "${WORKDIR}"
fi
if ! (docker ps --filter "name=${CONTAINER_NAME}" | grep "${CONTAINER_NAME}" >/dev/null) ; then
# Container is not running. Start it.
if [[ ! -e "${STORAGE_ROOT}" ]] ; then
# Make sure we have the directories to mount
mkdir -p "${STORAGE_ROOT}/lib"
mkdir -p "${STORAGE_ROOT}/cache"
mkdir -p "${STORAGE_ROOT}/systemd"
mkdir -p "${STORAGE_ROOT}/snap"
sudo chown -R root:root "${STORAGE_ROOT}"
fi
# Start the container
docker run --rm --network=host --cap-add SYS_ADMIN --security-opt apparmor:unconfined --security-opt seccomp:unconfined --volume="$(echo ~:/home/${USER})" --volume="${PASSWD_FILE}:/etc/passwd:ro" --volume="/etc/group:/etc/group:ro" --volume="/etc/shadow:/etc/shadow:ro" --volume="/etc/sudoers.d:/etc/sudoers.d:ro" --volume="/tmp/.X11-unix:/tmp/.X11-unix:rw" --volume="/sys/fs/cgroup:/sys/fs/cgroup:ro" --volume="/lib/modules:/lib/modules:ro" --device=/dev/fuse --tmpfs /run --tmpfs /run/lock --volume="/run/user/$(id -u):/run/user/$(id -u):rw" --tmpfs /tmp --volume="${STORAGE_ROOT}/lib/:/var/lib/snapd:rw" --volume="${STORAGE_ROOT}/cache/:/var/cache/snapd:rw" --mount "type=volume,volume-driver=local-persist,src=installed-snaps-systemd,target=/etc/systemd/system,volume-opt=mountpoint=${STORAGE_ROOT}/systemd" --mount "type=volume,volume-driver=local-persist,src=installed-snaps-snap,target=/snap,volume-opt=mountpoint=${STORAGE_ROOT}/snap" -it --name="${CONTAINER_NAME}" -d "${IMAGE_NAME}" >/dev/null
# Wait for it to come up
sleep 5
fi
# Make sure the snap is installed
docker exec snaphost snap install teatime
# Try and fail to run it as root to avoid complaints about not being able to capture mountpoints when we run it as us.
docker exec snaphost teatime || true
# Run it as us with X11 and Dbus set up
docker exec -d --user="$(id -u ${USER})" --env="DISPLAY" --env="DBUS_SESSION_BUS_ADDRESS" snaphost teatime