開発が進んでいる次期「Windows Subsystem for Linux」(WSL 2)で新たにサポートされたNTFSのソフトリンク対応が行われた。実際にいろいろなパターンでソフトリンクの対応状況を確認してみた。
この記事は会員限定です。会員登録(無料)すると全てご覧いただけます。
Windows 10の開発中のバージョンをいち早く試すことができるWindows Insider Programでは、2019年10月上旬現在、2019年秋の機能アップデート「19H2」と、2020年春の機能アップデート「20H1」の2つのWindows 10 Insider Preview版が提供されている(Windows Insider Programの参加方法は、Tech TIPS「Windows 10のプレビュー版をダウンロードする方法」参照のこと)。
「20H1」向けのプレビュー版では、Windows 10上でLinux環境が実行できる「Windows Subsystem for Linux(WSL)」の新しいバージョンである「WSL 2」の開発が進んでいる。
ビルド18980では、Windows OS(NTFS)のソフトリンクに対応できるようになった。
ビルド18980以前は、NTFSのソフトリンクに対応しておらず、lsコマンドなどでエラーが表示され、またリンク先も得られなかった。Linuxにもソフトリンク/ハードリンクがあり、コマンドによってはソフトリンクでリンク先を処理しなければならない場合もある。このため、実質上、ソフトリンクのあるWin32側のファイルやフォルダをLinux側コマンドで処理できなかった。
現行のWSL(以下、WSL 1)に関しても、当初はNTFSリンクを扱うことができなかったが、現在のWindows 10 May 2019 Update(バージョン1903)では正しくリンクを扱えるようになっている。
Windows OSのNTFSには、ハードリンクとソフトリンクの機能がある。ハードリンクとは、記憶デバイス上で同一の場所にあるファイルに対して別の名前(パス)を付けるものだ。違う場所にはあるものの、記憶装置上は同一なので、同一ファイルをコピーする場合に比べて、記憶容量の消費が少なくて済む。ただし、ファイルとしては同一になるため、ハードリンクされたファイル同士は常に同じ内容となる。1つを書き換えると、他のハードリンクされたファイルも書き換わる。
タイプ | ファイル | フォルダ | 管理者権限 | 対応コマンド | 概要 |
---|---|---|---|---|---|
ハードリンク | ○ | × | 不要 | mklink /H | 同一の場所にあるファイルに別のパスを付ける |
シンボリックリンク | ○ | ○ | 必要 | mklink、mklink /D | 他のファイル/フォルダを指し示すリンク |
ジャンクション | × | ○ | 不要 | mklink /J | 他のフォルダを指し示すリンク |
Windows OSにおけるハードリンクとソフトリンクの機能の違い |
これに対してソフトリンクは、単に他のファイルを指し示すものだ。このため、リンク先のファイルは存在している必要もない。Windows OSのソフトリンクには、「シンボリックリンク」と「ジャンクション」の2つがある。この辺りについては、Tech TIPS「Windowsのシンボリックリンクとジャンクションとハードリンクの違い」を参照いただきたい。
Windows OSでは、リンクの作成に「mklinkコマンド」を使う。これは、「内部コマンド」(cmd.exe内部に実装されているコマンド)である。一応、このコマンドで、3種のリンク全てに対応ができる。また、ハードリンクに関してのみ「fsutil.exe hardlinkコマンド」でも作成が可能だ。なお、3種のリンクのうち、シンボリックリンクのみフォルダへのリンク作成に管理者権限が必要になる。
ファイルのリストを表示させるdirコマンドは、シンボリックリンクとジャンクションを区別して表示できる。シンボリックリンクに関しては、リンク先がフォルダ(ディレクトリ)の場合には<SYMLINKD>、ファイルの場合には<SYMLINK>と表示する。
ジャンクションはリンク先がフォルダに限定されるため、表記は<JUNCTION>のみだ。ハードリンクは、特に表記はなく、DIRコマンドでは通常のファイルと区別できない。ただし、fsutil hardlink listコマンドを使うと、ファイルを指定して、同じ記憶域を使う他のハードリンクされたファイルを表示させることができる。
Linuxのリンクと区別するため、以下、Windowsの3種のリンクをそれぞれ「NTFSハードリンク」「NTFSシンボリックリンク」「ジャンクション」と表記することにする。
Linuxにもハードリンクやソフトリンクがある。ソフトリンクは、「シンボリックリンク」と呼ばれ、多くの場合「symlink」などと表記される。こちらについても、NTFSのリンクと区別するため、「Linuxハードリンク」「Linuxシンボリックリンク」と表記することにする。
タイプ | ファイル | フォルダ | 管理者権限 | 対応コマンド | 概要 |
---|---|---|---|---|---|
ハードリンク | ○ | (システム依存) | 不要 | lnコマンド | 同じ記憶装置上で別のパスを付ける |
シンボリックリンク | ○ | ○ | 不要 | ln -s コマンド | 他のファイル/フォルダを指し示すリンク |
Linuxにおけるハードリンクとシンボリックリンクの違い |
Linuxハードリンクは、Windows OSと同じく、記憶装置上で同一の場所を占める複数のファイルを作る機能だ。Linux系のファイルシステムでは、inodeというデータ構造を使ってファイルを管理している。このinodeには重複しないinode番号が割り振られえいる。個々のファイルは、システムでユニークなinode番号を持つ。inode番号を指定することで、inodeを指定できるため、inode番号はファイルを区別するIDとしても利用できる。ハードリンクの場合、このinode番号が同じになる。
これに対してシンボリックリンクは、リンク先を記録した特殊なファイルとして実現している。実装方法はいろいろあり、過去には、必要な情報をテキストで入れた小さなファイルだったこともあるが、inodeを利用して高速化した実装もある。Linuxのシンボリックリンクも、デバイス(Windows OSでいうボリューム)をまたがってリンクを張ることができるし、必ずしもリンク先が存在している必要もない。
Linuxでリンクを扱うには、「ln(リンク)コマンド」を使う。このコマンドで、ハードリンクとシンボリックリンクの両方を作成できる。ただし、ディレクトリのハードリンクのみ作成に管理者権限が必要になる。また、ファイルのリストを表示する「lsコマンド」は、オプション「-l」と「-i」を使うことで、シンボリックリンクやハードリンク関連の情報を表示できる。
Linuxには、複数のファイルシステムがあるが、全てのファイルシステムは、VFSという仮想的なファイルシステムとしてカーネル内で扱われている。ファイルに関する全ての機能はVFSに対するファンクションコールとして実装されており、Linuxのリンクに関連するプログラムも全てVFSの上で動作している。このため、ファイルシステムが変わっても、リンクの表示や作成などは全て同じコマンドで同じように操作できる。
ここでは、ビルド18990を使って、WSL 2のNTFSリンク対応について調べて見た。結果からいうとWSL 2は、以下の通りとなった。
具体的に動作を見ていこう。先に、Win32側で3種のリンクを作成しておく。
実際には、下画面のようなリンクを作成した。まずは、このフォルダをWSL 2側から開き、「ls -liコマンド」を実行する。これにより、ファイルの詳細とinode番号が表示される。結果の先頭にあるのがinode番号で、それ以降が“-l”オプションの出力である。この例で2つ目のフィールドの先頭が「l」になっているものがシンボリックリンクである。また、3つ目のフィールドの数値は、リンクカウントを示し、ハードリンクの存在を示す。
まずは、ハードリンクを見てみよう。この例では、Win32側で「text.txt」というファイルを作り、そのハードリンクを「mklink /Hコマンド」で「Hardlink-text.txt」という名前で作成した。lsコマンドで見ると、「text.txt」と「Hardlink-text.txt」は、リンクカウントが「2」となっており、先頭にあるinode番号が同じだ。Linuxでは、ハードリンクは同じinode番号を持ち、ハードリンクの数に応じてリンクカウントが加算されていく。つまり、WSL 2はNTFSのハードリンクを正しく認識しているといえる。
NTFSのシンボリックリンクとジャンクションは、どちらもWSL 2では、シンボリックリンクとして表示される。リンクかどうかはパーミッション表示の先頭が「l」になっていることで分かる。
また、そのリンク先も「->」以降に正しく表示されている。「lsコマンド」のカラーオプションが有効な場合、リンク先がアクセスできないとファイル名は赤で表示されるが、これも正しく動作している。また、この場合、リンク先がディレクトリだと緑の反転表示となる。シンボリックリンクがファイルを指し示している場合「catコマンド」で内容が表示でき、ディレクトリなら「cdコマンド」でカレントディレクトリを移動できる。WSL 2から見たとき、NTFSのシンボリックリンクとジャンクションを区別することはできないが、実用上問題はないだろう。
次に、NTFS上で、Linuxの「lnコマンド」を使って、リンクを作成してみる。リンクの作成には以下のコマンドを用いる。なお、「mklinkコマンド」とはターゲットとリンクの順番が逆になる点に注意されたい。
■ハードリンクの場合
ln <ターゲット> <リンク名>
■シンボリックリンクの場合
ln -s <ターゲット> <リンク名>
UNIX由来の「lnコマンド」では、ハードリンクの作成がデフォルトの動作となる。というのは、歴史的にはシンボリックリンクが後から追加された機能だからだ。ただし、上の方の書式で作成できるのはファイルへのハードリンクのみである。
ディレクトリのハードリンクの作成には、「-F」などのオプションを指定する必要があるが、ユーザーにハードリンクの作成を禁止しているシステムも少なくない。これは簡単に循環するリンクが作れてしまうなどの問題が起きるからだ(ただし、システムとしてはディレクトリに対するハードリンクを扱うことができる)。WSL 2で評価に利用したUbuntu-18.04もディレクトリへのハードリンク作成はできなかった。
このためテストは、ファイルへのハードリンクと、ファイルおよびディレクトリへのシンボリックリンクを作成して実行した。まず、ハードリンクだが、WSL 2から行ったファイルに対する「lnコマンド」は成功し、NTFS上にハードリンクが作成できた。これをWin32側の「fsutil hardlink listコマンド」で確認すると、ハードリンクされているファイルのリストを表示することができた。これにより、WSL 2の作成したハードリンクはWin32側で正しく解釈できていることが確認できる。
次に「ln -sコマンド」で、ファイルとディレクトリのシンボリックリンクを作成したが、これをWin32側からみるとジャンクションになっていた。比較のためにWin32側でジャンクションを作り、「fsutil reparsepoint queryコマンド」を使ってみるとLinux側でシンボリックリンクとして作成したものは、標準的なNTFSのジャンクションとも違ったものになっていた。
ただしWSL 2では、Windows 10の「開発者用モード」をオンにすることで、正しくNTFSのシンボリックリンクを作ることができるようになった。20H1の「開発者用モード」(19H1までの開発者モード)は、Microsoft Store以外からのアプリのインストールを許可するものになっている。これは、開発時に作成したアプリのテストなどのために許可するものであり、標準ではオフになっている。
これは、今回のWSL 2の強化には含まれていない範囲の話だが、LinuxコマンドでNTFS上にリンクを作ることができるのなら、Win32のコマンドでWSL 2のネイティブストレージであるExt4上にリンクを作ることはできるのだろうか?
結論から言うと、これはできない。というのは、まず、Win32側の「mklinkコマンド」(内部コマンド)は、ローカルNTFS上でしか動作しない。しかし、WSL 2のExt4をアクセスするには、Win32側からはネットワーク共有(\\wsl$\……)を使う必要があるため、コマンド自体が実行を拒否する。
ネットワークドライブを使って、ネットワーク共有にドライブ文字を割り当て、ローカルファイルのように扱うことはできるが、これでもmklinkコマンドは失敗する。少なくとも「mklinkコマンド」を使ってWSL 2のExt4ファイルシステム上にリンクを作ることはできないようだ。この辺りをまとめたのが下表だ。
WSL 2から | Win32から | 参考:WSL 1 | |||||
対象 | 対象 | アクセス | 作成 | アクセス | 作成 | アクセス | 作成 |
NTFSハードリンク | ファイル | ○ | ○ | ○ | ○ | ||
NTFSシンボリックリンク | ファイル/ディレクトリ | ○ | △ | ○ | △ | ||
NTFSジャンクション | ディレクトリ | ○*1 | × | ○*1 | × | ||
Ext4ハードリンク | ファイル | ○ | × | − | − | ||
Ext4シンボリックリンク | ファイル/ディレクトリ | ○ | × | − | − | ||
各リンクの対応状況 空欄:自システム側の機能なので当然対応できる。 −: WSL 1ではネイティブストレージのVolFsへのアクセスは推奨されない。またVolFsはNTFS上にあり、WSL 1はExt4などのファイルシステムを持たない。 △:開発者用モードを有効にする必要がある。 ×:作成できない。 ○:アクセス、または作成が可能。 *1:Linux側からはシンボリックリンクに見える。 |
Linuxの「lnコマンド」や各種のファイル関連のコマンドがさまざまなファイルシステムの上で動作することを考えると、「mklink」や「fsutil」といったWindows OSのリンク関連のコマンドは、NTFSとの関係が深く、論理的にファイルシステムとコマンドが分離できていない。
WSL 2では、NTFSへのアクセスに9P(9Pは、Plan 9 from Bell LabsというOS用に開発されたファイル共有プロトコル)を使う。これは、Win32からのExt4アクセスである「\\wsl$\ディストリビューション名」と同じプロトコルである。
しかし、Linux側では、通常のコマンドが9PでマウントしたNTFSに関しても動作するのに対して、Win32側では、9Pでのマウントはネットワーク共有フォルダとしてローカルのNTFSとは別扱いになり、「mklink」などのコマンドが動作できなくなる。「Dirコマンド」もリンクに関しては最低限の機能を持つが、「lsコマンド」の多機能さを見ると、多数の開発者が関わるオープンソースの威力を感じる(「lsコマンド」はUNIX由来だが、Linuxのディストリビューションに搭載されている「lsコマンド」のほとんどはオープンソースのGNU Coreutilsの一部)。
LinuxとWindows OSには、リンクのようにお互い似た機能があるものの、実装が違うなどのさまざまなギャップがある。WSL 2で、この辺りが次々と埋まっていくと、大半の作業はWSL 2側で可能になりそうだ。このとき、長年にわたって鍛えられてきたUNIX系コマンドやそのスタイルは、DOS時代から続く、Microsoft独特のコマンドスタイルよりも使いやすく、多くのユーザーにとって受け入れやすいだろう。
■更新履歴
【2019/11/01】「WSL2のNTFSリンク対応をテストする」におきまして、「NTFS上にLinuxシンボリックリンクを作成できるが、Win32側からはアクセスできない」としておりましたが、「開発者用モード」をオンにすることでWin32側からのアクセスが可能でした。そのため、関連する項目を修正しました。
【2019/10/11】初版公開。
Copyright© Digital Advantage Corp. All Rights Reserved.