# 介紹好用工具：WSLtty (Mintty as a terminal for WSL)

🔥 **本文介紹工具已不再推薦使用，建議改用 [Windows Terminal](https://www.microsoft.com/zh-tw/p/windows-terminal/9n0dx20hk701) ([GitHub](https://github.com/microsoft/terminal)) 來進行 WSL 操作** 🔥

Windows 下的任何命令列工具，都是基於傳統 [Windows Console](https://blogs.msdn.microsoft.com/commandline/2018/07/20/windows-command-line-inside-the-windows-console/) 介面進行互動，你很難想像 Windows Console 的原始碼已經超過 30 年沒有更新過，所以當 WSL 加入 Windows 之後，所遇到的挑戰比你想想的大許多，更新的速度也非常慢，目前也只有 Windows Insider 版本才能體驗新的功能。本篇文章我將分享幾個我曾經遇到過的問題，還有介紹 [WSLtty](https://github.com/mintty/wsltty) 工具，幫助你徹底解決這些難題。

使用 Windows Console 操作 WSL 通常不會出問題，但在特定情況下，整個 Windows Console 會直接凍結(hang)，完全無法輸入輸出，查問題的過程會非常耗時，我個人就遇過很多次，有時真的會氣到不太想再用它。

### 編碼問題

我有個主機代管的客戶，由於幫客戶管理的 Linux 主機已經使用超過 15 年，過程中升級過幾次，服務基本上都沒出什麼大狀況。不過去年有段時間需要連入主機設定 cronjob 排程，一般來說只要輸入 `crontab -e` 就可以進入編輯，我用 [PuTTY](https://www.chiark.greenend.org.uk/~sgtatham/putty/) 都沒事，但只要用 WSL 就會 hang 住。

當時這個問題困擾我好幾天，因為我所有管理的 Linux 電腦操作都沒問題，只有客戶的主機會 hang 住，我試圖找出問題發生的主因，後來發現這點根本無解，因為在 Windows Console 的限制下，如果在 WSL 視窗出現 "non-Unicode" 字元，就很有可能會整個畫面 hang 住，但其實程式還在執行，只是不能進行互動而已，最後只能整個 WSL 關閉重開。

像我這個客戶，他們的 cronjob 內容應該包含一些使用 Big5 編碼撰寫的註解，我就只是單純的透過 `crontab -l` 將內容顯示在畫面上而已，整個 WSL 視窗就會 hang 住，更別說要執行 `crontab -e` 了！進一步實驗，發現所有用 Big5 編碼的文字檔都有這種情況，實在不勝其擾！如果你將檔案內容的文字編碼改用 UTF-8 的話，所有問題就會自然消失，真的超雷！

光是這個問題，我就覺得 Windows Console 已經完全不能使用了，連正常的工作都不行！

以下我列出幾個跟 WSL 與 Windows Console 相關的網址，大家可以到這邊查問題或反饋問題：

-   [Windows Console issue tracker](https://github.com/microsoft/console/issues)
-   [WSL (Windows Subsystem for Linux) issue tracker](https://github.com/Microsoft/WSL)
    -   [Stack Overflow](https://stackoverflow.com/questions/tagged/wsl)
    -   [Ask Ubuntu](https://askubuntu.com/questions/tagged/wsl)
    -   [reddit](https://www.reddit.com/r/bashonubuntuonwindows)
    -   以下列出所有可以或不可以跑在 WSL 的應用程式清單：
        -   [https://github.com/ethanhs/WSL-Programs](https://github.com/ethanhs/WSL-Programs)
        -   [https://github.com/davatron5000/can-i-subsystem-it](https://github.com/davatron5000/can-i-subsystem-it)
    -   [Awesome WSL](https://github.com/sirredbeard/Awesome-WSL)
    -   [Tips and guides for new bash users](https://github.com/abergs/ubuntuonwindows)
-   Command Prompt / Console / Windows Subsystem for Linux (WSL): WSL/Bash – Windows developer feedback site!
-   [Windows Subsystem for Linux Documentation](https://learn.microsoft.com/windows/wsl)

如果可以的話，建議可以改用 [WSLtty](https://github.com/mintty/wsltty) 或 [Cmder](http://cmder.net/) 來開啟 WSL 進行操作。

### 安裝方式

1.  透過 Windows 安裝程式
    
    [WSLtty](https://github.com/mintty/wsltty) 官網有個 Windows 安裝程式，你直接到 [Release](https://github.com/mintty/wsltty/releases) 頁面下載最新版安裝即可。
    
2.  透過 [Chocolatey](https://chocolatey.org/) 自動安裝
    
    ```bash
    choco install wsltty
    ```
    
    升級版本
    
    ```bash
    choco upgrade wsltty
    ```
    
3.  透過 [Scoop](https://scoop.sh/) 自動安裝
    
    ```bash
    scoop bucket add extras
    scoop install wsltty
    ```
    
    升級版本
    
    ```bash
    scoop update wsltty
    ```
    

### 如何啟動

要將 WSL 啟動在 WSLtty 環境下，有以下幾種啟動方式：

1.  透過命令列模式啟動 WSLtty 環境
    
    安裝完成後，而 WSLtty 會在這個資料夾建立相對應的批次檔，用以啟動 WSLtty 為主的 Terminal 環境。
    
    > Windows 10 內建的 [WSL](https://learn.microsoft.com/windows/wsl/) 主要程式路徑位於 `%LOCALAPPDATA%\Microsoft\WindowsApps` 資料夾，所有相關程式都會置於這個資料夾內。而本文所介紹的 [WSLtty](https://github.com/mintty/wsltty) 主要程式路徑位於 `%LOCALAPPDATA%\wsltty` 資料夾下。
    
    -   如果你個人習慣的啟動方式是執行 `ubuntu.exe`
        
        -   那麼啟動 WSLtty 的批次檔就是 `Ubuntu.bat` 或 `Ubuntu~.bat`
    -   如果你個人習慣的啟動方式是執行 `ubuntu1804.exe`
        
        -   那麼啟動 WSLtty 的批次檔就是 `Ubuntu-18.04.bat` 或 `Ubuntu-18.04~.bat`
    -   如果你個人習慣的啟動方式是執行 `wsl` 或 `bash` 的話
        
        -   那麼啟動 WSLtty 的批次檔就是 `WSL.bat` 或 `WSL~.bat`
            
            > 因為在 `C:\Windows\System32\` 目錄下也有個 `wsl.exe` 執行檔，所以當你輸入 `wsl` 的時候，預設不會啟動 WSLtty，你必須輸入 `wsl.bat` 或 `wsl~` 才能真正啟動 WSLtty 終端機！
            
    
    請注意：上述的批次檔中，有加上 `~` 與沒有 `~` 的最大差異，在於：
    
    1.  若在 `G:\Projects` 執行 `WSL.bat` 預設在 WSL 中會停留在 `/mnt/g/Projects` 目錄下
    2.  若在 `G:\Projects` 執行 `WSL~.bat` 預設在 WSL 中會停留在 `$HOME` 目錄下
2.  從「開始功能表」(Start Menu) 啟動
    
    安裝完成後，你的開始功能表會多出一個 `WSLtty` 目錄，裡面有許多捷徑可以點擊啟動，也可以透過搜尋方式啟動。
    
    另外在第一層也會有個 `WSL Terminal` 捷徑，他會啟動預設的 WSL 安裝。
    
    在開始功能表的 `WSLtty` 分類下，還有個 `configure WSL shortcuts` 捷徑，當你從 Microsoft Store 安裝額外的 Linux 發行版本後，可以點擊這個捷徑，他會全自動幫你重新設定相對應的批次檔與捷徑，方便你日後啟動 WSLtty 終端機。
    
3.  從「檔案總管」按右鍵選擇 `WSL Terminal` 啟動
    
    在開始功能表的 `WSLtty` 分類下，也有個 `add default to context menu` 與 `add to context menu` 捷徑。如果執行 `add default to context menu` 的話，他會幫你自動註冊機碼，讓你之後在檔案總管中可以按滑鼠右鍵選擇 `WSL Terminal` 啟動終端機。選擇 `add to context menu` 的話，就會自動把所有安裝的 WSL 版本(Distro)全部加到右鍵選單中(Context Menu)。
    
    執行 `remove from context menu` 就可以解除安裝。
    
    如果想把 `Ubuntu 18.04` 的 WSL 設定為預設的話，你要手動修改 `%LOCALAPPDATA%\wsltty\config-distros.sh` 檔案，修改 158 行，將 `minttyargs='--WSL --configdir="'"$configdir"'"'` 修改為 `minttyargs='--WSL="Ubuntu-18.04" --configdir="'"$configdir"'"'` 即可。
    
    再者，如果你想調整啟動 `WSL Terminal` 的快捷鍵，可以修改 `HKEY_CURRENT_USER\Software\Classes\Directory\Background\shell\WSL_Terminal` 機碼內的 `(預設值)` 字串內容，將 `WSL Terminal` 修改為 `W&SL Terminal` 就會有 `S` 快捷鍵可以按。使用方式將會是：
    
    1.  先透過檔案總管瀏覽到特定目錄
    2.  在畫面空白處按下滑鼠右鍵並按下 `s` 按鍵，這樣就會自動啟動 `WSL Terminal`

### 主要設定檔位置

由於 [WSLtty](https://github.com/mintty/wsltty) 是 [Mintty](http://mintty.github.io/) 的一個子專案，所以他的所有設定都可以參照 [Mintty Manual](http://mintty.github.io/mintty.1.html) 的說明，你也可以從官網得知 Mintty 真正想解決的問題為何。

以下是安裝完 WSLtty 之後預設的 `%LOCALAPPDATA%\wsltty\Ubuntu-18.04~.bat` 批次檔內容，你可以發現啟動 WSLtty 其實就是啟動 `mintty.exe` 程式而已，只是特別加上 `--WSL` 參數指定 WSL 的特定 Linux 發行版本執行：

```batch
%LOCALAPPDATA%\wsltty\bin\mintty.exe -i "%LOCALAPPDATA%\wsltty\wsl.ico" --WSL="Ubuntu-18.04" --configdir="%APPDATA%\wsltty" -~
```

> 上述的 `--configdir` 就是指定 Mintty 的設定檔載入路徑。

啟動 WSLtty 的過程中，可以參考以下幾個路徑，這是載入設定檔的優先順序，越上面優先權越高：

1.  直接使用 `-c` 指定設定檔路徑 (預設 wsltty 安裝時不是用這個)
    
2.  直接使用 `--configdir` 指定設定檔所在資料夾，它會去找這個資料夾下的 `config` 檔案
    
    > WSLtty 預設的主要設定檔位於 `%APPDATA%\wsltty\config`
    
3.  自動搜尋 `%HOME%\.minttyrc` 檔案 (不建議使用這個檔案進行設定)
    
4.  自動搜尋 `%HOME%\.config\mintty\config` 檔案 (不建議使用這個檔案進行設定)
    
5.  自動搜尋 `%APPDATA%\mintty\config` 檔案
    
6.  自動搜尋 `%LOCALAPPDATA%\wsltty\etc\minttyrc` 檔案 (不建議使用這個檔案進行設定)
    

### 進階應用

要透過 WSLtty 啟動 WSL (Ubuntu 18.04) 除了用預設的批次檔外，還可以透過以下命令進行調整啟動參數：

-   直接呼叫啟動，進入**預設 shell 環境**，並停留在 `$HOME` 目錄下 (`-~`)
    
    ```bash
    %LOCALAPPDATA%\wsltty\bin\mintty.exe --WSL="Ubuntu-18.04" --configdir="%AppData%\wsltty" -~
    ```
    
-   直接呼叫啟動，進入**預設 shell 環境**，並設定終端機顯示文字以 **Big5 字集**為主 (預設為 `UTF-8` 字集)
    
    ```bash
    %LOCALAPPDATA%\wsltty\bin\mintty.exe --WSL="Ubuntu-18.04" --configdir="%APPDATA%\wsltty" -o Charset=Big5
    ```
    
-   直接呼叫啟動，進入**指定 shell 環境** (`bash`)
    
    ```bash
    %LOCALAPPDATA%\wsltty\bin\mintty.exe --WSL="Ubuntu-18.04" --configdir="%APPDATA%\wsltty" /bin/bash -l
    ```
    

> 像是上述指令都可以封裝成一個個批次檔，降低進入 WSL 的難度。預設 WSLtty 提供的批次檔都會複製一份到 `%LOCALAPPDATA%\Microsoft\WindowsApps` 資料夾，你也可以直接修改這裡的批次檔內容。

以往我們要直接啟動 WSL 並執行程式的方式有好多種，例如：

```bash
wsl ls -laF ~
```

```bash
bash -c "ls -laF ~"
```

```bash
ubuntu run ls -laF ~
```

```bash
ubuntu run sh -c 'ls -laF ~'
```

如果想要透過 WSLtty 啟動 WSL (Ubuntu 18.04) 並自動執行腳本後退出，可以透過以下命令：

-   直接呼叫啟動，並執行指定程式後關閉退出
    
    建議將**批次檔內容**加上 `%1 %2 %3 %4 %5 %6 %7 %8 %9` 參數，到執行 `mintty.exe` 這行的最後面，例如：
    
    ```bash
    %LOCALAPPDATA%\wsltty\bin\mintty.exe -i "%LOCALAPPDATA%\wsltty\wsl.ico" --WSL= --configdir="%APPDATA%\wsltty" %1 %2 %3 %4 %5 %6 %7 %8 %9
    ```
    
    如此一來就可以徹底簡化命令列輸入！
    
    1.  列出 `$HOME` 目錄所有檔案
        
        ```bash
        wsl.bat ls -laF ~
        ```
        
    2.  列出 `$HOME` 目錄所有檔案並將檔案輸出到 Windows 的當前目錄
        
        由於用到 `>` 符號，所以必須透過 `sh -c` 傳入執行
        
        ```bash
        wsl.bat sh -c "ls -laFR ~ > ./HOME_File_List.txt"
        ```
        
    3.  查看 `/var/log/dpkg.log` 檔案變更
        
        ```bash
        wsl.bat tail -f /var/log/dpkg.log
        ```
        
    4.  透過 WSL 使用 SSH 連線至遠端電腦
        
        ```bash
        wsl.bat ssh 172.14.19.3
        ```
        
    5.  透過 WSL 使用 SSH 執行遠端命令
        
        ```bash
        wsl.bat ssh 172.14.19.3 tail -f /var/log/syslog
        ```
        

### 常用快速鍵

有在玩 Linux 的人，應該各個都是快速鍵的好手，所以用了 WSLtty 之後，哪能不記一些好用的快速鍵呢！

底下的快速鍵中，請記得先開啟 `Ctrl+Shift+字母` 快捷鍵才能使用相關快速鍵，預設這個快速鍵組合是關閉的：

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/48d346151ad4ab9abc8c-image_3181.png)

-   新增終端機
    
    -   `Alt-F2`
    -   `Ctrl+Shift+N`
-   切換不同的 mintty 視窗
    
    -   `Ctrl-Tab`
    -   `Ctrl-Shift-Tab`
-   搜尋畫面中的文字
    
    -   `Alt-F3`
    -   `Ctrl+Shift+H`
-   關閉終端機
    
    -   `Alt-F4`
    -   `Ctrl+Shift+W`
    
    > 我個人愛用 `Ctrl+D` 正常退出，使用 `Alt-F4` 是強制關閉終端機。
    
-   重置畫面 (清空畫面與所有卷軸內容)
    
    -   `Alt-F8`
    -   `Ctrl+Shift+R`
-   調整字體大小 (這我在演講時超好用)
    
    -   鍵盤：`Ctrl-+` / `Ctrl--`
        
    -   鍵盤：`Ctrl-Shift-+` / `Ctrl-Shift--`
        
    -   滑鼠：`Ctrl-滾輪` (視窗不動，字體放大縮小)
        
    -   觸控板：`兩指縮放` (視窗不動，字體放大縮小)
        
    -   滑鼠：`Ctrl-Shift-滾輪` (視窗與字體一起等比例放大縮小)
        
    -   觸控板：`Shift-兩指縮放` (視窗與字體一起等比例放大縮小)
        
    -   重置字體大小：`Shift-Alt-F10` (當字體調整時，視窗預設不會連動放大/縮小)
        
    -   重置視窗大小：`Alt-F10` 或 `Ctrl+Shift+D` (重置視窗大小時會依據目前字體大小調整視窗大小)
        
-   進入全螢幕
    
    -   `Alt-F11`
    -   `Alt-Enter` (我個人比較愛用這組)
    -   `Ctrl+Shift+F`
-   翻轉螢幕 (Flip screen) ( 當使用 `vim` 的時候通常會用到**多螢幕**功能 )
    
    -   `Alt-F12`
    -   `Ctrl+Shift+S`
-   畫面捲動
    
    -   `Shift-PageUp/PageDown` 向上捲動一頁 / 向下捲動一頁
    -   `Shift-Up/Down` 向上捲動一行 / 向下捲動一行
    -   `Shift-Home/End` 向上捲動到最頂 / 向下捲動到最後
    -   `Ctrl+Shift+O` 顯示/隱藏垂直卷軸
-   切換鍵盤游標樣式 (有 3 種)
    
    -   `Ctrl+Shift+P`
-   切換視窗透明度 (有 8 級)
    
    -   `Ctrl+Shift+T`
-   移動視窗 (不用點標題列就可以移動)
    
    -   `Ctrl-Alt-滑鼠拖曳`
-   複製/貼上
    
    -   `Ctrl-Ins` 複製
    -   `Shift-Ins` 貼上
    -   `Ctrl-Shift-Ins` 複製+貼上
-   滑鼠選取文字
    
    -   `滑鼠選取` 範圍選取
    -   `Alt-滑鼠選取` 區塊選取

### 相關連結

-   [mintty/wsltty: Mintty as a terminal for Bash on Ubuntu on Windows / WSL](https://github.com/mintty/wsltty)
-   [Mintty — Cygwin Terminal emulator](http://mintty.github.io/)
    -   [Mintty Manual](http://mintty.github.io/mintty.1.html)
    -   [Mintty Wiki](https://github.com/mintty/mintty/wiki)
    -   [Mintty Tips](https://github.com/mintty/mintty/wiki/Tips) 
    -   [How to define KeyFunctions command #845](https://github.com/mintty/mintty/issues/845)
-   Windows Command-Line 系列文章
    1.  [Command-Line Backgrounder](https://blogs.msdn.microsoft.com/commandline/2018/06/20/windows-command-line-backgrounder/)
    2.  [The Evolution of the Windows Command-Line](https://blogs.msdn.microsoft.com/commandline/2018/06/27/windows-command-line-the-evolution-of-the-windows-command-line/)
    3.  [Inside the Windows Console](https://blogs.msdn.microsoft.com/commandline/2018/07/20/windows-command-line-inside-the-windows-console/)
    4.  [Introducing the Windows Pseudo Console (ConPTY)](https://blogs.msdn.microsoft.com/commandline/2018/08/02/windows-command-line-introducing-the-windows-pseudo-console-conpty/)
    5.  [Unicode and UTF-8 Output Text Buffer](http://blogs.msdn.microsoft.com/commandline/2018/11/15/windows-command-line-unicode-and-utf-8-output-text-buffer/)
