Search

[WSL2] systemd 삽질기

요약
[boot] systemd=true
게시일
2021/11/14
태그
WSL
1 more property

업데이트

2022.10.14

wsl 0.70.0에서 드디어 systemd를 지원한다. Windows 11에서는 지원되는데 Windows 10에서는 어떤지 모르겠다. /etc/wsl.conf 파일에 다음과 같이 설정한다.
[boot] systemd=true
JavaScript
복사
아래 내용은 더 이상 필요하지 않다. 기록 차원에서 남겨둔다.
WSL2에서 모든 프로세스를 제어하는 init 데몬인 systemd를 사용할 수 없다. 나처럼 시스템 부팅 단계에서 프로세스를 올려 작업을 하는 상황이 필요하다면 참 아쉽다. WSL2에서 systemd를 사용하는 방법을 구글링해보면 여러가지 방법이 나오는데, 거의 대부분 부작용이 있다. 그러다 그 중에서 가장 괜찮아 보이는 방법을 찾았다: https://github.com/shayne/wsl2-hacks
근데... 이대로 따라해도 뭔가 제대로 되지 않는 느낌적 느낌이 있다. 몇 가지를 더 해줘야 한다. 어차피 영어라 저거 다 읽기 귀찮을 분도 계실테니 그냥 전체 과정을 적어본다. 결론부터 말하자면,
systemd를 쓰려면 희생해야 할 것이 많아서 쓰지 않기로 했다.

daemonize 데몬 설치

모두 3개의 패키지(dbus, policykit-1, daemonize)가 필요하다. Windows 11에 설치되는 WSL는 WSLg를 지원하는 이유로 이미 dbus, policykit-1이 설치되어 있어서 건너뛰었다.
목차
sudo apt install -y daemonize
Shell
복사

wsl2hack 스크립트 구성

다음 명령을 실행한다.
sudo touch /usr/local/bin/wsl2hack sudo chmod +x /usr/local/bin/wsl2hack sudo vi /usr/local/bin/wsl2hack
Shell
복사
이제 아래 내용을 복사해 /usr/local/bin/wsl2hack으로 저장한다. <YOURUSER>에 자신의 WSL 로그인 id 넣는 걸 잊지 말자.
#!/bin/bash # your WSL2 username 여기에 반드시 wsl에 사용하고 있는 ID를 입력해야 한다. UNAME="<YOURUSER>" UUID=$(id -u "${UNAME}") UGID=$(id -g "${UNAME}") UHOME=$(getent passwd "${UNAME}" | cut -d: -f6) USHELL=$(getent passwd "${UNAME}" | cut -d: -f7) if [[ -p /dev/stdin || "${BASH_ARGC}" > 0 && "${BASH_ARGV[1]}" != "-c" ]]; then USHELL=/bin/bash fi if [[ "${PWD}" = "/root" ]]; then cd "${UHOME}" fi # get pid of systemd SYSTEMD_PID=$(pgrep -xo systemd) # if we're already in the systemd environment if [[ "${SYSTEMD_PID}" -eq "1" ]]; then exec "${USHELL}" "$@" fi if [[ -z ${SYSTEMD_PID} ]]; then # start systemd /usr/bin/daemonize -l "${HOME}/.systemd.lock" /usr/bin/unshare -fp --mount-proc /lib/systemd/systemd --system-unit=basic.target # wait for systemd to start retries=50 while [[ -z ${SYSTEMD_PID} && $retries -ge 0 ]]; do (( retries-- )) sleep .1 SYSTEMD_PID=$(pgrep -xo systemd) done if [[ $retries -lt 0 ]]; then >&2 echo "Systemd timed out; aborting." exit 1 fi fi # export WSL variables export WINPATH="$(echo "$PATH"|grep -o ':/mnt/c.*$'|sed 's!^:!!')" RUNOPTS="" RUNOPTS="$RUNOPTS -l" RUNOPTS="$RUNOPTS -w WINPATH" RUNOPTS="$RUNOPTS -w WSL_INTEROP" RUNOPTS="$RUNOPTS -w WSL_DISTRO_NAME" # enter systemd namespace exec /usr/bin/nsenter -t "${SYSTEMD_PID}" -m -p --wd="${PWD}" /sbin/runuser $RUNOPTS -s "${USHELL}" "${UNAME}" -- "${@}"
Shell
복사

wsl2hack을 실행할 계정 등록

shayne/wsl2-hack에서는 root 계정을 건드리지 않고 rootwsl이라는 계정을 만들어서 사용하라고 하는데, 전혀 필요없는 과정이다. 생략해도 된다.
sudo vipw를 실행해 원래 WSL에 있는 root 계정 설정을 전혀 건드리지 않도록 rootuid가 동일한 계정 rootwsl를 만든다. root 정보가 담긴 첫번째 행 바로 아래에 다음 내용을 복사해 넣는다.
rootwsl:x:0:0:root:/root:/usr/local/bin/wsl2hack
Shell
복사
shayne/wsl2-hack에 부족한 설명을 보충한다. sudo vipw -s 명령으로 /etc/shadow 파일에도 다음과 같이 rootwsl를 설정해준다.
rootwsl:*:18375:0:99999:7:::
Shell
복사

WSL 종료 및 기본 사용자 변경

이제 Powershell에서 다음 명령을 실행해 WSL을 종료하고, 기본 사용자를 변경한다.
wsl --shutdown # 설치한 WSL은 ubuntu.exe, 또는 ubuntu2004와 같은 이름으로 실행파일을 갖는다. # 나는 기본으로 설치되는 Ubuntu를 사용하므로 실행 파일 이름이 ubuntu.exe였다. ubuntu.exe config --default-user root
PowerShell
복사
shayne/wsl2-hack에 부족한 설명을 보충한다. Windows Terminal에서 Ctrl+,을 눌러 설정을 열고 명령줄을 다음과 같이 변경한다.
wsl.exe -d Ubuntu -- wsl2hack
PowerShell
복사
--을 넣고 뒤에 실행할 명령을 적는 것이다. 이렇게 하면 WSL이 wsl2hack을 실행하면서 systemd를 띄운다.

degraded 상태인 서비스 처리

systemtctl status 명령을 실행해보면 상태가 degraded로 나타난다. 두 개의 서비스에 문제가 있다.
systemd-remount-fs.service
multipathd.socket
강제로 systemctl을 실행하면 어떤 서비스에 문제가 있는지는 대략 다음 문서에서 알 수 있다.

systemd-remount-fs.service

/etc/fstab에서 cloudimg-rootfs이 포함된 행을 주석처리하고, sudo systemctl restart systemd-remount-fs.service

multipathd.socket

⟫ 그냥 sudo systemctl disable multipathd.socket

그러나, 결정적인 문제가...

systemd를 사용할 수 있어서 매우 만족스럽다...는 개뿔... 치명적인 문제가 있다.
1.
code . 명령으로 WSL 어디서나 띄울 수 있었던 Visual Studio Code를 사용할 수 없다!
2.
/mnt/c에 접근은 되지만 어떤 파일에서는 권한 문제가 생긴다.
3.
Windows의 명령어를 전혀 호출할 수 없다.
4.
불안정하다.
대체로, WSL에서 실행되는 systemd의 구현체는 cgroup으로 분리된 하나의 컨테이너로 봐야할 것같다.
모든 설정을 롤백하고 sudo -i -u root wsl2hack을 실행해보면 systemd를 이용해 실행 중인 프로세스가 다음과 같이 보인다(선 모양도 거지같다).
joshua@gram:~$ pstree -a systemd --system-unit=basic.target |-accounts-daemon | `-2*[{accounts-daemon}] |-agetty -o -p -- \\u --noclear --keep-baud console 115200,38400,9600 xterm-256color |-agetty -o -p -- \\u --noclear tty1 linux |-atd -f |-cron -f |-dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation --syslog-only |-networkd-dispat /usr/bin/networkd-dispatcher --run-startup-triggers |-polkitd --no-debug | `-2*[{polkitd}] |-rsyslogd -n -iNONE | `-3*[{rsyslogd}] |-snapd | `-16*[{snapd}] |-snapfuse /var/lib/snapd/snaps/bare_5.snap /snap/bare/5 -o ro,nodev,allow_other,suid |-snapfuse /var/lib/snapd/snaps/core20_1169.snap /snap/core20/1169 -o ro,nodev,allow_other,suid |-snapfuse /var/lib/snapd/snaps/gnome-3-38-2004_76.snap /snap/gnome-3-38-2004/76 -o ro,nodev,allow_other,suid |-snapfuse /var/lib/snapd/snaps/core18_1705.snap /snap/core18/1705 -o ro,nodev,allow_other,suid |-snapfuse /var/lib/snapd/snaps/firefox_701.snap /snap/firefox/701 -o ro,nodev,allow_other,suid |-snapfuse /var/lib/snapd/snaps/gtk-common-themes_1519.snap /snap/gtk-common-themes/1519 -o ro,nodev,allow_other,suid |-snapfuse /var/lib/snapd/snaps/lxd_14804.snap /snap/lxd/14804 -o ro,nodev,allow_other,suid |-snapfuse /var/lib/snapd/snaps/snapd_7264.snap /snap/snapd/7264 -o ro,nodev,allow_other,suid |-snapfuse /var/lib/snapd/snaps/snapd_13640.snap /snap/snapd/13640 -o ro,nodev,allow_other,suid |-snapfuse /var/lib/snapd/snaps/core18_2246.snap /snap/core18/2246 -o ro,nodev,allow_other,suid |-snapfuse /var/lib/snapd/snaps/lxd_21858.snap /snap/lxd/21858 -o ro,nodev,allow_other,suid |-systemd-journal |-systemd-logind |-systemd-network |-systemd-resolve |-systemd-udevd |-udisksd | `-4*[{udisksd}] `-unattended-upgr /usr/share/unattended-upgrades/unattended-upgrade-shutdown --wait-for-signal `-{unattended-upgr}
Shell
복사
다른 콘솔에서 pstree -a로 확인해보면...
joshua@gram:~$ pstree -a init ├─init │ └─init │ ├─bash │ │ └─sudo -i -u root wsl2hack │ │ └─bash --login -c wsl2hack │ │ └─nsenter -t 442 -m -p --wd=/home/joshua /sbin/runuser -l -w WINPATH -w WSL_INTEROP -w WSL_DISTRO_NAME -s ... │ │ └─runuser -l -w WINPATH -w WSL_INTEROP -w WSL_DISTRO_NAME -s /bin/bash joshua -- │ │ └─bash │ └─unshare -fp --mount-proc /lib/systemd/systemd --system-unit=basic.target │ └─systemd --system-unit=basic.target │ ├─accounts-daemon │ │ └─2*[{accounts-daemon}] │ ├─agetty -o -p -- \\u --noclear --keep-baud console 115200,38400,9600 xterm-256color │ ├─agetty -o -p -- \\u --noclear tty1 linux │ ├─atd -f │ ├─cron -f │ ├─dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation --syslog-only │ ├─networkd-dispat /usr/bin/networkd-dispatcher --run-startup-triggers │ ├─polkitd --no-debug │ │ └─2*[{polkitd}] │ ├─rsyslogd -n -iNONE │ │ └─3*[{rsyslogd}] │ ├─snapd │ │ └─16*[{snapd}] │ ├─snapfuse /var/lib/snapd/snaps/bare_5.snap /snap/bare/5 -o ro,nodev,allow_other,suid │ ├─snapfuse /var/lib/snapd/snaps/core20_1169.snap /snap/core20/1169 -o ro,nodev,allow_other,suid │ ├─snapfuse /var/lib/snapd/snaps/gnome-3-38-2004_76.snap /snap/gnome-3-38-2004/76 -o ro,nodev,allow_other,suid │ ├─snapfuse /var/lib/snapd/snaps/core18_1705.snap /snap/core18/1705 -o ro,nodev,allow_other,suid │ ├─snapfuse /var/lib/snapd/snaps/firefox_701.snap /snap/firefox/701 -o ro,nodev,allow_other,suid │ ├─snapfuse /var/lib/snapd/snaps/gtk-common-themes_1519.snap /snap/gtk-common-themes/1519 -o ... │ ├─snapfuse /var/lib/snapd/snaps/lxd_14804.snap /snap/lxd/14804 -o ro,nodev,allow_other,suid │ ├─snapfuse /var/lib/snapd/snaps/snapd_7264.snap /snap/snapd/7264 -o ro,nodev,allow_other,suid │ ├─snapfuse /var/lib/snapd/snaps/snapd_13640.snap /snap/snapd/13640 -o ro,nodev,allow_other,suid │ ├─snapfuse /var/lib/snapd/snaps/core18_2246.snap /snap/core18/2246 -o ro,nodev,allow_other,suid │ ├─snapfuse /var/lib/snapd/snaps/lxd_21858.snap /snap/lxd/21858 -o ro,nodev,allow_other,suid │ ├─systemd-journal │ ├─systemd-logind │ ├─systemd-network │ ├─systemd-resolve │ ├─systemd-udevd │ ├─udisksd │ │ └─4*[{udisksd}] │ └─unattended-upgr /usr/share/unattended-upgrades/unattended-upgrade-shutdown --wait-for-signal │ └─{unattended-upgr} ├─init │ └─init │ └─bash │ └─pstree -a └─2*[{init}]
Shell
복사
이래서야, 사용하는 의미가 없지... 그래서, 안쓰기로!
차라리, vagrant와 Hyper-V를 결합해 사용하는 게 낫겠다!