原文链接
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/bashsystemd_pid=if [ -z $(pidof systemd) ]; then daemonize /usr/bin/unshare -fp --propagation shared --mount-proc systemdfiwhile [ -z $systemd_pid ]do for pid in $(pidof systemd) do systemd_pid=$pid donedoneif [ -z $WHO ]; then WHO=root WD=/else WD=/home/$WHOfinsenter -t $systemd_pid -m -p --wd=$WD runuser -m -p -u $WHO zsh
使用方法:
WHO=`whoami` sudo -E ./wslsystemd.sh