LFS - часть 1.

Всем привет!

Это первая статья из цикла LFS.


В ней будет затронута начальная подготовка к сборке LFS.


Данная статья подразумевает наличие минимальных познаний в OS Linux.


Для начала немного нудной теории:


Linux - общее название Unix-подобных операционных систем, основанных на одноимённом ядре. Ядро Linux создаётся и распространяется в соответствии с моделью разработки свободного и открытого программного обеспечения. Поэтому общее название не подразумевает какой-либо единой «официальной» комплектации Linux; они распространяются в основном бесплатно в виде различных готовых дистрибутивов, имеющих свой набор прикладных программ и уже настроенных под конкретные нужды пользователя.


На самом деле, Википедии достаточно, чтобы понять что такое Linux – можете почитать в свободное время.


Теперь поговорим о LFS.


Что это такое? LFS – Linux From Scratch – книга, описывающая процесс сборки своего дистрибутива операционной системы Linux из исходных кодов. Следует сказать сразу — дистрибутив собранный по книге LFS умеет мало что. Хотя правильно сказать было бы, что он, самое главное, может включаться-выключаться, использовать Ethernet-соединение, и - самое важное для нас – компилировать все, что захотим. Это на случай дальнейшего преобразования LFS в BLFS.


Для чего мы собираем LFS? Как минимум – чтобы узнать подробности про каждый пакет в Вашей системе, но самое главное – узнать об их взаимодействии. Так сказать, небольшое изучение Linux изнутри.


Что для этого требуется? Для сборки LFS необходим компьютер или виртуальная машина с установленной на нем ОС GNU/Linux и достаточное количество места на диске (минимальное требование - 4Гб, но в идеале - берите от 20Гб). В принципе, подойдет любой дистрибутив. Лично я использую Сentos 7


==

[root@pm-for-lfs ~]# cat /etc/centos-release

CentOS Linux release 7.2.1511 (Core)

==


В качестве сравнения приведу «железные» параметры своей системы


==

[root@pm-for-lfs ~]# cat /proc/meminfo

MemTotal: 7942520 kB

[root@pm-for-lfs ~]# cat /proc/cpuinfo

model name : Intel(R) Core(TM) i5-4200U CPU @ 1.60GHz

==


Чтобы упростить процесс сборки, оставьте неразмеченную область на диске от 20Гб (на всякий случай). Чуть позже мы создадим из этой области необходимый нам раздел и возьмем в пользование.

В хостовой Linux-системе должны быть установлены пакеты, перечисленные в официальных системных требованиях. Скорее всего они все имеются, но в любом случае они легко устанавливаются из репозиториев. Одним из вариантов является использование любого LiveCd с Linux – в таком случае собирать LFS можно на машину, не содержащую никакой ОС. В общем, выбирать вам.


Настоятельно не рекомендую копипастить в терминал из этой статьи, либо из самой книги LFS – ведь мы будем собирать систему для того, чтобы разобраться с принципом построения работоспособной операционной системы, понимать что и как связано друг с другом. К каждому этапу, указанию, команде надо подходить осмысленно и не торопясь.


С чего начнем?


Для корректной сборки системы нам необходимы:

• компилятор

• линковщик

• требуемые библиотеки


У нас же есть только их исходники и компилятор в хостовой системе. Собирать необходимое ПО мы начнем именно им, однако есть нюанс – компиляция некоторых частей системы не будет работоспособна на начальном этапе ее построения – некоторые компоненты используют динамическую компоновку библиотек, а нам необходимо скомпоновать статически – т.е. включить весь необходимый код для работы в исполняемый файл явным образом.


Требования:


Хостовая система должна соответствовать следующим требованиям к установленному на машине ПО:


==

Bash-3.2 (/bin/sh должен быть симлимнком или ссылкой на bash)

Binutils-2.17 (версии новее, чем 2.27 не рекомендованы, т.к. не протестированы)

Bison-2.3 (/usr/bin/yacc должно быть ссылкой на bison или скриптом, который запускает bison)

Bzip2-1.0.4

Coreutils-6.9

Diffutils-2.8.1

Findutils-4.2.31

Gawk-4.0.1 (/usr/bin/awk должен быть ссылкой на gawk)

GCC-4.7 including the C++ compiler, g++ (версии новее 6.2.0 не рекомендованы, т.к. не протестированы)

Glibc-2.11 (версии новее 2.24 не рекомендованы, т.к. не протестированы)

Grep-2.5.1a

Gzip-1.3.12

Linux Kernel-2.6.32

M4-1.4.10

Make-3.81

Patch-2.5.4

Perl-5.8.8

Sed-4.1.5

Tar-1.22

Texinfo-4.7

Xz-5.0.0

==


Все пакеты имеют следующий алгоритм сборки, кроме тех случаев, когда в явном виде не указано иного:

• распаковка архива

$ tar -pxf <package-archive-file-name>

• Переход в распакованный каталог

$ cd <package-dir-name>

• Выполнение инструкции по сборке – для каждого пакета описаны отдельно

• Переход на каталог выше, назад в $LFS/source, затем удаление всех созданных при распаковке и сборке директорий.

Подготовка к сборке системы:


Для начала задействуем неразмеченное пространство с помощью fdisk:


==

[root@pm-for-lfs ~]# fdisk

Usage:

fdisk [options] <disk> change partition table

fdisk [options] -l <disk> list partition table(s)

fdisk -s <partition> give partition size(s) in blocks

Options:

-b <size> sector size (512, 1024, 2048 or 4096)

-c[=<mode>] compatible mode: 'dos' or 'nondos' (default)

-h print this help text

-u[=<unit>] display units: 'cylinders' or 'sectors' (default)

-v print program version

-C <number> specify the number of cylinders

-H <number> specify the number of heads

-S <number> specify the number of sectors per track

[root@pm-for-lfs ~]# fdisk -l

WARNING: fdisk GPT support is currently new, and therefore in an experimental phase. Use at your own discretion.

Disk /dev/sda: 120.0 GB, 120034123776 bytes, 234441648 sectors

Units = sectors of 1 * 512 = 512 bytes

Sector size (logical/physical): 512 bytes / 512 bytes

I/O size (minimum/optimal): 512 bytes / 512 bytes

Disk label type: gpt

==


Создадим раздел в неразмеченной области с помощью fdisk.

Первой опцией (n) мы говорим, что хотим создать новую партицию,

Далее нажимаем Enter для применения условий по умолчанию – либо вводим необходимые свои. Команда (w) запишет изменения в систему.


==

[root@pm-for-lfs ~]# fdisk /dev/sda

WARNING: fdisk GPT support is currently new, and therefore in an experimental phase. Use at your own discretion.

Welcome to fdisk (util-linux 2.23.2).

Changes will remain in memory only, until you decide to write them.

Be careful before using the write command.

Command (m for help): m

Command action

d delete a partition

g create a new empty GPT partition table

G create an IRIX (SGI) partition table

l list known partition types

m print this menu

n add a new partition

o create a new empty DOS partition table

q quit without saving changes

s create a new empty Sun disklabel

w write table to disk and exit

Command (m for help): n

Partition number (4-128, default 4):

First sector (34-234441614, default 94226432):

Last sector, +sectors or +size{K,M,G,T,P} (94226432-234441614, default 234441614):

Created partition 4

Command (m for help): p

Disk /dev/sda: 120.0 GB, 120034123776 bytes, 234441648 sectors

Units = sectors of 1 * 512 = 512 bytes

Sector size (logical/physical): 512 bytes / 512 bytes

I/O size (minimum/optimal): 512 bytes / 512 bytes

Disk label type: gpt

# Start End Size Type Name

1 2048 2050047 1000M EFI System EFI System Partition

2 2050048 4098047 1000M Microsoft basic

3 4098048 94226431 43G Linux LVM

4 94226432 234441614 66.9G Linux filesyste

Command (m for help): w

The partition table has been altered!

Calling ioctl() to re-read partition table.

WARNING: Re-reading the partition table failed with error 16: Device or resource busy.

The kernel still uses the old table. The new table will be used at

the next reboot or after you run partprobe(8) or kpartx(8)

Syncing disks.

==


Ядро не узнает о сделанных вами изменениях, пока вы не перезагрузитесь или не проинформируете его. Сделать это можно, использовав команду partprobe из пакета parted.


==

[root@pm-for-lfs ~]# partprobe

==

Отформатируем раздел в ext4


==

[root@pm-for-lfs ~]# mkfs.ext4 /dev/sda4

mke2fs 1.42.9 (28-Dec-2013)

Discarding device blocks: done

Filesystem label=

OS type: Linux

Block size=4096 (log=2)

Fragment size=4096 (log=2)

Stride=0 blocks, Stripe width=0 blocks

4382720 inodes, 17526897 blocks

876344 blocks (5.00%) reserved for the super user

First data block=0

Maximum filesystem blocks=2166358016

535 block groups

32768 blocks per group, 32768 fragments per group

8192 inodes per group

Superblock backups stored on blocks:

32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,

4096000, 7962624, 11239424

Allocating group tables: done

Writing inode tables: done

Creating journal (32768 blocks): done

Writing superblocks and filesystem accounting information: done

[root@pm-for-lfs ~]#

==


Ура! Мы создали раздел и отформатировали его. Что же дальше? Нам необходимо задать некоторые переменные среды. Начнем с определения и проверки переменной LFS:


==

[root@pm-for-lfs ~]# export LFS=/mnt/lfs

[root@pm-for-lfs ~]# echo $LFS

/mnt/lfs

[root@pm-for-lfs ~]#

==


Если у вас аналогичный вывод в консоли – вы все сделали правильно.

Далее нам необходимо создать директорию /mnt/lfs и примонтировать туда ранее созданный раздел:


==

[root@pm-for-lfs ~]# mkdir -pv $LFS

mkdir: created directory /mnt/lfs

[root@pm-for-lfs ~]# mount -v -t ext4 /dev/sda4 $LFS

mount: /mnt/lfs does not contain SELinux labels.

You just mounted an file system that supports labels which does not

contain labels, onto an SELinux box. It is likely that confined

applications will generate AVC messages and not be allowed access to

this file system. For more details see restorecon(8) and mount(8).

mount: /dev/sda4 mounted on /mnt/lfs.

==


Оп! А здесь мы наткнулись на SELinux. Не вдаваясь в подробности, просто отключим его.


==

[root@pm-for-lfs ~]#sed -i s/^SELINUX=.*/SELINUX=disabled/g /etc/selinux/config

[root@pm-for-lfs ~]#setenforce 0

==

Теперь создадим первоначально необходимую структуру папок:


==

[root@pm-for-lfs ~]# mkdir -v $LFS/sources

mkdir: created directory /mnt/lfs/sources™

[root@pm-for-lfs ~]# chmod -v a+wt $LFS/sources

mode of ‘/mnt/lfs/sources’ changed from 0755 (rwxr-xr-x) to 1777 (rwxrwxrwt)

[root@pm-for-lfs ~]#

==


Достаем wget-list отсюда:


==

http://www.linuxfromscratch.org/lfs/view/stable/wget-list

==


Создаем файлик wget-list и копируем туда содержимое страницы выше:


==

wget --input-file=wget-list --continue --directory-prefix=$LFS/sources

==


И ждем пока все скачается.

Ждем заветной надписи :


==

Total wall clock time: 3m 37s

Downloaded: 80 files, 351M in 2m 51s (2.05 MB/s)

==


Продолжаем создавать папки:


==

[root@pm-for-lfs ~]# mkdir -v $LFS/tools

mkdir: created directory ‘/mnt/lfs/tools’

==


Делаем символьную ссылку, необходимую для корректной работы компилятора, линковщика и компоновщика для изолированной среды в последующем.


==

[root@pm-for-lfs ~]# ln -sv $LFS/tools /

‘/tools’ -> ‘/mnt/lfs/tools’

==


Теперь создаем группу LFS и пользователя LFS:


==

[root@pm-for-lfs ~]# groupadd lfs

[root@pm-for-lfs ~]# useradd -s /bin/bash -g lfs -m -k /dev/null lfs

[root@pm-for-lfs ~]# passwd lfs

Changing password for user lfs.

New password:

Retype new password:

passwd: all authentication tokens updated successfully.

==


Меняем владельца на созданных нами папках:


==

[root@pm-for-lfs ~]# chown -v lfs $LFS/tools

changed ownership of ‘/mnt/lfs/tools’ from root to lfs

[root@pm-for-lfs ~]# chown -v lfs $LFS/sources

changed ownership of ‘/mnt/lfs/sources’ from root to lfs

==


И заходим под свежесозданным пользователем:


==

[root@pm-for-lfs ~]# su - lfs

-bash-4.2$

==

Создаем два скрипта оболочки для задания правильного рабочего окружения.

В первом файле мы заменяем запущенную уже оболочку на оболочку с пустой средой, за исключением переменных TERM и PS1. Term – переменная типа терминала, PS1 – первичная подсказка shell ($ по умолчанию).


==

-bash-4.2$ cat > ~/.bash_profile << "EOF"

> exec env -i HOME=$HOME TERM=$TERM PS1='\u:\w\$ ' /bin/bash

> EOF

-bash-4.2$

-bash-4.2$ cat > ~/.bashrc << "EOF"

> set +h

> umask 022

> LFS=/mnt/lfs

> LC_ALL=POSIX

> LFS_TGT=$(uname -m)-lfs-linux-gnu

> PATH=/tools/bin:/bin:/usr/bin

> export LFS LC_ALL LFS_TGT PATH

> EOF

-bash-4.2$ source ~/.bash_profile

lfs:~$

==



Скрипт оболочки — это просто файл, содержащий последовательность команд оболочки. Подобно функциям, скрипты можно выполнять как обычные команды. Синтаксис доступа к аргументам такой же, как и для функций.


В общем случае при запуске скрипта запускается новый процесс. Для того, чтобы выполнить скрипт внутри текущей сессии bash, необходимо использовать команду source, синонимом которой является просто точка ".". Скрипт оболочки служит просто аргументом этой команды.


На этом на сегодня закончим.


Буду благодарен за исправления, рекомендации или пожелания.


Обязательно напишите в комментариях, если Вам категорически не нравится данный материал, для меня это важно.