пятница, 11 октября 2013 г.

Step by step build realtime linux from sources Astra-linux-orel-1.9 first part

   Задача: Собрать real-time дистрибутив OS Linux из исходников Astra-linux, при этом для повышения отказоустойчивости и отзывчивости, дистрибутив должен работать в оперативной памяти.
    Поскольку дистрибутив должен представлять собой ОС реального времени, необходимо по максимуму снизить потребление ресурсов операционной системой, с целью максимального предоставления этих ресурсов программе ради которой создавался данный дистрибутив. 
    Дистрибутив создается под определенное железо, на нем и будут выполнятся все последующие действия.

1. Устанавливаем по дефолту Astra-linux-orel-1.9:

Необходимо иметь два жестких диска (не обязательно, но так меньше гемора), на один из которых устанавливается Astra-linux.
На этапе Выбор программного обеспечения, оставляем "Базовые средства" остальные рюшечки в дизэйбл.

2. По окончании установки, загружаемся с установленной Astra-linux, и разбиваем 2-ой диск, создаем один раздел:

cfdisk /dev/sdb

3. Форматируем созданный раздел в файловую систему ext4:

mkfs.ext4 /dev/sdb1

4. Монтируем созданный раздел в каталог /mnt/target:

mkdir -p /mnt/target
mount /dev/sdb1 /mnt/target


5. Для обновления репозитария необходимо отредактировать файл: /etc/apt/sources.list. Приводим /etc/apt/sources.list к следующему виду:

cat /etc/apt/sources.list

#deb cdrom:[OS Astra Linux 1.9 orel - amd64 DVD]/ orel contrib main non-free
#deb ftp://astra.rusbitech.ru/os/astra/stable/orel/repository orel main contrib non-free
deb ftp://astra-linux.com/astra/stable/orel/1.9/repository orel main contrib non-free


После внесенных изменений обновляем репозитарии

apt-get update

6. Устанавливаем пакет debootstrap:

apt-get install debootstrap

7. Редактируем скрипт debootstrap:

nano /usr/sbin/debootstrap
в строке                                    DISABLE_KEYRING=""
необходимо поставить 1            DISABLE_KEYRING="1"
           
8. Устанавливаем систему в каталог /mnt/target куда (см. п.4) при монтирован второй жесткий диск:

debootstrap --include=nano,openssh-server,busybox --variant=buildd --arch amd64 orel /mnt/target ftp://astra-linux.com/astra/stable/orel/1.9/repository

По завершении должно появиться сообщение
   
I: Base system installed successfully.

9. Монтируем виртуальные файловые системы:

mount -t proc none /mnt/target/proc
mount -o bind /dev /mnt/target/dev
mount -t tmpfs none /mnt/target/tmp
mount -o bind /sys /mnt/target/sys


10. ЧэнджРутимся в новую систему:

chroot /mnt/target /bin/bash

11. Устанавливаем пароль рута:

passwd root

12. Редактируем файлы hostname hosts resolv.conf network/interfaces:

echo "Astra" > /etc/hostname
echo "127.0.0.1        localhost" > /etc/hosts
echo "nameserver 192.168.1.1" > /etc/resolv.conf
echo "auto eth0" > /etc/network/interfaces
echo "allow-hotplug eth0" >> /etc/network/interfaces
echo "iface eth0 inet dhcp" >> /etc/network/interfaces


13. Редактируем fstab:

echo "/dev/sda1 / ext4 errors=remount-ro 0 1" > /etc/fstab
echo "proc /proc proc defaults 0 0" >> /etc/fstab


14. Редактируем sources.list:

echo "deb ftp://astra-linux.com/astra/stable/orel/1.9/repository orel main contrib non-free" > /etc/apt/sources.list

15. Обновляем репозитарии:

apt-get update

16. Настраиваем часовой пояс:

dpkg-reconfigure tzdata

17. Устанавливаем ядро, при установке в качестве зависимости должен установиться grub:

Посмотреть какие ядра имеются в репозитарии можно командой

apt-cache search linux-image

Выбираем понравившееся и устанавливаем командой

apt-get install linux-image-3.2.0-27-generic

18. Обновляем grub, в результате будет создан конфигурационный файл grub.cfg:

update-grub

19. Выходим из chroot, ребутимся, в BIOS меняем загрузку дисков, все временная система готова для дальнейшего использования:

exit
reboot


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

mkdir -p /root/initramfs

21. Переходим в созданный каталог initramfs, и создаем каталоги будущей файловой системы:

cd /root/initramfs
mkdir -p bin dev etc lib lib64 proc sbin sys tmp usr/bin usr/sbin usr/share var/empty
chmod 1777 tmp


22. Копируем жизненно необходимые либ-файлы для будущей файловой системы, и создаем недостающие сим линки:

mkdir /root/initramfs/lib/x86_64-linux-gnu && cd /root/initramfs/lib/x86_64-linux-gnu
cp /lib/x86_64-linux-gnu/ld-2.13.so .
cp /lib/x86_64-linux-gnu/libc-2.13.so .
cp /lib/x86_64-linux-gnu/libm-2.13.so .
cp /lib/x86_64-linux-gnu/libprocps.so.0.0.1 .
cp /lib/x86_64-linux-gnu/libnss_files-2.13.so .


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

cp /lib/x86_64-linux-gnu/libgcc_s.so.1 .

Сим линки

pwd
/root/initramfs/lib/x86_64-linux-gnu

ln -s ld-2.13.so ld-linux-x86-64.so.2
ln -s libc-2.13.so libc.so.6
ln -s libm-2.13.so libm.so.6
ln -s libnss_files-2.13.so libnss_files.so.2
ln -s libprocps.so.0.0.1 libprocps.so.0

cd /root/initramfs/lib64
ln -s /lib/x86_64-linux-gnu/ld-2.13.so ld-linux-x86-64.so.2


23. Скачиваем и компилируем busybox:

cd /root && mkdir -p sources && cd sources
wget ftp://astra-linux.com/astra/stable/orel/1.9/repository/pool/main/b/busybox/busybox_1.20.0.orig.tar.bz2
tar -xjf busybox_1.20.0.orig.tar.bz2
cd busybox-1.20.0
make menuconfig

#####################################################
General Configuration --->
    Build Options --->
        [*] Build Busybox as a static binary (no shared libs)
#####################################################


Кроме статической компиляции выбираем нужные опции и мэйкуем
 

make
mkdir ../bb-static
cp busybox ../bb-static/
cd .. && rm busybox_1.20.0.orig.tar.bz2
cp bb-static/busybox /root/initramfs/bin/

 

BusyBox является единым образом для многих утилит, которые обычно используюся в linux системах (такие как ash, awk, sed, и др.) . Преимущество BusyBox в том что он, включая в себя функциональность многих необходимых утилит, имеет куда меньший размер. Это идеальный вариант для встраиваемых систем.

24. Ченджрутимся в образ новой системы и инсталлируем сим линки на busybox:

cd /root/initramfs && chroot . /bin/busybox --install -s
ln -s /bin/busybox init
ln -s /bin/busybox /bin/sh
rm linuxrc
exit


25. fstab:

touch /root/initramfs/etc/fstab
cat << EOF > /root/initramfs/etc/fstab
none    /proc    proc    defaults    0 0
EOF


26. inittab:

touch /root/initramfs/etc/inittab
cat << EOF > /root/initramfs/etc/inittab
::sysinit:/etc/init.d/rcS
::askfirst:-/bin/sh
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a -r
::restart:/sbin/init
tty2::askfirst:-/bin/sh
EOF


27. rcS:

touch /root/initramfs/init.d/rcS
cat << EOF > /root/initramfs/init.d/rcS
#!/bin/ash
mount -t proc proc /proc
mount -t sysfs sysfs /sys
mount -o remount,rw /dev/ram0 /

mknod /dev/null c 1 3
mknod /dev/tty c 5 0
mdev -s

mkdir -p /dev/pts
mount -t devpts devpts /dev/pts

ifconfig lo 127.0.0.1 up
ifconfig eth0 192.168.1.230 netmask 255.255.255.0 broadcast 192.168.1.255 up
sleep 1 && pid_eth0=`ps | grep -v grep | grep '-eth0' |awk '{print $1}'`
renice -20 -p $pid_eth0 && chrt -f -p 99 $pid_eth0 && taskset -p 1 $pid_eth0 > /dev/null 2>&1

telnetd -l /bin/login
/etc/init.d/rrr start &
/etc/init.d/ftpd start &
/usr/sbin/it &

ulimit -s 0
EOF

chmod +x /root/initramfs/init.d/rcS


Поскольку программа активно использует сеть, сетевой интерфейс eth0 запускается с приоритетом ввода вывода (nice -20), т.е. самый максимальный, использует планировщик FIFO (первый зашел первый вышел), с максимальным приоритетом доступа к ресурсам процессора (chrt -p 99) и привязывается к первому ядру процессора (taskset -p 1), что бы исключить миграцию сетевого интерфейса между ядрами. 

28. group:

touch /root/initramfs/etc/group
cat << EOF > /root/initramfs/etc/group
root:x:0:
toor:x:500:
EOF


29. gshadow:

touch /root/initramfs/etc/gshadow
cat << EOF > /root/initramfs/etc/gshadow
root:*::
toor:*::
EOF


30. passwd:

touch /root/initramfs/etc/passwd
cat << EOF > /root/initramfs/etc/passwd
root:x:0:0:,,,:/:/bin/sh
toor:x:500:500:,,,:/var/empty:
EOF


31. shadow:

touch /root/initramfs/etc/shadow
cat << EOF > /root/initramfs/etc/shadow
root::14000:0:99999:7:::
toor::14000:0:99999:7:::
EOF


32. nsswitch.conf:

touch /root/initramfs/etc/nsswitch.conf
cat << EOF > /root/initramfs/etc/nsswitch.conf
passwd: files
shadow: files
group:  files
hosts: dns
EOF


33. busybox.conf:
touch /root/initramfs/etc/busybox.conf
cat << EOF > /root/initramfs/etc/busybox.conf
[SUID]
login = ssx root.root
EOF


34. /etc/init.d/rrr Скрипт запуска и перезапуска программы, данный скрипт запускает другой скрипт rrr который лежит /root/vm4/rrr:

touch /root/initramfs/etc/init.d/rrr
cat << EOF > /root/initramfs/etc/init.d/rrr
#!/bin/ash
case "$1" in
        start)
                cd /root/vm4 && chrt 99 nice -n -20 ./rrr > /dev/null 2>&1 &
                ;;
        stop)
                pid_rrr=`ps | grep -v grep | grep './rrr' |awk '{print $1}'`
                pid_vm40=`ps | grep -v grep | grep './vm40' |awk '{print $1}'`
                kill -9 $pid_vm40 $pid_rrr & killall vm40 > /dev/null 2>&1 &
                ;;
        restart)
                "$0" stop
                "$0" start
                ;;
        *)
                echo "only start stop restart"
                exit 1
esac
exit $?
EOF


35. /etc/init.d/ftpd:

touch /root/initramfs/etc/init.d/ftpd
cat << EOF > /root/initramfs/etc/init.d/ftpd
#!/bin/ash
case "$1" in
        start)
                tcpsvd -vE 0.0.0.0 21 ftpd -w /mnt/111 &
                ;;
        stop)
                pid_ftpd=`ps | grep -v grep | grep 'ftpd' |awk '{print $1}'`
                kill $pid_ftpd
                ;;
        restart)
                "$0" stop
                "$0" start
                ;;
        *)
                echo "only start stop restart"
                exit 1
esac
exit $?
EOF


36. Создаю скрипт /usr/sbin/it для синхронизации времени в момент загрузки:

touch /root/initramfs/usr/sbin/it
cat << EOF > /root/initramfs/usr/sbin/it
#!/bin/ash
busybox ntpd -nq -p 192.168.1.240  
    # на этом ip, ntp server в локальной сети
EOF                         


cp /etc/localtime /root/initramfs/etc/localtime    # Это исполняемый файл, долго мучался с часовым поясом, пока не догадался тупо скопировать данный файл в свою вновь созданную систему.

37. vm4 Каталог с исполняемым файлом, т.е. сама программа:

С мэйкованием отдельная песня, в этом каталоге лежит еще скрипт rrr, который запускает и перезапускает исполняемый файл vm40, об этом позже

cp -a /path/to/vm4 /root/initramfs/root/
chmod +x /root/initramfs/root/vm4/vm40


38. build initramfs:

cd /root/initramfs
find . | cpio -H newc -o | gzip -9 > /root/sources/initramfs.igz


39. build kernel:

cd /root/sources
wget ftp://astra-linux.com/astra/stable/orel/1.9/repository/pool/main/l/linux/linux_3.2.0.orig.tar.gz
wget https://www.kernel.org/pub/linux/kernel/projects/rt/3.2/older/patch-3.2-rt10.patch.bz2
wget http://www.anticore.org/ratgentoo/files/kernels/preempt/config-2.6.33.7.2-rt30-minimal
tar xvzf linux_3.2.0.orig.tar.gz
bzip2 -d patch-3.2-rt10.patch.bz2
cd linux-3.2
patch -p1 < ../patch-3.2-rt10.patch
cp ../config-2.6.33.7.2-rt30-minimal .config
linux64 make oldconfig
linux64 make menuconfig                                                      # Тут отдельная грустная песня, об этом в part two.
linux64 make -j3
cp arch/x86/boot/bzimage /root/sources/vmlinuz-preempt


40. Сборка конечной системы:

Новую систему будем устанавливать на первый жесткий диск, на который изначально устанавливалась Astra-linux-orel-1.9 в дефолтной конфигурации (см. п.1)

41. Разбиваем диск:

dd if=/dev/zero of=/dev/sdb bs=1 count=512
cfdisk /dev/sdb


Под первый раздел выделяем 1GB, под второй все остальное, на первом разделе необходимо установить метку BOOT.

/dev/sdb1    1024MB
/dev/sdb2    Все оставшиеся пространство диска

42. Форматируем разделы:

Первый раздел форматируем в файловую систему ext2, с первого раздела система в момент загрузки будет только читать файлы, запись на этот раздел производится не будет, соответственно журналирование не нужно, поэтому файловая система ext2 будет более предпочтительна на данном разделе.
На первом разделе будет лежать ядро системы vmlinuz-preempt, образ файловой системы initramfs.igz, и загрузчик grub.
На втором разделе, будут лежать необходимые файлы, образ системы из которого собирался initramfs.igz, необходимые скрипты и другое, соответсвенно будет производится запись на данный раздел, поэтому предпочтительной будет файловая система ext4.

mke2fs /dev/sdb1
tune2fs -c 0 -i 0 /dev/sdb1
mkfs.ext4 /dev/sdb2


43. Монтируем первый раздел в каталог /mnt/target:

mkdir -p /mnt/target
mount /dev/sdb1 /mnt/target


44. Копируем ядро и образ системы на раздел /dev/sdb1:

cp /root/sources/vmlinuz-preempt /mnt/target
cp /root/sources/initramfs.igz /mnt/target


45. Устанавливаем загрузчик GRUB:

На данном этапе существовала определенная проблема, дело в том, что в репозитариях Astra-linux, присутствовал только GRUB2, который существенно отличается от GRUB.
Чтобы я ни делал, у меня так и не получилось заставить работать GRUB2 в связке с initramfs.igz. Ман второго граба не подсказал решения проблемы, так же как и гугление.
После тщетных попыток было принято решение временно (до момента нахождения решения, как же заставить работать GRUB2 в связке с initramfs.igz) воспользоваться первым грабом, взятым с дистрибутива Gentoo LIVE CD.
Поскольку дистрибутив собирался из исходников Astra-linux, для загрузчика было сделано исключение, кроме загрузчика GRUB, исключение так же было сделано для реалтайм патча к ядру, который был скачан с kernel.org (см. п.39), так как данный патч так же отсутствовал в репозитариях Astra-linux.

Грузимся с Gentoo LIVE CD, монтируем раздел на который в п.44 были скопированы vmlinuz-preempt и initramfs.igz в директорию /mnt/target.
Внимание /dev/sdb1 после загрузки с Gentoo LIVE CD мог изменится на /dev/sdа1, необходима проверка

mkdir -p /mnt/target
mount /dev/sda1 /mnt/target


Проверям какой раздел примонтирован

ls -la /mnt/target
drwxr-xr-x    4   root    root             4096 Sep 18 15:41 .
drwxr-xr-x    15 root    root             0 Oct 10 10:28 ..
-rw-r--r--      1   root     root            3095790 Sep 18 15:41 initramfs.igz
drwx------     2   root     root            16384 Aug 20 14:49 lost+found
-rw-r--r--      1   root     root            2313184 Aug  7 15:15 vmlinuz-preempt 


Устанавливаем GRUB

mkdir /mnt/target/grub
cp /boot/grub/stage? /boot/grub/e2fs_stage1_5 /mnt/target/grub
umount /mnt/target

grub
grub> device (hd0) /dev/sda
grub> root (hd0,0)
grub> setup (hd0)
grub> quit


Создаем файл menu.lst

Для этого снова монтируем раздел

mount /dev/sda1 /mnt/target

touch /mnt/target/grub/menu.lst
echo "timeout 0" > /mnt/target/grub/menu.lst
echo "default 0" >> /mnt/target/grub/menu.lst
echo "fallback 2" >> /mnt/target/grub/menu.lst
echo "title Preempt" >> /mnt/target/grub/menu.lst
echo "kernel /vmlinuz-preempt initrd=/initramfs.igz quiet ramdisk_size=32768" >> /mnt/target/grub/menu.lst
echo "initrd /initramfs.igz" >> /mnt/target/grub/menu.lst


Проверяем

cat /mnt/target/grub/menu.lst

timeout 0
default 0
fallback 2
title Preempt
kernel /vmlinuz-preempt initrd=/initramfs.igz quiet ramdisk_size=32768
initrd /initramfs.igz


Отмонтируем раздел

umount /mnt/target

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


    Продолжение следует ...