WSL2のUbuntu 22.04.3でSnapdが使えなくて起きた悲劇

# 概要
とある個人開発で触ったことない使い勝手の良いツールないかなと思い、
VSCodeの拡張機能([Marp for VSCode](https://marketplace.visualstudio.com/items?itemName=marp-team.marp-vscode))を資料作成で使用することにしました。

ホストを直接汚したくはないので、WSL2のUbuntu22.04で操作していたのですが、
環境設定で長時間ハマってしまったので今回はその備忘録になります。

前提として、WSL2やVSCodeのセットアップは完了しているものとします。
Marpを使おうと思った理由は省略します。

# 目次
- 実行環境
- Marp とは
- snap とは
- セットアップ
- エクスポート
- エクスポートができない
- 悲劇の始まり(本題)
- 再度snap installだ！
- あとがき
- 参考記事

# 実行環境
- ホスト：Windows 10
- WSL2：Ubuntu 22.04.3
- 使用ツール：VSCode

# Marp とは
本題に進む前に[Marp](https://marp.app/)について軽く触れておきたいと思います。
[Marp](https://marp.app/)とは、`Markdown Presentation Ecosystem`の略で、
マークダウンでプレゼンスライドを作成可能なツールとなっています。

個人的には、プライベートでわざわざお金をかけてOfficeを導入したくない点や
本体がマークダウン形式のファイル (.md) のため、資料をgitなどのバージョン管理システムで管理できる点がとても魅力的だと感じています。

導入は以下を参考にしました。
- [【VS Code + Marp】Markdownから爆速・自由自在なデザインで、プレゼンスライドを作る](https://qiita.com/tomo_makes/items/aafae4021986553ae1d8)

今回はこの[Marp for VSCode](https://marketplace.visualstudio.com/items?itemName=marp-team.marp-vscode)を使って、スライドを作成し、pdfでエクスポートすることを目的としています。

# snap とは
wikipediaより引用
> Snap（旧称・Snappy）とはカノニカルが設計・開発したソフトウェアデプロイメントシステムかつパッケージ管理システムであり、元々はUbuntu Phoneオペレーティングシステム用に設計・開発された。パッケージは 'Snap' と呼ばれ、Snapを使うツールは 'Snapd' と呼ばれる。Snapは様々なLinuxディストリビューションで動作するので、ディストリビューションの上流のソフトウェアデプロイメントに依存しない。Snapのシステムは携帯電話、クラウド、IoTやデスクトップパソコン向けに設計されている

後述の操作でインストールコマンドを入力したため、aptの親戚かな？と解釈しました。
「snap」 も 「apt」と同じ、「パッケージマネージャ」ということになるようです。
snapとaptの違いは以下になります。

## snap
- 依存関係を1パッケージ内でおさめるため、作成も簡単で、削除時も目的のものを削除すれば、依存関係を持っているものも全て消える。
- 1パッケージにすべてまとめているため、aptに比べてパッケージ単位の容量が多い
- root権限なしで実行可能

## apt
- 依存関係を後から自動でインストールする。
- パッケージ単位の容量が小さい
- root権限でしか実行できない

# セットアップ
## Ubuntu から VSCodeを起動する。
はい。いわずと知れたcodeコマンドの出番です。
操作ディレクトリを作成した上で、wsl上からVSCodeを起動したいと思います。
```vscode起動.sh
mkdir marp_test
cd marp_test
code . # 現在のディレクトリでVSCodeを起動するコマンド
```
特に何もなければこれでVSCodeが起動したはずです。
## 拡張機能のインストール
今回使用する拡張機能をインストールします。
画像ではマークダウンを使用する際の基本的な拡張機能を入れていますが、
今回はMarp for VSCodeだけあればOKです。
- Marp for VSCode (※今回の主役)
- markdownlint
- Markdown All in One

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3681030/aab85ac3-f048-341f-5c3f-8262cbffe99f.png)

## 動作確認
拡張機能のインストールが完了したので、ファイルを作成して動作を確認してみましょう。
test.mdを作成し、以下を入力します。

``` test.md
----
marp: true
----

# テスト1

----
# テスト2

テスト

----
# テスト3

テスト
テスト
```

mdファイルを表示しているウィンドウの　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3681030/d514b68d-42b5-6d4d-d9c8-c555580a0dc8.png) マークを押下し、プレビュー表示は以下のようになりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3681030/7dbc3bce-6f85-4f3a-9224-03e5595ae50e.png)

おぉ～！！ちゃんとしたよく見るスライドでページ分けができてそうですね。
次はこちらをMarp for VSCodeの機能でpdfにエクスポートしたいと思います。

# エクスポート
では、さっそくエクスポート操作をしたいと思います。
プレビュー表示のアイコンの横に三角のマーク ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3681030/c10218c8-409c-7f36-4e69-74ea35c8256e.png) があるのでこちらを押します。

検索欄に出てきた「Export Slide Deck...」を押します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3681030/cc6a9d7c-fc52-a988-ecdf-8b8347c74dda.png)

エクスポートする名前を決めてOKを押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3681030/00fbc439-89a9-f30f-3c19-dff9696092f0.png)

これでエクスポートができるはず！

# エクスポートができない
・・・と思ったのですが
pdfへのエクスポート処理が失敗し、下記のエラーが表示されました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3681030/b6c9c11f-ef06-ec48-f1fd-bc986031af15.png)

変換処理には、Google Chrome, Chromium, Microsoft Edgeのどれかが必要とのことで、
この拡張機能は一応、Windowsとかで使用する前提で作られているのでしょうか。

できないものは仕方ないので、指示にしたがってブラウザをWSL2にインストールしたいと思います。

## Chromiumのインストール
てなわけでUbuntuにChromiumを入れたいと思います。
依存パッケージも全てインストールしたいので、今回はsnapを使用した以下コマンドを実行します。

```
sudo snap install chromium
```

WSL2のルート権限のパスワードを入力し、実行したところ下記エラーが出ました。

`
error: cannot communicate with server: Post http://localhost/v2/snaps/chromium: dial unix /run/snapd.socket: connect: no such file or directory
`

エラー文で調べたところ、snapデーモンが動いていないことが判明しました。
知恵をお借りし、下記記事の内容でセットアップしてみたいと思います。

[WSL2(Ubuntu 20.04)上でSnapdを動かす](https://zenn.dev/dozo/articles/63c3e066f3c6ed)

下記コマンドを打ち込んでみます。
```
sudo apt-get update && sudo apt-get install -yqq daemonize dbus-user-session fontconfig
sudo daemonize /usr/bin/unshare --fork --pid --mount-proc /lib/systemd/systemd --system-unit=basic.target
exec sudo nsenter -t $(pidof systemd) -a su - $LOGNAME
```

どうやらsystemdが動いていないと、snapdを動かせないようです。
設定したので再起動をします。

systemctlが動くかどうかも含めて、snapdの状態を確認します。
```
systemctl status snapd
```
`System has not been booted with systemd as init system (PID 1). Can't operate.
Failed to connect to bus: Host is down`

あれ、なんか動かないな。再起動したのにどういうことだろう。

# 悲劇の始まり (本題)
わかる人はパッと見ればわかったんだろうなと書きながら思っているのですが、こちらのエラーは`systemd`がPIDの1で動いていないことによるエラーでした。

当時の僕は「wsl2 install chromium snap 起動しない」みたいな感じで検索しました。
検索の結果、あまりにもみんなが使うから、コマンドをまとめたぜ！という感じのgithubのリポジトリにあたりました。
https://github.com/DamionGans/ubuntu-wsl2-systemd-script

壊れても責任取らんし、知らんよと書いていますが、まあ大丈夫やろと思いREADMEの手順に従い下記コマンドを実行
``` sh
git clone https://github.com/DamionGans/ubuntu-wsl2-systemd-script.git
cd ubuntu-wsl2-systemd-script/
bash ubuntu-wsl2-systemd-script.sh
# Enter your password and wait until the script has finished
```

WSL2のウィンドウが閉じて、ダウンしました。

・・・・っえ？？？？？？？

はい。Ubuntuのアプリケーションが起動しては一瞬で落ちるようになってしまい、中に入れなくなってしまいました。。。
なんでやねん！！！

コマンドプロンプトからもなんかうまくいかず。。。
以下のエラーが表示されます。
`nsenter: cannot open /proc/〇〇/ns/time: No such file or directory`

bashで実行したスクリプトになんか仕込まれていたのか・・・

エラー名で調べたところ、同じ被害にあった皆さんのissueがあった。
https://github.com/DamionGans/ubuntu-wsl2-systemd-script/issues/36

まさにこれです。
何言ってるのか最初はさっぱりでしたが、なんとか読み解き、以下手順で解決することができました。

1. コマンドプロンプトを起動し、`wsl -e bash --norc`コマンドでコマンドプロンプトからwslに入る。
1. cloneしてきたリポジトリのディレクトリを起動し、`enter-systemd-namespace`ファイルをsudo viコマンドで編集する。
1. `exec /usr/bin/nsenter -t "$SYSTEMD_PID" -a`を`exec /usr/bin/nsenter -t "$SYSTEMD_PID" -m -p`に編集する。
1. 環境変数`$USER_HOME`を`$HOME`にする。
1. `bash ubuntu-wsl2-systemd-script.sh`をroot権限(sudo)で実行する。

githubのコメントのやり取りを読み解くのに3時間ほど悪戦苦闘しましたが、なんとかUbuntuのアプリケーションを再インストールせずに済みました。
(再インストールしてまた最初からセットアップとか、やりたくなさすぎる)

# 再度snap installだ！
とりあえず、Ubuntuも起動するようになってイケてそうな雰囲気
再度下記コマンドでsnapデーモンの状態を確認します。
```
systemctl start snapd
systemctl status snapd
```

起動したあああああ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3681030/5cee467a-816f-e7c3-9c79-27f745db400d.png)

無事、snapdが起動したので、chromiumをインストールしたいと思います。
```
sudo snap install chromium
```
インストールが成功しました。(写真忘れた)

おそらくこれで、WSL2上からMarpで作成したスライドのエクスポートができるはずなので、
VSCodeに戻って実行します。

結果は無事に成功し、pdfのエクスポートができました！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3681030/2f7f039b-f203-da7d-d5ae-cb6cea1a8ca3.png)

中身を確認してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3681030/168d7a6b-541e-109d-9e86-1c1e759ab2c1.png)

しっかりとプレビューで見ていたスライドと同じスライドをpdfで作成することができました。
めでたしめでたし。

# あとがき
今回はMarpで作成したものをエクスポートする過程で起きた悲劇について記事の書きおこしを行いました。
普段は社会人として、プログラムを書いたりテストしたりがメインの仕事でプログラムは初めて触る言語でもある程度触れるのですが、こういった環境構築回りは簡単なようで難しく時間がかかってしまいました。

翻訳しながらとはいえ、普段からgithubの英語のやり取りや、英文しかない公式ドキュメントを読む経験があったおかげで、今回は答えにたどり着くことができました。

あと、内容がわからないファイルはちゃんと調べてから使おうと思いました。
こんな感じでgithubのリポジトリにあるライブラリを使用したらウイルスに感染しましたなんてことになったらヤバイですからね。

今回使ったMarpももう少し勉強して、見やすい資料作りの勉強に励んでいきたいなと思います。

# 参考記事
- [WSL2(Ubuntu 20.04)上でSnapdを動かす](https://zenn.dev/dozo/articles/63c3e066f3c6ed)
- [WSL2(Ubuntu 22.04)上でSnapdを動かす(2022)](https://zenn.dev/dozo/articles/625052a4c397b8)
- [WSL2のUbuntuでsystemd（systemctl）とsnapが使えない](https://nnahito.com/articles/62)