WSL
WSL ( Windows Subsystem for Linux ) は、Windows 上で動作できる Linux ( Unix ) っぽい環境の一つ。
有名どころでは Cygwin や MSYS2 などと競合するが、
- Microsoft が公式に提供している
- Linux Distributions 環境をほぼそのまま使える
- Windows 10 を利用しているユーザであれば、比較的簡単に入れられる
などは強みだ。最近ベータも外れたので、本格導入に向けて再調査した。
インストール
Install your Linux Distribution of Choice
WSL の有効化
まずは、有効にするために管理者権限で起動した Powershell で以下を実行する。
PS> Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux
その後再起動すると、WSL が使えるようになる。
アプリストアから Linux Distribution をインストール
古いバージョンが入っている場合は、最新版をストアから取得する。
● WSL のバージョン確認
もう使わないので、先にアンインストールした。
● 最新 WSL のインストール ( Ubuntu の場合 )
インストールが完了したら、Ubuntu が規定になっていることを確認する。
Ubuntu 以外にも、様々な Linux Distribution が提供されている。
- Debian
- SUSE Linux
- OpenSUSE
- Kali Linux
特にこだわりが無いなら、Ubuntu が最も情報が多く、安心。
個人的必須パッケージのインストール
自分が使う上で最低限必要なパッケージを入れておく。
$ sudo apt-get update
$ sudo apt-get upgrade
$ sudo apt-get install curl jq git tig openssl ca-certificates build-essential software-properties-common iproute2
# fzf
$ git clone --depth 1 https://github.com/junegunn/fzf.git ~/.fzf
$ ~/.fzf/install
# micro
$ cd /usr/local/bin
$ curl https://getmic.ro | sudo bash
# exa
$ curl -LO https://github.com/ogham/exa/releases/download/v0.8.0/exa-linux-x86_64-0.8.0.zip
$ unzip exa-linux-x86_64-0.8.0.zip
$ sudo chown root:root exa-linux-x86_64 && mv exa-linux-x86_64 /usr/bin/exa
# ripgrep
$ curl -LO https://github.com/BurntSushi/ripgrep/releases/download/0.8.1/ripgrep_0.8.1_amd64.deb
$ sudo dpkg -i ripgrep_0.8.1_amd64.deb && rm ripgrep_0.8.1_amd64.deb
# bat
$ curl -LO https://github.com/sharkdp/bat/releases/download/v0.4.1/bat_0.4.1_amd64.deb
$ sudo dpkg -i bat_0.4.1_amd64.deb && rm bat_0.4.1_amd64.deb
相互運用性
Fall Creators Update や Anniversary Update を経て、Windows と Linux ( WSL ) の相互運用性は大きく高まっていた。
WSL interoperability with Windows | Microsoft Docs
Bash on Windows と呼ばれていた時代は文字通り bash.exe
で起動していたが、これは現在 Deprecated となっている。
今後は wsl.exe
で起動 する。
bash.exe
時代からの違いとしては、以下がある。
-
-c
が要らなくなった - Windows の
%Path%
を$Path
に取り込める (あれ、この機能って昔から無かったっけ??)
◆ Windows Platform から Linux Platform を利用する場合
Windows 側から Linux コマンドを動かしたい場合、以下のように実行できる。
PS> ipconfig | wsl grep IPv4 # この grep は、Linux 上の grep
IPv4 Address. . . . . . . . . . . .: 172.10.20.30
IPv4 Address. . . . . . . . . . . .: 10.0.100.200
wsl
を頭につけるだけ で呼び出せる。とても楽だし、可読性も損ねてはいない。
● Windows 向けバイナリとの比較
これまで自分は、scoop を使って Windows 用にコンパイルされた Linux コマンドを山程入れていた 。
しかし、それらは大抵 起動がワンテンポ遅く、また一部のコマンドにおいてはバージョンも古かったり、動作やコマンド体系・オプションが Linux 版と全然違ったり と、満足行くものではなかった。
それに比べて今の WSL は、**簡単で、軽量で、**かつ シームレスに動作 できるものが 公式 に提供されている。
乗り換えない理由は無かった。
● Alias 追加
ということで、早速 wsl <<Linux コマンド>>
を Alias として登録し、よりシームレスに統合する。
Powershell で Alias を登録する場合、Powershell の Profile である Powershell_profile.ps1
に追加することで可能となる。
自分は別ファイルに切り出しモジュール化し、それをプロファイルで Import-Module
するようにしている。
function wsl_grep() {
$input | wsl grep $args
}
Set-Alias -Name:"grep" -Value:"wsl_grep" -Option:Allscope
Import-Module "C:\path\to\Wsl.ps1"
これで、ほぼシームレスな連携が可能となる。
PS> ipconfig | grep IPv4
IPv4 Address. . . . . . . . . . . .: 172.10.20.30
IPv4 Address. . . . . . . . . . . .: 10.0.100.200
自分用に使いそうなコマンドの Alias・Functions をまとめた Powershell ファイルを作ったので、参考に。
https://gist.github.com/kentork/bd85a670302a22852b55652afe59ef47
※ mkdir
のように Windows でも同名のコマンドが存在する場合は、Windows アプリケーションに意図しない影響を与える事もあるので注意。
◆ Linux Platform から Windows Platform を利用する場合
今度は、WSL の中から Windows コマンドを利用する場合を考える。
実は、これも簡単にできる。
$ ipconfig.exe | grep IPv4 # この ipconfig は、Windows 上の exe
IPv4 Address. . . . . . . . . . . : 172.10.20.30
IPv4 Address. . . . . . . . . . . : 10.0.100.200
ポイントとしては、Windows のバイナリを動かすときは ~.exe
までしっかり入力 すること。
また、dir /b
などの /
で指定するオプションは、 dir -b
のように /
を -
に変更する必要があるようだ。
◆ どっちがメイン?
CLI 周りのエコシステムを考えると、どうしたって Linux に軍配が上がってしまう。
今は Linux Platform から Windows Platform を利用する 方を基軸としている。
とは言え、まだまだ Powershell を使いたいケースはあるので、Windows Platform から Linux Platform を利用する方法も残している。
パス表現の違い
WSL を運用する上で無視できないのが、この パス表現の違い 。
見るだけであれば、慣れてくれば頭の中で変換できるようになってくるが、
- Case 1.
wsl rm -r hoge/piyo.json
のpiyo.json
を Tab 補完で見つけようとすると Windows スタイルになってエラー - Case 2.
wsl find -type f > files.txt
で出力されるファイル一覧が Linux スタイルに
などのケースがよく起こる。地味に辛い。Alias 使ってて意識が向きづらくなると特にハマりやすい。
● Windows 側での対応
一応、変換するための関数を Powershell で自作している。
function w2l($in) {
if ( $in -match "(^[a-zA-Z]:(\\{1,2})?$|^[a-zA-Z]:\\{1,2}[^\\])") {
$in = "/mnt/" + $in.Substring(0, 1).ToLower() + $in.Substring(2).Replace('\\', '/').Replace('\', '/')
} elseif ( $in -match "(^\.(\\{1,2})?$|^\.\\{1,2}[^\\])") {
$in = $in.Replace('\\', '/').Replace('\', '/')
}
return $in
}
function l2w($in) {
if ( $in -match "(^/mnt/[a-z]/?|^/mnt/[a-z]/[^/])") {
$in = $in.Substring(5, 1).ToUpper() + $in.Substring(6).Replace('/', '\')
} elseif ( $in -match "(^\./?$|^\./[^/])") {
$in = $in.Replace('/', '\')
}
return $in
}
function w2ls() { $input | %{ w2l($_) } }
function l2ws() { $input | %{ l2w($_) } }
PS> wsl rm -r $(w2l .\hoge)
PS> wsl find -type f | l2ws > files.txt
正直、エラーになって初めて気がつき、それから対策として使うケースが多い。
それでもやっていけないわけではないが、根本的な解決策は欲しい。
● Linux 側での対応
2018 年 3 月のアップデートから、Linux 側に wslpath
というコマンドが追加され、Linux style ⇔ Windows style ができるようになった。
せっかく公式にあるので、Linux 側ではそれを利用している。
( 以下、fish を前提にしている為、他の Shell の場合は読み替えて )
alias w2l='wslpath'
alias l2w='wslpath -w'
function w2ls
while read -l line
wslpath $line
end
end
function l2ws
while read -l line
wslpath -w $line
end
end
$ find -type f | l2ws > files.txt
● 環境変数の相互変換
wsl.exe
になり、 WSL → Windows または Windows → WSL で環境変数が継承されるようになったが、その場合にパス表現をどう引き継ぐのかという問題があった。
これに関し、ビルド17063 から、WSLENV
という環境変数が加わり 、パス変換のルールを指定できるようになった。
詳しくはリンク先を参照のこと。
Hyper
Hyper は、Windows でも動くクロスプラットフォームなターミナル。
https://hyper.is/
https://github.com/zeit/hyper
Powershell などを使う上でも素晴らしいターミナルであるが、今回は WSL と一緒に使う事を前提に設定していく。
インストール
scoop や Chocolatey でも提供されているので、簡単に入る。
PS> scoop install hyper
or
PS> choco install hyper
設定
Hyper の設定は ~/.hyper.js
で全て管理されているので、それを編集して設定を行う。
自分はこんな感じ。
...
- fontSize: 12,
+ fontSize: 16,
- cursorBlink: false,
+ cursorBlink: true,
- copyOnSelect: false
+ copyOnSelect: true
- shell: '',
+ shell: 'C:\\Windows\\System32\\wsl.exe',
...
フォント
フォントは MyricaM を使っている。
プログラミングフォント Myrica / Estable
Powerline 化は、以下リポジトリの手順を参考にした。
tsunesan3/awsome-jp-coding-fonts
...
- fontFamily: 'Menlo, "DejaVu Sans Mono", Consolas, "Lucida Console", monospace',
+ fontFamily: 'MyricaM, Menlo, "DejaVu Sans Mono", Consolas, "Lucida Console", monospace',
...
プラグイン
Hyper はプラグインで拡張することで機能を追加していく。
とは言え、現在は Hyper 2.0 移行期で未対応が多かった り、 Windows 対応が悲惨なことになっていたり と、胸が締め付けらる思いがする。
ウィンドウ
最前面固定のために、hyper-always-on-top を入れている。
背景透過もやりたかったが、hyper-transparent も hyper-transparent-dynamic も上手く動作しない。
ステータスバー
大人気の hyperline は残念ながら Windows 未対応。
今は hyper-statusline を使っている。が。これも WSL だと Git 管理下なのに Git 情報が表示されなかったりと不安定。
タブ
タブ機能の強化としては hyper-tabs-enhanced が便利だが、Windows で CPU 使用率が異常に上がる 問題があり、使えない。
テーマ
テーマも Plugin として導入ができる。
自分は、hypermaterial-vibrancy とか hyper-material-theme を使ったりいる。
Explorer 統合
Windows を使っていると、フォルダを右クリックして Open with Hyper
とかしたくなる。
インストールすると追加してくれるらしいが、自分が scoop で入れたときはなかった。
ので、自分で入れた。
Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT\Directory\Background\shell\Hyper]
"Icon"="C:\\Users\\<< YOUR_NAME >>\\scoop\\apps\\hyper\\current\\Hyper.exe,0"
@="Open Hyper here"
[HKEY_CLASSES_ROOT\Directory\Background\shell\Hyper\command]
@="C:\\Users\\<< YOUR_NAME >>\\scoop\\apps\\hyper\\current\\Hyper.exe \"%V\""
[HKEY_CLASSES_ROOT\Directory\shell\Hyper]
@="Open Hyper here"
"Icon"="C:\\Users\\<< YOUR_NAME >>\\scoop\\apps\\hyper\\current\\Hyper.exe,0"
[HKEY_CLASSES_ROOT\Directory\shell\Hyper\command]
@="C:\\Users\\<< YOUR_NAME >>\\scoop\\apps\\hyper\\current\\Hyper.exe \"%V\""
こんな感じで追加することで登録できた。
Tips
Copy / Paste
Ctrl+Shift+C
/ Ctrl+Shift+V
で可能
fish shell
細かな設定を行わなくても最初からそれなりに使える Shell。ものぐさな自分に最適。
Windows ではなく Linux を主軸に置きたいと思った要因として、fish があるから というのは大きい。
インストール
※ 以下、WSL 上で実行している
なぜか GPG エラーで鍵追加できなかったので、ビルドする。
# 最新のソースを取得
$ cd ~
$ git clone https://github.com/fish-shell/fish-shell && cd fish-shell
# インストール
$ mkdir -p build && cd build
$ cmake -DCMAKE_BUILD_TYPE=Release ..
$ make
$ sudo make install
$ rm -rf fish-shell
...
- shellArgs: [],
+ shellArgs: ['fish'],
...
設定
fish の設定は、~/.config/fish/config.fish
に書く。
# お好みのカスタマイズ
alias ls='exa -l'
alias grep='rg'
alias cat='bat'
function zz
set p (z -l | awk '{ print $2 }' | fzf)
if test $status -eq 0
cd $p
else
return $status
end
end
# Windows 側の Explorer で起動するコマンド
alias ii='explorer.exe'
# Windows のパスに合わせて移動するための関数
function wcd
if [ $argv[1] = "/" ]
cd /mnt/c
else if [ $argv[1] = ~ ]
cd /mnt/c/users/<<User Name>>
else
cd /mnt/c/$argv[1]
end
end
プラグイン
プラグインを管理するために、fisherman を導入する。
# fisher 導入
$ curl -Lo ~/.config/fish/functions/fisher.fish --create-dirs https://git.io/fisher
# 好きな Plugin 導入
$ fisher z fzf edc/bass spin 0rax/fish-bd
テーマ
fish のテーマも入れとく。
bobthefish はなぜか Powerline が出なかったので、諦めて agnoster にした。
悩みどころ
Q. WSL は普通の Linux として使えるのか
A. そんなことはない。
- ネットワーク周り
- ファイルシステムの違い
- FAT やネットワークドライブなどがマウントできるようになった
- Windows 側アプリから VolFS ( Volume File System ) にアクセスできない
- Linux 側から DrvFs の権限が変えられない
- Windows 側の Symlink にアクセスしようとすると Permission Denied になる
- デバイス認識
などなど。再構築を初めてから数ヶ月。その間に引っかかった点だけでもこれだけあった。
とは言え、あまり悲観はしていなくて、むしろすごいスピートで改善している事に驚く。
ファイルシステム辺りはある程度は諦めるとしても、それ以外はそのうち解決してくれるだろうと思ってる。
Q. パフォーマンスはどうなのか
-
vs Windows 向けバイナリ
- やっぱりファイル IO 系が遅い?
-
node/nodejs
リポジトリのgit status
は WSL の方が 3 倍遅かった - ripgrep で
rg -t yaml hoge -l
とかすると、ほとんど変わらない ( というか早すぎて良く分からん )
-
- ツールの癖をつかめば、上手く並行運用はできそう
- やっぱりファイル IO 系が遅い?
-
vs VM, Docker
- この記事で検証されている が、VM と比べると相当遅いらしい。
- やはり本格的な開発環境構築などを考えると、まだまだなんだろうか。
A. 諦めも肝心。癖を掴み、遅いものは大人しく Windows ネイティブ or VM, Docker を使おう。
Q. 開発環境はどちらで作るべきか
これを見れば分かるように、今は Windows 側と Linux 側、どちらにも Node.js が入っている。
さて、日々の開発はどちらですべきなのだろうか。
A. (暫定) とりあえずどっちも入れておいて、適宜変える。
これに関しては、Docker や VM なども考慮しベストを探す必要があるので、また別の機会に考える。
感想
使い慣れた Linux Distribution・Shell の使い心地で Windows ファイルシステムが操作できる という点ではとても良い。
本格的に Linux を使いたいのであれば、足りない部分はどうしても感じてしまう。
そこは無理せず、Docker や VM と併用する必要があるだろう。