0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Gentoo on WSL2でPATH連携が動くようにする

Last updated at Posted at 2025-02-17

TL;DR

追記

単なる私の調査不足でした。この記事に書いた内容はまるっと不要です。正しい対応方法は以下をご参照のこと。

WSL 内での Gentoo - Gentoo Wiki
https://wiki.gentoo.org/index.php?title=Gentoo_in_WSL/ja&oldid=1306568#Windows_.E3.83.97.E3.83.AD.E3.82.B0.E3.83.A9.E3.83.A0.E3.81.8C_PATH_.E3.81.AB.E3.81.AA.E3.81.84

env-updateの稼働でPATHが上書きされるので、その前にWindowsから与えられたPATHを退避させてenv-update稼働後に退避させたPATHを接続、復活させる方法という方法を用いれば無理なく対応できるということのようです。

ついでに、処理後のPATHに重複が目についたので手元ではこうしています:

/etc/profileより抜粋
# WSLにより自動生成されたPATHを退避
WSLPATH="$PATH"

# Load environment settings from profile.env, which is created by
# env-update from the files in /etc/env.d
if [ -e /etc/profile.env ] ; then
        . /etc/profile.env
fi

# 退避したPATHを回復。重複に対処
PATH=$(echo "$PATH:$WSLPATH" | awk -v RS=: -v ORS=: '!a[$0]++')
export PATH=${PATH%:}

unset WSLPATH

この記事は以上です。以下を読む必要はありません。

以下、この記事を書いた際の記録

この記事ではappendWindowsPathを通常通り使用することを断念し、以下のようにPowerShellを直呼びして対応しました。

/etc/profileの末尾に書き足す
# WindowsのPATHを取得して統合する関数
function append_windows_path() {
        # WindowsのシステムPATHを取得
        local sys_path=$(/mnt/c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe -Command '[System.Environment]::GetEnvironmentVariable("Path", "Machine")' | tr -d '\r\n')

        # WindowsのユーザーPATHを取得
        local user_path=$(/mnt/c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe -Command '[System.Environment]::GetEnvironmentVariable("Path", "User")' | tr -d '\r\n')

        # それぞれのPATHを統合
        local win_path="$sys_path;$user_path"

        # WindowsのPATH記法をBashの形式に変換
        local wsl_path=$(printf '%s' "$win_path" | sed 's/;/\n/g' | sed -e 's#\([A-Za-z]\):\\#\/mnt\/\L\1\/#g' -e 's#\\#\/#g' | tr '\n' ':' | sed 's/:$//')

        # WSLのPATHに追加。この際/usr/lib/wsl/libも追加する
        export PATH="$PATH:/usr/lib/wsl/lib:$wsl_path"
}

# wsl.confをチェックして関数を呼び出す
append_path_enabled="true"
if [ -f /etc/wsl.conf ]; then
   # appendWindowsPathの設定を取得
   append_path_enabled=$(grep -i '^\s*appendWindowsPath\s*=' /etc/wsl.conf | awk -F '=' '{print $2}' | tr -d ' ')
fi

# 設定がtrueの場合に関数を実行
if [ "$append_path_enabled" == "true" ]; then
   append_windows_path
fi

どうしてこうなった?

WSL2の連携機能とenv-updateの食い合わせが悪いんです。
PATHの設定が/etc/env.d/50baselayoutにあり、こいつにうまく手を入れて/etc/profile.env上のPATHがそれまでのPATHを読み込むようにすれば起動時にWSL2から受け取るPATHと統合できると思われるのですが、書き換えてもenv-updateは書かれた文言をシングルクォーテーションで書いてしまうんですよね。

一応、出てきた/etc/profile.envのシングルクォーテーションをダブルクオーテーションに書き換えるとWSL2が仕事していないわけではないことが理解できます。

とはいえ、ダブルクォーテーションで安定させようとしてenv-updateのそういう設定を仮に発見したとして、emergeコマンド等がsource /etc/profileを要求してくるので;$PATHが付いていると$PATHがどんどん長くなりそうです。……筋が悪い。

そこでCopilotに相談したところ出てきたのがこのスクリプトで、Windows上のPowerShellを直接呼び出して環境変数を取り出します。

当初はさっぱりWindowsのままのPATHを生のまま接続して空白まみれにしたり、空白を全部セミコロンに置き換えてしまってProgram;Filesってなっていたりシステム環境変数しか読んでなくてユーザーインストールしたVSCodeが呼べなくて何のために手間かけとんじゃってなったり、Cドライブ前提のsedが出てきてたりしていましたが、都度修正させて最後はThink Deeper兄貴にブラッシュアップして頂きました。

納得いっていない点

本当はWSL2自身が持っているWindowsのPATHを呼び出してくる仕組みを直接実行したいのですが、所在がわからないのでできずにいます。

また、appendWindowsPath[interop]以外に書かれていても認識してしまいます。ここをチェックする仕組みもCopilotに書かせたりしたのですが、結構長くなったしそもそも/etc/wsl.confを書くのは自分自身なのでとりあえず後回しにしています。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?