2022.09.30追記)
WSL2でのsystemd対応はubuntuのローカル対応ではなく、WSL自体で行われることになったようです。ストア版WSL preview 0.67.6以降 systemd対応が入っています。また、この対応は流動的で 0.68.2では一般的なディストロと同様に /sbin/init (Ubuntuの場合、これはシンボリックリンクで実体はsystemd)を起動するようになりました。まだ議論が重ねられているようなのでしばらく試行錯誤が続くと思います。
それではWSL0.67.6以降でのsystemdの利用方法ですが、/etc/wsl.confに以下の設定を行います。
[boot]
systemd = true
これでMicrosoft initではなくsystemdが起動するようになります。Microsoftの/initはPID2で起動し、ログインプロセス?(WSL.exeから起動するコンソールアクセス)については /init の子孫として起動します。nslogin等も不要です。
先日リリースされたUbuntu 22.04には/usr/libexec/wsl-systemd
というシェルスクリプトが同梱されています。中身を覗くとunshareで名前空間を分けてsystemdを起動するようです。過去様々なところで紹介されていた手法のようですね。
systemdを起動する
早速試してみましょう。
$ sudo /usr/libexec/wsl-systemd
$ ps ax
PID TTY STAT TIME COMMAND
1 ? Sl 0:00 /init
7 ? Ss 0:00 /init
8 ? R 0:00 /init
9 pts/0 Ss 0:00 -bash
98 ? S 0:00 /usr/bin/unshare --fork --mount-proc --pid --propagation unchanged -- sh -c exec /lib/systemd/systemd --unit=multi-user.target
99 ? Ss 0:00 /lib/systemd/systemd --unit=multi-user.target
139 ? S<s 0:00 /lib/systemd/systemd-journald
163 ? Ss 0:00 /lib/systemd/systemd-udevd
187 ? Ss 0:00 @dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation --syslog-only
190 ? Ss 0:00 /usr/bin/python3 /usr/bin/networkd-dispatcher --run-startup-triggers
191 ? Ssl 0:00 /usr/libexec/polkitd --no-debug
192 ? Ssl 0:00 /usr/sbin/rsyslogd -n -iNONE
193 ? Ss 0:00 /lib/systemd/systemd-logind
194 ? Ss 0:00 /lib/systemd/systemd-networkd
217 ? Ssl 0:00 /usr/sbin/ModemManager
291 ? Ss 0:00 /lib/systemd/systemd-resolved
301 ? Ss 0:00 /usr/sbin/cron -f -P
305 ? Ssl 0:00 /usr/bin/python3 /usr/share/unattended-upgrades/unattended-upgrade-shutdown --wait-for-signal
309 tty1 Ss+ 0:00 /sbin/agetty -o -p -- \u --noclear --keep-baud console 115200,38400,9600 linux
311 ? Ss 0:00 sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups
314 ? Ss 0:00 /sbin/agetty -o -p -- \u --noclear tty1 linux
起動しました。cronやsshd,systemd-resolvedなど様々起動しています。
systemctlで操作する
sshdを止めてみましょう。
$ sudo systemctl stop ssh
Failed to stop ssh.service: 通信端点が接続されていません
See system logs and 'systemctl status ssh.service' for details.
エラーです。systemd がPID 1ではないのが原因でしょうか?
先ほどの /usr/libexec に nslogin というファイルがあります。こちらはスクリプトではなくバイナリのようです。マニュアルは見当たりませんが、きっと nslogin = name space login でしょう。
実行してみます。
$ /usr/libexec/nslogin
何も起こりません。
名前空間に入ったに違いないという淡い期待でプロセスを確認してみます。
$ ps ax | grep system
1 ? Ss 0:00 /lib/systemd/systemd --unit=multi-user.target
systemdがPID 1になってます。
再度systemctlで操作してみます。
$ sudo systemctl stop ssh
エラーが出なくなりました。
停止できたかどうか確認してみます。
$ /usr/libexec/nslogin sudo systemctl stop ssh
ThinkCentre:~$ /usr/libexec/nslogin sudo systemctl status ssh
○ ssh.service - OpenBSD Secure Shell server
Loaded: loaded (/lib/systemd/system/ssh.service; enabled; vendor preset: enabled)
Active: inactive (dead) since Wed 2022-04-27 04:49:56 JST; 4s ago
Docs: man:sshd(8)
man:sshd_config(5)
Process: 204 ExecStartPre=/usr/sbin/sshd -t (code=exited, status=0/SUCCESS)
Process: 219 ExecStart=/usr/sbin/sshd -D $SSHD_OPTS (code=exited, status=0/SUCCESS)
Main PID: 219 (code=exited, status=0/SUCCESS)
4月 27 04:49:40 ThinkCentre systemd[1]: Starting OpenBSD Secure Shell server...
4月 27 04:49:41 ThinkCentre sshd[219]: Server listening on 0.0.0.0 port 22.
4月 27 04:49:41 ThinkCentre sshd[219]: Server listening on :: port 22.
4月 27 04:49:41 ThinkCentre systemd[1]: Started OpenBSD Secure Shell server.
4月 27 04:49:56 ThinkCentre sshd[219]: Received signal 15; terminating.
4月 27 04:49:56 ThinkCentre systemd[1]: Stopping OpenBSD Secure Shell server...
4月 27 04:49:56 ThinkCentre systemd[1]: ssh.service: Deactivated successfully.
4月 27 04:49:56 ThinkCentre systemd[1]: Stopped OpenBSD Secure Shell server.
ちゃんと停止しています。
nslogin の引数にコマンドラインを並べても実行できるようです。
ちなみに、、wsl-systemdを実行していない(=systemdを起動していない)状態でnsloginを実行すると以下のようにdistroを一旦停止させてやり直しなさいとエラーが出ます。
$ /usr/libexec/nslogin ls
ERROR: Systemd is not running. Please terminate this instance by running "wsl -t <distro>" from Windows shell and try again.
以前、Ubuntuのブログに我々はWSLでsystemdを動かす方法を検討している。今も方法はいろいろあるけどそれは標準じゃないぞ的なことが書かれていましたが、ちゃんと実現したようですね。
2022.04.30追記)
https://github.com/microsoft/WSL/issues/5126#issuecomment-1111957720 によると、
launch your shells with "/usr/libexec/nslogin /bin/bash", eg from Windows:
wsl -e /usr/libexec/nslogin /bin/bash
ubuntu2204.exeだとこうなっているそうです。インストーラーを使ってインストールしていれば実は自動だったんですね。Terminalのコマンドラインをこちらに書き換えておくと、特に意識することなく常に systemd が PID 1 の環境で使えるようですね。
2022.05.04追記)
wsl -e /usr/libexec/nslogin /bin/bash
でWSLに接続すると環境変数SHELLが/usr/libexec/nslogin
になってしまうようです。ssh_configのMatchのように環境変数SHELLに対してコマンドを引き渡すような場合はエラーになってしまいます。.bashrcでSHELLを再定義するというのもありですが、今はsystemdがPID 1でないといけないケースだけnsloginを使うのが良いかもしれません。