Linux From Scratch. Введение
Мне понадобился минимальный Linux, который бы удовлетворял следующим требованиям:
- Максимально оптимизированная система;
- Возможность полностью контролировать компоненты системы;
- Иметь полный контроль над системой в целом.
Поэтому я принял решение собрать LFS.
Опыт сборки уже был, примерно год назад я собирал LFS, а потом и BLFS, правда BLFS я не дособрал.
Сборка LFS у меня еще работает и осталась, но хочется собрать все по новой и сделать дополнительные заметки по сборке.
Сам по себе мануал по сборке LFS написан очень подробно и хорошо, поэтому переписывать его целиком не вижу смысла, но основные проблемы с которыми я буду сталкиваться я постараюсь описать подробно, а также все дополнительные настройки и “ковыряние” в исходиках разных пакетов.
Требования к хост-системе
По требованиям к системе, на которой будет собираться LFS - требуется как минимум 4 ядра и 8GB оперативной памяти. Это оправданные рекомендации, в целом чем больше тем лучше, потому что собираться это все дело даже на 4 ядрах будет довольно таки долго…
Я буду собирать всё на физической машине со следующими характеристиками:
OS | Kernel | CPU | RAM | Storage |
---|---|---|---|---|
Fedora Linux 39 | 6.5.6-300.fc39.x86_64 | AMD Ryzen 9 5950X | 128 GB | SSD на 240G |
Требования к софту на хост-системе
Версии софта на моей хост-системе:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
OK: Coreutils 9.3 >= 7.0
OK: Bash 5.2.15 >= 3.2
OK: Binutils 2.40 >= 2.13.1
OK: Bison 3.8.2 >= 2.7
OK: Diffutils 3.10 >= 2.8.1
OK: Findutils 4.9.0 >= 4.2.31
OK: Gawk 5.2.2 >= 4.0.1
OK: GCC 13.2.1 >= 5.1
OK: GCC (C++) 13.2.1 >= 5.1
OK: Grep 3.11 >= 2.5.1a
OK: Gzip 1.12 >= 1.3.12
OK: M4 1.4.19 >= 1.4.10
OK: Make 4.4.1 >= 4.0
OK: Patch 2.7.6 >= 2.5.4
OK: Perl 5.38.0 >= 5.8.8
OK: Python 3.12.0 >= 3.4
OK: Sed 4.8 >= 4.1.5
OK: Tar 1.35 >= 1.22
OK: Texinfo 7.0.3 >= 5.0
OK: Xz 5.4.4 >= 5.0.0
OK: Linux Kernel 6.5.6 >= 4.14
OK: Linux Kernel supports UNIX 98 PTY
Aliases:
OK: awk is GNU
ERROR: yacc is NOT Bison
OK: sh is Bash
Compiler check:
OK: g++ works
Скрипт для проверки, находится ниже по тексту Основного раздела из мануала
Есть одна ошибка: ERROR: yacc is NOT Bison
.
Так как Bison является заменой YACC, нужно сделать враппер, который будет запускать YACC из Bison.
Из man bison:
1
2
-y, --yacc
emulate POSIX Yacc
Файл нужно создать в переменных $PATH
. Я разместил скрипт в /usr/bin
.
Оригинальный YACC переименовал: mv /usr/bin/yacc /usr/bin/yacc_orig
Враппер /usr/bin/yacc
:
1
2
3
4
5
6
7
8
#!/usr/bin/env bash
BISON=$(which /usr/bin/bison)
if [ -z "$BISON" ]; then
echo "bison not found"
exit -1
fi
$BISON -y "$@"
И не забываем сделать chmod +x /usr/bin/yacc
.
После добавления враппера, ошибка должна уйти:
1
2
[spybull@fedora ~]$ bash version-check.sh | grep yacc
OK: yacc is Bison
Требования к разметке диска
Я буду использовать весь диск целиком под систему. Общий объем которого составляет 240GB.
Схема разметки
Partition | Filesystem | Size | Mount Point | Description |
---|---|---|---|---|
/dev/sda1 | fat32 | 600 MB | /boot/efi | Системный раздел EFI |
/dev/sda2 | ext4 | 1 GB | /boot | Раздел для хранения ядра, initramfs и т.д |
/dev/sda3 | отсутсвует | всё что осталось | отсутсвует | Раздел под LVM |
Схема разметки LVM
pv | vg | lv | fs | size |
---|---|---|---|---|
/dev/sda3 | lfs | root | ext4 | 15 GB |
/dev/sda3 | lfs | swap | swap | 4 GB |
/dev/sda3 | lfs | home | ext4 | 20 GB |
Этого достаточно, остальное место можно оставить свободным и в будущем расширить или добавить отдельные тома LVM.
Подготовка диска под систему
Для создания таблицы разделов буду использовать parted.
Заходим в утилиту parted /dev/sda
и далее идет список команд, которые использовались для создания разделов:
Разметка диска с помощью parted
1
2
3
4
5
6
7
unit MiB
mklabel gpt
mkpart primary fat32 1MiB 600MiB
mkpart primary ext4 601MiB 1625MiB
mkpart primary 1625MiB 100%
set 1 boot on
set 3 lvm on
Для удобства я выбрал юниты MiB. Эти единицы удобнее использовать, потому что MB = 1000/MiB = 1024
Настройка LVM
1
2
3
4
5
pvcreate /dev/sda3
vgcreate lfs /dev/sda3
lvcreate -L15G -n root lfs
lvcreate -L4G -n swap lfs
lvcreate -L20G -n home lfs
Создание файловых систем
1
2
3
4
5
mkfs.vfat /dev/sda1
mkfs.ext4 /dev/sda2
mkfs.ext4 /dev/lfs/root
mkswap /dev/lfs/swap
mkfs.xfs /dev/lfs/home
Ранее при сборке LFS я использовал xfs для / и точно помню, что версия файловой системы, которая использовалась для форматирования диска на основной системе не совпадала с версией xfs в LFS. Я думаю что эта проблема может возникнуть и с любой другой файловой системой, поэтому лучше заранее проверить версии и изменения в пакетах которыми вы форматируете разделы на хосте, и версии файловых систем которыми вы будете пользоваться в LFS.
Монтирование разделов
В качестве точки монтирования делаем /mnt/lfs
аналогично как написано в мануале. Заводим переменную LFS для удобства работы.
1
2
export LFS=/mnt/lfs
mkdir -p $LFS
Создаем директории и монтируем наши рабочие разделы, не забываем, что у нас LVM, поэтому монтируем корень из LVM в первую очередь:
1
2
mount /dev/lfs/root $LFS
mkdir -p $LFS/{boot,home}
Выглядит это так:
1
2
3
4
tree $LFS
/mnt/lfs
├── boot
└── home
Монтирование boot и home разделов
1
2
mount /dev/lfs/home $LFS/home/
mount /dev/sda2 $LFS/boot
Монтирование efi раздела
1
2
mkdir $LFS/boot/efi
mount /dev/sda1 $LFS/boot/efi/
Включаем swap
1
swapon /dev/lfs/swap
Swap должен стать активным:
1
2
3
4
[root@fedora ~]# swapon -s
Filename Type Size Used Priority
/dev/zram0 partition 8388604 0 100
/dev/dm-6 partition 4194300 0 -2
Результат создания и монтирования разделов
1
2
3
4
5
6
7
8
9
10
11
12
[root@fedora ~]# df -Th | grep lfs
/dev/mapper/lfs-root ext4 15G 496M 14G 4% /mnt/lfs
/dev/sda2 ext4 974M 268K 906M 1% /mnt/lfs/boot
/dev/sda1 vfat 598M 4.0K 598M 1% /mnt/lfs/boot/efi
/dev/mapper/lfs-home xfs 20G 175M 20G 1% /mnt/lfs/home
[root@fedora ~]# tree $LFS
/mnt/lfs
├── boot
│ └── efi
└── home
Пакеты и патчи
Создаем директорию sources
1
mkdir $LFS/sources
Для сборки базовой системы требуется набор пакетов и патчей, которые нужно скачать. LFS предоставляет URL лист с нужными версиями пакетов и патчей. Данный список мы и возьмем отсюда wget-list-sysv.
Также скачаем файл с хэшсуммами для проверки.
1
2
wget https://www.linuxfromscratch.org/lfs/view/stable/wget-list-sysv
wget https://www.linuxfromscratch.org/lfs/view/stable/md5sums --directory-prefix=$LFS/sources
Выкачиваем пакеты
1
wget --input-file=wget-list-sysv --continue --directory-prefix=$LFS/sources
После скачивания проверяем совпадает ли количество пакетов в файле с количеством скачанного
1
2
3
4
[root@fedora ~]# cat wget-list-sysv | wc -l
93
[root@fedora ~]# ls -1 $LFS/sources | grep -v md5 | wc -l
93
Проверка хэш сумм
1
2
3
pushd $LFS/sources/
[root@fedora sources]# md5sum -c md5sums | grep -iwv ok
[root@fedora sources]#
Вывод должен быть пустым
Необходимо сделать владельца и группу root для всех файлов:
1
chown root:root $LFS/sources/*
Окончательные настройки
Создание структуры директорий
Берем скрипт из документации и просто исполняем его:
1
2
3
4
5
6
7
8
9
mkdir -pv $LFS/{etc,var} $LFS/usr/{bin,lib,sbin}
for i in bin lib sbin; do
ln -sv usr/$i $LFS/$i
done
case $(uname -m) in
x86_64) mkdir -pv $LFS/lib64 ;;
esac
Создаем еще одну директорию для кросс-компилятора:
1
mkdir -pv $LFS/tools
Добавляем LFS пользователя
1
2
groupadd lfs
useradd -s /bin/bash -g lfs -m -k /dev/null lfs
Задаем пароль для пользователя:
1
passwd lfs
Выдаем права на директории:
1
2
3
4
chown -v lfs $LFS/{usr{,/*},lib,var,etc,bin,sbin,tools}
case $(uname -m) in
x86_64) chown -v lfs $LFS/lib64 ;;
esac
Логинимся:
1
su - lfs
Настройка окружения
Создаем .bash_profile
:
1
2
3
cat > ~/.bash_profile << "EOF"
exec env -i HOME=$HOME TERM=$TERM PS1='\u:\w\$ ' /bin/bash
EOF
Добавляем список необходимых переменных в .bashrc
:
1
2
3
4
5
6
7
8
9
10
11
12
cat > ~/.bashrc << "EOF"
set +h
umask 022
LFS=/mnt/lfs
LC_ALL=POSIX
LFS_TGT=$(uname -m)-lfs-linux-gnu
PATH=/usr/bin
if [ ! -L /bin ]; then PATH=/bin:$PATH; fi
PATH=$LFS/tools/bin:$PATH
CONFIG_SITE=$LFS/usr/share/config.site
export LFS LC_ALL LFS_TGT PATH CONFIG_SITE
EOF
Разница .bash_profile
и .bashrc
заключается в том, что при входе в систему читается .bash_profile
один раз, а .bashrc
- читается каждый раз, когда создается новый терминал. Соответсвенно внесенные изменения в .bashrc
можно применить сразу, создав новое окно терминала.
Перечитываем вручную .bash_profile
1
source ~/.bash_profile