Slack/mem-slack

メモリ領域でSlackwareを動かす

はじめに

 使い慣れたPC環境をどこでも使えるようにしたい.ノートPCを持ち歩けば良いが,軽量ノートでも1kg近くはあり鞄が重くなってしまう. PC利用する場所としてはオフィスやネカフェ,旅先のホテル,帰省先などあるが,何かしらPC端末があるのでこれを利用できるようにしたい.

他人のPCであり勝手にOSやアプリをインストールできないので,PCメモリ領域をストレージ空間にして、 そこへ予め用意した自環境(OS,アプリ)を起動時に展開する.起動DiskはUSBメモリを利用.

基本設計と事前準備

バージョン

  • slackware64-15.0

起動

  • UEFI起動で作成するが,古いPC(MBR)でも利用したいので,syslinuxの併用を試してみる
  • ルート領域はアーカイブ化しておき,initrdスクリプトでメモリへ展開する

ストレージ効率化

ストレージ領域を圧迫するkernelモジュール,firmwareはブートDiskに所持し,必要時にマウントして使う

 /
 |-EFI
    |-BOOT
    |  |-bootx64.efi
    |  |-elilo.conf
    |  |-syslinux.cfg
    |
    |-slack15
       |-vmlinuz
       |-initrd.gz
       |-root.tgz          # root領域アーカイブ
       |-firmware.sfs      # firmwareアーカイブ
       |-mod-kernel.sfs    # kernelモジュールアーカイブ

USBメモリの準備

  • EFI領域(vfat)だけ作成する.10G程度.
  • UUIDも確認しておく.⇒「89AB-CDEF」
# fdisk -l /dev/sda
....
Disklabel type: gpt                                   # GPTテーブルで作成
....
Device     Boot Start  End      Sectors   Size Type
/dev/sda1       2048   20973568 20971520  10G  EFI System

# ls -l /dev/disk/by-uuid | grep sda1
lrwxrwxrwx 1 root root 10 Oct  8 20:01 89AB-CDEF -> ../../sda1

# mkfs.vfat -F32 /dev/sda1
# mount UUID=89AB-CDEF /usb/
# mkdir /usb/EFI /usb/EFI/BOOT /usb/EFI/slack15
# cp /boot/vmlinuz-huge-5.15.19 /usb/EFI/slack15/vmlinuz  # 作業マシンのイメージを利用

アーカイブの作成

超基本部分だけで作成してみる

[a]パッケージ

$ grep ":ADD" ISO:/slackware64/a/tagfile | sed 's/:ADD/-*.t?z/g' > a
  • 内容:あまり使わないパッケージもありそう
$ grep ":ADD" ISO:/slackware64/a/tagfile | sed 's/:ADD/ /g' | tr -d '\n' | fmt -w 140
aaa_base aaa_glibc-solibs aaa_libraries acl attr bash bin bzip2 coreutils cpio cracklib dcron devs e2fsprogs elvis etc eudev exfatprogs
findutils floppy gawk glibc-zoneinfo gptfdisk grep gzip hdparm hostname hwdata infozip kernel-firmware kernel-huge kernel-modules
kmod less libgudev libpwquality lilo logrotate lzip mlocate nvi openssl-solibs pam pkgtools procps-ng reiserfsprogs sdparm sed shadow
sharutils smartmontools sysklogd syslinux sysvinit sysvinit-scripts tar usb_modeswitch usbutils util-linux xz
  • kernelは作業マシンのイメージを使うので不要
$ vi a
kernel-huge-*.t?z          # <- 行を削除

[l]パッケージ

  • [a]パッケージのみだとライブラリがないと怒られるので,必要最小限のライブラリパッケージを追加
  • ちなみに起動はするが,ncursesのライブラリが無いとログインできない(実はライブラリはあるがリンクがないだけ)
$ cat > l
ncurses-*.t?z
pcre-*.t?z
gmp-*.t?z
zstd-*.t?z
zlib-*.t?z

インストール(パッケージ展開)

  • 作成したパッケージリストに基づいてインストールを実行
# mkdir root
# for d in a ap l
do cat "${d}" | \
   while read f
   do /sbin/installpkg --terse --root root /mnt/cdrom/slackware64/${d}/"${f}"
   done
done
  • 不要(きっと使わない)ファイルを削除
# rm -rf root/usr/{doc,info,include,man}
# cd root/usr/share/zoneinfo; ls --ignore Asia | xarg rm -r
# cd root/usr/share/zoneinfo/Asia; ls --ignore Tokyo | xarg rm -r
# cd root/usr/share/locale; ls --ignore "ja" --ignore "en*" | xarg rm -r
  • 必要な設定を行う
# vi root/etc/fstab
# vi root/etc/HOSTNAME        <-Host名
# vi root/etc/hosts           <-Host名
# vi root/etc/passwd          <-ユーザアカウント追加
# vi root/etc/group           <-グループ追加
# ln -s /usr/share/zoneinfo/Asia/Tokyo root/etc/localtime <-TimeZone設定
...

インストール(アーカイブ配置)

  • kernelモジュール(mod-kernel.sfs)のアーカイブ作成
# cd root/lib/modules/5.15.19/
# mksquashfs kernel /usb/EFI/slack15/mod-kernel.sfs
# rm -f kernel/*
  • firmwareのアーカイブ作成
# cd root/lib
# mksquashfs firmware /usb/EFI/slack15/firmware.sfs
# rm -f firmware/*
  • root領域のアーカイブ作成
# cd root
# tar cvfz /usb/EFI/slack15/root.tgz *

OS起動ロジックの作成

initrdの作成

雛形の作成.USBホストドライバは使いそうなものを選定

# mkinitrd -s ./tree -o /usb/EFI/slack15/initrd.gz
           -m loop                                               # fileマウント用のモジュール (sfsファイル)
             :usb-storage:uas                                    # USBストレージドライバ
             :xhci-hcd:xhci-pci:xhci-plat-hcd:xhci-pci-renesas   # USB3.0ホストドライバ
             :ohci-hcd:ohci-pci:ohci-platform                    # USB1.0/1.xホストドライバ
             :uhci-hcd                                           # USB1.xホストドライバ
             :ehci-hcd:ehci-pci:ehci-platform                    # USB2.0ホストドライバ

スクリプトの編集

rootデバイスをマウントするあたり(322行あたり)を改造

# vi ./tree/init
  # Switch to real root partition:
  /sbin/udevadm settle --timeout=10
  echo 0x0100 > /proc/sys/kernel/real-root-dev
#### begin ###############################################################################
#  mount -o ro${ROOTFLAGS:+,$ROOTFLAGS} -t $ROOTFS $ROOTDEV /mnt  # コメントアウト
mkdir /boot
mount -o ro -t $ROOTFS $ROOTDEV /boot                             # USBメモリをマウント
mount -t tmpfs tmpfs /mnt                                         # メモリ空間にroot領域を作成
PKGROOT=/boot/EFI/slack15
tar xfz $PKGROOT/root.tgz -C /mnt                             # rootイメージを展開

# link oneoff directories
mkdir /kernel
mount -o ro,loop $PKGROOT/mod-kernel.sfs /kernel             # kernelモジュールをマウント
mkdir /firmware
mount -o ro,loop $PKGROOT/firmware.sfs /firmware             # firmwareをマウント
mount -o move /boot /mnt/boot                                     # USBメモリを/bootとしてリマウント
mount -o move /kernel /mnt/lib/modules/$(unamr -r)/kernel
mount -o move /firmware /mnt/lib/firmware

# add chip to fstab
cat <<EOF >> /mnt/etc/fstab                                       # USBメモリのマウントポイントをfstabへ追記しておく
# USB Chip
$ROOTDEV                     /boot                           vfat     noauto,user,rw 0 0
$PKGROOT/mod-kernel.sfs /lib/modules/$(uname -r)/kernel squashfs noauto,user,ro 0 0
$PKGROOT/firmware.sfs   /lib/firmware                   squashfs noauto,user,ro 0 0
EOF

mount -n -o remount,ro /mnt
############################################################################################

  if [ ! -r /mnt/sbin/init ]; then
    echo "ERROR: No /sbin/init found on rootdev (or not mounted).  Trouble ahead."

initrdの再作成

# mkinitrd -s ./tree -o /usb/EFI/slack15/initrd.gz      # モジュールは省略可(tree内にある) 
           -f vfat                                      # 上記スクリプトの${ROOTFS}
           -w 5                                         # USBデバイスの認識待ち時間(s).適当.

ブート設定

  • UEFI起動の設定
# cp /boot/elilo-x86_64.efi       /usb/EFI/BOOT/bootx64.efi      # 名前の変更が必要?
# vi /usb/EFI/BOOT/elilo.conf
image=/EFI/slack15/vmlinuz
        label=slackware
        initrd=/EFI/slack15/initrd.gz
        root=UUID=89AB-CDEF                             # USBデバイスのUUIDを設定
        read-only
  • MBR起動の設定
# /sbin/sgdisk -A 1:set:2 /dev/sda                      # /dev/sda1 の属性を(legacy BIOS bootable)に設定
# dd if=/usr/share/syslinux/gptmbr.bin of=/dev/sda      # GPTテーブル用のMBRを転記
# syslinux -i /dev/sda1 -d /EFI/BOOT                    # syslinuxをインストール

起動

  • いろいろ怒られる(kernelモジュールが無いとか)けど一応起動
  • メモリ消費は170M程度,USBメモリは500M程度
Welcome to Linux 5.15.19 x86_64 (tty1)

mem-slack15 login: root
Linux 5.15.19.
root@mem-slack15:~# df -h
Filesystem      Size  Used Avail Use% Mounted on
tmpfs            32M  132K   32M   1% /run
devtmpfs        8.0M     0  8.0M   0% /dev
/dev/sda1       498M  457M   42M  92% /boot
tmpfs           985M  170M  815M  18% /
/dev/loop0       55M   55M     0 100% /lib/modules/5.15.19/kernel
/dev/loop1      327M  327M     0 100% /lib/firmware
tmpfs           985M     0  985M   0% /dev/shm
cgroup_root     8.0M     0  8.0M   0% /sys/fs/cgroup

おまけ

  • 新デバイス認識が必要ない場合はメモリのみで利用可能
  • 起動後に一定時間でUSBマウントを外すのもあり
# vi /etc/rc.d/rc.local
boot_umount () {
  umount /lib/modules/5.15.19/kernel
  umount /lib/firmware
  umount /boot
}

sleep 60 && boot_umount &

追加パッケージ

後で必要になったパッケージを動的に追加できるようにしてみる

作成方法と置き場所

tmuxとdiffを任意ディレクトリへインストールしてsquashfs圧縮する

# mkdir app
# /sbin/installpkg --terse --root app /mnt/cdrom/slackware64/ap/diffutils-3.8-x86_64-1.txz
# /sbin/installpkg --terse --root app /mnt/cdrom/slackware64/ap/tmux-3.2a-x86_64-1.txz
# cd app
# rm -rf usr/{doc,info,include,man}                 # 不要なファイルを削除(メモリ節約するため)
# mksquashfs ../app.sfs *                           # パッケージファイル(app.sfs)完成

置き場所はusbメモリのslack15/sfsとする

 /
 |-EFI
    |-slack15
       |-sfs
          |-app.sfs        # 追加アプリパッケージ
          |-etc.sfs        # etc追加設定を集めたパッケージとかもいける

パッケージ利用選択

kernelへの追加パラメータで選ぶようにしてみる

# vi EFI/BOOT/elilo.conf
prompt
timeout=50
image=/EFI/slack15/vmlinuz
        label=slackware
        initrd=/EFI/slack15/initrd.gz
        root=UUID=89AB-CDEF
        read-only
image=/EFI/slack15/vmlinuz
        label=slackware+app
        initrd=/EFI/slack15/initrd.gz
        root=UUID=89AB-CDEF
        apped=sfs=app.sfs,etc.sfs                # 追加パッケージを指定
        read-only

パッケージの適用

initrdの中でパッケージの展開と適用を行う まずはcommand lineからsfs値を取得

# vi tree/init
    waitforroot=*|rootdelay=*)
      WAIT=$(echo $ARG | cut -f2 -d=)
    ;;
    ###追加部分###############################
    sfs=*)
      SFS=$(echo $ARG | cut -f2 -d=)
    ;;
    ##########################################
  esac

次にsfsファイルを展開し,root領域へ適用

# vi tree/init
mount -t tmpfs tmpfs /mnt 
tar xfz $PKGROOT/root.tgz -C /mnt

##パッケージ展開&適用########################
mkdir /sfs
for s in ${SFS//,/}
do
   f=$PKGROOT/sfs/${s}
   if [ -e "${f}" ]; then
      echo "expand: ${f}"
      mount -o ro,loop "${f}" /sfs              #↓OS領域のrsyncコマンドとライブラリを使う
      LD_LIBRARY_PATH=/mnt/lib64:/mnt/usr/lib64 /mnt/usr/bin/rsync -avH /sfs/* /mnt/ > /dev/null 2>&1
      umount /sfs
   fi
done
###############################################

# link oneoff directories
mkdir /kernel



---
update at 2024/12/02 10:09:14

※注:当サイトは特定環境において確認できた事象のみを記述しています。他の環境での動作は一切保証しません。