VSコードの拡張機能を開くフォルダごとに自動で切り替えるやり方
後で気づいたが
Devcontainer環境を作ってしまえば、それごとに拡張機能を固定できるよな。
と、思いました。
ただ、そこまで大掛かりなことしなくても、当記事の方法でも、
拡張機能は、切り替えられるので、当記事のノウハウは、これはこれで使えるかと思います。
はじめに
2025/09の下旬の話である。
本番環境が古めのLinuxでpython 2.7.5のシステムの保守開発のため、
ローカルにその環境を再現する環境を作った
開発環境としてdocker compose環境を構築した
本番はRed HatだったがDockerHub公開イメージがないため、
ベースになってるcentOSの対応するバージョンでのイメージを使った
dockerコンテナにpython2.7.5の古めのバージョンが入ってる環境で、
WSL2にRemoteWSLで接続しているVSコードをホスト側として
リモートデバッグできる環境を構築した
python2.7.5に対応してリモートデバッグ形で、デバッガーを動作させるには、
どうしても、ms-python.pythonの拡張プログラムをダウングレードするしかなかった
具体的には、
ms-python.python-2021.9.1246542782
にする必要があった
しかし、それをやると、
他の案件でVSコードを利用時は、最新版のms-python.pythonで
新しめのpythonのバージョンに対応させてのデバッガを効かせたいのに
影響してしまう。
上記の「python 2.7.5」での保守開発を実施時だけ、
該当の拡張プログラムをダウングレード
他の時は、最新の拡張プログラム
それを、切り替え作業の手間なく、共存できる環境にしたかった。
それを実現するため、環境構築しようとして、下記の失敗したやり方を経て
ようやく、うまくいくやり方が
見つかりました
この件を書いたのが当記事である。
失敗のやり方、その1
RemoteWSLで接続時の拡張プログラムは、
~/.vscode-server配下での管理であるため
WSL2上で別のユーザを作成し、「python 2.7.5」での保守開発を実施時だけ、
該当の拡張プログラムをダウングレードが必要なケースだけ
そのユーザ作業しようと試みたが、
の話があり、WSL2では、/etc/wsl.confで指定した
既定のユーザだけでしか、RemoteWSLができないため
毎度、/etc/wsl.confの切り替えが発生してしまうためやめることにした
失敗のやり方、その2
RemoteWSLが、/etc/wsl.confで指定した既定のユーザでしかできないため、
いつも、作業している既定のユーザ、一択での作業方法とした。
VSコードで、プロファイルを作成した。
既定か、そのプロファイルを選択できるようだった
作ったプロファイルに、該当のプロジェクトフォルダを追加、登録した
すると、該当のプロジェクトフォルダに対して、VSコードを開いた時だけ
プロファイルが有効になり、既定とは独立的に、
拡張プログラムの有効/無効が切り替えられ、
一見するとうまくいきそうには、見えたが・・・
ダメでした。
理由は、RemoteWSLの場合は、プロファイルがどうあれ、
~/.vscode-server配下の同じ場所に拡張プログラムが入る
もし、同じ種類の
ms-python.pythonについて、
最新版と、ms-python.python-2021.9.1246542782の2種類ある場合は、
問答無用で、最新版だけ認識され、ms-python.python-2021.9.1246542782のほうは
無視されるということがわかった
そのため、ダメでした。
うまくいったやり方
RemoteWSLが、/etc/wsl.confで指定した既定のユーザでしかできないため、
いつも、作業している既定のユーザ、一択での作業方法とした。
事前準備として、
~/.vscode-server
を
~/.vscode-server-mainにリネームした。
~/.vscode-server-python2.7.5-remote-debug
のフォルダを作成し
その中に、
ms-python.python-2021.9.1246542782
の中身を展開して、入れ込んだ
~/.vscode-serverをシンボリックリンクとして、
その指し示す場所を下記のように切り替えることにした。
VSコードを開くディレクトリに応じて
~/.vscode-server-main
にするのか
~/.vscode-server-python2.7.5-remote-debug
にするのか、を動的に切り替える仕組みを作った
順を追って、一個一個、説明を書く
まず、
ms-python.python-2021.9.1246542782.vsix
は、電子署名がない時代の拡張プログラムであったため
普通に、
code --install-extension ms-python.python@2021.9.1246542782
としても、
SignatureVarificationFailed: Signature verification failed with 'NotSigned' error.
のように署名がないというエラーになってしまう
そこで、
https://marketplace.visualstudio.com/_apis/public/gallery/publishers/ms-python/vsextensions/python/2021.9.1246542782/vspackage
よりダウンロードした
ms-python.python-2021.9.1246542782.vsix
をまずは、一旦、
ホームディレクトリにコピー
cp /mnt/c/Users/XXXXX/Downloads/ms-python.python-2021.9.1246542782.vsix ~/ms-python.python-2021.9.1246542782.vsix
ホームディレクトリの「mpp2021.9」というフォルダ名に展開
cd ~
unzip -q ms-python.python-2021.9.1246542782.vsix -d mpp2021.9
~/.vscode-server-python2.7.5-remote-debug/extensions
の空フォルダを準備し
mkdir -p ~/.vscode-server-python2.7.5-remote-debug/extensions
先ほど展開した「mpp2021.9」の中の「extension」フォルダを丸ごと
~/.vscode-server-python2.7.5-remote-debug/extensions
の直下に、ms-python.python-2021.9.1246542782というフォルダ名としてコピーする
cp -a ~/mpp2021.9/extension ~/.vscode-server-python2.7.5-remote-debug/extensions/ms-python.python-2021.9.1246542782
補足)
cp -a の -a は archive(アーカイブ)モード。
実質 -dR --preserve=all と同等
-Rは、再帰コピー
-dは、
シンボリックリンクはリンクのまま
パーミッション・タイムスタンプ・所有者など すべての属性を保持(--preserve=all)
※ 所有者保持は権限が必要な場合あるため、もし、必要なら sudoにすべきときもある。
事前作業として、
~/.vscode-server
を
~/.vscode-server-main
にリネームした
mv ~/.vscode-server ~/.vscode-server-main
~/.vscode-serverをシンボリックリンクとして、
~/.vscode-server-mainを見るように作成
ln -sfn ~/.vscode-server-main ~/.vscode-server
~/.bashrc
に下記の関数定義を追加した。
最初は、下記は
code() {
にして関数定義してたが、code .で、2重でVSコードが開くような事象が多発したため
それを抑制するため
my_code() {
にして
my_code .
と打ち込むことにした。( 本当は、code .をラップしたかったが・・・)
my_code() {
target_main="$HOME/.vscode-server-main"
target_py27="$HOME/.vscode-server-python2.7.5-remote-debug"
link="$HOME/.vscode-server"
proj="/my_dev/c/gin_dev/redhat/project"
use_py27=false
if [[ "$PWD" == "$proj" || "$PWD" == $proj/* ]]; then
use_py27=true
fi
current="$(readlink -f "$link" 2>/dev/null || echo "")"
want="$(readlink -f "$target_main")"
$use_py27 && want="$(readlink -f "$target_py27")"
if [[ "$current" != "$want" ]]; then
pkill -f vscode-server || true
ln -sfn "$want" "$link"
fi
command code "$@"
}
上記の関数定義の意味は、下記のとおりである。
my_code .をした時のカレントディレクトリが
/my_dev/c/gin_dev/redhat/project
または、その配下の場合は、
$use_py27がtrueになり、
wantの値が、~/.vscode-server-python2.7.5-remote-debug
となる
そうでない場合は、
$use_py27がfalseになり、
wantの値が、~/.vscode-server-main
になる
currentには、現在
~/.vscode-serverのシンボリックリンクが指し示しているフォルダのパス値が入っている
currentと、wantのパスの値が異なる場合は、
ln -sfn "
で、
~/.vscode-serverのシンボリックリンクが指し示しているフォルダのパス値を
wantの値で更新する
その際には、
pkill -f vscode-server || true
をする
なぜ、このpkillが必要なのかというと、
~/.vscode-server-main
~/.vscode-server-python2.7.5-remote-debug
のうち、
今から起動するほうが、前のものと切り替わるような時は、
前のプロセスの残骸が残っていると(VSコード自体は見た目上閉じてても、プロセスが残ってる)
前の情報で起動しようとしてしまい
意図したとおりにならない
そのため
今から起動するほうが、前のものと切り替わるような時は、
一旦
pkill -f vscode-server || true
にて、プロセスの情報に、vscode-serverの文字列が含んでるもの
つまり、VSコードのプロセスであるが、それは、一旦、終了させる
ここまで、必要ならば、やるべきことやったあとに、
command code "$@"
にて、codeコマンドで、VSコードを起動する
codeコマンドは、
~/.vscode-server
より、拡張プログラムを展開しようとする仕様である。
その際には、
~/.vscode-server
実フォルダであろうが、
どこかのフォルダへのシンボリックリンクになっていようが、
問題なく動作してくれる
以上より、
code .をした時に、そのカレントディレクトリの値に応じて
拡張プログラムの状況を自動的に切り替えれる仕組みを実現できたのである。
終わり
Discussion