想必很多人在使用 WSL 時都遇到過與 Windows 主機通信的問題。在日常編程中,很常用的場景是在 Windows 中訪問部署在 WSL 中的數據庫、web 或其它服務等。Windows 本身是會做映射的,比如使用如下命令啟動一個 http server:
➜ source git:(master) python -m http.server
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
這時在 Windows 上訪問 localhost:8000
是可以正常打開的。但在某些其它場景(如數據庫連接時),該映射又會失效。可能是因為 WSL 默認只映射了 http 服務的端口?(存疑)
為了解決上述問題,我們需要一種手段來確保 Windows 主機能夠輕鬆訪問到 WSL。以下列舉三種解決方式,並最後詳細描述我的解決方案。
手動查找 WSL 的局域網 IP,並使用該 IP 訪問#
這種方法最為簡單直白,手動找到 WSL 的 IP 訪問即可。
在 WSL 中執行ifconfig
命令,可獲得大量輸出:
➜ source git:(master) ifconfig
.....
eth0: .......
inet 172.21.255.188 .....
.....
找到上面inet
後的 IP 地址,即為 WSL 的局域網 IP。
但 WSL 的 IP 在每次啟動時都會變化,如果經常需要訪問 WSL 的話該方法並不是一個好選擇。
連接映射#
使用 HobaiRiku/wsl2-auto-portproxy 將 WSL 中的所有 TCP 端口映射到 Windows localhost 上(暫不支持 UDP)。
該方法在需要訪問 WSL 時下載二進制文件運行即可,不需要額外操作。
將 WSL IP 添加到 Windows 的 hosts 文件中#
剛剛第一種方法的缺點是 IP 在每次啟動時都會變化,這讓我們想到了域名。
眾所周知域名解析會先查找 hosts 文件,如未找到才會使用 DNS,因此該方法是將 WSL 的 IP 和自定義的域名添加到 Windows 的 hosts 文件,訪問時只需訪問自己設定的域名。
實施思路類似於 DDNS 的 “本機 IP 變化,修改域名解析記錄”,需要做到 “WSL IP 變化,修改 hosts 文件”,而我們知道 WSL IP 變化其實就是指 WSL 啟動,所以最終需求變為了:WSL 啟動時將 IP 寫入 Windows 的 hosts 文件。
從這個需求開始,又衍生出了兩個思路
- 在 Windows 上完成該過程,具體方法是為 WSL 啟動的事件綁定自定義任務,該任務通過在 WSL 中執行
ifconfig
加以正則匹配獲取 IP,將其寫入到 hosts 文件中; - 在 WSL 上完成該過程,具體方法是添加開機自啟腳本,在該腳本中通過任意手段獲取本機 IP,並將其寫入到 /mnt/c/Windows/System32/drivers/etc/hosts (因為 Windows 的盤符會自動掛載到 WSL 的 /mnt 下)
思路 1#
思路 1 的核心是自定義任務,具體的工作流程可以通過很多手段實現。比較簡單的是 shayne/go-wsl2-host,該項目會自動添加在 WSL 啟動時觸發的自定義任務,理論上裝上即可用(可惜在我這裡沒有正常運行,不知道是什麼原因)。
思路 2#
思路 2 的實現較少,因為在過去 WSL 中沒有一種行之有效的 “開機自啟” 方法。但該障礙已隨著 WSL 對 systemd 的支持而消失不見,因此我手撸了一個採用這種方式的項目。
要使用該項目,對於 Arch Linux:
- 確保 WSL 能夠正常讀寫 /mnt/c/Windows/System32/drivers/etc/hosts 文件;
- 下載 release 中的 .pkg.tar.zst 文件並使用
sudo pacman -U
安裝; - 使用
sudo systemctl enable --now wah.service
啟用服務。
對於其它發行版,僅需把上述的第二個流程替換為手動安裝:
install -D -m 755 $srcdir/wah $pkgdir/usr/bin/wah
install -D -m 755 $srcdir/wah.service $pkgdir/usr/lib/systemd/system/wah.service
install -D -m 755 $srcdir/domains $pkgdir/etc/wah/domains
其它步驟完全相同。
該項目默認會使用的域名是 arch.wsl,如果需要自定義,可編輯 /etc/wah/domains 文件,對於多個自定義域名,請使用單個空格分割。
該項目會自動在 hosts 文件底部添加 WSL 的地址,並在每次 WSL 啟動時自動更新: