kledgeb Ubuntuの使い方や日本語化、アプリの使い方を紹介しています。

WSLとWindowsの相互運用

build 14951」にて、BashからWindowsのコマンドを実行できるようになりました。



ここでは以下の2パターンを紹介します。

  1. WindowsのコマンドラインからLinuxコマンドを呼び出す
  2. 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」バイナリーを実行すると、以下の内容が適用されます。

  1. CMDやPowerShellと同じワーキングディレクトリーが設定される
  2. Linuxバイナリーは、WSLのデフォルトのユーザーで実行される
  3. 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"


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」オプションは「"」で括っていますが、さらにその中で「"」を使用する場合は、「\"」のようにエスケープする必要があります。


関連記事一覧
オプション