Slackware 14.2 の LVM への OS インストール例


当方執筆の技術情報に関するライセンス、免責事項、禁止事項



執筆動機

lvm に関連する一連のコマンドラインツール群、及び eliloconfig を活用することで、そこそこシンプルに LVM 領域への Slackware のインストールが可能でした。

※ なお、ESP( EFI システムパーティション)は LVM の中には置けないようです。おのれディケイドぉぉぉぉぉ!!


参考文献:

参考文献:

https://www.slackwiki.com/LVM/Luks_Encryption

https://wa3.i-3-i.info/word25557.html

https://wa3.i-3-i.info/word12796.html

https://www.debian.org/releases/stable/i386/apcs04.ja.html

https://wiki.archlinux.jp/index.php/LVM

https://wiki.gentoo.org/wiki/LVM/ja

https://ansaikuropedia.org/wiki/Uncyclopedia:%E9%A6%AC%E9%B9%BF%E3%81%AB%E3%81%AA%E3%82%89%E3%81%9A%E3%81%AB%E3%83%90%E3%82%AB%E3%83%90%E3%82%AB%E3%81%97%E3%81%8F%E3%82%84%E3%82%8B%E6%96%B9%E6%B3%95

https://www.linuxquestions.org/questions/slackware-14/slackware-current-elilo-lvm-4175534140/

http://www.slackware.com/~alien/archive/13.1/README_LVM.TXT

https://docs.slackware.com/howtos:slackware_admin:set_up_syslinux_as_boot_loader_on_uefi_based_hardware

http://docs.slackware.com/howtos:slackware_admin:set_up_grub_as_boot_loader_on_uefi_based_hardware

https://docs.slackware.com/howtos:slackware_admin:installing_on_uefi_hardware

https://www.reddit.com/r/slackware/comments/4ydl83/slackware_and_uefi_help/

https://blog.paranoidpenguin.net/2016/07/configuring-elilo-with-a-generic-kernel-on-slackware-14-2/

https://www.linuxquestions.org/questions/slackware-14/slackpkg-lilo-elilo-initrd-4175628620/

https://www.ibm.com/developerworks/jp/linux/library/l-initrd/index.html

https://tech.nikkeibp.co.jp/it/article/COLUMN/20061025/251702/

https://linux.die.net/man/8/mkinitrd

https://duckduckgo.com/?q=lvm+can't+deactivate

https://duckduckgo.com/?q=LVM+アンマウント

https://rin-ka.net/centos7-lvm/

https://www.youtube.com/watch?v=njxzwMGTWWs

https://wiki.gentoo.org/wiki/Chroot/ja

https://wiki.archlinux.jp/index.php/Chroot

http://toaruhenjin.com/digimono-review/hotswap

https://www.linuxquestions.org/linux/answers/Hardware/Mini_HOW_TO_Hibernate_and_resume_0

https://wiki.gentoo.org/wiki/Suspend_and_hibernate

https://takuya-1st.hatenablog.jp/entry/2016/12/16/183718

https://duckduckgo.com/?q=スーパー牛さんパワー

https://qiita.com/kon_yu/items/b8864ff566b8b67a9810

https://qiita.com/mkamotsu/items/0135d2e756db4a18d965

https://qiita.com/g_maeda/items/3602dc2f7af3f711f9c4

https://qiita.com/takaki@github/items/5d96d80dc78b09ea600b



デスクトップ用途での LVM の利点として思いつくこと

色々インストールしたりダウンロードしたりコンパイルしたり好き放題していたらいつの間にか容量が足りない!という場合に少ない手間で容量を継ぎ足せます


基本工程

OS インストール環境の立ち上げ

GPT でフォーマット

LVM パーティションの作成

・LVM 論理ボリュームの作成

通常の OS インストール手順

ブートローダーの LVM 対応

再起動


インストール時に HDD/SSD/swap を暗号化したい場合

LVM/Luks Encryption - SlackWiki

https://www.slackwiki.com/LVM/Luks_Encryption

↑こちらをご覧下さい。

※ EFI システムパーティションをこの方法で暗号化するのは無理っぽいです。改竄防止などは BIOS/UEFI 側の機能で行えるのかな?

※ Fat32 の EFI システムパーティションってセキュリティ的にはどうなんだろ?意外と強いのか?


各工程の詳細


OS インストール環境の立ち上げ


インストールメディアの用意

!!!CAUTION!!!イメージを書き込むドライブを間違えないこと!

dd で空の USB メモリに インストール DVD の iso を流し込むのが楽です。

インストールイメージ入手先

http://www.slackware.com/getslack/


インストールメディアからブート

UEFI ブート。その際、インストール対象 HDD/SSD は IDE 互換モードではなく AHCI モードにしておく1


GPT でフォーマット

!!!CAUTION!!!フォーマットするドライブを間違えないこと!

# fdisk -l

# sgdisk -o /dev/moo

※ /dev/moo は環境に応じて適宜読み替えて下さい。

参考文献:


LVM パーティションの作成

# sgdisk -p /dev/moo

# sgdisk -n 1:2048:1050623 -c 1:"ESP" -t 1:ef00 /dev/moo
# sgdisk -n 2:1050624:3147775 -c 2:"swap" -t 2:8200 /dev/moo
# sgdisk -n 3:3147776:$(sgdisk -E /dev/sda) -c 3:"LVM00" -t 3:8e00 /dev/moo
# sgdisk -p /dev/moo

※ /dev/moo は環境に応じて適宜読み替えて下さい。

※ EFIシステムパーティション(ESP)は LVM の外に。

※ Swap パーティションは LVM の中でも外でも( 中に置くと swsusp させる場合 mkinitrd で一工夫必要 swsusp させる場合は mkinitrd で -h オプションを使うのが無難)。

※ 各パーティションに割り当てる容量はシステム環境や管理方針によります。

※ 2048 セクタ:1 MiB(1 セクタ 512 バイトの場合)

※ 1024 MiB = 1 GiB

※ 1024 GiB = 1 TiB

※ メモ書きからのコピペやシェルスクリプトに記述する用途では sgdisk 。通常使うなら対話的な gdisk や cgdisk が使いやすいかと。

参考文献:

Man page of SGDISK

http://www.rodsbooks.com/gdisk/sgdisk.html

An sgdisk Walkthrough

http://www.rodsbooks.com/gdisk/sgdisk-walkthrough.html

sgdisk(gdisk コマンドライン版) でまとめて変更する使い方 - それマグで!

https://takuya-1st.hatenablog.jp/entry/2016/12/16/183718

bash Tips - コマンド置換と算術式展開、パラメータ展開 - Qiita

https://qiita.com/mashumashu/items/bbc3a79bc779fe8c4f99

Man page of BASH

https://linuxjm.osdn.jp/html/GNU_bash/man1/bash.1.html

メビバイト - Wikipedia



LVM 論理ボリュームの作成

# pvcreate /dev/moo3

# vgcreate SlackVG /dev/moo3
# lvcreate -l 100%FREE SlackVG -n root

※ /dev/moo3 SlackVG root は環境や用途、sgdisk の実行状況等に応じて適宜読み替えて下さい。

※ pv=PhysicalVolume vg=VolumeGroup lv=LogicalVolume 略語のもとになった言葉。

参考文献:

pvcreate(8) - Linux man page

https://linux.die.net/man/8/pvcreate

vgcreate(8) - Linux man page

https://linux.die.net/man/8/vgcreate

lvcreate(8) - Linux man page

https://linux.die.net/man/8/lvcreate

LVM/Luks Encryption - SlackWiki

https://www.slackwiki.com/LVM/Luks_Encryption

LVM - ArchWiki

https://wiki.archlinux.jp/index.php/LVM



通常の OS インストール手順

# setup

※ 完了時にうっかり再起動をかけないこと。

VirtualBox_Slackware_14.2_113.png

参考文献:

http://www.slackware.com/install/setup.php


OS インストール環境におけるブートローダーの LVM 対応

VirtualBox_Slackware64_10_07_2019_16_42_24.png

# chroot /mnt

# $(/usr/share/mkinitrd/mkinitrd_command_generator.sh -r)
# exit
# eliloconfig /mnt /dev/SlackVG/root

※ mkinitrd_command_generator.sh は mkinitrd に対する適切な引数を自動生成するコマンドです。詳細は /usr/share/mkinitrd/mkinitrd_command_generator.sh --longhelp で確認。

※ eliloconfig は引数1で OS ルートを、引数2でルートに対応するデバイスを指定出来るようです。

※ /dev/SlackVG/root は作成した論理ボリュームに応じて適宜読み替えて下さい。

※ 再起動後、インストール済みの Slackware からは eliloconfig に引数を与えなくとも正しく /boot/efi/EFI/Slackware/elilo.conf を生成出来ました。

※ カーネルのアップグレードを行った場合は忘れずに $(/usr/share/mkinitrd/mkinitrd_command_generator.sh -r) 及び eliloconfig を実行すること。インストール済みの Slackware で行う場合 chroot の必要はありません。

参考文献:

bash Tips - コマンド置換と算術式展開、パラメータ展開 - Qiita

https://qiita.com/mashumashu/items/bbc3a79bc779fe8c4f99

Man page of BASH

https://linuxjm.osdn.jp/html/GNU_bash/man1/bash.1.html

GNU Coreutils: 23.1 chroot: ルートディレクトリを変更して、コマンドを実行する

https://linuxjm.osdn.jp/info/GNU_coreutils/coreutils-ja_169.html#chroot-invocation

Chroot - Gentoo Wiki

https://wiki.gentoo.org/wiki/Chroot/ja

chroot - ArchWiki

https://wiki.archlinux.jp/index.php/Chroot

LVM/Luks Encryption - SlackWiki

https://www.slackwiki.com/LVM/Luks_Encryption

[SOLVED] Slackware-current elilo lvm

https://www.linuxquestions.org/questions/slackware-14/slackware-current-elilo-lvm-4175534140/

eliloconfig 本体


/usr/sbin/eliloconfig

#!/bin/sh

# Copyright 2013, 2016, 2017 Patrick Volkerding, Sebeka, Minnesota, USA
# All rights reserved.
#
# Redistribution and use of this script, with or without modification, is
# permitted provided that the following conditions are met:
#
# 1. Redistributions of this script must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
# EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#

# This script installs the elilo boot loader, the kernel, and optionally
# an initrd into the EFI System Partition. A boot menu entry can also be
# installed using efibootmgr. The kernel used will be whatever the symlink
# /boot/vmlinuz points to, and if /boot/initrd.gz exists, that will be
# installed as the initrd.
#
# The EFI System Partition is expected to be mounted on /boot/efi before
# running this script.

TMP=/var/log/setup/tmp

# Set the OS root directory (called T_PX for some unknown reason).
# If an argument is given to this script and it is a directory, it
# is taken to be the root directory. First though, we check for a
# directory named $T_PX, and that gets the first priority.
if [ ! -d "$T_PX" ]; then
if
[ ! "$1" = "" ]; then
if
[ -d "$1" ]; then
T_PX="$1"
fi
else

# Are we on the installer image?
if [ -r /usr/lib/setup/SeTpartitions ]; then
T_PX=/mnt
# Or, are we on a running system?
elif [ -r /etc/slackware-version ]; then
T_PX=/
# One more installer-likely thing:
elif [ -r /usr/lib/setup/setup ]; then
T_PX=/mnt
else
# We will have to assume we're on an installed and running system.
T_PX=/
fi
fi
fi

# Determine the root partition (such as /dev/sda1)
ROOT_DEVICE=$2
if [ "$ROOT_DEVICE" = "" ]; then
if
[ -r $TMP/SeTrootdev ]; then
ROOT_DEVICE="$(cat $TMP/SeTrootdev)"
else
ROOT_DEVICE="$(mount | cut -f 1 -d ' ' | head -n 1)"
fi
fi

# If the system is not running under EFI, skip running this script:
if [ ! -d /sys/firmware/efi ]; then
if
[ "$T_PX" = "/" ]; then
echo "ERROR: System is not running under UEFI."
fi
exit
fi

# If there's no vfat mounted on /boot/efi or $T_PX/boot/efi, forget it:
if ! mount | grep vfat | grep -wq /boot/efi ; then
if
! mount | grep vfat | grep -wq $T_PX/boot/efi ; then
if
[ "$T_PX" = "/" ]; then
echo "ERROR: No EFI System Partition mounted on /boot/efi."
fi
exit
fi
fi

# Figure out the device and partition number of the ESP:
DEVLEN=8
PARTLEN=9
if mount | grep vfat | grep -wq /boot/efi ; then
mount | grep vfat | grep -w /boot/efi | grep -q -e nvme -e mmcblk && DEVLEN=12 && PARTLEN=14
EFI_DEVICE=$(mount | grep vfat | grep -w /boot/efi | cut -b 1-${DEVLEN})
EFI_PARTITION=$(mount | grep vfat | grep -w /boot/efi | cut -f 1 -d ' ' | cut -b ${PARTLEN}- | tr -d [a-z])
else
mount | grep vfat | grep -w $T_PX/boot/efi | grep -q -e nvme -e mmcblk && DEVLEN=12 && PARTLEN=14
EFI_DEVICE=$(mount | grep vfat | grep -w $T_PX/boot/efi | cut -b 1-${DEVLEN})
EFI_PARTITION=$(mount | grep vfat | grep -w $T_PX/boot/efi | cut -f 1 -d ' ' | cut -b ${PARTLEN}- | tr -d [a-z])
fi

# There better be a kernel:
if [ ! -r $T_PX/boot/vmlinuz ]; then
if
[ "$T_PX" = "/" ]; then
echo "ERROR: No kernel found at /boot/vmlinuz."
fi
exit
fi

dialog --title "INSTALL ELILO" \
--backtitle "ELILO (EFI Linux Loader) installation" \
--menu "ELILO is a Linux boot loader for \
EFI based systems. Installing ELILO will allow you to boot your Linux
\
system from the hard drive after selecting it from the UEFI boot menu.
\
Since an EFI System Partition was detected on this machine, it is
\
recommended that you install ELILO now. Please select an option:"
\
13 70 2 \
"install" "Install ELILO on the EFI System Partition" \
"skip" "Do not install ELILO" 2> $TMP/reply
if [ $? = 1 -o $? = 255 ]; then
exit
fi
REPLY="`cat $TMP/reply`"
rm -f $TMP/reply
if [ "$REPLY" = "skip" ]; then
exit
fi

mkdir -p $T_PX/boot/efi/EFI/Slackware 1> /dev/null 2> /dev/null
cat << EOF > $T_PX/boot/efi/EFI/Slackware/elilo.conf
chooser=simple
delay=1
timeout=1
#
EOF
cp -a $T_PX/boot/elilo-x86_64.efi $T_PX/boot/efi/EFI/Slackware/elilo.efi 1> /dev/null 2> /dev/null
cp $T_PX/boot/vmlinuz $T_PX/boot/efi/EFI/Slackware 1> /dev/null 2> /dev/null
cat << EOF >> $T_PX/boot/efi/EFI/Slackware/elilo.conf
image=vmlinuz
label=vmlinuz
EOF
touch -r $T_PX/boot/vmlinuz $T_PX/boot/efi/EFI/Slackware/vmlinuz
if [ -r $T_PX/boot/initrd.gz ]; then
cp $T_PX/boot/initrd.gz $T_PX/boot/efi/EFI/Slackware 1> /dev/null 2> /dev/null
touch -r $T_PX/boot/initrd.gz $T_PX/boot/efi/EFI/Slackware/initrd.gz
cat << EOF >> $T_PX/boot/efi/EFI/Slackware/elilo.conf
initrd=initrd.gz
EOF
fi
cat << EOF >> $T_PX/boot/efi/EFI/Slackware/elilo.conf
read-only
append="root=
$ROOT_DEVICE vga=normal ro"
EOF

dialog --title "INSTALL BOOT MENU ENTRY?" \
--backtitle "ELILO (EFI Linux Loader) installation" \
--menu "Would you like to install \
a boot menu entry so that you can easily select Slackware when you boot your
\
machine? WARNING: DO NOT install a boot menu entry on Apple hardware.
\
Apple computers use a different type of EFI firmware, and efibootmgr has
\
been known to damage them. On all other computers, it is recommended to add
\
a boot menu entry. Please select an option:"
\
14 70 2 \
"install" "Install a boot menu entry" \
"skip" "Do not install a boot menu entry" 2> $TMP/reply
if [ $? = 1 -o $? = 255 ]; then
exit
fi
REPLY="`cat $TMP/reply`"
rm -f $TMP/reply
if [ "$REPLY" = "skip" ]; then
exit
fi

if [ ! -d /sys/firmware/efi/vars ]; then
modprobe efivars 1> /dev/null 2> /dev/null
sleep 1 # Probably not needed, but playing it safe
fi
# If it's still gone, we fail silently:
if [ ! -d /sys/firmware/efi/vars ]; then
exit
fi

efibootmgr -v | rev | cut -f 2- | rev | grep Boot0 | grep Slackware | while read line ; do
# Reject entries that don't exactly match as not our business
if [ ! "$(echo $line | cut -f 2- -d ' ')" = "Slackware" ]; then
continue
fi
ENTRY="$(efibootmgr -v | grep "^$(echo $line | cut -b1-8)")"
dialog --title "REMOVE OLD \"Slackware\" EFI BOOT ENTRY?" \
--backtitle "ELILO (EFI Linux Loader) installation" \
--yesno "An old Slackware boot entry has been found in your EFI boot menu. \
Would you like to remove this before installing the new Slackware boot
\
entry? This is recommended.
\n\nOld EFI boot menu entry:\n$ENTRY" 13 70
if [ ! $? = 0 ]; then
continue
fi

# Remove the boot entry:
efibootmgr -q -B -b $(echo $line | cut -b5-8)
done

efibootmgr -q -c -d $EFI_DEVICE -p $EFI_PARTITION -l "\\EFI\\Slackware\\elilo.efi" -L "Slackware"

efibootmgr -v | rev | cut -f 2- | rev | grep Boot0 | grep Slackware | while read line ; do
# Reject entries that don't exactly match as not our business
if [ ! "$(echo $line | cut -f 2- -d ' ')" = "Slackware" ]; then
continue
fi
ENTRY="$(efibootmgr -v | grep "^$(echo $line | cut -b1-8)")"
if echo $ENTRY | grep -q -F "\EFI\Slackware\elilo.efi" ; then
dialog --title "EFI BOOT ENTRY INSTALLED" \
--backtitle "ELILO (EFI Linux Loader) installation" \
--msgbox "A Slackware boot entry has been installed to your EFI boot
menu.
\n\nEFI boot menu entry:\n$ENTRY" 11 70
fi
done

# Done.



mkinitrd_command_generator.sh 本体


/usr/share/mkinitrd/mkinitrd_command_generator.sh

#!/bin/sh

# $Id: mkinitrd_command_generator.sh,v 1.45 2011/02/17 09:27:05 eha Exp eha $
# Copyright 2013 Patrick J. Volkerding, Sebeka, Minnesota, USA
# Copyright 2008, 2009, 2010, 2011 Eric Hameleers, Eindhoven, Netherlands
#
# Copyright 2008, 2009 PiterPUNK, Sao Paulo, SP, Brazil
#
# All rights reserved.
#
# Permission to use, copy, modify, and distribute this software for
# any purpose with or without fee is hereby granted, provided that
# the above copyright notice and this permission notice appear in all
# copies.
#
# THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
# -----------------------------------------------------------------------------
#
# Create an initrd which fits the system.
# Take into account the use of LVM/LUKS/RAID.
# Find out about any hardware drivers the system may need in an initrd when
# booting from a generic lightweight kernel.
#
# -----------------------------------------------------------------------------

# The script's revision number will be displayed in the help text:
REV=$( echo "$Revision: 1.45 $" | cut -d' ' -f2 )

# Define some essential parameter values:
USING_LVM=""
USING_LUKS=""
USING_RAID=""
MLIST=""
REALDEV="" # The device that contains the LUKS volume
BASEDEV="" # Lowest level device (raw block device or RAID volume)

FSTAB=${FSTAB:-"/etc/fstab"} # so we can test with alternate fstab files

# These are needed by -c and -i options:
SOURCE_TREE=${SOURCE_TREE:-"/boot/initrd-tree"}
CLEAR_TREE=${CLEAR_TREE:-1}
KEYMAP=${KEYMAP:-"us"}
UDEV=${UDEV:-1}
# ARM devices need more time:
case "$( uname -m )" in
arm*) WAIT_DEFAULT=4;;
*) WAIT_DEFAULT=1;;
esac
WAIT=${WAIT:-$WAIT_DEFAULT}

# A basic explanation of the commandline parameters:
basic_usage() {
cat <<-EOT

*** $(basename $0) revision $REV ***
Usage:
$(basename $0) [ options ] [ kernel_filename ]
Options:
-a <"additional params"> Additional parameters to pass to mkinitrd.
-c | --conf Show a suitable mkinitrd configuration file.
-h | --help Show this help.
-i | --interactive Navigate through menus instead of using
commandline arguments.
--longhelp Show more detailed information/examples.
-k <kernelversion> Use specific kernel version.
-m <"additional mods"> Additional modules to pass to mkinitrd,
separated by colons (:).
-l | --lilo Only show lilo.conf section
(requires a kernel_filename).
-r | --run Only show 'mkinitrd' command.
EOT
}

# More of a tutorial here:
extended_usage() {
cat <<-EOT

This script is useful in situations where you require an initrd image
to boot your computer.
For instance, when booting a kernel that does not have support for your
storage or root filesystem built in (such as the Slackware 'generic'
kernels').

* When you run the script without parameters, it will examine your
running system, your current kernel version and will output an example
of a 'mkinitrd' commandline that you can use to generate an initrd
image containing enough driver support to boot the computer.

* You can make it more specific: when you add the filename of a kernel
as parameter to the script, it will determine the kernel version from
that kernel, and also give an example of the lines that you should add
to your '/etc/lilo.conf' file.

* If you want your initrd image to have a custom name instead of the
default '/boot/initrd.gz' you can add it as another parameter to the
script, as follows:

$(basename $0) -a "-o /boot/custom.gz"

The arguments to the '-a' parameter will be used as additional arguments
to the 'mkinitrd' command.

* If you need additional modules in the initrd image, apart from what
the script determines, you can pass then to the script using the '-m'
parameter as follows:

$(basename $0) -m "uhci-hcd:usbhid:hid_generic"

The above example adds support for USB keyboards to the initrd - you
may need that if you have encrypted your root partition and need to
enter a passphrase using a USB keyboard.

* Instead of copying and pasting the script's output, you can create
an initrd by directly executing the output, like in this example:

EOT

echo " \$($(basename $0) --run /boot/vmlinuz-generic-smp-2.6.35.11-smp)"

cat <<-EOT

That used the '-r' or '--run' switch to make the script only write
the 'mkinitrd' commandline to the terminal.

* When you want to add a section for a specific kernel to
'/etc/lilo.conf' directly, use the '-l' or '--lilo' switch and use a
command like in this example:

EOT

echo " $(basename $0) --lilo /boot/vmlinuz-generic-smp-2.6.35.11-smp >>/etc/lilo.conf"

cat <<-EOT

That command will result in the following lines being added to your
'/etc/lilo.conf' file (example for my hardware):

# Linux bootable partition config begins
# initrd created with 'mkinitrd -c -k 2.6.35.11-smp -m ata_generic:pata_amd:mbcache:jbd:ext3 -f ext3 -r /dev/hda7'
image = /boot/vmlinuz-generic-smp-2.6.35.11-smp
initrd = /boot/initrd.gz
root = /dev/hda7
label = 2.6.35.11-smp
read-only
# Linux bootable partition config ends

The last two examples show how easy it is to configure your computer
for the use of an initrd if you need one. The only thing left to do
afterwards is running 'lilo'.

EOT
}

# Find the device that holds the root partition:
get_root_device() {
if [ -e $FSTAB ]; then
RD=$(cat $FSTAB |tr '\t' ' ' |grep -v '^ *#' |tr -s ' ' |grep ' / ' |cut -f1 -d' ')
if [ "$(echo $RD | cut -f1 -d=)" = "LABEL" -o "$(echo $RD | cut -f1 -d=)" = "UUID" ]; then
DKEY=$(echo $RD | cut -f1 -d=)
# The value can be LABEL=foo or LABEL='foo' or LABEL="foo"
DVAL=$(echo $RD | cut -f2 -d= | tr -d "'\042")
RD=$(/sbin/blkid | grep -w $DKEY | grep -w $DVAL | cut -f1 -d:)
fi
else
RD=$(grep -m1 "^/dev/.*[[:blank:]]/[[:blank:]]" /proc/mounts | cut -f1 -d' ')
fi
echo $RD
}

# Get the root fs information:
get_rootfs_type() {
if $(type blkid 1>/dev/null 2>&1) ; then
blkid -s TYPE -o value $ROOTDEV
elif $(type vol_id 1>/dev/null 2>&1) ; then
vol_id $ROOTDEV | grep ID_FS_TYPE | cut -f2 -d=
else
# As a fallback, use:
cat $FSTAB |tr '\t' ' ' |grep -v '^ *#' |tr -s ' ' |grep ' / ' |cut -f3 -d' '
fi
}

# Add the module(s) needed for the root filesystem:
add_rootfs_module() {
local FSMOD
FSMOD=$(/sbin/modprobe --set-version $KVER --show-depends ${ROOTFS} 2>/dev/null | while read LINE; do
echo $(basename $(echo $LINE | cut -d' ' -f2) .ko )
done)
if [ -n "$FSMOD" ]; then
[ -n "$MLIST" ] && echo "$MLIST:$(echo $FSMOD | tr ' ' ':')" \
|| echo $FSMOD | tr ' ' ':'
fi
}

# Determine the list of kernel modules needed to support the root device:
determine_blockdev_drivers() {
# Walk the /sys tree to find kernel modules that are
# required for our storage devices.
# Thanks to PiterPUNK for help with this code.
local MLIST
MLIST=$(for i in $(find /sys/block/*/ -name "device" -print0 | xargs -0 -i'{}' readlink -f '{}' | sort -u); do
/sbin/udevadm info --query=all --path=$i --attribute-walk | \
sed -ne 's/^[[:blank:]]\+DRIVER[S]*=="\([^"]\+\)"$/\1/p' | \
xargs -I@ /sbin/modprobe --set-version $KVER --show-depends @ \
2>/dev/null | grep -v "builtin " | \
while read LINE ; do
echo $(basename $(echo $LINE | cut -d' ' -f2) .ko )
done
done)

MLIST=$( echo $MLIST | tr ' ' ':' )
echo $MLIST
}

# Search for USB keyboards:
function add_usb_keyboard() {
local USBMOD
if cat /proc/bus/input/devices | sed -e 's/^$/\$/g' | \
tr "\n$" " \n" | grep -q " Phys=.*usb.* .*Handlers=.*kbd.*B:"; then
USBMOD="xhci-pci:ohci-pci:ehci-pci:xhci-hcd:uhci-hcd:ehci-hcd:hid:usbhid:i2c-hid:hid_generic:hid-cherry:hid-logitech:hid-logitech-dj:hid-logitech-hidpp:hid-lenovo:hid-microsoft:hid_multitouch"
[ -n "$MLIST" ] && MLIST="$MLIST:$USBMOD" \
|| MLIST="$USBMOD"
fi
echo $MLIST
}

# Determine what USB Host Controller is in use
function add_usb_hcd() {
local USBMOD
for i in $(ls -Ld /sys/module/*_hcd/drivers/* 2> /dev/null); do
if
ls -L $i | grep -q "[0-9a-f]*:" ; then
USBMOD=$( echo $i | cut -f4 -d/ | tr "_" "-")
[ -n "$MLIST" ] && MLIST="$MLIST:$USBMOD" \
|| MLIST="$USBMOD"
fi
done
echo $MLIST
}

# Is the root partition on a (combination of) LVM/LUKS volume?
check_luks_lvm_raid() {
if $( lvdisplay -c $ROOTDEV 1>/dev/null 2>/dev/null ); then
# Our root partition is on a LV:
USING_LVM=1
# Search the Physical Volume of our Logical Volume:
MYVG=$( echo $(lvdisplay -c $ROOTDEV 2>/dev/null) | cut -d: -f2 )
for LINE in $(pvdisplay -c) ; do
VG=$(echo $LINE | cut -d: -f2)
[ "$VG" = "$MYVG" ] && break
done
PV=$(echo $LINE | cut -d: -f1)
# Check if there is a LUKS device underneath:
if $( cryptsetup status $PV 1>/dev/null 2>/dev/null ) ; then
# Our root partition's LV is on a LUKS volume:
USING_LUKS=1
REALDEV=$( cryptsetup status $PV | grep 'device: ' | tr -d ' ' | cut -d: -f2 )
BASEDEV=$REALDEV
else
BASEDEV=$PV
fi
elif
$( cryptsetup status $ROOTDEV 1>/dev/null 2>/dev/null ) ; then
# Our root device is on a LUKS volume:
USING_LUKS=1
REALDEV=$( cryptsetup status $ROOTDEV | grep 'device: ' | tr -d ' ' | cut -d: -f2 )
ROOTDEV=$(basename $ROOTDEV)
# Check for LVM:
for LV in $(lvdisplay -c 2>/dev/null | tr -d ' ' | cut -f1 -d:) ; do
# Note: cryptsetup shows the real device, whereas
# lvdisplay requires the /dev/<myvg>/... symlink to the real device.
if [ "$(readlink $LV)" = "$REALDEV" ]; then
REALDEV=$LV
break
fi
done
if
$( lvdisplay -c $REALDEV 1>/dev/null 2>/dev/null ); then
# Our root partition's LUKS device is on a LV:
USING_LVM=1
# Search the Physical Volume of our Logical Volume:
MYVG=$( echo $(lvdisplay -c $REALDEV 2>/dev/null) | cut -d: -f2 )
for LINE in $(pvdisplay -c) ; do
VG=$(echo $LINE | cut -d: -f2)
[ "$VG" = "$MYVG" ] && break
done
PV=$(echo $LINE | cut -d: -f1)
BASEDEV=$PV
else
BASEDEV=$REALDEV
fi
else
BASEDEV=$ROOTDEV
fi

# Finally, we should check if base device is
# a real block device or a RAID volume:
for MD in $(cat /proc/mdstat | grep -w active | cut -d' ' -f1) ; do
if
[ "$BASEDEV" = "/dev/$MD" ]; then
USING_RAID=1
break
fi
done

}

# Before we start
[ -x /bin/id ] && CMD_ID="/bin/id" || CMD_ID="/usr/bin/id"
if [ "$($CMD_ID -u)" != "0" ]; then
echo "You need to be root to run $(basename $0)."
exit 1
fi

# Parse the commandline parameters:
while [ ! -z "$1" ]; do
case
$1 in
--longhelp)
basic_usage
extended_usage
exit 0
;;
-a)
MKINIT_PARAMS="$2"
shift 2
;;
-c|--conf)
[ -n "$EMIT" ] && { echo "Do not mix incompatible parameters!"; exit 1; }
EMIT="conf"
shift
;;
-h|--help)
basic_usage
exit 0
;;
-i|--interactive)
INTERACTIVE=1
shift
;;
-k)
KVER=$2
shift 2
;;
-m)
MKINIT_MODS=$2
shift 2
;;
-l|--lilo)
[ -n "$EMIT" ] && { echo "Do not mix incompatible parameters!"; exit 1; }
EMIT="lilo"
shift
;;
-L|--fromlilo)
FROMLILO=1
shift
;;
-r|--run)
[ -n "$EMIT" ] && { echo "Do not mix incompatible parameters!"; exit 1; }
EMIT="run"
shift
;;
-R|--rootdev)
ROOTDEV=$2
shift 2
;;
-*)
echo "Unsupported parameter '$1'!"
exit 1
;;
*) # Everything else but switches (which start with '-') follows:
if [ -f $1 ]; then
KFILE=$1
# Construction of KFILE's full filename:
KFILEPATH=$(cd $(dirname $KFILE) && pwd)
if [ -L $KFILE ]; then
KFILE=$(readlink $KFILE)
else
KFILE=$(basename $KFILE)
fi
KFILE=${KFILEPATH}/$KFILE
if [ -z "$(file $KFILE | grep -E 'Linux kernel x86 boot|x86 boot sector')" ]; then
echo "File '$KFILE' does not look like it is a kernel file!"
exit 1
fi
else
echo "File $1 not found!"
exit 1
fi
shift
;;
esac
done

# Determine what to show as output (other options may have set EMIT already)
EMIT=${EMIT:-"all"}

# An EMIT value of 'lilo' requires a kernel filename as script parameter:
if [ "$EMIT" = "lilo" ]; then
if
[ -z "$KFILE" ]; then
echo "A kernel_filename is required with the '-l|--lilo' option!"
exit 1
fi
fi

# Determine kernel version to use,
# and check if modules for this kernel are actually present:
if [ -z "$KVER" ]; then
if
[ -n "$KFILE" ]; then
KVER="$(strings $KFILE | grep '([^ ]*@[^ ]*) #' | cut -f1 -d' ')"
else
KVER="$(uname -r)"
fi
fi
if
[ ! -d /lib/modules/$KVER ]; then
echo "Modules for kernel $KVER aren't installed."
exit 1
fi

# Determine whether the user passed an alternate filename for the initrd:
if [ -n "$MKINIT_PARAMS" ]; then
SRCHLIST="$MKINIT_PARAMS"
for ELEM in $MKINIT_PARAMS ; do
SRCHLIST=$(echo $SRCHLIST | cut -d' ' -f2-) # cut ELEM from the list
if [ "$ELEM" = "-o" ]; then
IMGFILE=$(echo $SRCHLIST | cut -d' ' -f1)
break
fi
done
fi
IMGFILE=${IMGFILE:-"/boot/initrd.gz"}

# Get information about the root device / root filesystem:
ROOTDEV=${ROOTDEV:-$(get_root_device)}
ROOTFS=$(get_rootfs_type)

# Determine the list of kernel modules needed to support the root device:
MLIST=$(determine_blockdev_drivers)

# Check if we are running in a kvm guest with virtio block device driver
# (add all virtio modules, we sort out the doubles later):
if echo $MLIST | grep -q "virtio"; then
MLIST="$MLIST:virtio:virtio_balloon:virtio_blk:virtio_ring:virtio_pci:virtio_net"
fi

# Determine if a USB keyboard is in use and include usbhid and hid_generic
# to module list
MLIST=$(add_usb_keyboard)

# If we use any USB module, try to determine the Host Controller
if echo $MLIST | grep -q "usb"; then
MLIST=$(add_usb_hcd)
fi

# Check what combination of LUKS/LVM/RAID we have to support:
# This sets values for USING_LUKS, USING_LVM, USING_RAID, REALDEV and BASEDEV.
check_luks_lvm_raid

# This is the interactive part:
if [ "$INTERACTIVE" = "1" ]; then
if
[ "$FROMLILO" != "1" ]; then
dialog --stdout --title "WELCOME TO MKINITRD COMMAND GENERATOR" --msgbox "\
The main goal of this utility is to create a good initrd to
\
fit your needs. It can detect what kernel you are running,
\
what is your root device, root filesystem, if you use encryption,
\
LVM, RAID, etc.
\
\n\n\
Usually the probed values are OK and they will be the
\
defaults in all subsequent dialogs, but maybe you want
\
to change something.
\n\
If in doubt, leave the defaults."
0 0

KVER=$( ls -d1 --indicator-style=none /lib/modules/* | \
awk -F/ -vVER=$KVER '{
if ( VER == $NF ) {
ONOFF="on"
} else {
ONOFF="off"
} ; printf("%s \"\" %s\n",$NF,ONOFF) }'
| \
xargs dialog --stdout --title "CHOOSE KERNEL VERSION" \
--default-item $KVER --radiolist "\
Please, select the kernel version you want to create this initrd for."
0 0 4 )
[ -z "$KVER" ] && exit 1

OLDROOTDEV=$ROOTDEV
ROOTDEV=$( dialog --stdout --title "SELECT ROOT DEVICE" --inputbox "\
Enter your root device. Root device is the one where your '/' filesystem
\
is mounted."
0 0 "$ROOTDEV" )
[ -z "$ROOTDEV" ] && exit 1

# We need to re-check our defaults in case the user changed the default
# value for ROOTDEV:
[ "$OLDROOTDEV" != "$ROOTDEV" ] && check_luks_lvm_raid
ROOTFS=$(get_rootfs_type)

ROOTFS=$( dialog --stdout --title "SELECT ROOT FILESYSTEM" --inputbox "\
Enter the type of your root filesystem."
0 0 "$ROOTFS" )
[ -z "$ROOTFS" ] && exit 1
fi

MLIST=$(add_rootfs_module)

LLR=$( dialog --stdout --title "LVM/LUKS/RAID" --checklist "\
Do you use some of those in your root filesystem?
\
If this is the case, please select one or more options."
12 45 3 \
"LVM" "Logical Volume Manager" $([ "$USING_LVM" = "1" ] && echo on || echo off) \
"LUKS" "Linux Unified Key Setup" $([ "$USING_LUKS" = "1" ] && echo on || echo off) \
"RAID" "Linux Software RAID" $([ "$USING_RAID" = "1" ] && echo on || echo off))

if [ "$?" != "0" ]; then
exit 1
fi

echo $LLR | grep -q LUKS && USING_LUKS="1"
echo $LLR | grep -q LVM && USING_LVM="1"
echo $LLR | grep -q RAID && USING_RAID="1"

if [ "$USING_LUKS" = "1" ]; then
REALDEV=$( dialog --stdout --title "LUKS ROOT DEVICE" --inputbox "\
Please, enter your LUKS root device:"
0 0 "$REALDEV" )
[ -z "$REALDEV" ] && exit 1
fi
fi

# Step out of the interactive loop for a moment. The next block needs to be
# executed in all cases.

# We need to 'undouble' the MLIST array. Some people report that walking the
# /sys tree produces duplicate modules in the list.
# The awk command elimitates doubles without changing the order:
MLIST=$( echo $MLIST | tr ':' '\n' | awk '!x[$0]++' | tr '\n' ' ' )
MLIST=$( echo $MLIST | tr ' ' ':' )
MLIST=$(echo ${MLIST%:}) # To weed out a trailing ':' which was reported once.

# Back to the interactive part:

if [ "$INTERACTIVE" = "1" ]; then
MLIST=$( dialog --stdout --title "INITRD'S MODULE LIST" --inputbox "\
The list here shows all modules needed to support your root filesystem
\
and boot from it. But you can change the list to use some alternative
\
or additional modules. If you don't know what to do, the default is safe."
\
0 0 "$MLIST" )
if [ "$?" != "0" ]; then
exit 1
fi

EXTRA=$( dialog --stdout --title "EXTRA CONFIGURATION" --checklist "\
Now is your chance for some additional configuration. All of these
\
configurations are optional and you can stick to the defaults."
11 72 3 \
"KEYMAP" "Select keyboard layout (default: US)" \
$([ $USING_LUKS = 1 ] && echo on || echo off) \
"RESUMEDEV" "Select device for 'suspend-to-disk' feature" off \
"UDEV" "Use UDEV in the initrd for device configuration" $(test $UDEV -eq 1 && echo on || echo off) \
"WAIT" "Add delay to allow detection of slow disks at boot" $(test $WAIT -gt $WAIT_DEFAULT && echo on || echo off) )
if [ "$?" != "0" ]; then
exit 1
fi

if echo $EXTRA | grep -q KEYMAP ; then
KEYMAP=$( dialog --stdout --title "KEYBOARD LAYOUT SELECTION" \
--cancel-label "Skip" \
--menu "You may select one of the following keyboard layouts. \
If you do not select a keyboard map, 'us.map'
\
(the US keyboard layout) is the default. Use the UP/DOWN
\
arrow keys and PageUp/PageDown to scroll
\
through the whole list of choices."
\
22 55 11 \
"qwerty/us.map" "" \
"azerty/azerty.map" "" \
"azerty/be-latin1.map" "" \
"azerty/fr-latin0.map" "" \
"azerty/fr-latin1.map" "" \
"azerty/fr-latin9.map" "" \
"azerty/fr-old.map" "" \
"azerty/fr-pc.map" "" \
"azerty/fr.map" "" \
"azerty/wangbe.map" "" \
"azerty/wangbe2.map" "" \
"dvorak/ANSI-dvorak.map" "" \
"dvorak/dvorak-l.map" "" \
"dvorak/dvorak-r.map" "" \
"dvorak/dvorak.map" "" \
"dvorak/no-dvorak.map" "" \
"fgGIod/tr_f-latin5.map" "" \
"fgGIod/trf-fgGIod.map" "" \
"olpc/es-olpc.map" "" \
"olpc/pt-olpc.map" "" \
"qwerty/bg-cp1251.map" "" \
"qwerty/bg-cp855.map" "" \
"qwerty/bg_bds-cp1251.map" "" \
"qwerty/bg_bds-utf8.map" "" \
"qwerty/bg_pho-cp1251.map" "" \
"qwerty/bg_pho-utf8.map" "" \
"qwerty/br-abnt.map" "" \
"qwerty/br-abnt2.map" "" \
"qwerty/br-latin1-abnt2.map" "" \
"qwerty/br-latin1-us.map" "" \
"qwerty/by-cp1251.map" "" \
"qwerty/by.map" "" \
"qwerty/bywin-cp1251.map" "" \
"qwerty/cf.map" "" \
"qwerty/cz-cp1250.map" "" \
"qwerty/cz-lat2-prog.map" "" \
"qwerty/cz-lat2.map" "" \
"qwerty/cz-qwerty.map" "" \
"qwerty/defkeymap.map" "" \
"qwerty/defkeymap_V1.0.map" "" \
"qwerty/dk-latin1.map" "" \
"qwerty/dk.map" "" \
"qwerty/emacs.map" "" \
"qwerty/emacs2.map" "" \
"qwerty/es-cp850.map" "" \
"qwerty/es.map" "" \
"qwerty/et-nodeadkeys.map" "" \
"qwerty/et.map" "" \
"qwerty/fi-latin1.map" "" \
"qwerty/fi-latin9.map" "" \
"qwerty/fi-old.map" "" \
"qwerty/fi.map" "" \
"qwerty/gr-pc.map" "" \
"qwerty/gr.map" "" \
"qwerty/hu101.map" "" \
"qwerty/il-heb.map" "" \
"qwerty/il-phonetic.map" "" \
"qwerty/il.map" "" \
"qwerty/is-latin1-us.map" "" \
"qwerty/is-latin1.map" "" \
"qwerty/it-ibm.map" "" \
"qwerty/it.map" "" \
"qwerty/it2.map" "" \
"qwerty/jp106.map" "" \
"qwerty/kazakh.map" "" \
"qwerty/kyrgyz.map" "" \
"qwerty/la-latin1.map" "" \
"qwerty/lt.baltic.map" "" \
"qwerty/lt.l4.map" "" \
"qwerty/lt.map" "" \
"qwerty/mk-cp1251.map" "" \
"qwerty/mk-utf.map" "" \
"qwerty/mk.map" "" \
"qwerty/mk0.map" "" \
"qwerty/nl.map" "" \
"qwerty/nl2.map" "" \
"qwerty/no-latin1.map" "" \
"qwerty/no.map" "" \
"qwerty/pc110.map" "" \
"qwerty/pl.map" "" \
"qwerty/pl1.map" "" \
"qwerty/pl2.map" "" \
"qwerty/pl3.map" "" \
"qwerty/pl4.map" "" \
"qwerty/pt-latin1.map" "" \
"qwerty/pt-latin9.map" "" \
"qwerty/pt.map" "" \
"qwerty/ro.map" "" \
"qwerty/ro_std.map" "" \
"qwerty/ru-cp1251.map" "" \
"qwerty/ru-ms.map" "" \
"qwerty/ru-yawerty.map" "" \
"qwerty/ru.map" "" \
"qwerty/ru1.map" "" \
"qwerty/ru2.map" "" \
"qwerty/ru3.map" "" \
"qwerty/ru4.map" "" \
"qwerty/ru_win.map" "" \
"qwerty/ruwin_alt-CP1251.map" "" \
"qwerty/ruwin_alt-KOI8-R.map" "" \
"qwerty/ruwin_alt-UTF-8.map" "" \
"qwerty/ruwin_cplk-CP1251.map" "" \
"qwerty/ruwin_cplk-KOI8-R.map" "" \
"qwerty/ruwin_cplk-UTF-8.map" "" \
"qwerty/ruwin_ct_sh-CP1251.map" "" \
"qwerty/ruwin_ct_sh-KOI8-R.map" "" \
"qwerty/ruwin_ct_sh-UTF-8.map" "" \
"qwerty/ruwin_ctrl-CP1251.map" "" \
"qwerty/ruwin_ctrl-KOI8-R.map" "" \
"qwerty/ruwin_ctrl-UTF-8.map" "" \
"qwerty/se-fi-ir209.map" "" \
"qwerty/se-fi-lat6.map" "" \
"qwerty/se-ir209.map" "" \
"qwerty/se-lat6.map" "" \
"qwerty/se-latin1.map" "" \
"qwerty/sk-prog-qwerty.map" "" \
"qwerty/sk-qwerty.map" "" \
"qwerty/speakup-jfw.map" "" \
"qwerty/speakupmap.map" "" \
"qwerty/sr-cy.map" "" \
"qwerty/sv-latin1.map" "" \
"qwerty/tr_q-latin5.map" "" \
"qwerty/tralt.map" "" \
"qwerty/trf.map" "" \
"qwerty/trq.map" "" \
"qwerty/ttwin_alt-UTF-8.map.gz" "" \
"qwerty/ttwin_cplk-UTF-8.map.gz" "" \
"qwerty/ttwin_ct_sh-UTF-8.map.gz" "" \
"qwerty/ttwin_ctrl-UTF-8.map.gz" "" \
"qwerty/ua-cp1251.map.gz" "" \
"qwerty/ua-utf-ws.map" "" \
"qwerty/ua-utf.map" "" \
"qwerty/ua-ws.map" "" \
"qwerty/ua.map" "" \
"qwerty/uk.map" "" \
"qwerty/us-acentos.map" "" \
"qwerty/us.map" "" \
"qwertz/croat.map" "" \
"qwertz/cz-us-qwertz.map" "" \
"qwertz/cz.map" "" \
"qwertz/de-latin1-nodeadkeys.map" "" \
"qwertz/de-latin1.map" "" \
"qwertz/de.map" "" \
"qwertz/de_CH-latin1.map" "" \
"qwertz/fr_CH-latin1.map" "" \
"qwertz/fr_CH.map" "" \
"qwertz/hu.map" "" \
"qwertz/sg-latin1-lk450.map" "" \
"qwertz/sg-latin1.map" "" \
"qwertz/sg.map" "" \
"qwertz/sk-prog-qwertz.map" "" \
"qwertz/sk-qwertz.map" "" \
"qwertz/slovene.map" "" )
[ -n "$KEYMAP" ] && KEYMAP=$(basename $KEYMAP .map)
fi

if echo $EXTRA | grep -q UDEV ; then
UDEV=1
fi

if echo $EXTRA | grep -q RESUMEDEV ; then
# Print information about swap partitions:
FREERAM=$(free -k | grep "^Mem:" | tr -s ' ' | cut -d' ' -f2)
SWPINFO=""
for SWPDEV in $(grep -w swap $FSTAB | cut -d' ' -f1) ; do
SWPINFO="$SWPINFO $SWPDEV Linux swap partition $(fdisk -s $SWPDEV) KB \\n"
[ $(fdisk -s $SWPDEV) -gt $FREERAM ] && RESUMEDEV=$SWPDEV
done
FREERAM=$(free -m | grep "^Mem:" | tr -s ' ' | cut -d' ' -f2)
RESUMEDEV=$( dialog --stdout --no-collapse --title "HIBERNATE RESUME DEVICE" --inputbox "\
When using suspend-to-disk feature (hibernate), your computer's RAM is copied
\
to a swap device when it shuts down. The kernel will resume from that RAM
\
image at boot. This means that the swap partition must not be smaller than
\
the amount of RAM you have (
$FREERAM MB). \n\
$SWPINFO \n\
Please specify a swap partition to be used for hibernation:"
\
0 0 "$RESUMEDEV")
[ -z "$RESUMEDEV" ] && exit 1
fi

if echo $EXTRA | grep -q WAIT ; then
WAIT=$( dialog --stdout --title "WAIT FOR ROOT DEVICE" --inputbox "\
Some block devices are too slow to be detected properly at boot. USB storage
\
devices and some disk arrays have this 'feature'. To make your machine
\
boot properly, you can add some delay here, to wait until all your disks are
\
probed and detected. The time is in seconds:"
0 0 "$WAIT")
[ -z "$WAIT" ] && exit 1
fi

IMGFILE=$( dialog --stdout --title "INITRD IMAGE NAME" --inputbox "\
Enter your initrd image filename."
0 0 "$IMGFILE" )
[ -z "$IMGFILE" ] && exit 1

else
MLIST=$(add_rootfs_module)
fi

# Add any modules passed along on the commandline:
if [ -n "$MKINIT_MODS" ]; then
[ -n "$MLIST" ] && MLIST="$MLIST:$(echo $MKINIT_MODS | tr ' ' ':')" \
|| MLIST="$(echo $MKINIT_MODS | tr ' ' ':')"
fi

# Constructing the mkinitrd command:
MKINIT="mkinitrd -c -k $KVER -f $ROOTFS -r $ROOTDEV"

# If we have a module list, add them:
if ! [ -z "$MLIST" -o "$MLIST" = ":" ]; then
MKINIT="$MKINIT -m $MLIST"
fi

# Deal with LUKS/LVM/RAID:
if [ "$USING_LUKS" = "1" ]; then
MKINIT="$MKINIT -C $REALDEV"
fi
if
[ "$USING_LVM" = "1" ]; then
MKINIT="$MKINIT -L"
fi
if
[ "$USING_RAID" = "1" ]; then
MKINIT="$MKINIT -R"
fi

if [ -n "$RESUMEDEV" ]; then
# Add hibernation partition:
MKINIT="$MKINIT -h $RESUMEDEV"
fi
if
[ -n "$KEYMAP" -a "$KEYMAP" != "us" ]; then
# Add non-us keyboard mapping:
MKINIT="$MKINIT -l $KEYMAP"
fi
if
[ $UDEV -eq 1 ]; then
# Add UDEV support:
MKINIT="$MKINIT -u"
fi
if
[ -n "$WAIT" -a $WAIT -ne $WAIT_DEFAULT ]; then
# Add non-default wait time:
MKINIT="$MKINIT -w $WAIT"
fi
if
! echo "$MKINIT_PARAMS" | grep -q -- '-o ' ; then
# Add default output filename:
MKINIT="$MKINIT -o $IMGFILE"
fi
if
[ -n "$MKINIT_PARAMS" ]; then
# Add user-supplied additional parameters:
MKINIT="$MKINIT $MKINIT_PARAMS"
fi

# Notify the user:
if [ "$EMIT" = "all" ]; then
cat <<-EOT
#
#
$(basename $0) revision $REV
#
# This script will now make a recommendation about the command to use
# in case you require an initrd image to boot a kernel that does not
# have support for your storage or root filesystem built in
# (such as the Slackware 'generic' kernels').
# A suitable 'mkinitrd' command will be:

$MKINIT
EOT
elif [ "$EMIT" = "run" ]; then
echo "$MKINIT"
elif [ "$EMIT" = "conf" ]; then
cat <<-EOT
SOURCE_TREE="
$SOURCE_TREE"
CLEAR_TREE="
$CLEAR_TREE"
OUTPUT_IMAGE="
$IMGFILE"
KERNEL_VERSION="
$KVER"
KEYMAP="
$KEYMAP"
MODULE_LIST="
$(echo $MLIST | cut -f2 -d\ )"
LUKSDEV="
$REALDEV"
ROOTDEV="
$ROOTDEV"
ROOTFS="
$ROOTFS"
RESUMEDEV="
$RESUMEDEV"
RAID="
$USING_RAID"
LVM="
$USING_LVM"
UDEV="
$UDEV"
WAIT="
$WAIT"
EOT
fi

if [ -n "$KFILE" ]; then
if
[ "$EMIT" = "all" ]; then
cat <<-EOT
# An entry in 'etc/lilo.conf' for kernel '
$KFILE' would look like this:
EOT
fi
if
[ "$EMIT" = "all" -o "$EMIT" = "lilo" ]; then
# Compensate for the syntax used for the LUKS-on-LVM case:
[ "$(basename $ROOTDEV)" = "$ROOTDEV" ] && BASE="/dev/mapper/" || BASE=""
cat <<-EOT
# Linux bootable partition config begins
# initrd created with '
$MKINIT'
image =
$KFILE
initrd =
$IMGFILE
root =
$BASE$ROOTDEV
label =
$KVER
read-only
# Linux bootable partition config ends
EOT
fi
fi





再起動

# reboot

※ インストールメディアを取り出し忘れないこと。

参考文献:

https://linuxjm.osdn.jp/html/0MultiFileIdx/man8/reboot.8.html


/ に容量を継ぎ足す場合

コマンド実行例:

# fdisk -l

# pvcreate /dev/moomoo
# lvs
# vgextend SlackVG /dev/moomoo
# lvextend -l +100%FREE SlackVG/root
# resize2fs /dev/SlackVG/root
# lvs

※ 100%FREE って何だか体に良さそう

※ /dev/moomoo SlackVG root はハードウェア構成や LVM の設定に応じて適宜読み替えてください。

※ ファイルシステムのオンラインリサイズについて、

 ・ext2/3/4 の場合は resize2fs

 ・btrfs の場合は btrfs filesystem resize

 ・reiserfs の場合は resize_reiserfs

 ・xfs の場合は xfs_growfs

参考文献:

Man page of FDISK

https://linuxjm.osdn.jp/html/util-linux/man8/fdisk.8.html

pvcreate(8) - Linux man page

https://linux.die.net/man/8/pvcreate

lvs(8) - Linux man page

https://linux.die.net/man/8/lvs

vgextend(8) - Linux man page

https://linux.die.net/man/8/vgextend

lvextend(8) - Linux man page

https://linux.die.net/man/8/lvextend

resize2fs(8) - Linux man page

https://linux.die.net/man/8/resize2fs

btrfs(8) - Linux man page

https://linux.die.net/man/8/btrfs

Man page of RESIZE_REISERFS

https://linuxjm.osdn.jp/html/reiserfsprogs/man8/resize_reiserfs.8.html

xfs_growfs(8) - Linux man page

https://linux.die.net/man/8/xfs_growfs

LVM - ArchWiki

https://wiki.archlinux.jp/index.php/LVM

Pantora Networks » 3章 LVM操作 応用編

http://pantora.net/pages/linux/lvm/3/

LVMで新たにディスクを追加して既存のLVを拡張する - Qiita

https://qiita.com/g_maeda/items/3602dc2f7af3f711f9c4

LVM上のbtrfsのRAID1のサイズを拡張する - Qiita

https://qiita.com/takaki@github/items/5d96d80dc78b09ea600b



備考


シャットダウン・リブート時の “lvm can't deactivate …” エラー

VirtualBox_Slackware64_10_07_2019_15_32_53.png

LVM に置いたルートでは毎回このエラーが出ますが、リードオンリーで再マウントした後の話なので最悪でもデータが飛ぶ恐れはないそうです。

# This never hurts again (especially since root-on-LVM always fails

# to deactivate the / logical volume... but at least it was
# remounted as read-only first)
/bin/sync

出典:

/etc/rc.d/rc.6 本体


/etc/rc.d/rc.6

#! /bin/sh

#
# rc.6 This file is executed by init when it goes into runlevel
# 0 (halt) or runlevel 6 (reboot). It kills all processes,
# unmounts file systems and then either halts or reboots.
#
# Version: @(#)/etc/rc.d/rc.6 2.47 Sat Jan 13 13:37:26 PST 2001
#
# Author: Miquel van Smoorenburg
# Modified by: Patrick J. Volkerding
#

# Set the path.
PATH=/sbin:/etc:/bin:/usr/bin

# If there are SystemV init scripts for this runlevel, run them.
if [ -x /etc/rc.d/rc.sysvinit ]; then
. /etc/rc.d/rc.sysvinit
fi

# Set linefeed mode to avoid staircase effect.
/bin/stty onlcr

echo "Running shutdown script $0:"

# Find out how we were called.
case "$0" in
*0)
shutdown_command="halt"
;;
*6)
shutdown_command=reboot
;;
*)
echo "$0: call me as \"rc.0\" or \"rc.6\" please!"
exit 1
;;
esac

# Save the system time to the hardware clock using hwclock --systohc.
# This will also create or update the timestamps in /etc/adjtime.
if [ -x /sbin/hwclock ]; then
# Check for a broken motherboard RTC clock (where ioports for rtc are
# unknown) to prevent hwclock causing a hang:
if ! grep -q " : rtc" /proc/ioports ; then
CLOCK_OPT="--directisa"
fi
if
[ /etc/adjtime -nt /etc/hardwareclock ]; then
if
grep -q "^LOCAL" /etc/adjtime ; then
echo "Saving system time to the hardware clock (localtime)."
else
echo "Saving system time to the hardware clock (UTC)."
fi
/sbin/hwclock $CLOCK_OPT --systohc
elif grep -q "^UTC" /etc/hardwareclock 2> /dev/null ; then
echo "Saving system time to the hardware clock (UTC)."
if [ ! -r /etc/adjtime ]; then
echo "Creating system time correction file /etc/adjtime."
fi
/sbin/hwclock $CLOCK_OPT --utc --systohc
else
echo "Saving system time to the hardware clock (localtime)."
if [ ! -r /etc/adjtime ]; then
echo "Creating system time correction file /etc/adjtime."
fi
/sbin/hwclock $CLOCK_OPT --localtime --systohc
fi
fi

# Run any local shutdown scripts:
if [ -x /etc/rc.d/rc.local_shutdown ]; then
/etc/rc.d/rc.local_shutdown stop
fi

# Stop the Apache web server:
if [ -x /etc/rc.d/rc.httpd ]; then
/etc/rc.d/rc.httpd stop
fi

# Stop the MySQL database:
if [ -r /var/run/mysql/mysql.pid ]; then
. /etc/rc.d/rc.mysqld stop
fi

# Stop the Samba server:
if [ -x /etc/rc.d/rc.samba ]; then
. /etc/rc.d/rc.samba stop
fi

# Shut down the NFS server:
if [ -x /etc/rc.d/rc.nfsd ]; then
/etc/rc.d/rc.nfsd stop
fi

# Shut down the SSH server:
if [ -x /etc/rc.d/rc.sshd ]; then
/etc/rc.d/rc.sshd stop
fi

# Shut down the SASL authentication daemon:
if [ -x /etc/rc.d/rc.saslauthd ]; then
/etc/rc.d/rc.saslauthd stop
fi

# Shut down OpenLDAP:
if [ -x /etc/rc.d/rc.openldap ]; then
/etc/rc.d/rc.openldap stop
fi

# Stop D-Bus:
if [ -x /etc/rc.d/rc.messagebus ]; then
sh /etc/rc.d/rc.messagebus stop
fi

# Kill any processes (typically gam) that would otherwise prevent
# unmounting NFS volumes:
unset FUSER_DELAY
for dir in $(/bin/mount | grep 'type nfs ' | cut -d ' ' -f 3 ) ; do
echo "Killing processes holding NFS mount $dir open..."
# Background this to prevent fuser from also blocking shutdown:
/usr/bin/fuser -k -m $dir &
FUSER_DELAY=5
done
# If fuser was run, let it have some delay:
if [ ! -z "$FUSER_DELAY" ]; then
sleep $FUSER_DELAY
fi

# Unmount any NFS, SMB, or CIFS filesystems:
echo "Unmounting remote filesystems:"
/bin/umount -v -a -l -f -r -t nfs,smbfs,cifs | tr -d ' ' | grep successfully | sed "s/:successfullyunmounted/ has been successfully unmounted./g"

# Try to shut down pppd:
PS="$(ps ax)"
if echo "$PS" | /bin/grep -q -w pppd ; then
if
[ -x /usr/sbin/ppp-off ]; then
/usr/sbin/ppp-off
fi
fi

# Shut down YP services:
if [ -x /etc/rc.d/rc.yp ]; then
if
grep -wq stop /etc/rc.d/rc.yp ; then
/etc/rc.d/rc.yp stop
fi
fi

# Bring down the networking system, but first make sure that this
# isn't a diskless client with the / partition mounted via NFS:
if ! /bin/mount | /bin/grep -q 'on / type nfs' ; then
if
[ -x /etc/rc.d/rc.inet1 ]; then
. /etc/rc.d/rc.inet1 stop
fi
fi

# In case dhcpcd might have been manually started on the command line,
# look for the .pid file, and shut dhcpcd down if it's found:
if /bin/ls /etc/dhcpc/*.pid 1> /dev/null 2> /dev/null ; then
/sbin/dhcpcd -k 1> /dev/null 2> /dev/null
# A little time for /etc/resolv.conf and/or other files to
# restore themselves.
sleep 2
fi

# Shut down PCMCIA devices:
if [ -x /etc/rc.d/rc.pcmcia ]; then
. /etc/rc.d/rc.pcmcia stop
# The cards might need a little extra time here to deactivate:
/bin/sleep 5
fi

# Turn off process accounting:
if [ -x /sbin/accton -a -r /var/log/pacct ]; then
/sbin/accton off
fi

# Terminate acpid before syslog:
if [ -x /etc/rc.d/rc.acpid -a -r /var/run/acpid.pid ]; then # quit
. /etc/rc.d/rc.acpid stop
fi

# Stop udev:
if [ -x /etc/rc.d/rc.udev ]; then
sh /etc/rc.d/rc.udev force-stop
fi

# Kill all remaining processes.
OMITPIDS="$(for p in $(pgrep mdmon); do echo -o $p; done)" # Don't kill mdmon
if [ ! "$1" = "fast" ]; then
echo "Sending all processes the SIGTERM signal."
/sbin/killall5 -15 $OMITPIDS
/bin/sleep 5
echo "Sending all processes the SIGKILL signal."
/sbin/killall5 -9 $OMITPIDS
fi

# Try to turn off quota.
if /bin/grep -q quota /etc/fstab ; then
if
[ -x /sbin/quotaoff ]; then
echo "Turning off filesystem quotas."
/sbin/quotaoff -a
fi
fi

# Carry a random seed between reboots.
echo "Saving random seed from /dev/urandom in /etc/random-seed."
# Use the pool size from /proc, or 4096 bits:
if [ -r /proc/sys/kernel/random/poolsize ]; then
/bin/dd if=/dev/urandom of=/etc/random-seed count=1 bs=$(expr $(cat /proc/sys/kernel/random/poolsize) / 8) 2> /dev/null
else
/bin/dd if=/dev/urandom of=/etc/random-seed count=1 bs=512 2> /dev/null
fi
/bin/chmod 600 /etc/random-seed

# Before unmounting file systems write a reboot or halt record to wtmp.
$shutdown_command -w

# Turn off swap:
echo "Turning off swap."
/sbin/swapoff -a
/bin/sync

# Stop cgmanager and cgproxy:
if [ -x /etc/rc.d/rc.cgmanager ]; then
sh /etc/rc.d/rc.cgmanager stop
fi

echo "Unmounting local file systems:"
/bin/umount -v -a -t no,proc,sysfs | tr -d ' ' | grep successfully | sed "s/:successfullyunmounted/ has been successfully unmounted./g" 2> /dev/null

echo "Remounting root filesystem read-only:"
/bin/mount -v -n -o remount,ro /

# This never hurts:
/bin/sync

# Close any volumes opened by cryptsetup:
if [ -f /etc/crypttab -a -x /sbin/cryptsetup ]; then
cat /etc/crypttab | grep -v "^#" | grep -v "^$" | while read line; do
# NOTE: we only support LUKS formatted volumes (except for swap)!
LUKS=$(echo $line | tr '\t' ' ' | tr -s ' ' | cut -f1 -d' ')
DEV=$(echo $line | tr '\t' ' ' | tr -s ' ' | cut -f2 -d' ')
OPTS=$(echo $line | tr '\t' ' ' | tr -s ' ' | cut -f4 -d' ')
if /sbin/cryptsetup isLuks $DEV 2>/dev/null ; then
echo "Locking LUKS crypt volume '${LUKS}':"
/sbin/cryptsetup luksClose ${LUKS}
elif echo $OPTS | grep -wq swap ; then
# If any of the volumes was used as encrypted swap,
# then run mkswap on the underlying device -
# in case other Linux installations on this computer should use it:
echo "Erasing encrypted swap '${LUKS}' and restoring normal swap on ${DEV}:"
/sbin/cryptsetup remove ${LUKS}
mkswap $DEV
fi
done
fi

# Deactivate LVM volume groups:
if [ -r /etc/lvmtab -o -d /etc/lvm/backup ]; then
echo "Deactivating LVM volume groups:"
/sbin/vgchange -an --ignorelockingfailure
fi

# This never hurts again (especially since root-on-LVM always fails
# to deactivate the / logical volume... but at least it was
# remounted as read-only first)
/bin/sync

# sleep 3 fixes problems with some hard drives that don't
# otherwise finish syncing before reboot or poweroff
/bin/sleep 3

# This is to ensure all processes have completed on SMP machines:
wait

if [ -x /sbin/genpowerd ]; then
# See if this is a powerfail situation:
if /bin/egrep -q "FAIL|SCRAM" /etc/upsstatus 2> /dev/null ; then
# Signal UPS to shut off the inverter:
/sbin/genpowerd -k
if [ ! $? = 0 ]; then
echo
echo
"There was an error signaling the UPS."
echo "Perhaps you need to edit /etc/genpowerd.conf to configure"
echo "the serial line and UPS type."
# Wasting 15 seconds of precious power:
/bin/sleep 15
fi
fi
fi

# Now halt (poweroff with APM or ACPI enabled kernels) or reboot.
if [ "$shutdown_command" = "reboot" ]; then
echo "Rebooting."
/sbin/reboot
else
/sbin/poweroff
fi




ELILO におけるハイバネート機能(SWSUSP)の有効化、任意のカーネルパラメータの適用

/usr/sbin/eliloconfig を編集することで swsusp に対応させることが出来る他、起動時にお好みのカーネルパラメータを渡すことが可能です。

該当個所を、例えば以下のように編集します。


/usr/sbin/eliloconfig

cat << EOF >> $T_PX/boot/efi/EFI/Slackware/elilo.conf

read-only
append="root=
$ROOT_DEVICE vga=normal ro"
EOF


/usr/local/sbin/eliloconfig-modified

cat << EOF >> $T_PX/boot/efi/EFI/Slackware/elilo.conf

read-only
append="root=
$ROOT_DEVICE resume=/dev/moo2 vga=normal ro"
EOF

resume=/dev/moo2 はインストールした Slackware で使用している swap 領域を指定。

直接編集せず、/usr/local/sbin/eliloconfig-modified 等の名前でコピーを作成してそちらを編集すると安全かも。

swap 領域が LVM の中にある場合 initramfsを使い、かつ swsusp を行う場合は mkinitrd-h /dev/moo 等を渡してやる 必要があるようです のが無難です。2 3

参考文献:


initramfs と swsusp と LVM についての掘り下げ

/boot/initrd.gz 内の init スクリプト


init

#!/bin/ash

#
# /init: init script to load kernel modules from an initramfs
# This requires that your kernel supports initramfs!!!
#
# Copyright 2004 Slackware Linux, Inc., Concord, CA, USA
# Copyright 2007, 2008, 2009, 2010, 2012 Patrick J. Volkerding, Sebeka, MN, USA
# All rights reserved.
#
# Redistribution and use of this script, with or without modification, is
# permitted provided that the following conditions are met:
#
# 1. Redistributions of this script must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
# EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
##################################################################################
# With a generic kernel, you need to load the modules needed to mount the
# root partition. This might mean a SCSI, RAID, or other drive controller
# module, as well as the module to support the root filesystem. Once the
# root partition is mounted all the other modules will be available so you
# don't need to load them here.
#
# Config files used by this script:
#
# /rootdev Contains the name of the root device, such as: /dev/hda1
#
# /rootfs Contains the root filesystem type, such as: xfs
#
# /initrd-name Contains the name of the initrd file.
#
# /resumedev Contains the name of the device to resume from hibernation.
#
# /luksdev Contains colon separated list of luks encrypted devices to
# be unlocked.
#
# /lukstrim Contains colon separated list of luks encrypted devices to
# pass '--allow-discards' when unlocking
#
# /lukskey Contains the path to a LUKS key-file for automatic unlock
# Format: LABEL=<partition_label>:/path/to/file
# UUID=<partition_uuid>:/path/to/file
#
# /wait-for-root Contains a number - the init script will wait this amount
# of seconds before creating device nodes.
#
# /keymap Contains the name for a custom keyboard map
#
# Optional:
#
# /load_kernel_modules
# A script that uses modprobe to load the desired modules.
#
# There's an example in here. To actually use it, you'll
# need to make it executable:
#
# chmod 755 load_kernel_modules
##################################################################################
# Changelog
# 10-Dec-2012 mozes
# * Added support for the official Kernel parameters to select root filesystem
# type ('rootfstype') and pause before attempting to mount the root filesystem
# ('rootdelay'). The original parameters may continue to be used.
##################################################################################

INITRD=$(cat /initrd-name)
ROOTDEV=$(cat /rootdev)
ROOTFS=$(cat /rootfs)
LUKSDEV=$(cat /luksdev)
LUKSTRIM=$(cat /lukstrim 2>/dev/null)
LUKSKEY=$(cat /lukskey)
RESUMEDEV=$(cat /resumedev)
WAIT=$(cat /wait-for-root)
KEYMAP=$(cat /keymap)
INIT=/sbin/init

PATH="/sbin:/bin:/usr/sbin:/usr/bin"

# Mount /proc and /sys:
mount -n proc /proc -t proc
mount -n sysfs /sys -t sysfs
mount -n tmpfs /run -t tmpfs -o mode=0755,size=32M,nodev,nosuid,noexec

if grep devtmpfs /proc/filesystems 1>/dev/null 2>/dev/null ; then
DEVTMPFS=1
mount -n devtmpfs /dev -t devtmpfs -o size=8M
fi

# Parse command line
for ARG in $(cat /proc/cmdline); do
case
$ARG in
0|1|2|3|4|5|6|S|s|single)
RUNLEVEL=$ARG
;;
init=*)
INIT=$(echo $ARG | cut -f2 -d=)
;;
luksdev=/dev/*)
LUKSDEV=$(echo $ARG | cut -f2 -d=)
;;
lukskey=*)
LUKSKEY=$(echo $ARG | cut -f2- -d=)
;;
rescue)
RESCUE=1
;;
resume=*)
RESUMEDEV=$(echo $ARG | cut -f2- -d=)
;;
root=/dev/*)
ROOTDEV=$(echo $ARG | cut -f2 -d=)
;;
root=LABEL=*)
ROOTDEV=$(echo $ARG | cut -f2- -d=)
;;
root=UUID=*)
ROOTDEV=$(echo $ARG | cut -f2- -d=)
;;
rootfs=*|rootfstype=*)
ROOTFS=$(echo $ARG | cut -f2 -d=)
;;
waitforroot=*|rootdelay=*)
WAIT=$(echo $ARG | cut -f2 -d=)
;;
esac
done

# If udevd is available, use it to generate block devices
# else use mdev to read sysfs and generate the needed devices
if [ -x /sbin/udevd -a -x /sbin/udevadm ]; then
/sbin/udevd --daemon --resolve-names=never
/sbin/udevadm trigger --subsystem-match=block --action=add
/sbin/udevadm settle --timeout=10
else
[ "$DEVTMPFS" != "1" ] && mdev -s
fi

# Load kernel modules (ideally this was already done by udev):
if [ ! -d /lib/modules/$(uname -r) ]; then
echo "No kernel modules found for Linux $(uname -r)."
elif [ -x ./load_kernel_modules ]; then # use load_kernel_modules script:
echo "${INITRD}: Loading kernel modules from initrd image:"
. ./load_kernel_modules
else # load modules (if any) in order:
if ls /lib/modules/$(uname -r)/*.*o 1> /dev/null 2> /dev/null ; then
echo "${INITRD}: Loading kernel modules from initrd image:"
for module in /lib/modules/$(uname -r)/*.*o ; do
/sbin/modprobe $module
done
unset module
fi
fi

# Sometimes the devices need extra time to be available.
# A root filesystem on USB is a good example of that.
sleep $WAIT

# Load a custom keyboard mapping:
if [ -n "$KEYMAP" ]; then
echo "${INITRD}: Loading '$KEYMAP' keyboard mapping:"
tar xzOf /etc/keymaps.tar.gz ${KEYMAP}.bmap | loadkmap
fi

if [ "$RESCUE" = "" ]; then
# Initialize RAID:
if [ -x /sbin/mdadm ]; then
# If /etc/mdadm.conf is present, udev should DTRT on its own;
# If not, we'll make one and go from there:
if [ ! -r /etc/mdadm.conf ]; then
/sbin/mdadm -E -s >/etc/mdadm.conf
/sbin/mdadm -S -s
/sbin/mdadm -A -s
# This seems to make the kernel see partitions more reliably:
fdisk -l /dev/md* 1> /dev/null 2> /dev/null
fi
fi

# Unlock any encrypted partitions necessary to access the
# root filesystem, such as encrypted LVM Physical volumes, disk
# partitions or mdadm arrays.
# Unavailable devices such as LVM Logical Volumes will need to be
# deferred until they become available after the vgscan.

if [ -x /sbin/cryptsetup ]; then

# Determine if we have to use a LUKS keyfile:
if [ ! -z "$LUKSKEY" ]; then
mkdir /mountkey
KEYPART=$(echo $LUKSKEY |cut -f1 -d:)
KEYNAME=$(echo $KEYPART |cut -f2 -d=)
LUKSPATH="/mountkey$(echo $LUKSKEY |cut -f2 -d:)"
# Catch possible mount failure:
if blkid |grep "TYPE=\"vfat\"" |grep $KEYNAME 1>/dev/null 2>&1 ; then
MOUNTOPTS="-t vfat -o shortname=mixed"
else
MOUNTOPTS="-t auto"
fi
mount $MOUNTOPTS $(findfs $KEYPART) /mountkey 2>/dev/null
# Check if we can actually use this file:
if [ ! -f $LUKSPATH ]; then
LUKSKEY=""
else
echo ">>> Using LUKS key file: '$LUKSKEY'"
LUKSKEY="-d $LUKSPATH"
fi
fi

LUKSLIST_DEFERRED=""
LUKSLIST=$(echo $LUKSDEV | tr -s ':' ' ')
for LUKSDEV in $LUKSLIST ; do
if
/sbin/cryptsetup isLuks ${LUKSDEV} 1>/dev/null 2>/dev/null ; then
if
echo $ROOTDEV | grep -q "LABEL=" || echo $ROOTDEV | grep -q "UUID=" ; then
CRYPTDEV="luks$(basename $LUKSDEV)"
elif [ "x$ROOTDEV" = "x$(basename $ROOTDEV)" ]; then
CRYPTDEV="$ROOTDEV"
else
CRYPTDEV="luks$(basename $LUKSDEV)"
fi
if
echo $LUKSTRIM | grep -wq $LUKSDEV 2>/dev/null ; then
LUKSOPTS="--allow-discards"
else
LUKSOPTS=""
fi
if
[ -z "${LUKSOPTS}" ]; then
echo "Unlocking LUKS encrypted device '${LUKSDEV}' as luks mapped device '$CRYPTDEV':"
else
echo "Unlocking LUKS encrypted device '${LUKSDEV}' as luks mapped device '$CRYPTDEV' with '$LUKSOPTS':"
fi
/sbin/cryptsetup ${LUKSOPTS} ${LUKSKEY} luksOpen ${LUKSDEV} ${CRYPTDEV} </dev/tty0 >/dev/tty0 2>&1
if [ "$ROOTDEV" = "$LUKSDEV" -o "$ROOTDEV" = "$CRYPTDEV" ] ; then
ROOTDEV="/dev/mapper/$CRYPTDEV"
fi
else
LUKSLIST_DEFERRED="${LUKSLIST_DEFERRED} ${LUKSDEV}"
fi
done
fi

# Initialize LVM:
if [ -x /sbin/vgchange ]; then
mkdir -p /var/lock/lvm # this avoids useless warnings
/sbin/vgchange -ay --ignorelockingfailure 2>/dev/null
/sbin/udevadm settle --timeout=10
fi

# Unlock any LUKS encrypted devices that were deferred above but have now
# become available due to the vgscan (i.e. filesystems on LVM Logical Volumes)

if [ -x /sbin/cryptsetup -a -n "${LUKSLIST_DEFERRED}" ]; then
for
LUKSDEV in ${LUKSLIST_DEFERRED} ; do
if
/sbin/cryptsetup isLuks ${LUKSDEV} 1>/dev/null 2>/dev/null ; then
if
echo $ROOTDEV | grep -q "LABEL=" || echo $ROOTDEV | grep -q "UUID=" ; then
CRYPTDEV="luks$(basename $LUKSDEV)"
elif [ "x$ROOTDEV" = "x$(basename $ROOTDEV)" ]; then
CRYPTDEV="$ROOTDEV"
else
CRYPTDEV="luks$(basename $LUKSDEV)"
fi
echo "Unlocking LUKS encrypted device '${LUKSDEV}' as luks mapped device '$CRYPTDEV':"
/sbin/cryptsetup ${LUKSKEY} luksOpen ${LUKSDEV} ${CRYPTDEV} </dev/tty0 >/dev/tty0 2>&1
if [ "$ROOTDEV" = "$LUKSDEV" -o "$ROOTDEV" = "$CRYPTDEV" ] ; then
ROOTDEV="/dev/mapper/$CRYPTDEV"
fi
else
echo "LUKS device '${LUKSDEV}' unavailable for unlocking!"
fi
done

/sbin/udevadm settle --timeout=10
fi

# Scan for btrfs multi-device filesystems:
if [ -x /sbin/btrfs ]; then
/sbin/btrfs device scan
fi

# Find root device if a label or UUID was given:
if echo $ROOTDEV | grep -q "LABEL=" || \
echo $ROOTDEV | grep -q "UUID=" ; then
ROOTDEV=$(findfs $ROOTDEV)
fi

# Clean up after LUKS unlock using a keyfile:
if grep -q mountkey /proc/mounts 2>/dev/null ; then
umount -l /mountkey
rmdir /mountkey 2>/dev/null
fi

# Resume state from swap
if [ "$RESUMEDEV" != "" ]; then
# Find resume device if a label or UUID was given:
if echo $RESUMEDEV | grep -q "LABEL=" || \
echo $RESUMEDEV | grep -q "UUID=" ; then
RESUMEDEV=$(findfs $RESUMEDEV)
elif ls -l $RESUMEDEV | grep -q "^l" ; then
RESUMEDEV=$(readlink -f $RESUMEDEV)
fi
echo "Trying to resume from $RESUMEDEV"
RESMAJMIN=$(ls -l $RESUMEDEV | tr , : | awk '{ print $5$6 }')
echo $RESMAJMIN > /sys/power/resume
fi

# Switch to real root partition:
/sbin/udevadm settle --timeout=10
echo 0x0100 > /proc/sys/kernel/real-root-dev
mount -o ro -t $ROOTFS $ROOTDEV /mnt

if [ ! -r /mnt/sbin/init ]; then
echo "ERROR: No /sbin/init found on rootdev (or not mounted). Trouble ahead."
echo " You can try to fix it. Type 'exit' when things are done."
echo
/bin/sh
fi
else
echo
echo
"RESCUE mode"
echo
echo
" You can try to fix or rescue your system now. If you want"
echo " to boot into your fixed system, mount your root filesystem"
echo " read-only under /mnt:"
echo
echo
" # mount -o ro -t filesystem root_device /mnt"
echo
echo
" Type 'exit' when things are done."
echo
/bin/sh
fi

# Need to make sure OPTIONS+="db_persist" exists for all dm devices
# That should be handled in /sbin/mkinitrd now
/sbin/udevadm info --cleanup-db
/sbin/udevadm control --exit

unset ERR
mount -o move /proc /mnt/proc
mount -o move /sys /mnt/sys
mount -o move /run /mnt/run

[ "$DEVTMPFS" = "1" ] && mount -o move /dev /mnt/dev
echo "${INITRD}: exiting"
exec switch_root /mnt $INIT $RUNLEVEL



考察:

LVM に "/" をいれた場合、ramdisk(initrd.gz)無しだと "/" をマウント出来ずカーネルパニックに。ramdisk を生成させると上記で引用した init スクリプトが LVM や LUKS 及び RAID を上手く扱ってくれる。

また、Slackware の mkinitrd に -h オプションで swap デバイスのパス渡すと initrd.gz 内の resumedev 内に swsusp 対象デバイスのパスが書き込まれる。

ramdisk の init は最後に "/" をリードオンリーでマウントし、"/" 内部の sbin/init を呼び出すが、mkinitrd に -h オプションを渡しておくことで、ramdisk の段階でレジュームしてくれる。

結論:

Slackware でブート時に ramdisk(initrd.gz)を使う場合は -h オプションでサスペンド/ レジュームのための swap 領域を指定しておくと、実ドライブ側の init に移ってからレジュームプロセスを始めるより早い段階でレジューム出来、時間短縮になると予想する。また、レジュームが実ドライブマウント前に行われるので問題も生じにくいと思われる。

懸念:

EFI システムパーティション上の initrd.gz を第三者に改竄されるとヤバい(ESP がいじれる段階まで侵入されている時点で既にアウトではあるけれども)。

参考文献:

howtos:slackware_admin:hibernation - SlackDocs

https://docs.slackware.com/howtos:slackware_admin:hibernation

18:initrdファイルの作成 | 日経 xTECH(クロステック)

https://tech.nikkeibp.co.jp/it/article/COLUMN/20061025/251702/

Linux 初期 RAM ディスク (initrd) の概要

https://www.ibm.com/developerworks/jp/linux/library/l-initrd/index.html



編集後記:

主要な設定・管理ツールがすべてシェルスクリプト4というのは見通しが良いし、改造するにも楽しいので助かります。怪しげなツールを自作する際の教材としても Good!

何だこのエラー?と思ってスクリプトを開くとコメント行で解説がついているのはとても助かりました。

Slackware、使って楽しいディストリです。





  1. なんとなくドライブの潜在能力がもったいない気がするので。 



  2. https://docs.slackware.com/howtos:slackware_admin:hibernation 



  3. https://www.slackwiki.com/LVM/Luks_Encryption 



  4. 例えば pkgtool 関係は軒並みシェルスクリプト(+ dialog コマンド)。