WSL2内のUbuntuにKotlinを入れる際に詰まったこと

最近Kotlinの学習を始めたおかず盛りです。
今回私が[とほほさんのKotlin入門](https://www.tohoho-web.com/ex/kotlin.html)を見ながら、手持ちのPCにKotlinを入れる際に詰まったことと解決方法について書きます。
備忘録的な内容ですが、同じように困っている方の助けになりますと幸いです。

### この記事で分かること
* WSL2上に新しくKotlinをインストールする手順
* WSL2のディレクトリ構造について（ざっくりと）
* 調べれば先駆者は居る

### 今回行ったこと
今回は、windowsターミナルからWSL2上のUbuntuを操作してKotolinをインストールしました。
内容的にはこちらの方が行ったことと全く同じです。
[UbuntuにKotlinをインストールしてハローワールドまでやってみた](https://qiita.com/n0bisuke/items/686c1717a894713fdd06)

参考にした[とほほさんのサイト](https://www.tohoho-web.com/ex/kotlin.html)に記載されている下記のコマンドを順番に実行していきました。
windowsターミナル上で行ったため、コマンドはすべて`/home/username`ディレクトリで実行しました。
```
>$ curl -s https://get.sdkman.io | bash
$ source "/root/.sdkman/bin/sdkman-init.sh"
$ sdk install kotlin
$ sdk install java
$ kotlinc -version
>info: kotlinc-jvm 1.9.22 (JRE 21.0.2+13-LTS)
```
私がコマンドを実行した際にエラーが出たのは、一行目、二行目、五行目です。
内容としては一行目がツールの問題、二行目と五行目がパスを通す際の問題です。五行目に関しては二行目でのミスが原因でエラーが発生していました。

#### 実際に実行したコマンド
WSL2上でKotlinをインストールするために、私が実行したコマンド一覧はこちらです。
```
$ sudo apt-get install zip unzip // unzipをインストール済みなら不要
$ curl -s https://get.sdkman.io | bash
$ source "/home/username/.sdkman/bin/sdkman-init.sh"  // usernameは各自が設定したもの
$ sdk install kotlin
$ sdk install java
$ kotlinc -version
```
こちらのコマンドを順番に実行することで、Kotlinのインストールは問題なく行えると思います。

以下、とほほさんのサイトに記載のとおりにコマンドを実行した時に、問題が発生した箇所を順に見ていきます。

## 発生した問題とその原因や解決方法
### その1~SDKMANがインストールできない~原因はunzipがないこと
一行目のコマンドでは、SDKMANというパッケージマネージャをインストールします。
```
$ curl -s https://get.sdkman.io | bash
```

このコマンドを実行した際に、このようなメッセージが表示されました。
>Looking for a previous installation of SDKMAN...
Looking for unzip...
Not found.
 Please install unzip on your system using your favourite package manager.
 >Restart after installing unzip.

 内容を要約すると、「SDKMANのインストールしたいけど、unzipがシステムにないよ。unzipをインストールしたらSDKMANのインストールを再開するよ」ということみたいです。

 unzipをインストールするには下記のコマンドを実行します。
 ```
 $sudo apt-get install zip unzip
```
簡単ですね。

参考記事 "[Linux環境にZip, Unzipをインストールする](https://qiita.com/rookie/items/f168a66829baa504c064)"

unzipをインストールした後、再度SDKMANのインストールを実行すると次のようなメッセージが表示されます。（usernameは自分で設定したユーザー名が表示されます）
```
All done!
You are subscribed to the STABLE channel.
Please open a new terminal, or run the following in the existing one:
    source "/home/username/.sdkman/bin/sdkman-init.sh"
Then issue the following command:
    sdk help
Enjoy!!!
```

このメッセージ中の`source "/home/username/.sdkman/bin/sdkman-init.sh"`が重要です。このメッセージをそのままターミナル上で実行することによってパスを通すことができます。作業時にはメッセージの意味を理解しておらず、この記事を書いている時に気づきました(笑)

### その2~SDKMANのパスを通す~権限がないのではなくディレクトリ構造が違う
次にインストールしたSDKMANのパスを通すコマンドを実行します。
```
$ source "/root/.sdkman/bin/sdkman-init.sh"
```
こちらはファイルを指定するパスが`/root`から始まっており、このままだとWSL2上ではパスを通すことができません。
このまま実行すると表示されるメッセージはこちらです。
```
-bash: /root/.sdkman/bin/sdkman-init.sh: Permission denied
```
このメッセージを見て私は権限の問題だと思ったので、`ls -l`で確認すると権限は`drwxr-xr-x`となっていました。実行権限はすべて付与されているので権限の問題ではありません。

次に、`ls -a`で現在のディレクトリ内のファイル等をすべて確認してみました。するとその中に`.sdkman`がありました。これを見て閃いた私は次のコマンドを実行しました。
```
$ source ".sdkman/bin/sdkman-init.sh"
```
こちらのコマンドは無事に実行できましたので、このままKotlinとJavaのインストールコマンドを実行しました。
```
Kotlinの場合
$ sdk install kotlin
~result message~
Installing: kotlin 1.9.23
Done installing!
Setting kotlin 1.9.23 as default.


Javaの場合
$ sdk install java
~result message~
Installing: java 21.0.2-tem
Done installing!
Setting java 21.0.2-tem as default.
```
そして最後のコマンド、Kotlinのバージョン確認を行った結果がこちらです。
```
$ kotlinc -v
/home/username/.sdkman/candidates/kotlin/current/bin/kotlinc: line 98: java: command not found
```
**あれ？コマンドが見つからない？**
ここまでたどり着いてうまく行ったと思ってたのですが、最後の最後に問題がありました。

### 原因は絶対パスで指定する箇所を、カレントディレクトリからのパスで指定したこと
原因が分からず`ubuntu kotlinc`で検索すると、冒頭でもご紹介した[こちらの記事](https://qiita.com/n0bisuke/items/686c1717a894713fdd06)が出てきました。この記事を読んで始めてパスの通し方が悪かったのだと分かりました。

先ほどSDKMANをインストールした際に重要なメッセージがあると触れました。そのメッセージこそが、WSL2上でパスを通すための正しいコマンドでした。
```
$ source "/home/username/.sdkman/bin/sdkman-init.sh"
```

WSL2ではディレクトリの最上位が`home`であり`root`ではありません。`/home/username/`と記載しているように、`/home`の下にユーザーのディレクトリがあり、こちらのユーザーディレクトリ配下のファイル等をWSL2では操作しています。そのため、インストールしたSDKMANやKotlinは`/home/username/`配下に配置されています。

パスを通すためには絶対パスの指定が必要になるため、`.sdkman/bin/sdkman-init.sh`ではなく`/home/username/.sdkman/bin/sdkman-init.sh`になるのです。

パスを通すことについてはこちらの記事が参考になりました。
[今日こそ『パスが通らない！！』から完全におさらばするための記事](https://qiita.com/rihib/items/79f19029b4160eb81226)

この記事を見ると`source`コマンドはパスを通すのではなく、設定ファイルの変更を反映するためのコマンドであるということが分かります。つまり、ここまで来て私の認識が誤りであり、ろくに調べてもいなかったことが露呈するわけですね(笑)

## おわりに
こんな感じでなんとか勉強しています。
ミスの指摘等随時受け付けておりますので、どうぞよろしくお願いします。
それでは皆様、最後までお読み頂きありがとうございました。