これはなに

WSLのtmuxへテキストを貼り付けられない問題を解決したときの備忘録。
起きた問題

Windowsのメモ帳でコピーしたテキストをWSL上のtmuxに貼り付けようとしたとき、何をコピーしても何も貼り付けされなくなってしまった。
環境

- Windows 11 + WSL2 (Ubuntu 24.04) + tmux
- ターミナルはVS Codeの統合ターミナルを使っていた
原因

原因はWSL interopが壊れていたことだった。
原因調査

既知の文字列をクリップボードに注入してから貼るというテストをした。
printf 'PASTE_TEST_OK_123' | clip.exe # クリップボードを既知の値にする
# 直後に Ctrl+V する。問題なければ PASTE_TEST_OK_123 が貼り付けられるはず。このテストをした結果、まったく異なる文字が貼り付けられた。 この挙動より、貼り付けの手前の段階であるクリップボードへの書き込みに問題があると考えられた。
実際調査してみると、この問題が生じていたとき、WSLではすべてのWindows実行ファイルが下記のように壊れていた。
$ powershell.exe
/mnt/c/.../powershell.exe: 1: MZ����: not found
/mnt/c/.../powershell.exe: 9: Syntax error: "(" unexpectedAIに聞くと、このMZはWindows実行ファイルのマジックナンバーらしく、MZ����: not foundというのはexeがシェルスクリプトとして実行されていることを表しているらしい。
WSL interopの実行ハンドラが消えたときに見られる特徴的な症状とのこと。
そもそもWSL内からWindowsバイナリを実行できるのは、「先頭バイトが特定のマジックナンバーだったら特定のインタープリタに渡して実行するという」登録を、Linuxカーネルのbinfmt_miscという機能が行っているかららしい。
本来、先頭バイトがMZで始まる場合は、WSLのinteropブリッジに渡してWindows側でプロセスを起動する。しかし今回はこの登録が消えてしまったために、clip.exeがシェルスクリプトとして実行されてしまい、貼り付けできなくなってしまった。
要因であるbinfmt_misc機能の持つ/proc/sys/fs/binfmt_misc/以下は永続化されないため、登録が消えてしまった原因は明確にはわかっていない。
少なくとも今回の環境では、ログに次の記録があった。
- Docker DesktopのクラッシュとWSL統合ディストロのマウント解除
Clock change detectedの連発: これはスリープからの復帰の痕跡と考えられるcannot create /proc/sys/fs/binfmt_misc/WSLInterop: Permission deniedという、登録の競合失敗のログ
個人的には、おそらくDocker Desktopのクラッシュが原因ではないかと思っている。
解決策

本当にWSL interopが壊れていることが原因かどうかは、次のコマンドで確認できる。
# 登録の存在確認: WSLInterop が表示されれば登録されている
ls /proc/sys/fs/binfmt_misc/
# 実動作確認: interop-alive と表示されれば正常
cmd.exe /c "echo interop-alive"上記で、実動作確認のコマンドが MZ...: not foundエラーになるなら、登録を書き戻すだけで問題は解決する。登録を書き戻すだけなので、シェルを再起動せずとも貼り付けが復活する。
sudo sh -c "echo ':WSLInterop:M::MZ::/init:PF' > /proc/sys/fs/binfmt_misc/register"echo: I/O errorというエラーになる。これはレジスタへの書き込みが同名エントリーの二重登録を拒否するためで、なにか問題があるわけではない。ちなみに、判定と修復を1行にまとめると次のようになる。
[ -e /proc/sys/fs/binfmt_misc/WSLInterop ] && echo "修復不要" || sudo sh -c "echo ':WSLInterop:M::MZ::/init:PF' > /proc/sys/fs/binfmt_misc/register"おわりに

Claude Codeくんありがとう。
