> 編集中
====== WSL2 LinuxとのWindowsの相互運用性 ======
--- //[[http://www.y2sunlight.com|y2sunlight]] 2020-12-10//
[[wsl2:top|WSL2に戻る]]
関連記事
* [[wsl2:install|WSL2 インストール]]
* [[wsl2:command|WSL2 コマンドリファレンス]]
* WSL2 LinuxとのWindowsの相互運用性
* [[wsl2:clone|WSL2 ディストリビューションの複製]]
* [[wsl2:terminal|Windows ターミナル]]
リンク
* [[https://docs.microsoft.com/ja-jp/windows/wsl/interop|Linux との Windows の相互運用性]] --- Microsoftドキュメント
----
===== ファイルアクセス =====
==== WindiswからLinuxのファイルをアクセスする ====
以下の形式で、WindiswからLinux上のファイルをアクセスできます:
\\wsl$\{distribution name}\{path}
実行例
PS C:\> dir \\wsl$\Ubuntu-20.04\
ディレクトリ: \\wsl$\Ubuntu-20.04
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 2020/12/11 8:57 home
d----- 2020/08/05 6:39 srv
d----- 2020/12/24 13:54 etc
d----- 2020/08/05 6:39 opt
d----- 2020/12/11 23:40 root
d----- 2020/12/11 8:57 mnt
d----- 2020/08/05 6:40 usr
...
\\
==== LinuxからWindiswのファイルをアクセスする ====
以下の形式で、LinuxからWindisw上のファイルをアクセスできます:
/mnt/{drive name}/{path}
実行例
$ ls /mnt/c/Users -l
total 0
lrwxrwxrwx 1 root root 18 Dec 7 2019 'All Users' -> /mnt/c/ProgramData
dr-xr-xr-x 1 root root 512 Dec 18 23:44 Default
lrwxrwxrwx 1 root root 20 Dec 7 2019 'Default User' -> /mnt/c/Users/Default
drwxrwxrwx 1 root root 512 Dec 18 23:29 Public
-r-xr-xr-x 1 root root 174 Dec 7 2019 desktop.ini
drwxrwxrwx 1 root root 512 Dec 18 23:55 y2sunlight
\\
===== ネットワークアクセス =====
==== WLS2の仮想ネットワーク ====
{{ :wsl2:interop:wsl2-network01.svg |}}
WSL2は、[[https://ja.wikipedia.org/wiki/Hyper-V|Hyper-V]]が管理する仮想マシン環境で動作します。このとき物理ハードウェアの上で動いているOSをホストOS、仮想マシン内で動作しているOSをゲストOSと呼ぶ事にします。そして、ホストマシンには物理NICが、仮想マシンには仮想NICが提供されています。
ホストマシンとゲストマシンの間にはHyper-Vの仮想ネットワークが構築されます。この仮想的ネットワークは、ホストマシンと仮想マシンが共に接続した状態を作ります。
WSL2を起動すると、「vEthernet(WSL)」という仮想ネットワークに接続するホスト側のネットワークアダプター(NIC)が作られますが、仮想ネットワークを構成している仮想スイッチは、ホストOSのネットワーク機能で見ることはできません。
仮想ネットワークのIPアドレスはプライベートアドレスが割り当てられ、ホストOSの再起動によって変更されます。
> 複数のWSL2ディストリビューションは同じネットワーク名前空間を使用し、ネットワークの分離はありません。''参考'' https://github.com/microsoft/WSL/issues/4304
=== WSL2のリスニングポート ===
WSL2では、仮想マシン側でリスニングされているポート番号と同じポート番号を、ホスト側で動作しているwslhost.exeがリスニングします。
例えば、仮想マシン側でポート80をリスニングしていると、ホスト側でも wslhost.exe がポート80をリスニングします。そして、 wslhost.exe は、受け取ったパケットを仮想ホスト側の同じポート番号に転送します。つまり、ホスト側がlocalhostの(仮想ホスト側がリスニングしていると同じ)ポート番号にアクセスすると、仮想ホスト側のネットワークサービスからは、eth0からのアクセスのように見えます。
=== localhost ===
IPv4では、ネットワークアドレス ''127.0.0.0'' が localhost の数値表現として扱われ、慣例的に末尾 1 の ''127.0.0.1'' を自分自身のIPアドレスの名前として使用されます。localhostという名前は、どんな名前解決システムも使うことなく 127.0.0.1 に解決で出来ます。IPv6では、''::1'' だけが localhost の数値表現として扱われ、IPv4のようにlocalhostはホスト名でありネットワークの表現ではありません。
WSL2が稼働しているとき、仮想マシン上の特定のポート番号をリスニングしている、HTTPサーバなどのTCP/IPアプリケーションに対して、ホストマシン側からは、localhost を接続先として指定すれば( http://localhost:<ポート番号>/ )、そのアプリケーションにアクセスすることが出来ます。
\\
==== WLS2側からWindows側のネットワークにアクセスする ====
> TODO:
\\
==== Windows側からWLS2側のネットワークにアクセスする ====
> TODO:
\\
===== WindowsからのLinuxコマンドを実行する =====
==== デフォルトのディストリビューション ====
Windows から Linux のコマンドを実行する場合、特に指定しなければデフォルトのディストリビューションが対象になります。デフォルトのディストリビューションを調べるには、以下のようにします:
実行例:
PS C:\Users\sunlight> wsl -l -v
NAME STATE VERSION
* Ubuntu-20.04-2 Running 2
CentOS7.6 Running 2
Ubuntu-20.04 Stopped 2
* この例では、''Ubuntu-20.04-2'' がディストリビューションです。
以下のようにすれば、デフォルトのディストリビューションが変更できます:
wsl -s {distribution name}
\\
==== Linux のコマンドの実行 ====
wsl コマンドを使って、次の形式で Windows のコマンドプロンプト(cmd) または PowerShell から Linux のコマンドを実行できます。
wsl {Linux command}
* この形式はデフォルトのシェルを起動し、Linux コマンドを実行します。
* 直接Linux コマンドを実行する場合: ''wsl -e {Linux command}''
また、 ディストリビューションやユーザを指定してコマンドを実行するには:
wsl -d {distribution name} -u {user name} {Linux command}
**実行例1**:簡単な例
PS C:\Users\sunlight> wsl ls -l
lrwxrwxrwx 1 root root 66 Dec 18 23:34 スタート メニュー -> /mnt/c/Users/sunlight/AppData/Roaming/Microsoft/Windows/Start Menu
drwxrwxrwx 1 root root 512 Dec 18 23:45 3D Objects
drwxrwxrwx 1 root root 512 Dec 18 23:35 AppData
lrwxrwxrwx 1 root root 37 Dec 18 23:34 Application Data -> /mnt/c/Users/sunlight/AppData/Roaming
...
**実行例2**:ユーザを指定
PS C:\Users\sunlight> wsl whoami # ユーザを指定しない場合
root
PS C:\Users\sunlight> wsl -u y2sunlight whoami # ユーザを指定する場合
y2sunlight
**実行例3**:ディストリビューションとユーザを指定
PS C:\Users\sunlight> wsl -d CentOS7.6 -u y2sunlight cat /etc/redhat-release
CentOS Linux release 7.9.2009 (Core)
**実行例4**:dockerサービスを起動してコンテナを開始する
PS C:\Users\sunlight> wsl sudo service docker start
* Starting Docker: docker [ OK ]
PS C:\Users\sunlight> wsl docker start myphp73
myphp73
* wslはLinuxコマンドを1つしか受け付けてくれません(以下の「複雑なコマンドを実行する」を参照して下さい)。従って以下のようなコマンドはエラーになります:\\ ''wsl sudo service docker start && docker start myphp73''\\
**実行例5-1**:PowerShellコマンドとLinuxコマンドの組み合わせ
PS C:\Users\sunlight> netstat -an|wsl grep 8080
TCP [::1]:8080 [::]:0 LISTENING
* パイプ( ''|'' )の左がPowerShell、右がLinuxコマンドです。
**実行例5-2**:PowerShellコマンドとLinuxコマンドの組み合わせ
PS C:\Users\sunlight> wsl netstat -an|Select-String 8080
tcp6 0 0 :::8080 :::* LISTEN
* パイプ( ''|'' )の左がLinuxコマンド、右がPowerShellです。
* 上2例で分かるように、パイプ( ''|'' )はPowerShellが支配しています。
>''wsl netstat'' はLinux側のポートを見ている点に注意して下さい。確認の為、''wsl netstat'' と ''netstat'' の両方をそのまま実行してその違いを比べる事ができます。
**実行例6**:複雑なコマンドを実行する
PS C:\Users\sunlight> wsl -d Ubuntu-20.04-2 -u root bash -c "service docker start && docker start myphp73"
* Starting Docker: docker [ OK ]
myphp73
* ''bash'' の ''-c'' オプションを使って複雑なLinuxコマンドを実行しています。
* ''-u root'' は不要ですが、''sudo'' していないので明示しました。
\\
==== bashターミナルに切り替える ====
Windowsのコマンドプロンプト(cmd) または PowerShell から bash ターミナルに切り替えるには ''bash'' コマンドを使用します:
PS C:\Users\sunlight> bash
bash コマンドには、ディストリビューションやユーザのオプション指定がないので、その場合は、wsl コマンドを使用します。実行例:
PS C:\Users\sunlight> wsl -d CentOS7.6 -u y2sunlight bash
\\
===== LinuxからのWindowsコマンドを実行する =====
==== Windowsのコマンドの実行 ====
次のようにして、LinuxからのWindowsコマンドを実行できます:
{command name}.exe
* Windows側コマンドを起動するには、拡張子まで含めて指定します。
* PATH環境変数に登録されていないコマンドは、フルパスで指定します。
* Windows側は ''UTF-8'' の環境下で実行されます。
* コマンドプロンプト(''cmd.exe'')の内部コマンド ''cmd.exe /c {command}'' と指定します。
* パス名を指定する場合の特殊文字は ''\'' でエスケープするか、引用符で囲みます。\\ 例: ''cmd.exe /c dir D:\\''
**実行例1**:簡単な例
$ hostname.exe # コンピュータ名の取得
zeus2
**実行例2**:Windows側のIPアドレスの取得
$ ipconfig.exe
Windows IP 構成
イーサネット アダプター イーサネット:
接続固有の DNS サフィックス . . . . .:
リンクローカル IPv6 アドレス. . . . .: fe80::a058:d977:ab7:9f83%7
IPv4 アドレス . . . . . . . . . . . .: 192.168.11.18
サブネット マスク . . . . . . . . . .: 255.255.255.0
デフォルト ゲートウェイ . . . . . . .: 192.168.11.1
イーサネット アダプター vEthernet (WSL):
接続固有の DNS サフィックス . . . . .:
リンクローカル IPv6 アドレス. . . . .: fe80::2858:9897:3574:179e%20
IPv4 アドレス . . . . . . . . . . . .: 172.26.144.1
サブネット マスク . . . . . . . . . .: 255.255.240.0
デフォルト ゲートウェイ . . . . . . .:
**実行例3**:WindowコマンドとLinuxコマンドの組み合わせ
$ ipconfig.exe | grep IPv4
IPv4 Address. . . . . . . . . . . : 192.168.11.18
IPv4 Address. . . . . . . . . . . : 172.26.144.1
**実行例4**:コマンドプロンプト(''cmd.exe'')の内部コマンド
~$ cmd.exe /c ver
'\\wsl$\Ubuntu-20.04-2\home\y2sunlight'
上記の現在のディレクトリで CMD.EXE を開始しました。
UNC パスはサポートされません。Windows ディレクトリを既定で使用します。
Microsoft Windows [Version 10.0.19041.685]
**実行例5**:WindowのGUIアプリを起動する
$ notepad.exe # フォアグラウンドで実行
$ notepad.exe & # バックグランドで実行
\\
==== Windowsのターミナルに切り替える ====
コマンドプロンプト(cmd)に切り替える:
$ cmd.exe
Power Shellに切り替える:
$ powershell.exe
何れの場合も、''exit'' コマンドで終了してLinuxターミナルに戻ります。
\\
===== 環境変数の共有 =====
WSL2には、Windows と Linux の両方で使用できる環境変数 ''WSLENV'' があります。''WSLENV'' はWindows と Linux の双方で共有される特殊な環境変数です。
PowerShell:
PS C:\Users\sunlight> echo $env:WSLENV
WT_SESSION::WT_PROFILE_ID
Bash:
$ echo $WSLENV
WT_SESSION::WT_PROFILE_ID
''WSLENV'' の内容は、Windows と Linux の間で引き継ぎたい環境変数が '':'' で区切られて列挙されています。例えば上の例の、''WT_PROFILE_ID'' を双方のシェルで確認してみると以下のようになっています。
PowerShell:
PS C:\Users\sunlight> echo $env:WT_PROFILE_ID
{61c54bbd-c2c6-5271-96e7-009a87ff44bf}
Bash:
$ echo $WT_PROFILE_ID
{048a85e4-0278-5ae1-8add-531a3d3eb4ac}
環境変数 ''WT_PROFILE_ID'' の内容は、ディストリビューションのGUIDです。
以下のタイミングで環境変数の引継ぎが行われます:
* Win32からWSLプロセスを起動するとき
* WSLからWin32プロセスを起動するとき
この相互運用性は地味なものに見えますが、WindowsとLinuxの双方でシームレスにデータを利用するアプリケーションにとっては非常に便利な機能だと思います。本編では、''WSLENV'' についての説明は、紹介程度に留めておきたいと思います。詳細は以下を参照して下さい:
* [[https://docs.microsoft.com/ja-jp/windows/wsl/interop#share-environment-variables-between-windows-and-wsl|Windows と WSL の間での環境変数の共有]]
* [[https://devblogs.microsoft.com/commandline/share-environment-vars-between-wsl-and-windows/|Share Environment Vars between WSL and Windows]]
\\