WSL與Windows交互實踐

1. WSL是什麼

​ WSL 是Windows Subsystem for Linux 的簡稱,主要是爲了在Windows 10上原生運行Linux二進制可執行文件(ELF格式),而提供的兼容層。 通俗來說是在Windows10 嵌入了個Linux子系統(默認是ubuntu),方便運行大部分 Linux 命令及軟件,好比grep MySQL Apache。這很大方便了使用Windows作開發的同窗,不須要雙系統或虛擬機了。c++

在Windows功能中啓用```適用於Linux的Windows子系統```,而後在Windows CMD中直接輸入```bash```,便可進入Linux環境,執行命令:

2. WSL新特性

從Windows10 1709版本時開始,能夠直接輸入wsl進入交互環境, bash方式會逐漸廢棄掉。git

之前的 bash -c [command]直接用 wsl [command]來替代。github

另外一個特性是:Windows 10商店裏,能夠下載安裝其餘Linux發行版。這樣就能夠自由選擇,不用限制到Ubuntu。
web

而後能夠在程序列表中直接打開Ubuntu進入,或在CMD或Powershell中直接輸入ubuntu進入:docker

PS D:\> ubuntu
mush@mushroom ~ % ls
go  mush  test
mush@mushroom ~ % pwd
/home/mush
mush@mushroom ~ %

後面都基於wslUbuntupowershell來介紹和演示。shell

3. WSL管理配置

Windows10自帶了wslconfig,去管理多個安裝的發行版,好比卸載某個發行版,設置默認啓動的髮型版。ubuntu

在PowerShell中輸入wslconfig /?, 能夠看到:windows

PS D:\> wslconfig /?
在 Linux Windows 子系統上執行管理操做

用法:
    /l, /list [/all] - 列出已註冊的分發內容。
        /all - 有選擇地列出全部分發內容,包括目前
               正安裝或未安裝的分發內容。
    /s, /setdefault <DistributionName> - 將指定的分發內容設置爲默認值。
    /u, /unregister <DistributionName> - 註銷分發內容。

切換默認發行版:bash

PS D:\> wslconfig /l
# 適用於 Linux 的 Windows 子系統:
Legacy (默認)
Ubuntu
PS D:\> wslconfig /s Ubuntu
PS D:\> wslconfig /l
# 適用於 Linux 的 Windows 子系統:
Ubuntu (默認)
Legacy

在Windows 1803 後,還支持更多配置。好比網絡,root目錄等。進入發行版後, 能夠在/etc/wsl.conf中配置。 若是沒有該文件,能夠手動建立一個配置:網絡

[automount]
enabled = true  # 自動掛載 c:/ 等到 /mnt
root = /windir/
options = "metadata,umask=22,fmask=11"
mountFsTab = false

[network]
generateHosts = true
generateResolvConf = true

4. WSL交互

也是從1709開始,WSL支持在Windows 10上直接使用 Linux命令:

PS D:\test>  wsl ls -la
total 5836
drwxrwxrwx 1 root root    4096 Jan 25 13:20 .
drwxrwxrwx 1 root root    4096 Apr 20 16:25 ..
-rwxrwxrwx 1 root root     105 Oct 14  2017 03-build.ps1

一樣在 WSL 內也可使用Windows應用程序,好比notepad,docker:

root@mushroom:/mnt/d/go/src/code.teambition.com/soa/webhooks# docker.exe ps
CONTAINER ID        IMAGE                        COMMAND                  CREATED             STATUS              PORTS                                                                                        NAMES
63698edb01a8        quay.io/coreos/etcd:latest   "/usr/local/bin/etcd"    2 days ago          Up 27 hours         0.0.0.0:2379->2379/tcp, 2380/tcp                                                             etcd

這是個很是讚的特性,極大方便了開發者。但在使用過程當中發現,有個體驗很是很差的地方,必須帶.exe後綴才行,否則會提示找不到命令 :

root@mushroom:/mnt/d/go/src/code.teambition.com/soa/webhooks# docker
The program 'docker' is currently not installed. You can install it by typing:
apt-get install docker

好比同事在mac上寫了個docker build的腳本,放到Windows上後 想使用WSL去執行,發現必須加後綴才行,這樣腳本就沒辦法統一了

5. 解決方案

固然也能夠在中裝個docker,而不是使用宿主機上的docker。但這樣會很冗餘,並且性能很差。通過一番折騰找到幾種解決方案:

5.1 使用別名

在WSL 中.bashrc設置別名,去掉後綴:

alias docker=docker.exe
alias docker-compose=docker-compose.exe

這樣就能夠正確運行命令了, 但別名只在交互環境有效,腳本執行壞境不行。

5.2 多複製一份

在宿主機上找到 docker.exe,而後複製一份重命名爲 docker 放到同級目錄,這樣在wsl中也是能夠執行的,有點蠢萌黑魔法的感受。

5.3 重定向

思路是定義command_not_found_handle函數(bash 4.0+ 支持),當任何命令找不到時,都會調用調用它。 而後在該函數中嘗試調用宿主機上cmd.exe,由它來來執行命令,並返回結果。

在.bashrc中添加:

command_not_found_handle() {
    if cmd.exe /c "(where $1 || (help $1 |findstr /V Try)) >nul 2>nul && ($* || exit 0)"; then
        return $?
    else
        if [ -x /usr/lib/command-not-found ]; then
           /usr/lib/command-not-found -- "$1"
           return $?
        elif [ -x /usr/share/command-not-found/command-not-found ]; then
           /usr/share/command-not-found/command-not-found -- "$1"
           return $?
        else
           printf "%s: command not found\n" "$1" >&2
           return 127
        fi
    fi
}

或在.zshrc中添加:

command_not_found_handler() {
    if cmd.exe /c "(where $1 || (help $1 |findstr /V Try)) >nul 2>nul && ($* || exit 0)"; then
        return $?
    else
        [[ -x /usr/lib/command-not-found ]] || return 1
        /usr/lib/command-not-found --no-failure-msg -- ${1+"$1"} && :
    fi
}

使用符號鏈接,講宿主機上的docker.exe 映射到 WSL中:

ln -sf /mnt/c/Program\ Files/Docker/Docker/resources/bin/docker.exe /usr/bin/docker

6. 其餘

6.1 閒聊

差很少有2年左右,沒寫博客了。主要是由於從C#/Net,轉向Golang相關的技術棧了,須要從新積累和學習下。前期寫了段時間c++,而後寫Golang,發現Golang寫着舒服多了。固然跟有了女友後,變懶也有很大關係。

這篇是開頭,但願能繼續堅持分享,也有利於本身成長。新博客會同步到github一份,方便備份修改。

6.2 參考

https://docs.microsoft.com/en-us/windows/wsl/interop

https://docs.microsoft.com/en-us/windows/wsl/wsl-config

https://github.com/Microsoft/WSL/issues/2003

相關文章
相關標籤/搜索