共计 862 个字符,预计需要花费 3 分钟才能阅读完成。
原文链接
WSL2 因为是基于 Hyper- V 虚拟化的一个 Linux,因此我想着在 WSL 里跑 Docker。当我高高兴兴地安装好了 Docker 之后发现不能启动,因为 PID 为 1 的进程不是 systemd,而是 init,让我这个菜鸡呆了。一番搜索之后发现有人在 GitHub 给出一个解决方案,Genie,原理是利用 Linux namespace 实现隔离,在隔离出的空间里运行 systemd,这样 systemd 的 PID 就是 1 了。
看过代码之后得到里几个关键的命令
- unshare:在新的 namespace 里运行命令。man page
- nsenter:在某个 namespace 里运行命令。man page
- runuser:切换执行命令的用户。man page
我们的步骤是
- 用
pidof
检查是否有systemd
进程,有则跳到 3,否则 2。 - 让
unshare
运行systemd
,这样systemd
在新的 namespace 里的 PID 就是 1。整个命令用daemonize
命令执行,这样创建出来的systemd
以后台进程形式一直运行。 - 用
nsenter
和runuser
进入新创建的 namespace 里以某个用户身份运行 shell。
于是我们可以得到这样的一个脚本,GitHub 传送门
#!/bin/bash
systemd_pid=
if [-z $(pidof systemd) ]; then
daemonize /usr/bin/unshare -fp --propagation shared --mount-proc systemd
fi
while [-z $systemd_pid]
do
for pid in $(pidof systemd)
do
systemd_pid=$pid
done
done
if [-z $WHO]; then
WHO=root
WD=/
else
WD=/home/$WHO
fi
nsenter -t $systemd_pid -m -p --wd=$WD runuser -m -p -u $WHO zsh
使用方法:
WHO=`whoami` sudo -E ./wslsystemd.sh
正文完