随分試行錯誤したが、これが決定版といえる手順が確立できたと思う。電源を入れるだけでサーバが動作する。
wsl2に入れたubuntuでサーバを動かす場合を考えると、問題になるのは起動スクリプトをどのように動かすかとwsl2特有のネットワーク構成の対処をどうするかという2点。
デーモン起動については通常のLinuxならrc.localとかsystemdなど使うところだが、これらはどちらも動作しないので面食らうことになる。さらにwsl2はネットワークがブリッジ型ではなくホストWindowsの中に仮想ネットワークが作られるので、外部からubuntuに接続するためにはWindowsにポートフォワード設定をする必要がある。さらにubuntuのIPアドレスは再起動のたびに変わる。ポートフォワード設定に使うnetコマンドは管理者権限が必要なのでWindows側から実行したいところだが、その際はubuntuのIPアドレスが必要になるからwsl2の起動が先でなければいけない。めんどくさい!
ともあれこれらの課題を一発で解決する手順を確立してしまったのでここに大公開する。例えばsshdを動かすならば以下の手順になる。
まずは普通にsshdが動くようにする
ホストWindowsのコマンドプロンプトからubuntuのIPアドレスにsshできるようにする。以下のようにインストール。
sudo apt install openssh-server
パスフレーズを有効にするとかは自分好みに設定すればいい。
次に起動スクリプトを作成する
ubuntuの/etc/rc.local.wslにファイルを作成して以下のようにスクリプトを書き込む。chmod 755も忘れないこと。
なおここでcronも一緒に起動しておくといい。cronのないlinuxなんてつまんないことこの上ない。ちなみにcronを起動すると/etc/rc.localが実行される仕組みになっているので注意してほしい。もし/etc/rc.localにcron起動処理を書いてしまうと2重に動いてしまう。
#!/bin/sh /usr/sbin/service cron start /usr/sbin/service ssh start /home/foo/script/portforwardwsl2.sh
portforwardwsl2.shの中身は以下のようにする。
#!/bin/sh /mnt/c/Windows/System32/netsh.exe interface portproxy delete v4tov4 listenport=22 listenaddress=0.0.0.0 IP=`ifconfig | sed -rn "s/inet ([0-9\.]+?)(.*)/\1/p" | head -1` /mnt/c/Windows/System32/netsh.exe interface portproxy add v4tov4 listenport=22 listenaddress=0.0.0.0 connectport=22 connectaddress=$IP
Windows起動とともに起動するようにする
これが肝。タスクスケジューラにwsl起動用のタスクを作成するのだが、ログオン状態に関わらず実行することと、特権で実行することをチェックする。
トリガーはシステム起動時。
コマンドラインはこのようにする。ubuntuが起動してrootがrc.local.wslを実行する形になる。
C:\Windows\System32\wsl.exe -u root -- /etc/rc.local.wsl
特権ユーザで動作するのでnetshコマンドが管理者パスワードを聞いてこない。これで終わり。
ただこの特権utuntuは危険なコマンドでホストWindowsを破壊することもできるので覚悟が必要。安全性を気にするなら特権をつけずにrunas.exeをかましてadministratorでnetshを動かしexpectでパスワードを流し込むとか、Cドライブのマウントを解除してしまうといった対応をしてほしい。
おおっと、もう一つ忘れていた。Windowsのファイアウォール設定でポート22の受信を許可する必要がある。これで終わり。