Umi Uyuraのブログ

プログラミング関連の作業ログ

WindowsのNode.jsバージョン管理をNodistからfnmに変えてみる

これまでWindowsでNode.jsのバージョン管理はNodistを使っていましたが、改めて環境構築を構築をしていくにあたってMicrosoftのドキュメントを眺めていたところ、Nodist以外にもそういったツールがあることを知りました。

WSL2(Linux)向けの方で掲載されているパッケージ管理ツールのほうが多いですが、その中のいくつかはマルチプラットフォームで、ネイティブWindowsでも使えそうなものもあります。

2020 年ではもう使えない Nodist はアンインストールする (Windows)

この記事に触発されたというわけでもないのですが、最近WSLを触り始めたこともあり、Windows/Mac/Linux(WSL)で同じように使えるツールにしておけると迷うことも少ないかなと思い、Nodistから乗り換えてみることにしました。

マルチプラットフォームなNode.jsバージョン管理ツール

Windowsをサポートしているマルチプラットフォームなものをピックアップしてみました。

それぞれのリポジトリや公式サイトを眺めてみての個人的に気になった点を挙げてみました。

名前 対応プラットフォーム ポイント
nvm-windows Windows nvmWindows版、なのかと思いきやが互換性があるわけではないみたい
・Go製
・自動バージョン切り替えはない
nvs Windows/Mac/Linux VSCode連携あり
コマンドプロンプトのサポートが弱い(PowerShellだと自動バージョン切り替えができる)
・wingetでインストールできる
Volta Windows/Mac/Linux ・Rust製、速度重視
・他のツールと若干使い方が違う印象
・package.jsonに使うNodeのバージョンなどを記録する
・wingetでインストールできる
fnm Windows/Mac/Linux ・Rust製、こちらも速度重視
・自動バージョン切り替えに対応
(番外)asdf-nodejs Mac/Linux asdf公式
・自動バージョン切り替えに対応

Nodistも備えていましたが、プロジェクトディレクトリにある .node-version.nvmrc などを参照して使うNodeのバージョンを切り替えてくれる機能は欲しいところ。

Linux(WSL)とMacだけで考えれば asdf公式のNode.jsプラグイン が自動切り替えにも対応していて良さそうではありますが、Windowsでも使えるものからとなると、nvs、Volta、fnmあたりが選択肢になりそうです。

(nvm-windowsは紛らわしいですが、本家nvmのクローンということではないらしい。コマンドも微妙に使い方が違っていたりと今回の目的に合わないため選外)

その中でnvsとVoltaについては以下のような点が自分的に気になったので、今回はfnmを使ってみることにしました。

  • nvsコマンドプロンプト主体で考えると切り替え機能がサポートされない
  • Voltaは他のツールと違ってpackage.jsonにバージョンを記録する(業務利用を考えたときに、自分の会社ではそのあたりのツールが統一されているわけではないため、自分のためだけに編集はしにくい)

Nodistをアンインストールする

まずは既存環境のNodistを削除する手順で、この点については先のNodistアンインストールの記事がとても参考になりました。

2020 年ではもう使えない Nodist はアンインストールする (Windows)

以下、その記事の手順をなぞったときのメモ。

  • Nodistのアンインストール
    • 記事ではコントロールパネルから実施していましたが、私はChocolateyでインストールしていたので、 choco uninstall nodist で削除しました
  • Nodistインストール先フォルダの削除
    • 確かに残っていて、npmの各バージョンが残っていたと1GB近くありました
  • npm-cacheフォルダの削除
    • これも残っていて、3.5GBもありました…
  • .npmrcの削除
    • これについては、私の環境ではNodistに関するもの以外の設定もあったので、該当行のみ削除してファイル自体は残しました

fnm (Fast Node Manager)をインストールする

インストールは簡単で、 Releases · Schniz/fnm から利用しているプラットフォーム向けのバイナリをダウンロードして、PATHが通っているところに置くだけでも使えます。

またWindows向けにはChocolateyからもインストールすることもできるので、私はこちらの方法を使いました。

# 要管理者権限
> choco install fnm -y

or

# Use gsudo
> gsudo choco install fnm -y

gerardog/gsudo を使うと、わざわざ管理者権限でターミナルを開き直さなくても良いので便利です。

コマンドプロンプト向けシェルセットアップ

さてインストールが完了したら、使っているシェルに合わせてfnmを使うための初期化処理を設定する必要があります。

Bash向けなどは .bashrceval "$(fnm env)" を追記すれば良いという感じで非常に簡単なのですが、Windows特にコマンドプロンプト向けのセットアップは一筋縄ではいきませんでした。

Windows Command Prompt aka Batch aka WinCMD

コマンドプロンプトを起動したときに何か処理をおこないたい場合、レジストリHKEY_CURRENT_USER\SOFTWARE\Microsoft\Command ProcessorAutoRun キーに設定することで実行させることができます。

fnmのREADMEによれば、そこに以下のコマンドを登録することでセットアップがおこなわれるようです。

FOR /f "tokens=*" %i IN ('fnm env --use-on-cd') DO CALL %i

ただ自分の場合は、他にも初期化処理でやりたいことがあったので、バッチファイルを登録して、その中で上記の処理を呼び出すことにしました。

[HKEY_CURRENT_USER\SOFTWARE\Microsoft\Command Processor]
"AutoRun"="C:\Users\<user>\mystartup.cmd"

ところがこれがうまくいかず、コマンドプロンプトを起動すると i was unexpected at this time. というメッセージが表示されました。

これはfnmのREADMEにも対処法が書かれていますが、原因としてはバッチファイルの中で FOR を使う場合の変数の書き方を %i ではなく %%i としなければいけないからでした。

for | Microsoft Docs

よって以下のように書き換えます。

FOR /f "tokens=*" %%i IN ('fnm env --use-on-cd') DO CALL %%i

これでうまくいくかと思いきや、確かに先のメッセージは出なくなったものの、今度は処理が戻ってこない状態になりました。

いろいろ調べた結果、次のことがわかりました。

  • for /f はサブプロセス実行時に cmd.exe を起動するため、そこでまたAutoRunが走ってしまうことで無限ループに陥る可能性がある
  • cmd /d を指定することでAutoRunを無効にできるが、 for の中では効かないっぽい

参考:

fnmのREADMEにはCmderというターミナルアプリの起動スクリプト機能を使うことで回避する方法が載っていますが、これだとWindows Terminalが使えないので個人的にはイマイチ。

Usage with Cmder

そこで起動バッチのなかで多重実行を防ぐような仕組みを入れたところ、無限ループにならずに初期化処理が実行できるようになりました。

具体的には初回実行時にある環境変数に値を入れるようにして、実行時にその環境変数に値がある場合はそこで処理を終了するというもので、以下のような実装です。

mystartup.cmd

@ECHO OFF

IF "%MYSTARTUP_INIT%"=="OK" (
    EXIT /b
)

ECHO ... Running startup script
SET MYSTARTUP_INIT=OK

REM Setup fnm
FOR /f "tokens=*" %%z IN ('fnm env --use-on-cd') DO CALL %%z

ECHO ... Complete startup script

これでfnmを使うことができるようになりました。

基本的な使い方

# インストール可能なバージョンの一覧
> fnm ls-remote
v0.1.14
v0.1.15
v0.1.16
... # 省略
v16.8.0
v16.9.0
v16.9.1
v16.10.0

# 指定したバージョンをインストール
> fnm install v16.10.0
Installing Node v16.10.0 (x64)

# インストール済のバージョン一覧
> fnm ls
* v14.17.6
* v16.10.0 default
* system

# 現在のデフォルトで使われるバージョン
> fnm current
v16.10.0

# デフォルトバージョンの設定
> fnm default v14.17.6
> node -v
v14.17.6

自動バージョン切り替えを試してみる

あらかじめ、16系と14系をインストールしておきます。現在のデフォルトは16。

> fnm install 14
Installing Node v14.17.6 (x64)

> fnm list
* v14.17.6
* v16.10.0 default
* system

わかりやすく node14node16 フォルダを作り、それぞれに対応するバージョンを書いた .node-version ファイルを配置します。

> type node14\.node-version
v14
> type node16\.node-version
v16.10.0

それぞれのフォルダに移動してみます。

> cd node14
Using Node v14.17.6

> fnm current
v14.17.6

> node -v
v14.17.6

> cd ..\node16
Using Node v16.10.0

> fnm current
v16.10.0

> node -v
v16.10.0

node14 フォルダに入るとカレントバージョンが14に、 node16 フォルダに移動するとカレントバージョンは16になりました。

.node-version ファイルの内容に合わせて使うNodeバージョンが切り替わってくれることが確認できました。

※2021/10/06追記

プロジェクトのバージョン指定に使うファイルは .node-version だけでなく、nvm由来の .nvmrc を使うツールもあります。

fnmは .nvmrc にも対応しているようだったので試してみたところ、同じようにバージョンが切り替わってくれました。

> type node14\.nvmrc
14

> type node16\.nvmrc
v16.10.0

> node -v
v14.17.6

> cd node16
Using Node v16.10.0

node16> fnm current
v16.10.0

node16> node -v
v16.10.0

node16> cd ..\node14
Using Node v14.17.6

node14> fnm current
v14.17.6

node14> node -v
v14.17.6

おわり

Rust製で売りの一つにスピードとあるだけに、たしかに速い気がします。

Linux(WSL)やMacにもHomebrewで入れられるので、そちらにもセットアップしていこうと思います。

FontBaseを導入してVSCode/Windows Terminal/Slackのフォントを設定してみた

エディタの文字がキレイだと、それだけで何か書きたい気持ちになります。

思えば昔自分のメインマシンをWindows(XP)からMacに変えようと思った理由のひとつは、Macで起動したEmacsで開いたテキストの文字のキレイさに感動したからでした。

最近のWindowsにはメイリオや游ゴシックといった見栄えの良いフォントも入っていますが、コーディング向きのプログラミングフォントというものもあるので、そういったものを気軽に試せるように、フォント管理ツールを導入してみることにしました。

FontBaseのインストール

FontBaseはWindowsだけでなく、MacLinuxにも提供されているフォント管理ツールです。

FontBase

公式サイトからダウンロードできますが、wingetからもインストールすることができます。

> winget install --id Levitsky.FontBase -s winget

使い方はこちらの記事がわかりやすかったです。

フォント管理ソフト『FontBase』の使い方 | modelax

簡単に説明すると、あらかじめ任意の場所にフォントを入れておくフォルダを用意して、FontBaseから参照するように設定しておくことで、そこに入れたフォントの有効化・無効化を管理することができるようになるという感じです。

注意点としては、FontBaseで管理しているフォントはFontBaseが起動していないと使えません。(OS起動時に自動起動する設定がデフォルトで有効です)

f:id:umi-uyura:20210924222124p:plain

フォント確認用にサンプルで表示する文言はデフォルトだと英語(と数字・記号)しかないのですが、このように任意のものに変更することもできます。

Visual Studio Codeに設定

コーディングメインとなるVSCodeには開発者向けフォントのJetBrains Monoを使いつつ、日本語用にIBM Plex Sans JPを併用してみることしました。

VSCodeの設定の Editor: Font Family の先頭に "'JetBrains Mono', 'IBM Plex Sans JP' を追加します。

(settings.jsonを直接編集する場合は editor.fontFamily キーに設定します)

f:id:umi-uyura:20210924222234p:plain

VSCodeのデフォルト

f:id:umi-uyura:20210924222250p:plain

JetBrains Mono + IBM Plex Sans JP

f:id:umi-uyura:20210924222302p:plain

文字の輪郭がクッキリとして見やすくなった気がします。

アルファベットの幅もちょうどよい感じ。

参考: IBM Plex Sans JP フォントをVS Codeで使う|junkawa@Chromebookで始める開発日記|note

こちらの方はフォント指定時に 'IBM Plex Sans JP Text' と指定されているようでしたが、私の環境では 'IBM Plex Sans JP' にしないと変わりませんでした。

Linuxで使われているようなので、OSによって指定の仕方が違うのかもしれません。

Windows Terminalに設定

VSCodeCSS的に複数のフォントを指定して組み合わせることができましたが、Windows Terminalは一般的なアプリケーションのようにひとつしか指定することができません。

ターミナルはコード的な英数字の表示が多いわけですが、Windowsは日本語ロケールということもあってやはり日本語もキレイに表示したいので、PlemolJPというフォントを使ってみることにしました。

すべてのターミナルでPlemolJPを使うようにしたいので、Windows Terminalの設定をJSONで開き、 profiles キーに defaults を追加して、以下のように font.face を指定しました。(サイズはお好みで)

{
  "profiles": 
  {
    "defaults":
    {
      "font":
      {
        "face": "PlemolJP35 Console HS",
        "size": 11
      }
    },
    "list": {
      ...
    },

PlemolJPには4種のフォントファミリーがありますが、その中から PlemolJP35 Console HS を使ってみています。( 35 は文字幅比率「半角3:全角5」ということらしく、それがどんな感じなのか試してみたかったのと、全角スペースの可視化は不要だったので HS 付きのものを指定しています)

winget list を実行したときの表示を、初期フォントの Cascadia Mono を使っている場合と比べてみると、こんな感じでした。

Cascadia Mono

f:id:umi-uyura:20210924222321p:plain

PlemolJP35 Console HS

f:id:umi-uyura:20210924222333p:plain

初期フォントだとカタカナが半角っぽくて個人的にバランスが悪い印象がありましたが、そのあたりが改善されてとても見やすくなりました。

Slackに設定

Slackアプリのフォントを変更したい場合、以前はアプリを展開して中のファイルを書き換えるといった技が使われていましたが、いつの間にかフォント変更用のコマンドが付いていたんですね。

【小ネタ】Slack のフォントを変えて気分を変える話 | わたしにゅーす – Me(ow)News

Slackも日本語メインなので、PlemolJPを設定しようと思います。

Slackアプリのメッセージに以下のコマンドを入れると、UI部分も含めてアプリ全体のフォントがPlemolJPに変わりました。

/slackfont PlemolJP35 Console HS

おわり

フォントをインストールするだけのために常駐する管理ツールを入れるのはどうなんだろうと思ったりもしましたが、ツール起因でOSの動作が怪しくなるようであれば、そのとき必要なフォントに絞って直接インストールしてしまえば良いのかなと思っています。

どちらかと言うとフォントのインストールすること自体というよりは、あとから自分で入れたものがどれなのかが把握できるので、使わなくなったものを無効化したり削除したりといったことをする点で有用なのかなと考えています。

WSL2環境構築(Homebrewとasdf)

先日Windows PCのセットアップをおこなって、ひとまずWindowsとWSLの環境を整えるとっかかりはできましたので、次にWSL側の環境構築を進めました。

umi-uyura.hatenablog.com

方針

WSL2で選択できるLinuxディストリビューションはいろいろとありますが、WSLを利用しようとした際にまず挙げられるUbuntuにしています。

Ubuntuには標準でaptというパッケージマネージャが備わっていますが、そういえばMacでお世話になっているHomebrewがLinuxにも対応していることを思い出したので、これも利用してみることにしました。

またプログラミング言語関連はプロジェクトによって異なるバージョンを扱うこともあるため、asdfというツールも導入してみます。

と、いろいろと入れてしまいますが、以下のような使い分けをしていこうかなと思っています。

  • プログラミング言語環境のようにプロジェクトによって使いたいバージョンが変わる(複数のバージョンを切り替えて使う)可能性があるものはasdf
  • 開発ツールのように新しいバージョンが出たら素直にアップデートしていくものはHomebrew
  • 必要に応じてapt

Homebrewインストール

Linux版Homebrewというものが別にあるのかと思っていましたが(当初はLinuxbrewという名前で別物ではあったようですが)、現在ではMac版に統合されているようで、インストールスクリプトは同じものを使うようです。

そのためパッケージによってはMac版はあるものの、Linux版はないというものもあるようです。

また当然といえば当然ですが、Mac用のアプリケーションを管理するHomebrew Caskのパッケージは、そもそもLinuxにはインストールできません。

Homebrew on Linux — Homebrew Documentation

たまに内容が変わっていることがあるようですが、今回実行したときは以下のようなものでした。

$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

Windows TerminalでWSLのUbuntuに入って、上記のワンライナーを実行します。すると、

$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
==> Checking for `sudo` access (which may request your password).
==> Select the Homebrew installation directory
- Enter your password to install to /home/linuxbrew/.linuxbrew (recommended)
- Press Control-D to install to /home/<user>/.linuxbrew
- Press Control-C to cancel installation
[sudo] password for <user>:

と表示され、最後のところで sudo のパスワードを要求されました。

インストール後はHomebrewが sudo を必要とすることはないようですが、 sudo が使えるかどうかでインストール先が変わるのと、それによってより多くのバイナリパッケージがインストールできるようです。

そちらが推奨のようなので、 sudo ありで進めました。

==> This script will install:
/home/linuxbrew/.linuxbrew/bin/brew
/home/linuxbrew/.linuxbrew/share/doc/homebrew
/home/linuxbrew/.linuxbrew/share/man/man1/brew.1
/home/linuxbrew/.linuxbrew/share/zsh/site-functions/_brew
/home/linuxbrew/.linuxbrew/etc/bash_completion.d/brew
/home/linuxbrew/.linuxbrew/Homebrew
==> The following new directories will be created:
/home/linuxbrew/.linuxbrew/bin
/home/linuxbrew/.linuxbrew/etc
/home/linuxbrew/.linuxbrew/include
/home/linuxbrew/.linuxbrew/lib
/home/linuxbrew/.linuxbrew/sbin
/home/linuxbrew/.linuxbrew/share
/home/linuxbrew/.linuxbrew/var
/home/linuxbrew/.linuxbrew/opt
/home/linuxbrew/.linuxbrew/share/zsh
/home/linuxbrew/.linuxbrew/share/zsh/site-functions
/home/linuxbrew/.linuxbrew/var/homebrew
/home/linuxbrew/.linuxbrew/var/homebrew/linked
/home/linuxbrew/.linuxbrew/Cellar
/home/linuxbrew/.linuxbrew/Caskroom
/home/linuxbrew/.linuxbrew/Frameworks

Press RETURN to continue or any other key to abort

インストールされるコマンドや作成されるフォルダについて説明が出たあとで、続けるかどうかの確認が出るので、そのままENTER。

...
Warning: /home/linuxbrew/.linuxbrew/bin is not in your PATH.
  Instructions on how to configure your shell for Homebrew
  can be found in the 'Next steps' section below.
...

インストール処理が完了すると、途中で上記のようなWarningが出ているとおり、HomebrewのbinをPATHに追加する必要があります。

それについて、サイトには以下のような手順が示されていましたが、

$ test -d ~/.linuxbrew && eval $(~/.linuxbrew/bin/brew shellenv)
$ test -d /home/linuxbrew/.linuxbrew && eval $(/home/linuxbrew/.linuxbrew/bin/brew shellenv)
$ test -r ~/.bash_profile && echo "eval \$($(brew --prefix)/bin/brew shellenv)" >>~/.bash_profile
$ echo "eval \$($(brew --prefix)/bin/brew shellenv)" >>~/.profile

スクリプトの実行結果を見ていると、最後のあたりに Next steps という出力がありました。

それによると、

...
==> Next steps:
- Run these two commands in your terminal to add Homebrew to your PATH:
    echo 'eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"' >> /home/<user>/.profile
    eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"
- Run `brew help` to get started
- Further documentation:
    https://docs.brew.sh
- Install the Homebrew dependencies if you have sudo access:
    sudo apt-get install build-essential
    See https://docs.brew.sh/linux for more information
- We recommend that you install GCC:
    brew install gcc

とあったので、まずは以下を実行。

$ echo 'eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"' >> /home/<user>/.profile
$ eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"

そのあとで brew help を実行して、ヘルプが表示されることを確認。

$ brew help
Example usage:
  brew search TEXT|/REGEX/
  brew info [FORMULA|CASK...]
...

あとHomebrewの依存関係で必要らしいので、以下を入れておきます。

$ sudo apt install build-essential

※公式には apt-get と書かれていましたが、今は apt が推奨らしいので、そこだけ変更しています。

※公式には procps curl file git も記載されていましたが、私の環境にはすでに入っていたためか、上記しか要求されませんでした。

あとこれも推奨とのことなので、さっそく brew コマンドで入れておきます。

$ brew install gcc

Next steps にはありませんでしたが、公式の手順にやっておくと良いよと書いてあったので、 brew doctor を実行。

$ brew doctor
Your system is ready to brew.

問題なし。

無事にインストールできたようです。

asdfインストール

続いて、asdfをインストールします。

asdf

公式のインストール手順は以下のリンク先にあります。

Getting Started | asdf

ですが、実はHomebrewでも提供されているので、せっかくなので今回はHomebrewで入れてみました。

$ brew install asdf

...
==> Summary
🍺  /home/linuxbrew/.linuxbrew/Cellar/asdf/0.8.1_1: 122 files, 364.4KB
==> Caveats
==> asdf
To use asdf, add the following line to your ~/.profile:
  . /home/linuxbrew/.linuxbrew/opt/asdf/libexec/asdf.sh

Restart your terminal for the settings to take effect.

Bash completion has been installed to:
  /home/linuxbrew/.linuxbrew/etc/bash_completion.d

.profileに . /home/linuxbrew/.linuxbrew/opt/asdf/libexec/asdf.sh を追記しておけとあるので、そのとおりにしておきます。

その後、ターミナルを開き直して、試しに以下のコマンドを実行してみます。

$ asdf plugin list all
1password-cli                 https://github.com/NeoHsu/asdf-1password-cli.git
R                             https://github.com/asdf-community/asdf-r.git
act                           https://github.com/grimoh/asdf-act.git
adr-tools                     https://gitlab.com/td7x/asdf/adr-tools.git
ag                            https://github.com/koketani/asdf-ag.git
age                           https://github.com/threkk/asdf-age
aks-engine                    https://github.com/robsonpeixoto/asdf-aks-engine.git
...

するとプラグインの一覧が出力されました。

これは asdf-vm/asdf-plugins リポジトリに集められているプラグインの一覧のようで、ここに掲載されているプラグインについてはインストール時にPlugin ListのLanguage欄の名前で指定することができるようです。(基本的にはリポジトリのURLを指定する)

これでasdfもインストールできました。

asdfを使ったPythonのインストール

さっそくasdfを使って何かインストールしてみることにしました。

公式のチュートリアルでは続けてNode.jsをインストールしていますが、Node.jsは別途専用の管理ツールを使いたいと考えていたので、代わりにPythonを入れてみます。

さきほどのPlugin Listの中にPythonも含まれていましたので、必要な依存関係を確認するためにそのリポジトリを見てみます。

danhper/asdf-python

Pythonプラグインは内部的にpyenvを使っているようで、以下のページを参照して必要な依存関係をインストールします。

Suggested build environment | pyenv/pyenv Wiki

Ubuntuだと以下のものをインストールするようです。

$ sudo apt install make build-essential libssl-dev zlib1g-dev \
libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm \
libncursesw5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev

※今回asdfはHomebrewで入れていたこともあり、最初はLinuxberwと指定されている方をインストールしてみたのですが、Pythonをインストールする際にエラーになったため、Ubuntuで指定されているものをインストールしました。

もろもろのインストールが終わったら、Pythonプラグインを追加します。

$ asdf plugin add python
$ asdf plugin list
python

次に、提供されているPythonのバージョンを確認します。

$ asdf list all python
Downloading python-build...
Cloning into '/home/<user>/.asdf/plugins/python/pyenv'...
remote: Enumerating objects: 20296, done.
remote: Counting objects: 100% (1208/1208), done.
remote: Compressing objects: 100% (533/533), done.
remote: Total 20296 (delta 718), reused 950 (delta 566), pack-reused 19088
Receiving objects: 100% (20296/20296), 4.14 MiB | 769.00 KiB/s, done.
Resolving deltas: 100% (13653/13653), done.
2.1.3
2.2.3
2.3.7
2.4.0
2.4.1
2.4.2
2.4.3
2.4.4
...

初回だからか、まずは裏で使われているpyenvのインストールが走ったあとで、バージョンの一覧が表示されました。

この時点の3.9系の最新版を入れてみます。

$ asdf install python 3.9.7
remote: Enumerating objects: 17, done.
remote: Counting objects: 100% (17/17), done.
remote: Compressing objects: 100% (6/6), done.
remote: Total 17 (delta 10), reused 10 (delta 10), pack-reused 0
Unpacking objects: 100% (17/17), 15.13 KiB | 3.03 MiB/s, done.
From https://github.com/pyenv/pyenv
   58e20879..90d0d205  master     -> origin/master
python-build 3.9.7 /home/<user>/.asdf/installs/python/3.9.7
Downloading Python-3.9.7.tar.xz...
-> https://www.python.org/ftp/python/3.9.7/Python-3.9.7.tar.xz
Installing Python-3.9.7...
python-build: use readline from homebrew
Installed Python-3.9.7 to /home/<user>/.asdf/installs/python/3.9.7

グローバルで利用するバージョンをセットしておきます。

$ asdf global python 3.9.7
$ python --version
Python 3.9.7
$ cat $HOME/.tool-versions
python 3.9.7

asdfで使用するバージョンは .tool-versions というファイルで管理されるようなので、HOMEディレクトリにそのファイルが生成されていることも確認できました。

Windows 10開発環境構築(WSL2とGit/VSCodeの連携)

今業務で使っているWindowsマシンは、gnupackとChocolateyをベースに環境構築していました。

umi-uyura.hatenablog.com

最近、作業の都合でWSL2を使うことになり、さらにVisual Studio Codeとの連携を使ってみたところ非常に便利だったのと、Windowsのソフトウェア管理ツールとしてwinget (Windows Package Manager)というものが出てきていたので、改めてこれらをベースにした環境を作ってみることにしました。

プライベートでもWindows触っておこうと思って買ったものの放置していて、もはや子供のマインクラフト用になっていたノートPCがようやく活用されるときが来た。

コンセプト

改めてWSL2を使う想定の環境作りをするにあたり考えていたこと。

  • 開発環境はWSLに寄せる
    • 最近はWeb開発的なことが多いので、その方が都合が良さそう
    • ただWindows用のElectronアプリの開発なども多少あるので、Windows側にも一応開発環境を用意することも想定しておく
  • ソフトウェア管理ツールは活用する
    • Windows: なるべくwingetにして、Chocolateyから移行
    • WSL2 (Ubuntu): apt、asdfというのも気になる
  • Gitとssh-agent(ssh鍵)はWindowsとWSLで共有したい
    • GitHubの認証はSSHキーでおこなっているが、Windows側とWSL側でそれぞれ認証するのは面倒
  • Windowsでふだん使うシェルはコマンドプロンプトにする
  • 何はともあれEmacs
    • Windows版ではなくLinux(WSL)版を使うようにしたい
    • GUI版を使いたいけど、WSLgはもう少し先になりそう

まずはWSL2の環境を作りつつ、VSCodeを連携するところまでを目指しました。

Windows側の構築

wingetインストール

まずは色々インストールするためにwingetを入れます。

winget ツールを使用したアプリケーションのインストールと管理 | Microsoft Docs

Microsoft Storeで アプリ インストーラー をインストールすることが推奨されているようですが、Windows 10 InsiderビルドでないとStoreからはインストールできないもよう。

その場合、GitHubからインストーラをダウンロードしてきます。

インストール後、コマンドプロンプトを開いてコマンドを打ち込み、インストールされていることを確認しておきます。

> winget
Windows Package Manager v1.0.11692
Copyright (c) Microsoft Corporation. All rights reserved.

WinGet コマンド ライン ユーティリティを使用すると、コマンド ラインからアプリケーションやその他のパッケージをインストールできます。
...

Windows Terminalインストール

素のコマンドプロンプトでも良いですが、せっかくなので今のうちにWindows Terminalを入れおきます。

さっそくインストールしたばかりのwingetを使います。

wingetはMicrosoft Storeをソースにすることもできますが、いったんストアアカウントなしでインストールしたいので、 sourcewinget にして実行します。

> winget install -e --id Microsoft.WindowsTerminal -s winget

UACのプロンプトが出るのでOKすれば、インストールがおこなわれます。

コマンドプロンプトを管理者権限で起動すればUACを出さずに実行できるのですが、いったん必要なときだけやる方針でいこうと思います。

Google Chrome

完全な初期状態からであればwingetで入れるところですが、このとき使ったPCは別ユーザーでChromeをインストール済だったので、今回は使わず。

ただ winget list -q chrome と実行したところ、インストール済のアプリとしてChromeが認識されていました。

> winget list -q chrome
名前          ID            バージョン
-----------------------------------------
Google Chrome Google.Chrome 92.0.4515.159

どうやらwingetは独自にインストールしたものについて管理をしているわけではなく、PCにインストールしたものを認識しているっぽい。

また、アプリに利用可能なアップデートがある場合は「利用可能」列が現れることも発見。

Gitインストール、GitHub接続

Git for Windowsもwingetでインストールできます。

> winget install -e --id Git.Git -s winget

とりあえず、ユーザーの設定はしておきます。

> git config --global user.name "Umi Uyura"
> git config --global user.email <my_email@example.com>

GitHubSSH接続できるようにする

次にGitHubへアクセスできるようにします。

私はふだんSSHで接続しているので、GitHub用のSSH鍵を作ります。

最近はアルゴリズムRSAではなくED25519が良いらしい。

> ssh-keygen -t ed25519 -C "my_email@example.com" -f %USERPROFILE%¥.ssh¥github_ed25519

今のWindows 10にはOpenSSLが標準で含まれているので、認証のためにssh-agentを起動しておこうとしたところ、エラー発生。

> ssh-agent -s
unable to start ssh-agent service, error: 1058

Windows 10のssh-agentをコマンド プロンプト、WSL、Git Bashで使ってみた - Qiita

上の記事によると、どうやらOpenSSHのサービスが起動していないことが原因らしいので、

  • Win + R(ファイル名を指定して実行)から services.msc を実行してサービス管理画面を起動
  • OpenSSH Authentication Agent のスタートアップの種類を「自動」に変更

を行ってから、改めてssh-agentを起動して、 ssh-addSSH鍵を追加。その際にSSH鍵のパスフレーズを要求されるので入力。

問題なければ、 ssh-add -l で登録した鍵の情報が表示されるはず。

> ssh-agent -s
> ssh-add %USERPROFILE%¥.ssh¥github_ed25519
> ssh-add -l
256 SHA256:CTVT24F8dLFqlAtBULhuB2dZjLQmIz05G4730mD4Ii8 my_email@example.com (ED25519)
256 SHA256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx my_email@example.com (ED25519)

あとはGitHubの手順どおり。

GitHub に SSH で接続する - GitHub Docs

公開鍵を clip コマンドでクリップボードにコピーして、GitHubSSH Keyにペーストして登録。

> clip < %USERPROFILE%¥.ssh¥github_ed25519.pub

ssh -T で接続確認。

> ssh -T git@github.com
...
Hi umi-uyura! You've successfully authenticationed, but GitHub does not provide shell access.

自分のGitHubアカウント名が表示されれば、接続されています。

ちなみに ssh -T-T ってなんだろうとおもって調べたところ、以下の記事が参考になりました。

pseudo-tty とは? - kz-engineer -SCRAP-

環境変数 GIT_SSH の登録

これで sshGitHubに接続できるようになったものの、実はGit for Windowsは独自にバンドルしている ssh を使うようで、このままでは git コマンド経由でSSH接続しようとしたときにつながりません。

そこで、環境変数 GIT_SSHWindows標準の ssh.exe のパスを設定することで、こちらの ssh を使ってもらえるようになります。

> where ssh
C:\Windows\System32\OpenSSH\ssh.exe

> echo %GIT_SSH%
C:\Windows\System32\OpenSSH\ssh.exe

Visual Studio Codeのインストール

これもwingetでインストールできます。

> winget install -e --id Microsoft.VisualStudioCode -s winget

いろいろと設定変えたり拡張機能インストールしたりとありますが、まずはWSL2との連携をしたいので、そのあたりは後ほど。

Chocolateyインストール

wingetに対応できるものはインストーラ形式があるものを前提としていて、ZIPなどで配布しているものは対象外なもよう。

対応要望のissueはある( Support installing .zip files · Issue#140 · microsoft/winget-cli )ので今後に期待しつつ、それはそれとして、SysinternalsやこのあとWSL2との連携で必要になる npiperelay などがこのためにwingetでは入れられないため、当面そういったものを管理するためにChocolateyも併用することにしました。

インストールは公式サイトの手順通りに実施します。

Chocolatey Software | Installing Chocolatey

PowerShellは極力使わない方針としつつ、Chocolateyのインストールスクリプトは.ps1なので、しかたなく管理者権限で起動したPowerShellで、まずは以下のコマンドを実行。

> Get-ExecutionPolicy 
Restricted

公式サイトによると、ここは Bypass もしくは AllSigned となっていることが良いらしく、設定の変更方法が載っていました。

が、どうやら Now run the following command: に示されているコマンドを見ると、その設定変更からインストールスクリプトのダウンロードと実行までやってくれるもののようだったので、素直にコピペして実行。

> Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))

インストールが終わったら choco コマンドが使えることを確認。

> choco /?
This is a listing of all of the different things you can pass to choco.
...

npiperelayのインストール

混沌を極めるWindowsのssh-agent事情 - Qiita

上記の記事にあるように用途によってssh-agentの選択は分かれるようですが、私はWindowsとWSL2で、Windows側は標準搭載されているOpenSSHを使うようにしようと思ったので、npiperelay+socat方式にすることにしました。

npiperelayはChocolateyから入れられます。

管理者権限でコマンドプロンプトを起動して、

> choco install -y npiperelay
...
C:\ProgramData\chocolatey\lib\npiperelay\tools
 ShimGen has successfully created a shim for npiperelay.exe
 The install of npiperelay was successful.
  Software installed to 'C:\ProgramData\chocolatey\lib\npiperelay\tools'

Chocolatey installed 1/1 packages.
 See the log for details (C:\ProgramData\chocolatey\logs\chocolatey.log).

> where npiperelay
C:\ProgramData\chocolatey\bin\npiperelay.exe

インストール中にも出力されていますが、最後に where npiperelay で確認した実行ファイルへのパスがあとで必要になるのでメモしておきます。

WSL2 (Ubuntu)側の構築

続いてWSL2のセットアップ。

ここはMicrosoftのドキュメントを参考に進めました。

Windows 10 に WSL をインストールする | Microsoft Docs

上記によると、WSLのインストールには「簡略化されたインストール」と「手動インストール」があるようですが、「簡略化」の方はこちらもInsider Programに入っていることが条件のようなので、手動インストールをおこないました。

WSLには1と2がありますが、用途によっては1を選択することもあるようです。

WSL 1 と WSL 2 の比較 | Microsoft Docs

インストール中、私のPCでは「インストールがエラー 0x80070003 またはエラー 0x80370102 で失敗した」が発生しましたが、ドキュメントのインストールのトラブルシューティングの項にとおりBIOSから仮想化を有効化したところ発生しなくなりました。

WSL2が有効になったところで、いちどパッケージを最新状態にしておきます。

パッケージの更新とアップグレード

$ sudo apt update && sudo apt upgrade

Git(最新版)インストール

概要WSL で Git を使用する | Microsoft Docs

$ sudo apt install git
Reading package lists... Done
Building dependency tree
Reading state information... Done
git is already the newest version (1:2.25.1-1ubuntu3.1).
0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.

$ git --version
git version 2.25.1

Windows側に入れたものは 2.32.0 でしたが、ふつうにaptでインストールしたところ古いバージョンでした。

最新版のGitを入れるには、別のリポジトリを追加する必要があるとのこと。

$ sudo add-apt-repository ppa:git-core/ppa
$ sudo apt update
$ apt list --upgradable
Listing... Done
git-man/focal 1:2.32.0-1~ppa0~ubuntu20.04.1 all [upgradable from: 1:2.25.1-1ubuntu3.1]
git/focal 1:2.32.0-1~ppa0~ubuntu20.04.1 amd64 [upgradable from: 1:2.25.1-1ubuntu3.1]

$ sudo apt install git
$ git --version
git version 2.32.0

WindowsSSHキーの共有

まずはnpiperelayと組み合わせて使うsocatをインストールします。

$ sudo apt install socat

続いて、Chocolateyで入れたnpiperelay.exeへのパスを含めたスクリプトを.bashrcに追記します。

export SSH_AUTH_SOCK=$HOME/.ssh/agent.sock
ss -a | grep -q $SSH_AUTH_SOCK
if [ $? -ne 0   ]; then
    rm -f $SSH_AUTH_SOCK
    ( setsid socat UNIX-LISTEN:$SSH_AUTH_SOCK,fork EXEC:"/mnt/c/ProgramData/chocolatey/bin/npiperelay.exe
 -ei -s //./pipe/openssh-ssh-agent",nofork & ) >/dev/null 2>&1
fi

一度WSLを抜けて入り直し、Windows側と同様 ssh -T での接続確認をおこないます。

$ ssh -T git@github.com
Hi umi-uyura! You've successfully authenticationed, but GitHub does not provide shell access.

ホストWindows側でSSHキーを登録しておくことで、WSL2側ではキーの作成や登録をせずにSSH接続できました。

Visual Studio Code + Remote Developmentのセットアップ

基本はMSのドキュメントどおりに進めればOK。

WSL で VS Code の使用を開始する | Microsoft Docs

まずは指示通りに必要なものをインストール。

VSCode側には Remote Development - Visual Studio Marketplace拡張機能をインストールし、WSL側にはwgetとca-certificatesをインストールします。

$ sudo apt-get update
$ sudo apt install wget ca-certificates

その後、WSL側で code . を実行すると、サイトのアニメーションGIFのようにVS Code Server for x64のインストールが始まり、それが終わるとホストWindows側でVSCodeが起動し、WSLのフォルダが開かれていました。

パスを確認すると、それまでは \\wsl$\Ubuntu\home\<user>\... と表示されていたものが /home/<user>/... [WSL] という表示になり、Remote Developmentで接続できていることを確認できます。

WSL2の初期化

途中で失敗したときのため(失敗した)、WSL2を最初から作り直す方法についても調べておきました。(やりました)

Windows 10のWSL環境を初期化してクリーンな状態に戻す:Tech TIPS - @IT

WSLが停止していることを確認。

> wsl --list --verbose
  NAME      STATE           VERSION
* Ubuntu    Stopped         2

記事のとおり、設定アプリアプリと機能 のアプリケーション一覧から、対象となるディストリビューションの、アプリケーションの設定からリセットをおこないます。

そのあとでMS Storeのディストリビューションから起動をすればアカウントの作成から始まります。

おわり

実際になにか開発をするには、さらに対象の言語環境やツールが必要になってきますが、そのためのベースとなる環境はできたかなと思います。

CygwinMacで多少Linuxコマンドを使ったりしてはいたものの、ちゃんとLinux環境で開発をしたことはほとんどないので、WSL側についてはこれから手探りですね。

Goose houseは実在しました

UstreamYoutube中心に活躍しているGoose house

前からライブを見てみたかったのですが、ようやくチケットが手に入って行くことができました。

Goose house

今週大阪公演があったようですが、私が行ったのは11/22(水)にZepp DiverCity Tokyoで開催された東京公演。


演目は、シングル「笑顔の花」の発売に合わせたツアーということもあってなのか、オリジナル曲以外にも、ふだん彼らがやっているようなカバー曲を半分くらい?やっていたような気がします。

一緒に歌いましょう!という呼びかけで始まった「明日があるさ」、「わか〜い僕には…」と歌いながら「あれ、自分たぶん若くない方だ…」と一瞬怯んでしまいましたが(笑)

これもみんなと一緒に声を出したい!というところから作られたという、シングルのカップリング曲「何もかも有り余っている こんな時代も」もカッコいいですね。 拳を振り上げて歌う、こういうの、好きな感じでした。


曲ごとに違う楽器を操るジョニーさん。

一番小さい、でも最年長なので敬って欲しいマナミさん。

いつもより黒が多めだったワッシュウさん。

フォロワー数No.1の竹渕慶さん。

キュートな声が素敵なさや姉さん。

そして、いつも素敵な笑顔のリーダー(仮)の工藤さん。

ふだんは画面の中でしか見られない彼らですが、それとは違ったステージ上での生パフォーマンスが観られて、とても楽しかったです。


月一の土曜日に定期的におこなわれるUstream Live。

そんなUstream Live、次回はHOY (Goose house of The Year)ですねー。

その年のカバー曲の中からNo.1を、視聴者の投票で決めるという一大イベント。

Live放送している時間帯は、ちょうど子供をお風呂に入れて寝かしつけるころ(しかもそのまま一緒に寝てしまったりする)なので、なかなかリアルタイムでは見られないのですが、今年は途中からでも見られると良いなー。

USTREAM: Goosehouse


さてさて、今までたくさんのカバーをやっているGoose houseですが、そんな中で個人的にイチオシを1つ紹介させていただくと、これですかねー。


One Night Carnival /氣志團(Cover)

オリジナルの雰囲気を残しつつ、Gooseメンバーの個性が加わった爽やかな感じのアレンジがカッコいい。

実はそれまで原曲はちゃんと聴いたことがなかったのですけれど、その新しい魅力に気づかせてくれた1曲です。

というわけで、今度はオリジナル曲多めのライブに行きたい!

High SierraにしたらSlackアプリがクラッシュするようになったけど直った

先日Mac OSからmacOSにアップグレードしたわけですが。

その後、Slackアプリを実行すると、起動中にクラッシュしてしまうらしく、使えない状態になってしまいました。

ログアウトして再ログインしてもダメ、アンインストールしてMac App Storeから再インストールしてもダメ、そんなことをしている間にSlackアプリのアップデートが来ていたけど、それを入れてもダメ。

必要なときはブラウザでアクセスしていたものの、やはり使い勝手が悪く、困っていました。

直った

ググっていろいろと試していたのですが、最終的にElectronのIssueに載っていた方法で復旧することができました。

Crash in GetLoginItemSettings on macOS 10.13 · Issue #10561 · electron/electron

具体的には、 /Users/$your_user/Library/Application Support/com.apple.backgroundtaskmanagementagent/backgrounditems.btm を削除して、macを再起動します。($your_usermacのユーザー名が入ります)

再起動後にSlackアプリを実行したところ、クラッシュせずに起動するようになりました。


調べてみると、Spotifyアプリでも同じような問題が起きていたっぽい。

Fix for Spotify Crash at startup on MacOS High Sie... - The Spotify Community

Electronベースのアプリは可能性があるのかも。

他の問題も直ることがあるみたい

上記で削除したファイルは、macの他の機能にも関連しているらしく、実は私ももう一つ発生していた「ログイン項目に不明という項目が残ってしまう」問題が合わせて直りました。

Can't remove 'unknown login items'? | Official Apple Support Communities

最初は こちら の方法を試して解決しなかったのですが、一緒に直って良かったです。

Superfly10周年記念ライブのライブ・ビューイングに行ってきました

去年、春に始まったラジオ番組「Superfly into the Radio」が、喉の不調ということで途中で打ち切りになってしまって以降、あまり表立った活動を目にしていなかったので、1ファンとしても心配していました。

今回のライブのMCや、途中に挟まれたライブまでのドキュメンタリータッチの映像などで知ったのは、1年以上歌からは離れていた状態だったとのこと。

何はともあれ、また彼女の歌が聴けることがうれしいですね。

Superflyのライブビューイング観た!

そんな休養期間が終わって最初のライブ。

全国の映画館でライブ・ビューイングがあるということで、私は横浜のブルク13で見ていました。


ライブ会場は東京オペラシティコンサートホール。クラシックや演劇などのイメージが強いところなのでどういうライブになるのかと思っていましたが、オーケストラを従えてのアコースティックな編成ということで納得。

そして驚いたのは、髪をバッサリ切ってベリーショートなスタイルになったSuperfly!

やっぱり長い髪をなびかせながら歌うイメージが強かったので、これは意外でしたねー。


厳選されたオーケストラアレンジの楽曲も、どれも良かったです。

個人的に一番好きな「Wildflower」が入っていたのが、さらに満足。

ライブ・ビューイングだったけど、相変わらず力強い歌で、パワーをもらいました。


個人的にはそんなこともあり、到着したのは第一幕の終わり頃だったので、最初の方は見逃してしまったのが残念。

あとで当日のセットリスト見たら、Box Emotionsからのオーケストラ合いそうな曲を3つもやっていて、仕事とは言え遅れたのが悔やまれる。

ぜひ、映像作品化して欲しい。


次はライブ会場で見たい!

Box Emotions

Box Emotions