WSLとWindowsの相互運用
「build 14951」にて、BashからWindowsのコマンドを実行できるようになりました。ここでは以下の2パターンを紹介します。
- WindowsのコマンドラインからLinuxコマンドを呼び出す
- BashからWindowsコマンドを呼び出す
「WSL」はネイティブのWindowsバイナリーを呼び出せるようになり、また、Windowsのコマンドラインから「WSL」を呼び出せるようになりました。
この機能は「build 14951」で盛り込まれた機能であり、新しい相互運用機能を「Windows」と「WSL」にもたらし、分け隔てなく利用できるようになりました。
文字コードについて
「Ubuntu」のデフォルトの文字コードは「UTF-8」です。一方「Windows」のコマンドプロンプトや「PowerShell」のデフォルトのコードページは「CP932(シフトJIS)」です。
この違いにより文字データの扱いが変わるため、相互運用時に文字化けが発生する可能性があります。
例えば以下の例では、「月」の文字が化けています。
この点に注意してください。
コマンドプロンプトやPowerShellのコードページをUTF-8に変更するには
「コマンドプロンプト」や「PowerShell」のコードページをUTF-8に変更するには、以下のコマンドを実行します。
chcp 65001
以下のようにコードページが「UTF-8」に変わります。
以下のように文字化けが解消されます。
「月」の文字が表示されていますね。
PowerShellでは文字化け発生
「PowerShell」でコードページを「UTF-8」に変更してみましたが、以下のように「月」が表示されません。コードページの変更だけではうまくいかないようです。
WindowsのコマンドラインからLinuxコマンドを呼び出す
「Linux」バイナリーは、Windowsの「コマンドプロンプト」や「PowerShell」から実行することが出来ます。「Windows」から「Linux」バイナリーを実行すると、以下の内容が適用されます。
- CMDやPowerShellと同じワーキングディレクトリーが設定される
- Linuxバイナリーは、WSLのデフォルトのユーザーで実行される
- CMDやPowerShellを実行しているWindowsのユーザーと同じ権限が引き継がれる
権限の補足
「3.」に関して補足すると、「CMD(コマンドプロンプト)」や「PowerShell」を管理者として実行している場合、それらから「Linux」バイナリーを呼び出すと、「Linux」バイナリーにも管理者権限が適用されます。これは「WSL(Bash)」の「root」とは異なる権限であり、「WSL」の「root」よりも優先される権限です。
ただし「Windows」の管理者権限が「root」権限を包括しているという意味ではありません。
異なる権限が同時に存在し得るという意味です。
通常のWindowsユーザーで「CMD(コマンドプロンプト)」や「PowerShell」を実行している場合、「Windows」の管理者権限が必要になる操作は「WSL」の「root」でも操作できません。
「Windows」の管理者権限が必要になる操作を「Bash」から実行したい場合、「CMD(コマンドプロンプト)」や「PowerShell」を管理者として実行している必要があります。
従って「Bash」から何かしら操作を行う場合、「root」と「Windows」の管理者権限の2種類の権限の存在を意識する必要があります。
以下も参考にしてください。
実行するLinuxコマンドの指定は-cオプションで指定する
Linuxのコマンドは、「bash.exe」経由で実行します。実行するLinuxコマンドの指定は、「bash.exe」の「-c」オプションで指定します。
bash -c "実行するLinuxのコマンド"
1.Ubuntuのlsコマンドを呼び出す例
「Windows」の「コマンドプロンプト」から「Ubuntu」の「ls」を呼び出す例です。「Ubuntu」のコマンドの呼び出しは、「bash.exe」を経由して呼び出します。
ここでは例として「c:¥temp」を対象に「ls -ls」コマンドを実行します。
「コマンドプロンプト」から以下のコマンドを実行します。
cd c:\temp
bash -c "ls -la"
bash -c "ls -la"
1番目のWindowsコマンドで現在のディレクトリーを「c:¥temp」に移動しているため、Ubuntuのコマンドである「ls -la」は、「c:¥temp」を対象に実行されています。
2.パイプでLinuxコマンドとWindowsコマンドをつなぐ例
パイプでLinuxコマンドとWindowsコマンドをつなぐ例です。Linuxコマンドの出力結果をWindowsコマンドが受け取り、処理を行います。
ここでは例として、「1.」の出力結果をWindowsコマンドの「findstr」でフィルタリングします。
「コマンドプロンプト」から以下のコマンドを実行します。
bash -c "ls -la" | findstr hello
Windowsコマンドが「ls -la」の結果を受け取り、その中から「hello」が含まれる行を出力しています。
3.パイプでWindowsコマンドとLinuxコマンドをつなぐ例
今度はパイプでWindowsコマンドとLinuxコマンドをつなぐ例です。Windowsコマンドの出力結果をLinuxコマンドが受け取り、処理を行います。
ここでは例として、Linuxコマンドの「grep」でフィルタリングを行います。
「コマンドプロンプト」から以下のコマンドを実行します。
dir | bash -c "grep hello"
LinuxコマンドがWindowsコマンドの「dir」の結果を受け取り、その中から「hello」が含まれる行を出力しています。
4.ファイルへのリダイレクト
リダイレクトも利用できます。ここでは例として「1.」の出力内容を「out.txt」ファイルへ出力します。
「コマンドプロンプト」から以下のコマンドを実行します。
bash -c "ls -la" > out.txt
「out.txt」ファイルの中身を出力すると、以下のようになります。
5.rootでコマンドを実行する例
「Ubuntu」のコマンドを「root」で実行する例です。ここでは例として、「root」で実行する必要がある「apt-get update」を実行します。
「コマンドプロンプト」から以下のコマンドを実行します。
bash -c "sudo apt-get update"
パッケージインデックスファイルが更新されました。
6.ファイルパスを含むコマンドの実行例
ファイルパスを含むコマンドを実行するときは、ファイルパスの基準は「WSL」のパスが基準になります。すなわち、「/(VolFs)」が基準になります。
ここでは例として、「/proc/cpuinfo」内のファイルの一覧を表示します。
「コマンドプロンプト」から以下のコマンドを実行します。
bash -c "ls -la /proc/cpuinfo"
DrvFS内のファイルを指定する例
「DrvFs」内のファイルを指定する場合でも、「/(VolFs)」を基準にしてパスを記述します。ここでは例として、「c:¥temp」内のファイルの一覧を表示します。
「/(VolFs)」から「c:¥temp」のパスを見ると、パスは「/mnt/c/temp」になります。
「コマンドプロンプト」から以下のコマンドを実行します。
bash -c "ls -la \"/mnt/c/temp\""
「bash.exe」の「-c」オプションは「"」で括っていますが、さらにその中で「"」を使用する場合は、「\"」のようにエスケープする必要があります。