以WSL+Ubuntu+zsh打造Windows上高富帥的命令列模式

以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,有趣的人也能參考規範文件

WSL Ubuntu first open

完成之後開啟 Ubuntu Bash Shell 視窗,除了帶了點顏色外,感覺其實也沒和命令提示字元(cmd.exe)畫面差多少。

Windows 不會自動更新你的 Linux Distribution,請定期在 Shell 輸入 sudo apt update && sudo apt upgrade 來更新。

WSL Ubuntu Update

切換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 bashchsh 再換回去。

重開之後,操作的畫面已經有些不一樣。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 有圖示與底色的佈景主題。
Themes OhMyZsh bira

bira 佈景主題

Themes OhMyZsh agnoster

agnoster 佈景主題

Themes OhMyZsh robbyrussell

robbyrussell 佈景主題

WSL with Windows Command

WSL Run 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 輸入 pingping.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 Command Notfound

在 WSL 要跟 Docker on Windows 的 Docker Engine 溝通,需要進行一些調整。

  1. 開啟 Docker on Windows 的 SettingGeneral 勾選 Expose daemon on tcp://localhost:2375 without TLS
  2. 編輯 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 不太熟,步驟如下:

  1. 複制上面所有文字。
  2. 將游標移至最下方,按 oi
  3. 按滑鼠左鍵,貼上複製內容
  4. ESC:wq

或許試試 Code . 是個不錯的選擇 😉

  1. 在 sudoer 加入 DOCKER_HOST 加入預設環境變數中,執行 sudo visudo 加入以下內容:
#docker
Defaults env_keep += "DOCKER_HOST"

sudo visudo 修改完按 Ctrl+XEnter 直接存檔即可。

重開 Ubuntu Shell,再次輸入 Docker CLI:

WSL Run Docker CLI

這裡也學到一個重要的技巧 alias,如果在 WSL Shell 不想加 .exe 執行 Windows 指令,可以自行定義 alias

整合 VS Code

你能調整 VS Code 終端機設定,以指定新的 Shell 來作業。

如果覺得 VS Code 新的 GUI 設定編輯器不習慣,那麼可以在「Ctrl+Shift+P」直接輸入「Open Settings (JSON)」來開啟 settings.json 進行設定。

VS Code Setting Shell Windows

將 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 Setting Shell Windows - settings.json

啟動之後怪怪的:

VS Code - Terminal 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'"
}
VS Code - Terminal - Font family
VS Code - Terminal - Font family - settings.json

不過這樣又跑出新的問題出來,你可以按 Ctrl+Shift+` 或終端機裡「+」符號:

terminal-multiple-instances

你能發現,現在我想切換至 PowreShell 或 cmd.exe 又切不回去了。每個終端機都會被指定為 zsh。想要任意切換 Shell 可以靠第三方外掛 Shell launcher 來解決。

設定有兩個動作,一是指定快速鍵,二是指定 Shell 啟動路徑參數。按快速鍵 Ctrl+K, Ctrl+S(檔案 → 喜好設定 → 鍵盤快速鍵)開啟 keybindings.json 指定以下內容:

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"
        }
    ]
}
Run ShellLauncher

VS Code 加上 Shell launcher 就能自由切換想要的 Shell。

整合 wsltty

wsltty 是另一套整合 WSL 的終端機,為什麼還要介紹它呢?如果你大量在 WSL 終端機工作,非常有機會出現了 non-Unicode 字元,例如,出現 Big5 編碼字元,它會造成 WSL 終端機視窗凍結。這個問題,可以改用 wsltty 來解決。wsltty 透過 Chocolatey 安裝相當簡單:

choco install wsltty
wsltty StartMenu

它會去偵測系統安裝的 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/
wsltty Distrib Terminal

現示怪怪的,你應該知道怎麼處理了,選擇對的字型即可:

wsltty select font family error

我們使用的 Ubuntu 字型無法透過 GUI 來設定,還好,wsltty 有提供 fonts 相關參數值,-o Font="Ubuntu Mono derivative Powerline" 加入你想使用捷徑參數中:

wsltty select ubuntu Powerline font family

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" -~
cmder zsh

如果想要加入原始 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 下也能擁有高富帥的命令列模式,不用老是羨慕咬一口了。

參考

1 則留言:

  1. fb 看到的,一個 ZSH 專用的佈景,很起來很不錯:https://github.com/Powerlevel9k/powerlevel9k

    回覆刪除

感謝您的留言,如果我的文章你喜歡或對你有幫助,按個「讚」或「分享」它,我會很高興的。