RSS訂閱

2020年11月3日 星期二

適用於Linux的Windows子系統(Windows Subsystem for Linux;WSL)

Windows子系統Linux版(Windows Subsystem for Linux;WSL)是微軟Windows作業系統邁向支援開源Linux核心的一大躍進,讓Windows平台使用者無需手動建立虛擬機器,也無需擔心傳統虛擬機器設定管理及資源上的額外負荷,就可以直接在Windows平台上執行GNU / Linux環境,包括大部分的Linux命令列工具、公用程式和應用程式,而WSL最主要的優點乃在於允許使用者無縫共享Windows和Linux資源,包括共享檔案系統,環境變數,網路資源和命令列解譯器(如cmd和PowerShell)

,讓系統使用者員與開發人員在Windows環境下即可同時擁有使用Linux命令工具和利用Linux開發環境的能力。

一. WSL 歷史沿革與版本區別

WSL 最早出現於2016年八月推出的Windows 10 週年更新版(1607),最初只有提供一個Ubuntu Linux映像;後來,微軟於2017年10月推出的Windows 10 秋季創作者更新(1709)時改成透過Windows 市集進行下載與安裝Linux發行版本,並新增了SUSE發行版本映像,2019年5月,微軟宣佈了一個完全不同架構的 WSL 2,利用『虛擬機器平台』引入了原生Linux核心的重大變更,而且自2019年6月起,經由Windows測試人員計畫 (Windows Insider)來向Windows 10客戶提供WSL 2版,至於正式版本中目前也只有Windows 10 2004版以後的作業系統可直接安裝WSL 2。

WSL 1 與 WSL 2主要不同點在於:WSL1使用了轉譯層(translation layer)來轉換Windows與Linux底層的系統呼叫,但WSL 2 則是微軟首度包含了一個初始於4.19版的客制化Linux 核心做為Windows元件,而這個WSL 2 Linux 核心為開放原始碼,核心是被執行於一個輕巧、幕後自動進行管理及執行之虛擬機器上。因此WSL 2具有比前版更佳的效能和完整的系統呼叫相容性。

下圖為WSL 1與WSL 2架構圖示。

wsl_architecture

二. 安裝WSL

目前僅有Windows 10 與Windows Server 2019可以安裝WSL,但只有OS組建18917(OS Build)以後才能支援WSL2,亦即需使用Window 10 版本2004(OS組建19041) 或Windows Server 2019 2004 (半年通道,無圖形介面)以後版本才能安裝WSL2,因此你可以先執行『ver』或『winver』命令來查看組建數字(五個數字)是否大於等於18917就可知道是否可支援二版的WSL。

若決定使用WSL 2版,則您還需要在Windows 10 上安裝啟用『虛擬機器平台』功能並確定也已在機器的BIOS中啟用虛擬化功能,然後在安裝重新開機後輸入 wsl --set-default-version 2   (可能須先更新WSL 2核心)來設定日後安裝之Linux發行版本要執行二版架構,否則即使您在OS組建19041以上的作業系統上只是安裝好Windows子系統Linux版和Linux發行版本,仍然只能夠執行一版架構的WSL。

安裝WSL須執行下列二個步驟:

  1. 安裝『Windows子系統Linux版』(Windows 10)或『Windows子系統Linux版』(Windows Server 2019)。
  2. 至少安裝一個Linux發行版本 (如Ubuntu、OpenSuse、kali …….)

(一) 安裝『Windows子系統Linux版』(Windows 10)或『Windows子系統Linux版』

使用圖形介面的Windows 10的程式功能(appwiz.cpl))安裝『Windows子系統Linux版』和『虛擬機器平台』(WSL 2需要)或Windows Server 2019伺服器管理員(ServerManager.exe)的新增功能來安裝『適用於Linux的Windows子系統』。

wsl_features

您也可以使用Powershell命令執行安裝WSL:

Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux
dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart    (Windows 10 組建19041以後;為了支援WSL 2)


若是需要在Hyper-V的Windows 10虛擬機器啟用WSL 2,請確定虛擬機器已透過下列命令啟用巢狀虛擬化功能: Set-VMProcessor -VMName -ExposeVirtualizationExtensions $true
若是想要在VMWare 的的Windows 10虛擬機器啟用WSL 2,則需確認已如下圖般的啟用處理器的虛擬化功能:

vm_virtualize

(二) 安裝Linux發行版本—ubuntu

一旦安裝了WSL後,接下來就可以安裝支援WSL的Linux 發行版本,Windows 10可以直接由Microsoft Store安裝,目前透過Microsoft 市集可下載與安裝在WSL的發行版本如下:

  • Ubuntu 16.04 LTS
  • Ubuntu 18.04 LTS
  • Ubuntu 20.04 LTS
  • openSUSE Leap 15.1
  • SUSE Linux Enterprise Server 12 SP5
  • SUSE Linux Enterprise Server 15 SP1
  • Kali Linux
  • Debian GNU/Linux
  • Fedora Remix for WSL
  • Pengwin
  • Pengwin Enterprise
  • Alpine WSL

一般而言,ubuntu是最普遍且支援度最高的發行版本,下圖是由Microsoft Store安裝Ubuntu 18的畫面。

ubuntu_install

另一方面,雖然Windows Server 2019作業系統並無Microsoft Store可用,但可經由網址 https://docs.microsoft.com/zh-tw/windows/wsl/install-manual 內容的超連結進行下載各種支援WSL的Linux發行版本,下載成功後可能是一個appx或是zip檔案,如果是appx檔可以直接更改延伸名稱為zip檔,再執行 ZIP檔內的執行檔即可,當然你可以依據你的偏好或習慣,利用檔案總管或命令指令完成,底下乃是透過Powershell命令安裝ubuntu20:

Rename-Item Ubuntu_2004.2020.424.0_x64.appx Ubuntu_2004.2020.424.0_x64.zip
Expand-Archive Ubuntu_2004.2020.424.0_x64.zip ubuntu
cd ubuntu
.\ubuntu2004.exe

當第一次執行發行版本後,畫面將會提示並要求請輸入使用者名稱及密碼,若有需要也可手動啟用root帳戶(su passwd –u root;sudo passwd root)。

name_password

總括而言,欲使用WSL,您需要在作業系統上安裝『Windows子系統Linux版』(V1,V2)、『虛擬機器平台』功能(V2),啟用機器的BIOS硬體虛擬化功能(V2),再安裝支援WSL的Linux發行版本(V1,V2)。

安裝了WSL Linux系統時,安裝的基本組態會被註冊在登錄資料庫的『\HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Lxss』機碼底下,每一個發行版本以一128位元的GUID來加以表達,你可以在GUID下找到每個已安裝的Linux版本的基本路徑(BasePath)、發行版本名稱(DistributionName)、預設登入使用者(DefaultID)、預設環境變數(DefaultEnvironment)等資訊。

wsl_registry

三. 使用和管理 WSL

一旦成功的完成安裝後就可以開始使用WSL了。

Linux發行版本與WSL執行版本

若欲了解目前已經安裝的Linux發行版本和所執行的WSL版本,不論是WSL 1和WSL 2皆可輸入使用 wslconfig /l 命令,但只有WSL 2版可以使用 wsl -l –v,因此如果此一命令導致出現「命令列選項無效: -l」的錯誤訊息,則代表您的機器就只能使用WSL 1版,不能支援WSL 2,例如下圖為WSL 2的執行結果,顯示目前已安裝了多少Linux發行版本,其執行時的版本為一版或二版,而前置 *符號代表此為預設啟動的Linux(本例為Ububtu-18.04) , 可使用 wsl –s <Linux名稱> 命令來變更預設上所想要啟動的Linux發行版本,若只支援WSL 1版的Windows系統就只能使用wslconfig命令了。 
此外,在支援WSL 2版的Windows系統上,日後可依據所需來隨時變更Linux系統應採用WSL 1或是WSL 2的架構來執行,  只需使用命令 wsl --set-version <linux 名稱> <版本> 即可,不過有些Windows可能需要先更新WSL 2 Linux核心才行,下圖將原本以WSL 2版架構執行的Ubuntu-18.04改以WSL 1方式執行,而原本以WSL 1版架構執行的kali-linux改以WSL 2方式執行,最後再以 wsl –l –v 確認是否已成功的變更。    
wsl-l-v

wslconfig 

此外,利用指令 wsl --set-default-version 2 可設定日後所安裝的Linux發行版本預設上採用 WSL 2 。

啟動與關閉WSL

使用者只需在命令提示字元或Powershell提示下輸入wsl或bash命令,或者是經由開始功能表內找到並按下Linux發行版本的圖示,就可以進入預設Linux系統的SHELL開始作業,一旦完成工作後就在Linux shell下輸入 exit 即可離開,但也可以wsl命令開頭的方式來執行linux指令,而無需進入shell提示,常用的WSL執行與關閉選項如下表說明。

命  令 說  明 範  例
--exec, -e 不使用預設的Linux Shell執行指定的命令 (wsl –e `echo date` 指令無法執行,因無shell) wsl -e curl www.google.com.tw
-- 使用預設的Linux Shell執行指定的命令 (wsl `echo date` 指令可以透過shell正確執行) wsl -- curl www.msn.com
--distribution, -d 啟動某個特定的Linux 發佈版本的SHELL wsl -d kali-linux
--user, -u 以特定的帳戶執行wsl shell或命令 wsl -d Ubuntu-20.04 -u root
--shutdown 立即關閉所有的wsl linux發佈版本 wsl --shutdown
--terminate, -t 關閉某一個wsl linux發佈版本 wsl -t ubuntu-18.04

如上表所示,若要以非預設的使用者帳戶登入(ubuntu預設帳戶為uid=1000),則使用命令 wsl -u <username>,若要變更每次登入時的預設帳戶,則需先找到每個Linux發行版本的exe檔案名稱(位於C:\Program Files\WindowsAPP 隱藏目錄下),再執行 <DistributionEXEName> config --default-user <Username> ,如下圖所示,日後你進入Linux系統時就會改用root帳戶。

wsl_change_user

若不再需要使用WSL時,除了可以直接在Linux Shell內執行exit來離開Linux系統,或在 Windows 命令列下使用wsl -t <發行版名稱> 來結束某個Linux版本,或是執行 wsl --shutdown 關閉所有正在執行中的WSL Linux發行版本,下圖示範了關閉與結束的用法。

wsl-t-shutdown

WSL Linux 發行版本檔案系統

安裝WSL 的Linux發行版本時,WSL 1會將Linux檔案系統根目錄安裝在『 %USERPROFILE%\AppData\Local\Packages\版本目錄\LocalState\rootfs』這個目錄下,下圖為WSL 1下安裝二套Linux系統後所產生的二個安裝目錄。所以WSL 1版的Linux允許您在Windows環境下直接透過上述的rootfs目錄來存取Linux檔案系統。

wsl1_dir

至於WSL 2採用了輕量級虛擬機器的執行方式,故安裝的Linux系統會被儲存成vhdx檔,而非像一版的目錄階層,下圖就是ubuntu二版位於『 %USERPROFILE%\AppData\Local\Packages\版本目錄\LocalState』目錄下的ext4.vhdx檔案(一版的rootfs已經不見了),這個WSL 2 VHDX 檔採用 ext4 檔案系統,會自動調整大小以符合使用的儲存體需求,但其初始大小之上限為 256GB,一般而言是夠用的,如果您的 Linux 檔案系統所需的儲存空間超過此大小,您可以使用diskpart工具予以擴充。

由於Windows作業系統無法識別與存取Linux 的ext4檔案系統,因此你無法在Windows 環境下直接以掛接或連接vhdx檔的方式存取 WSL 2 Linux的檔案系統。

wsl2_dir

總之,若是想要在Windows系統環境中存取WSL 1 Linux檔案系統,可直接存取rootfs目錄即可,若是支援WSL 2的Windows 系統則必須改用類似網路存取的方式,以 \\wsl$\<Linux名稱> 格式存取特定版本檔案系統,或以 \\wsl$  檢視目前已啟動的所有Linux檔案系統,如下圖以先檢視所有已啟動之檔案系統,然後再以命令指令連結至三個不同的Linux檔案系統。

wslshare

wsl2_w_acces_l
wsl2_w_acces_l2 

另一方面,WSL 的 Linux檔案系統會自動將每個Windows的磁碟區代號掛載到 /mnt/c /mnt/d …….等目錄上,下圖顯示了 df –T 命令的結果,Windows 的C: D:磁碟機已被掛載到/mnt/c與/mnt/d,因此WSL Linux Shell只需要透過/mnt/c 目錄就可以存取整個Windows磁碟區,並且直接利用標準的Linux命令執行Windows磁碟區的檔案相關各項操作。

wsl_linux_mnt_c

備份與匯入WSL發行版本

WSL下的Linux發行版本可以透過匯出的方式來將其備份成一個.tar的封裝檔案,其命令如下:

wsl --export <版本名稱>  <匯出位置及檔名(.tar)>
日後若有需要,可將之前的備份tar檔匯入使用。完整命令格式如下,--import 後面的第 1 個參數為 WSL發行版本名稱、第 2 個參數為匯入的 WSL 發行版本的檔案系統要存放的位置,第 3 個參數為先前備份匯出的 *.tar 檔案路徑,第4個選項參數可設定匯入後使用的WSL版本。

wsl --import <版本名稱>  <匯入的存放位置>  <tar 檔案路徑> <--version 1|2 >

底下二圖分別示範了WSL發行版本的匯入與匯出命令的用法。

wsl_export

wsl_import

WSL 網路

WSL 一版與二版的網路設計完全不同,WSL 1直接使用Windows的實體網路,包括Windows作業系統的所有實體網路介面,所設定的DNS與預設閘道器,但Linux與Windows使用相同IP位址的做法在許多應用場合是缺乏彈性的,因此WSL 2改執行在一個輕量級的擬機器上,故具有自已獨立的虛擬網路介面,您可以在支援WSL2的Windows作業系統上,經由網路連線來檢視名稱為 「vEthernet (WSL)」的這個WSL 2虛擬介面,WSL2的Linux發行版本會利用這個虛擬介面經由網路位址轉譯協定(NAT)來與外界連線溝通。

wsl_vnic

下圖中您可以分別在 WSL 1和WSL 2 這二個不同的Linux發佈版本的Shell下,檢視出設定為WSL 2架構執行的Linux發佈版本使用了172.16-31.x.x此等私自指定的IP位址,而使用 WSL 1的Linux系統,其eth介面則使用與Windows 系統相同的介面卡卡號與相同的IP位址。

wsl-ip

由於WSL 2使用網路位址轉譯協定(NAT)  ,所以一旦您在Linux系統安裝了伺服服務(例如網站或sshd),就只有Windows本機可以連線存取,若需要讓網路上其它機器也可以連線存取WSL 2 Linux系統,則需要建立連接埠轉送規則(Port Forwarding)才行,底下舉一個sshd的應用例子來說明整個連接埠轉送的執行過程與步驟:

  1. 安裝與設定ssh :首先安裝ssh套件-- apt install ssh -y ,由於WSL Ubuntu的sshd服務缺乏主機金鑰,經常會出現 「sshd: no hostkeys available -- exiting」的錯誤,解決方法相當簡單,只要輸入『 ssh-keygen -A 』就會產生主機金鑰了,接下來則依需求變更 /etc/ssh/sshd_config 這個組態檔(通常開放PermitRootLogin yes與PasswordAuthentication yes選項讓root可以方便的以密碼方式遠端登入),然後再以『 service ssh start 』命令就可啟動sshd服務了,不過這時就只有Windows本機可以連線進來。
  2. 找出已執行的WSL2 Linux的IP位址: wsl hostname –I
  3. 在Windows上可以利用 "netsh interface portproxy add v4tov4... "命令來建立連接埠轉送規則,完整的命令語法為:

    netsh interface portproxy add v4tov4 listenaddress=<主機傾聽的IP位址> listenport=<傾聽連接埠> connectport=<轉送的連接埠> connectaddress=<Linux的IP位址>

    底下為作者機器上的實例命令:
    netsh interface portproxy add v4tov4 listenaddress=0.0.0.0 listenport=22 connectaddress=172.26.195.107 connectport=22
  4. 最後,還需要開放sshd服務使用的TCP 22連入的防火牆規則:
    netsh advfirewall firewall add rule name="允許TCP 22連入連接埠” dir=in action=allow protocol=TCP localport=22

WSL2_Port_ford

完成上述四個步驟的工作後,使用者就可以在區域網路上的其它機器以任何ssh用戶軟體連線至WSL 2 Linux 主機了。

混合Windows 與Linux命令

Windows平台上安裝了WSL後,一個主要的好處是可以混合Windows 的cmd或Powershell命令與Linux bash命令來達到更彈性暨效率的作業,您有三種混搭執行方式:

  1. Windows 命令列上執行 Linux 命令
    從 Windows 命令提示字元 (CMD) 或 PowerShell 執行 Linux 二進位檔相當簡單,只須 wsl <命令> ,例如wsl ls -la ~ ; pwd ; uname ; cat /etc/*-release 可連續執行數個Linux命令並顯示在Windows命令提示字元視窗中。
  2. Linux Shell下執行Windows工具
    在WSL Linux Shell的提示符號下($或#),可直接輸入Windows執行檔案全名(需含.exe)即可啟動Windows程式,例如 $ calc.exe; notepad.exe 就可在Linux下啟動小算盤和記事本二個Windows應用。
  3. 在Windows命令列下混合二種指令

混合二種指令通常是利用管線命令(pipe)的作法,將Windows命令的結果傳遞給linux bash來執行,或相反的將Linux bash執行結果再傳遞給Windows命令來執行。

  • powershell –> bash
    先執行Winodws命令後,再將結果傳給bash命令處理。如下圖例,利用powershell –childitem命令顯示目錄清單後,再丟給linux的grep命令來搜尋特定關鍵字。第二個串接指令是先利用Windows的ipconfig顯示網路組態後,再依序丟給linux的grep與 cut命令以顯示本機所有IP位址。   
    powershell_to_bash  
  • bash –> powershell
    您也可以先透過wsl執行Linux命令後,再傳給Windows命令處理,例如下圖先以Linux ls命令列出目錄清單後,再送至Windows的findstr命令來搜尋。
    bash_to_cmd

共享環境變數 WSLENV

WSL利用一個特殊的環境變數WSLENV來讓Windows系統與Linux系統分享環境變數, 由於預設上WSL Linux中唯一可存取的Windows環境變數為PATH, 透過變數WSLENV可讓使用者自行定義要分享的變數,而WSLENV 提供了四個可用的旗標,它們影響了環境變數的轉譯方式:

  • /p - 轉譯 WSL/Linux 和 Windows 二者之間的路徑,可從WSL/Linux 轉換至 Windows的路徑,也可從至 WSL/Linux 轉換到WSL/Linux的路徑
  • /l - 指出環境變數是數個路徑的清單,故到時會須轉換 : 與 ;分隔符號。
  • /u - 表示從 Windows 執行 WSL 應用與工具時,才包含此環境變數,不會轉換路徑。
  • /w - 指出只有從 WSL Linux執行 Windows 應用與工具時,才會包含這個環境變數,不會轉換路徑。

底下四個圖例,說明了/p、/l、/u、/w之使用方法及不同。

wslenv_p

wslenv_l

wslenv_up

wslenv_wp

安裝Linux 圖形介面系統

如果您需要在WSL上執行圖形介面,那就需要Linux GUI,傳統的gname與kde均屬功能豐富但資源耗費的桌面環境,較不適合輕量級的WSL Linux系統,所以最輕快與資源耗費低的 xfce4遂成為首選,另一方面,由於Windows 系統預設上並無X 伺服器,也無vnc,因此圖形顯示上最好直接採用Windows原本內建的顯示協定-rdp來建立遠端圖形連線 (當然您仍可以在Windows平台上安裝X Server來提供顯示服務)。

本例將在ubuntu20.04上安裝xfce4與xrdp,然後再利用Windows RDP顯示協定完成連線與顯示,步驟如下:

  1. 先更新ubuntu系統:請執行 sudo apt -y update && sudo apt upgrade –y
  2. 安裝 xfce4與xrdp:請執行 sudo apt -y install xfce4 xrdp
  3. 啟動 xrdp:請執行 sudo service xrdp restart ,若不想每次重新進入WSL時均須手動啟動xrdp服務,可將這一行寫入/etc/profile檔案(最好設定/etc/sudoers無需密碼)
  4. 設定RDP連線時啟用 xfce4(每位登入GUI帳戶均需設定):請執行 echo xfce4-session > ~/.xsession
  5. 執行 ip a 以確認目前的IP位址,然後在Windows 系統上執行 mstsc 啟動遠端桌面連線軟體,輸入ubuntu Linux的IP位址,再輸入帳號密碼後即可建立圖形介面連線
    xfce4

移除WSL Linux發行版本

若基於任何理由需要移除已安裝的WSL Linux發行版本,則直接使用命令 wsl --unregister <發行版本名稱> 刪除之,這個命令會將 WSL Linux版本下的所有的檔案都加以全數刪除,且刪除後亦無法復原,請小心使用,或移除前先匯出為 tar檔。

四. 結語

微軟發布了WSL強化了Windows/Linux開發人員的整合平台,使得需要Linux開發環境的人員能夠以最簡單、最少資源和無需複雜部署的情況下在Windows上進行許多開發工作,包括在Windows平台上透過WSL在Linux環境中使用Visual Studio Code、Git與docker….等。另一方面,系統管理員也可以混合更強大和彈性的Linux指令來完成各項管理工作,雖然WSL已經朝著向正確的方向邁出了一大步,但離成熟尚有一段距離,未來的發展趨勢將讓開發人員、系統人員有更高的期待。