以WSL + Ubuntu + zsh打造Windows上高富帥的命令列模式
Windows Subsystem for Linux (WSL) 是讓我們在 Windows 裡使用非 VM 方式可以直接與 Linux 底層溝通。網路上關於 WSL 使用與配置有許多精彩文章。最近在重設新電腦,以下順手記錄整合 WSL + Ubuntu + zsh 的配置,並且整合至 Docker CLI、VS Code、wsltty 與 cmder,讓我們體驗一個完全不同檔次指令列模式。
安裝 Windows Subsystem for Linux (WSL)
開啟 PowerShell (系統管理員)
Windows 10 (需 1709 版之後):
Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux
Windows Server 2019 (含之後更新):
Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux
安裝 WSL 是把執行環境設定好,接下來選擇要安裝 Linux Distribution,你可以直接點擊以下連結「ms-windows-store://search/?query=Linux」它會開啟 Windows Store 直接進行關鍵字搜尋,或在 Windows Stoer 搜尋關鍵字:
- Ubuntu
- OpenSUSE
- SLES
- Kali Linux
- Debian GNU/Linux
以我安裝的 Ubuntu 18.04 為例,第一次啟動請保持網路連線並且它會要求你設定一組帳號密碼,帳號會當成預設登入帳號,密碼則為 sudo 的密碼。如果真的忘了,可以參考文件重設。比較好玩的是,目前有開放自行客製化的 Linux Distribution,有趣的人也能參考規範文件。
完成之後開啟 Ubuntu Bash Shell 視窗,除了帶了點顏色外,感覺其實也沒和命令提示字元(cmd.exe)畫面差多少。
Windows 不會自動更新你的 Linux Distribution,請定期在 Shell 輸入
sudo apt update && sudo apt upgrade
來更新。
切換Shell:Z Shell(zsh) + Oh My Zsh
Linux Shell 不像 Windows 只有 cmd.exe / powershell.exe 並且與作業系統綁的那麼死,它有許多的選擇,我個人使用 Z Shell(zsh) + Oh My Zsh,而非 Ubuntu 的 /bin/bash。
透過以下指令可以快速安裝與設定使用 zsh:
$ sudo apt-get install zsh
$ which zsh
/usr/bin/zsh
$ chsh -s /usr/bin/zsh
預設為
/bin/bash
,一樣可以用which bash
與chsh
再換回去。
重開之後,操作的畫面已經有些不一樣。zsh 另一個優點是本身透過 https://ohmyz.sh 來安裝外掛來增強。
$ sh -c "$(curl -fsSL https://raw.github.com/robbyrussell/oh-my-zsh/master/tools/install.sh)"
$ git clone https://github.com/zsh-users/zsh-completions ~/.oh-my-zsh/custom/plugins/zsh-completions
$ git clone https://github.com/zsh-users/zsh-autosuggestions $ZSH_CUSTOM/plugins/zsh-autosuggestions
$ git clone https://github.com/zsh-users/zsh-syntax-highlighting.git ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting
第一行安裝 Oh My Zsh 之外,我又安裝三個我個人覺得好用的 zsh-users 外掛,安裝之後,需要使 vim 編輯 .zshrc
來啟用這些外掛:
ZSH_THEME="agnoster"
plugins=(git zsh-completions zsh-autosuggestions zsh-syntax-highlighting)
- Plugin 預設只啟用了 git,可自行查詢文件來安裝與啟用想使用的外掛,也歡迎大家介紹。
- Oh My Zsh 官方有特別說明,許多佈景主題需要額外安裝 Powerline Fonts,如果佈景主題設定之後沒效果或怪怪的,那麼安裝一下:
sudo apt-get install fonts-powerline
,但不要在 WSL 上安裝,這會是無效的,因為它底層還是讀取 Windows 的字型,我們應該把字型下載回來安裝在 Windows 上,例如,安裝 Ubuntu Mono derivative Powerline。各種佈景主題展示參考這裡,另外,如果選擇的佈景主題的效果在 WSL 沒想像中的完整,建議選擇像bira
而不要選agnoster
有圖示與底色的佈景主題。
bira 佈景主題
agnoster 佈景主題
robbyrussell 佈景主題
WSL with Windows Command
WSL 整合 Windows 的環境變數($PATH
),所以兩邊指令是能互通的。例如,我們都知道 Linux 下有個強大的 grep 指令,我們現在也能輕鬆把 Windows Command 的結果交給 grep
來處理。也注意一下,Windows 磁碟機會被掛載至 /mnt/c
or /mnt/d
以此類推,盡量不要把 Windows 的檔案儲存在 WSL 裡。
Get-Service | wsl grep W32Time
在 WSL 的 Shell 模式下,使用 code .
都能正確開啟 Visual Studio Code 進行作業,就算是在 WSL 的 Linux 目錄裡也行哦,超棒的。有一點要注意,如果在 WSL Shell 要執行 Windows 指令需加上 .exe,例如,在 WSL Shell 輸入 ping
與 ping.exe
是不同的,那是剛好 WSL 裡有名為 ping
的指令。例如,我們突然要切回 PowerShell,那麼需要輸入 powershell.exe 而不是 powershell。
Windows 10 1903 版可能會更新 WSL 與檔案總管(explorer.exe)的整合,讓我們在 Windows 更容易瀏覽存取 WSL 資料。
整合 Docker on Windows
到前段為止,我們把 WSL 的 Ubuntu 的 bash
改為 zsh
並加入外掛與佈景主題來提升體驗。但工作上有許多會命令列模式的地方,我也想改用這個好用的 WSL Ubuntu zsh 環境,像 Docker CLI 就是一大部分,在 WSL 環境下直接輸入 docker images
會得到一個錯誤訊息。
在 WSL 要跟 Docker on Windows 的 Docker Engine 溝通,需要進行一些調整。
- 開啟 Docker on Windows 的 Setting 在 General 勾選 Expose daemon on tcp://localhost:2375 without TLS。
- 編輯 zsh 的
vim ~/.zshrc
加入以下內容:
- 使用 bash 應修改
~/.bashrc
。
# docker
PATH="$PATH:/mnt/c/Program\ Files/Docker/Docker/resources/bin"
alias docker=docker.exe
alias docker-machine=docker-machine.exe
alias docker-compose=docker-compose.exe
export DOCKER_HOST="tcp://localhost:2375"
如果 vim 不太熟,步驟如下:
- 複制上面所有文字。
- 將游標移至最下方,按
o
或i
- 按滑鼠左鍵,貼上複製內容
- 按
ESC
按:wq
或許試試
Code .
是個不錯的選擇 😉
- 在 sudoer 加入
DOCKER_HOST
加入預設環境變數中,執行sudo visudo
加入以下內容:
#docker
Defaults env_keep += "DOCKER_HOST"
sudo visudo
修改完按Ctrl+X
按Enter
直接存檔即可。
重開 Ubuntu Shell,再次輸入 Docker CLI:
這裡也學到一個重要的技巧
alias
,如果在 WSL Shell 不想加 .exe 執行 Windows 指令,可以自行定義alias
。
整合 VS Code
你能調整 VS Code 終端機設定,以指定新的 Shell 來作業。
如果覺得 VS Code 新的 GUI 設定編輯器不習慣,那麼可以在「
Ctrl+Shift+P
」直接輸入「Open Settings (JSON)」來開啟 settings.json 進行設定。
將 powrshell 改為 bash.exe:
- 預設:C:\WINDOWS\System32\WindowsPowerShell\v1.0\powershell.exe
- 修改:C:\Windows\System32\bash.exe
因為我們用 zsh,所要帶參數來指定切換到 zsh,這部分目前還是需要到 settings.json 設定:
{
"editor.fontFamily": "'Source Code Pro',Consolas, 'Courier New', monospace",
"workbench.colorTheme": "Visual Studio Dark",
"terminal.integrated.shell.windows": "C:\\Windows\\System32\\bash.exe",
"terminal.integrated.shellArgs.windows": [
"-c",
"zsh"
]
}
啟動之後怪怪的:
還好前面處理過了,一看就能知道字型問題,VS Code 本身的終端機可以另外指定字型:
{
"editor.fontFamily": "'Source Code Pro',Consolas, 'Courier New', monospace",
"workbench.colorTheme": "Visual Studio Dark",
"terminal.integrated.shell.windows": "C:\\Windows\\System32\\bash.exe",
"terminal.integrated.shellArgs.windows": [
"-c",
"zsh"
],
"terminal.integrated.fontFamily": "'Ubuntu Mono derivative Powerline'"
}
不過這樣又跑出新的問題出來,你可以按 Ctrl+Shift+` 或終端機裡「+」符號:
你能發現,現在我想切換至 PowreShell 或 cmd.exe 又切不回去了。每個終端機都會被指定為 zsh。想要任意切換 Shell 可以靠第三方外掛 Shell launcher 來解決。
設定有兩個動作,一是指定快速鍵,二是指定 Shell 啟動路徑參數。按快速鍵 Ctrl+K, Ctrl+S
(檔案 → 喜好設定 → 鍵盤快速鍵)開啟 keybindings.json 指定以下內容:
[{
"key": "ctrl+shift+t",
"command": "shellLauncher.launch"
}]
在 settings.json 裡加入 Shell Launcher 組態:
{
"editor.fontFamily": "'Source Code Pro',Consolas, 'Courier New', monospace",
"workbench.colorTheme": "Visual Studio Dark",
"terminal.integrated.shell.windows": "C:\\Windows\\System32\\bash.exe",
"terminal.integrated.shellArgs.windows": [
"-c",
"zsh"
],
"terminal.integrated.fontFamily": "'Ubuntu Mono derivative Powerline'",
"shellLauncher.shells.windows": [
{
"shell": "C:\\Windows\\System32\\cmd.exe",
"label": "cmd"
},
{
"shell": "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe",
"label": "PowerShell"
},
{
"shell": "C:\\Program Files\\PowerShell\\6\\pwsh.exe",
"label": "PowerShell Core"
},
{
"shell": "C:\\Windows\\System32\\bash.exe",
"args": ["-c", "zsh"],
"label": "WSL Bash"
}
]
}
VS Code 加上 Shell launcher 就能自由切換想要的 Shell。
整合 wsltty
wsltty 是另一套整合 WSL 的終端機,為什麼還要介紹它呢?如果你大量在 WSL 終端機工作,非常有機會出現了 non-Unicode
字元,例如,出現 Big5 編碼字元,它會造成 WSL 終端機視窗凍結。這個問題,可以改用 wsltty 來解決。wsltty 透過 Chocolatey 安裝相當簡單:
choco install wsltty
它會去偵測系統安裝的 Linux Distribution 產生對應的啟動設定,wsltty 有多種觸發執行方式:
- 開始的捷徑 (如上圖裡【WSL Terminal %】等)
- .bat 腳本
- 右鍵選單 (需手動產生,如上圖裡【add default to context menu】等)
你能發現開始捷徑會產好幾個啟動捷徑,簡單區分:
Terminal
開啟 WSL 的 user home 目錄。以pwd
來看會是在 WSL 裡的 /home/。Terminal %
(結尾多個%
) 開啟 WSL 的 Windows %USERPROFILE% 目錄。以pwd
來看會是在 WSL 裡的 /mnt/c/Users/
現示怪怪的,你應該知道怎麼處理了,選擇對的字型即可:
我們使用的 Ubuntu 字型無法透過 GUI 來設定,還好,wsltty 有提供 fonts 相關參數值,-o Font="Ubuntu Mono derivative Powerline"
加入你想使用捷徑參數中:
wsltty wiki 文件也有提到類似 Powerline 的字型問題,它建議可以到 Nerd Fonts 找合適的字型。
整合 cmder(ConEmu)
又是 cmd.exe,又是 powershell.exe,WSL 有 Bash 與 zsh,前還加了 wsltty,你搞得我好亂呀!那有無一個好的 Shell 管理工具?這時候超合適介紹 cmder 出場。如果你是個開發人員,我相信電腦都已經有 git 了,那只需下載 Comder Mini 離線版即可。
在 ≡ 選單的地方選 settings,找到 Startup → Tasks,這裡會有系統預設的 cmd 與 powershell 設定,我們可以任意去增減 Shell 的設定。
按一下 + 來加入一組設定:
- Name:
WSL::zsh
- icon:
-icon "%LOCALAPPDATA%\wsltty\wsl.ico"
- Commmand:
%LOCALAPPDATA%\wsltty\bin\mintty.exe --WSL= --configdir="%APPDATA%\wsltty" -o Font="Ubuntu Mono derivative Powerline" -~
如果想要加入原始 Ubuntu Shell:
- Name:
WSL::Ubuntu
- icon:
-icon "%LOCALAPPDATA%\wsltty\wsl.ico"
- Commmand:
ubuntu1804.exe -cur_console:p
這裡兩個選擇:
C:\Windows\System32\wsl.exe
%LOCALAPPDATA%\Microsoft\WindowsApps\ubuntu1804.exe
差異在於啟動後的目錄,類似前目的 `Terminal` 有無 `%`,wsl.exe 會進入當下目錄,`ubuntu1804.exe` 會進入 user home。
透過 cmder 我們就能在一個介面中去使用系統裡的各種 Shell。
小結
怎麼沒介紹 Visual Studio 的整合呢?說實在,在 Visual Studio 裡去整合 cmd.exe / powershell.exe 真的不難,我相信要整合 WSL Shell 進去也沒多難。但工作上真的會需要在 Visual Studio 下指令機會實在很少,Visual Studio 實在整合的太好,還是留些事給滑鼠,點一點能把工作做好也是很重要的。
現在,Windows 下也能擁有高富帥的命令列模式,不用老是羨慕咬一口了。
參考
- https://blogs.msdn.microsoft.com/microsoft_student_partners_in_taiwan/2017/10/03/wsltune/
- https://medium.com/hungys-blog/windows-subsystem-for-linux-configuration-caf2f47d0dfb
- https://medium.com/@ericsk/在-windows-subsystem-for-linux-wsl-下使用-windows-上的-docker-engine-8dc0040ca240
- https://hackmd.io/s/BJByCIUHf#
- https://blog.miniasp.com/post/2019/02/09/Useful-tool-WSLtty-Mintty-as-a-terminal-for-WSL
fb 看到的,一個 ZSH 專用的佈景,很起來很不錯:https://github.com/Powerlevel9k/powerlevel9k
回覆刪除