はじめに
いつの間にかWSL上でsystemdを動かせるようになっていましたが、systemdを有効にした状態でシェルを閉じるとWSLのインスタンスが自動的にStoppedになってしまいました。
色々試行錯誤した結果、以下の方法で落ち着いたので備忘録的にまとめています。
TL;DR
- daemonizeコマンドを使用して、initの子プロセスを走らせ続ける。
- 具体例として、以下のPowershellスクリプトを使用してWSLを起動する。
背景
WSL上でのsystemd
- 以下のブログで公式にサポートされたことがアナウンスされている。
- https://devblogs.microsoft.com/commandline/systemd-support-is-now-available-in-wsl/
- 以下のファイルを作成することで有効になる。
/etc/wsl.conf
[boot]
systemd=true
systemdを有効にした際の問題
- 上記の記事の記述から以下がわかる。
- systemdのサービスはWSL instanceの生存に寄与しない。
- 既存の手順でinstanceを起動させ続けることができるとのこと。
It is also important to note that with these change, systemd services will NOT keep your WSL instance alive. Your WSL instance will stay alive in the same way it did before, which you can read more about here.
既存の手順では常時起動させることができない
- 上記の記事から以下の記事へリンクが張られている。
- この記事ではtmuxを使用して、一般的なバックグラウンドタスクの実行方法について解説してある。
- これを参考に実行しても、上手くいかない。
> wsl -d Ubuntu -e tmux new -d -s htop htop
> wsl -d Ubuntu -e pstree
systemd─┬─
........<中略>......
├─tmux: server───htop
> wsl -d Ubuntu
$ tmux new -d -s htop htop
$ exit
> wsl -d Ubuntu -e pstree
systemd─┬─
........<中略>......
├─tmux: server───htop
解決方法
- daemonizeコマンドを使用し、initの子プロセスとしてsleepコマンドが無限ループするbashプロセスを起動する。
Param(
[String]$distro = "Ubuntu"
)
Write-Host "Start WSL $distro ..."
wsl -d $distro -u root -e bash -c 'apt list daemonize || (apt update && apt install daemonize -y) && daemonize $(which bash) -c \"while true; do sleep 1d; done\"'
Write-Host "WSL $distro has been started."
プロセスツリーを確認すると、確かにinitの子プロセスになっている。
> wsl -d Ubuntu -e pstree
systemd─┬─
........<中略>......
├─init───bash───sleep
おまけ: ssh向けポートフォワーディング
- 以下でWindowsホストからのproxyを設定
$wsl_ip = wsl -d $distro -e bash -c "hostname -I | cut -d' ' -f1"
netsh interface portproxy delete v4tov4 listenport=22
netsh interface portproxy add v4tov4 listenport=22 connectaddress=$wsl_ip