俺様サーバー構築記 - Arch Linux + ZFS + GRUB に緊急起動メニューを付ける@ノートパソコン(BIOS)

タグは grub か grub2 かでちょっと悩みました。ど〜でもいい事ですがね。両方付けるのも馬鹿莫迦しいと思ったんで、ちょっと悩んだ末に grub だけにしました。

「[俺様サーバー構築記 - 基本方針](https://qiita.com/katz_engineer/items/dbabcff4e14e9db2b10f)」に基づいて自宅サーバーの構築を進め、[ノートパソコンにも Arch Linux + ZFS をインストール](https://qiita.com/katz_engineer/items/9d177766baf95c1e2674)しました。

大きなインストールをする際にはやり直す可能性もある訳で、実際に[インストールのやり直し](https://qiita.com/katz_engineer/items/f42a2536c74b9123bc33)が発生したりしました。まあこの時は勘違いだったようで、わざわざロールバックする必要も無かったのですが。

こういう時には仮想コンソールを切り替えて原因の調査と対応という手段もありまして、それが Linux の凄い所ではあります。しかしせっかく超絶ファイルシステム ZFS を入れ、それを直接読み出せるブートローダ GRUB を入れたので、一捻りした設定をしてみました。

# 目標

やりたいこと:

- 安全確実に起動できる時点の環境を残す
- その安全確実環境でブートする選択肢を用意する

# スナップショットのクローン

[Xfce をインストールした際に用意した、インストール直前のスナップショット](https://qiita.com/katz_engineer/items/f42a2536c74b9123bc33#%E3%82%B9%E3%83%8A%E3%83%83%E3%83%97%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88)がまだ残っているので、これを利用します。

このスナップショットを使えるようにします。具体的にはスナップショットからクローンを作成します。

参考文献1: [Documentation Home  > Oracle Solaris ZFS 管理ガイド  > 第 7 章 Oracle Solaris ZFS のスナップショットとクローンの操作  > ZFS スナップショットの概要  > ZFS スナップショットを作成および破棄する: ZFS スナップショットの名前を変更する](https://docs.oracle.com/cd/E19253-01/819-6260/gbcya/index.html#6n89n6cje)
参考文献2: [Documentation Home  > Oracle Solaris ZFS 管理ガイド  > 第 7 章 Oracle Solaris ZFS のスナップショットとクローンの操作  > ZFS クローンの概要  > ZFS クローンを作成する](https://docs.oracle.com/cd/E19253-01/819-6260/gbcyg/index.html)

Xfce が動いているので、ターミナルエミュレータを起動してコマンドラインを使用します。ちなみに一般ユーザでも ```zfs``` コマンドを使用できる模様。

（2019/03/23 修正ここから）

```
$ ls -l /.zfs/snapshot/
合計 0
drwxrwxrwx 1 root root 0  3月 23 21:38 20190317_001325_before_Xfce
drwxrwxrwx 1 root root 0  3月 23 21:38 20190317_193558_before_nkf
$ zfs list -t snapshot -o name -S name
tank/main@20190317_193558_before_nkf
tank/main@20190317_001325_before_Xfce
```
（2019/03/23 修正ここまで）

このスナップショットからクローンを作成します。```zfs clone``` は一般ユーザでは実行できないようなので、 root ユーザになって実行。

（2019/03/23 修正ここから）

```
$ zfs list -t snapshot -o name -S name | tail -n1 | xargs -t -I{} zfs clone {} tank/oldversion
zfs clone tank/main@20190317_001325_before_Xfce tank/oldversion
cannot create 'tank/oldversion': permission denied
$ su
パスワード:
# zfs list -t snapshot -o name -S name | tail -n1 | xargs -t -I{} zfs clone -o mountpoint=/ {} tank/oldversion
zfs clone -o mountpoint=/ tank/main@20190317_001325_before_Xfce tank/oldversion
cannot mount '/': directory is not empty
filesystem successfully created, but not mounted
# zfs list
NAME              USED  AVAIL  REFER  MOUNTPOINT
tank             4.36G   140G    24K  /tank
tank/main        4.35G   140G  4.31G  /
tank/oldversion     1K   140G  1.91G  /
```
（2019/03/23 修正ここまで）

# GRUB メニュー

[GRUB は外付けのUSBメモリにインストールしました](https://qiita.com/katz_engineer/items/9d177766baf95c1e2674#%E3%83%96%E3%83%BC%E3%83%88%E3%83%AD%E3%83%BC%E3%83%80%E3%83%BC)。その設定ファイルなどもUSBメモリに入っていますので、アクセスできるようにマウントします。

```
# mount /dev/sdb1 /mnt/usb
# cd /mnt/usb/boot/grub/
```

設定 grub.cfg に新しいメニュー項目を追加します。

（2019/03/23 修正ここから）

```
# mv -v grub.cfg grub.org 
renamed 'grub.cfg' -> 'grub.org'
# cp -v grub.org grub.cfg
'grub.org' -> 'grub.cfg'
# vi grub.cfg
〈編集内容省略〉
# diff -U0 grub.org grub.cfg
--- grub.org	2019-03-23 22:00:24.000000000 +0900
+++ grub.cfg	2019-03-23 22:01:08.000000000 +0900
@@ -115,0 +116,11 @@
+menuentry 'Arch Linux: old version' --class arch --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-simple-/dev/sda' {
+	load_video
+	set gfxpayload=keep
+	search --set --label tank
+	insmod zfs
+
+	echo	'Loading Linux linux ...'
+	linux	/oldversion@/boot/vmlinuz-linux zfs=tank/oldversion rw
+	echo	'Loading initial ramdisk ...'
+	initrd	/oldversion@/boot/intel-ucode.img /oldversion@/boot/initramfs-linux.img
+}
# rm -v grub.org 
'grub.org' を削除しました
```
（2019/03/23 修正ここまで）

ここで再起動すると、GRUB のメニューに ```Arch Linux: old version``` が追加されています。
これを選択すると、 Xfce のウィンドウ画面ではなくて無骨なコンソール画面になります。

```

Arch Linux 4.20.7-arch1-1-ARCH (tty1)

〈マシン名〉 login: root
Password: 〈rootユーザのパスワードを入力〉
Last login: Sat Feb  9 19:53:34 on tty1
# mount | grep zfs
tank/oldversion on / type zfs (rw,relatime,xattr,noacl)
```

確かに古いバージョンで起動したようです。
やったね:thumbsup_tone1: