WSL2が使えない
Windows PCでは諸事情でVPNを張っているんですが、これまた諸事情でVPNを張るとWindows上で動くVMからインターネットに出ることができません。 これで課題になるのがWSL2の利用です。WSL2ではVMの中でLinuxカーネルを動かす形態を取るので、僕はWindows PCでWSL2が使えないことになります。
WSL 2 は、Linux ディストリビューションをインストールするときの現在の既定のバージョンであり、最新かつ最も優れた仮想化テクノロジを使用して、軽量ユーティリティ仮想マシン (VM) 内で Linux カーネルを実行します
coreutils等のユーティリティが使えないと、なかなか不便です。困りましたね。
VPNを張りつつ、WSL2からインターネットに出るには色々と回避策もある一方、いずれの対応も諸事情でおこられが発生し得ます。
- VPN に繋ぐと WSL2 や Hyper-V VM でネットワークに繋がらなくなる問題を解消する | Aqua Ware つぶやきブログ
- Workaround for WSL2 network broken on VPN · GitHub
- GitHub - sakai135/wsl-vpnkit: Provides network connectivity to WSL 2 when blocked by VPN
おこられが発生し得る件は色々と対応するとして、Windows上でcoreutils等のコマンドラインツールを利用する方法として、2023年にCygwinを利用することにしました。
今さらCygwinとはというエントリを書くことになるとは思ってもみなかったのですが、チームの方に説明する必要も生じそうなので、改めてcygwinとはどのようなものかを調べてみました。
Cygwinとは
Cygwinは、一言で言えばWindows環境上で動作するLinux的な環境です。 この「Linux的な」というところが味噌で、あくまでWindows OS上で、各種ツールを含みLinuxのような振る舞いをする環境を構成できます。
アーキテクチャ
その実現アーキテクチャはシンプルで、cygwin1.dllというDLLが、POSIXのエミュレーションレイヤーを構成します。雑に図にすると、以下のような形。
何が良いかというと、各コマンドは1つのWindowsアプリケーションとして動作することになり、VMが介在しません。従って、VPNにより(正確には、VPNアプリケーションによって変更されるルーティング等により)インターネットリーチアビリティが阻害されることもありません。
Cygwinってまだ更新されてるの?
2023/9/6に更新されてます。
性能面での課題
上記のアーキテクチャに起因しcygwin1.dllのエミュレーションレイヤーが一段噛むので、Cygwin環境上で動作させるプログラムは性能が出ません。Cygwinが提供するgcc等でCプログラムをビルドしたとして、その動作はクソ遅いです。そういうユースケースの場合は、素直にLinux PCとか使ったほうが良い。
上記のように書くと誤解されがちですが、性能が出ないのはcygwin1.dllを介在するからです。Cygwinで動くシェルから(cywgin1.dllを利用しない)Windowsアプリケーションを動かす場合は、このような性能が出ない問題は起こりません。 別にcygwin上で動くbashから、PostgresqlのWindowsバイナリを動作させたところで、性能が出ないとかはない。
POSIXとWindowsの差異
Cygwinが良きにエミュレーションしてくれるわけではありますが、LinuxとWindowsは異なるOSであり、エミュレーションも万全ではありません。 そのあたり、少しまとめます。
そもそもファイルパスが異なるよね
Windowsのパスはドライブレターでドライブが区切られ、ディレクトリのセパレータは\
が使われます。一方で、Linuxではドライブレターは存在せず、セパレータは/
になります。
cygwin1.dllを介するアプリケーション(bashやls)からみたとき、パスはPOSIX互換として扱われます。つまり、ls /etc
といった形でコマンドは発行する形になり、ls c:\cygwin\etc
ではない。このときの/etc
からc:\cygwin\etc
への変換はcygwin1.dll
がよしなにやってくれます。
一方で、Cygwin上で動くbashからC:\Program Files
ディレクトリのファイル一覧を表示したい等、ユーザ側でこのパス変換を行いたいユースケースはあります。このような場合はCygwinに同梱されているcygpath
といったユーティリティを使えばよろしい。
ls $(cygpath -u 'C:\Program Files')
Linux的なルートディレクトリはWindows上のどこに対応するの
CygwinをインストールしたディレクトリがLinuxにおけるルートになるように、cygwin1.dllが計らってくれます。cygwinをC:\cygwin
にインストールし、結果としてcygwin1.dllがC:\cygwin\bin\cygwin1.dll
に配置されたのであれば、ルートはC:\cygwin
になります。
文字コードどうなるの
WindowsのファイルシステムNTFSではUTF-16が使われます。CygwinではLOCALEによりますが、"C"
を指定しておけばUTF-8で扱います。トラブルを起こしたくなければ、"C"
に設定しておくのが良い。
In the default "C" locale, Cygwin creates filenames using the UTF-8 charset. This will always result in some valid filename by default, but again might impose problems when switching to a non-"C" or non-"UTF-8" charset.
Case sensitivyは?
NTFSが基本的にデフォルトでCase-insensitiveな以上、Cygwinでも同様になります。
abc.txt
とAbc.txt
のような大文字・小文字だけが異なるファイルを同じディレクトリに置いちゃダメだぞ。
ACL
WindowsとLinuxではそもそもセキュリティモデルが異なります。 WindowsではSIDをベースにしており、LinuxではUID/GIDのペアをベースとしています。
このあたりの変換もcygwin1.dllが頑張ります。cygwin1.dll優秀ですね。
Starting with Cygwin 1.7.34, Cygwin uses an automatic, internal translation from Windows SID to POSIX UID/GID.
ただし、セキュリティモデルが異なる以上、完全なマッピングはできません。 特にWindowsで可能な「このグループに所属する人には実行させない」といった制御。
Windows上のアカウントとPOSIXのアカウント
POSIXにおいては、/etc/group
、/etc/passwd
によりアカウントが管理されます。
一方でWindowsにはWindowsのアカウントがある。
このマッピングについてですが、私が認識していた世界がCygwin 1.7.34から変更になっているようです。
Cygwin's mapping between SIDs and uid/gid values works in two ways.
- Read /etc/passwd and /etc/group files if they exist, just as in the olden days, mainly for backward compatibility.
- If no files are present, or if an entry is missing in the files, ask Windows.
まずCygwin上では/etc/passwd
、/etc/group
ファイルを読みにいって、Windows上のアカウントとPOSIX上でのアカウントのマッピングが定義できるかを確認する。できなければ、Windowsの方に問い合わせる、という挙動の模様。