> 編集中 ====== 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]] \\