Budujemy Linuksa od zera

Jeśli naprawdę chcemy się dowiedzieć, jak działa Linux, jedną z najlepszych opcji jest zbudowanie go od podstaw.

Linux od Scratch (LFS) [1] i Beyond Linux od Scratch (BLFS) [2] to samouczki online, które zawierają szczegółowe instrukcje, jak krok po kroku skompilować i złożyć własny system linuksowy, korzystając z dostępnych źródeł. Skrót „LFS” odnosi się zarówno do dokumentacji, jak i wynikowego systemu.

Jeśli pracujemy na Linuksie wystarczająco długo, prawdopodobnie spotkaliśmy się z potrzebą kompilacji oprogramowania – czy to własnej aplikacji, czy też projektu pobranego z GitHuba bądź innej witryny z kodem źródłowym. Mogłoby się wydawać, że kompilacja systemu operacyjnego jest podobna – i faktycznie, pod pewnymi względami tak jest, jednak budowanie kompletnego systemu operacyjnego jest znacznie bardziej skomplikowane niż kompilacja typowej aplikacji użytkowej.

Pamiętajmy, że współczesne dystrybucje, których używamy do zbudowania danej aplikacji, zawierają kompletny zestaw narzędzi, który został odpowiednio przetestowany pod kątem zgodności. Wyobraźmy sobie, że to środowisko służące do budowania jeszcze nie istnieje i musimy stworzyć je sami. Obejmuje ono kompilator, a także ważne biblioteki, takie jak glibc i libstdc++. Instrukcje opisane w dokumencie Linux from Scratch (nazywane przez autorów dokumentu „książką”, dla odróżnienia od LFS jako systemu) obejmują 11 rozdziałów podzielonych na pięć głównych części. Autorzy dzielą proces budowania systemu na trzy etapy (Rysunek 1):

  • konfiguracja hosta służącego do kompilacji (część II, rozdziały 2 do 4)
  • zbudowanie zestawu do kompilacji skrośnej i tymczasowo wymaganych narzędzi (Część III, rozdziały 5 do 7)
  • utworzenie faktycznego systemu LFS (Część IV, rozdziały 8 do 11).

Gerard Beekmans, autor LFS-a, rozpoczął pracę z Linuksem w 1998 roku. Po doświadczeniach z różnymi dystrybucjami zdał sobie sprawę, że nie istnieje rozwiązanie idealne, które będzie odpowiadało wszystkim, i postanowił zbudować własny system. Kiedy zaczął go kompilować, szybko odkrył, że wcale nie jest to proste – od razu napotkał mnóstwo błędów podczas kompilacji i problemów ze wzajemnymi zależnościami. Zdobyte doświadczenie, którym podzielił się ze społecznością linuksową, spotkało się z tak szerokim zainteresowaniem, że narodził się projekt LFS.

LFS jest jednym z kilku zestawów dystrybucyjnych, które skupiają się na umożliwieniu użytkownikowi zbudowania własnego systemu. Większość pozostałych projektów tego typu specjalizuje się w obszarze wbudowanym, np. BitBake z projektu Yocto [3]. Inne opcje to m.in. Linux Target Image Builder [4], OpenWrt [5] czy Scratchbox [6].

LFS stara się przestrzegać standardów, takich jak POSIX.1-2008 [7], który definiuje interfejs systemu operacyjnego, w tym środowiska do celów przenośności, Filesystem Hierarchy Standard FHS 3.0 [8] i Linux Standard Base LSB 5.0 [9]. Linux Standard Base definiuje cztery standardy (podstawowy, pulpit, środowiska uruchomieniowego języków i obrazowania), które są przedmiotem gorących dyskusji. LFS może je obsługiwać tylko częściowo ze względu na minimalne zasoby programowe.

Jeśli będziemy postępowali zgodnie z instrukcjami, otrzymamy minimalny system linuksowy, który (zgodnie z LFS v10.1 z marca 2021 r.) będzie zawierał: system plików Ext4, Grub 2.04, jądro 5.10.17, Bash 5.1, GCC 10.2, Perl 5.32.1, Python 3.9.2 i Vim 8.2. Możemy wybierać między LFS z SysVinit [10] i LFS z Systemd i D-Bus [11]. W tym miejscu omówimy wariant Systemd, który obejmuje klienty DHCP i NTP, a także inne elementy, które nie są zawarte w wariancie SysVinit LFS, chociaż BLFS oferuje kilka dodatkowych opcji związanych z SysVinit.

Rysunek 1: Trzy etapy procesu budowania LFS.

Kompilacja zajmuje dużo czasu: używając testowej maszyny wirtualnej opisanej w tym artykule z KVM na maszynie z Core i7 10. generacji i dyskiem SSD NVMe, kompilacja zajmuje kilka godzin, nawet jeśli wyłączymy testy.

Kompilacja skrośna

Aby zminimalizować wpływ systemu operacyjnego hosta na kompilację, należy upewnić się, że system LFS jest od niego niezależny. Rozdziały 5 i 6 pomogą nam stworzyć narzędzia programowe potrzebne do zbudowania LFS. Następnie instalujemy te narzędzia w izolowanym środowisku chroot powstałym w celu zbudowania LFS.

Proces kompilacji opiera się na zasadzie kompilacji skrośnej: kompilator skrośny jest zwykle używany do kompilowania kodu dla innych architektur systemowych. Teoretycznie nie jest niezbędny, ponieważ najprawdopodobniej kompilujemy na systemie x86_64 dla x86_64. Zależy nam jednak, aby LFS był wolny od oprogramowania dołączonego z hosta, na którym jest przeprowadzana kompilacja – a to właśnie gwarantuje kompilator skrośny.

Dokumentacja LFS zakłada, że mamy trzy hosty, każdy o innej architekturze. Host A ma kompilator dla własnej architektury. Host jest powolny, a jego pojemność jest ograniczona. Host B nie ma początkowo kompilatora, ale jest szybki i dobrze wyposażony. Będzie produkować oprogramowanie dla hosta C. Host C, z jeszcze inną architekturą, również nie ma kompilatora, jest mały i powolny.

Ten scenariusz wymaga dwóch kompilatorów skrośnych: kompilatora skrośnego A i kompilatora skrośnego B. Na hoście A kompilator buduje kompilator skrośny A, który z kolei kompiluje kompilator skrośny B. kompilator skrośny B jest używany na hoście B do kompilowania kompilatora C i wszystkie programy dla hosta C. Nie można ich jednak przetestować na hoście B. Dlatego kompilator C przebudowuje się i testuje na hoście C.

Aby kompilacja skrośna LFS na tym samym hoście się powiodła, musimy nieco zmodyfikować identyfikator x86_64-pc-linux-gnu w LFS_TGT, aby oszukać kompilator – ma być przekonany, że musi zbudować oprogramowanie na różne architektury. Następnie, na hoście służącym do kompilacji, host kompilujący kompilator najpierw buduje hosta do kompilacji skrośnej, który z kolei buduje kompilator dla LFS. W środowisku chroot LFS na hoście służącym do kompilacji jest budowany kompilator LFS. Następnie testujemy go i jeśli testy przebiegną pomyślnie, będzie gotowy do użytku.

W przypadku LFS musisz użyć kompilatora skrośnego, aby skompilować nie tylko kompilator C, ale także biblioteki glibc i libstdc++. Problem w tym, że zbudowanie kompilatora C wymaga biblioteki libgcc, która z kolei wymaga konsolidacji z glibc – a ta przecież jeszcze nie istnieje.

Aby obejść te i podobne problemy z cyklicznymi zależnościami, najpierw budujemy minimalną wersję hosta do kompilacji skrośnej kompilatora – musi być wystarczająco dobra, byśmy mogli skompilować pełną bibliotekę glibc, a także bibliotekę libstdc++ z minimum funkcji. Biblioteka libstdc++ zostanie ponownie zbudowana później w środowisku chroot, już w pełnej wersji. Dalsze szczegóły na ten temat można znaleźć w dokumentacji LFS.

Sprzęt

Proces kompilacji LFS nie powiedzie się, o ile host służący do kompilacji nie będzie działał idealnie. Niniejszy samouczek zakłada, że dysponujemy nieużywaną maszyna wirtualną, opartą na w pełni załatanej, bieżącej minimalnej instalacji CentOS 8.3 z rozruchem systemu z BIOS-u. Jeśli używamy innej dystrybucji Linuksa, może być konieczna nieznaczna modyfikacja niektórych kroków, jednak cały proces jest bardzo podobny.

Kompilator C GCC korzysta z szybkiego rdzenia. Dokumentacja omawia co prawda wielowątkową kompilację przebiegającą na kilku rdzeniach równocześnie, ale w praktyce taka konfiguracja nie jest zalecana ze względu na mogące sporadyczne wystąpić warunki wyścigu.

W przypadku serwera kompilacji wystarczą nam tylko dwa rdzenie, 2 GB pamięci RAM, hipernadzorca z dyskiem SSD i karta sieciowa Intel e1000. Do pamięci masowej potrzebny jest dysk 10 GB (VirtIO, /dev/vda/) dla systemu i dysk 20 GB (SATA lub SCSI, /dev/sda/) dla LFS.

Unikajmy VirtIO dla dysku LFS i karty sieciowej, ponieważ instrukcje w podręczniku LFS nie wspominają o kompilacji obsługi VirtIO w jądrze. LFS zadowoli się wirtualnym dyskiem SATA lub SCSI, który zidentyfikuje jako /dev/sda/ i klasyczną kartą sieciową Intel e1000 o przepustowości 1 Gb/s. Nazwa dysku jest ważna ze względu na proces uruchamiania LFS. Z kolei nazwa karty sieciowej (taka jak enp1s0) ma znaczenie sytuacji, kiedy chcemy użyć przewidywalnych nazw interfejsów sieciowych [12].

Pierwsze kroki

Po zainstalowaniu CentOS-a musimy skonfigurować pakiety wymagane na początkowych etapach kompilacji. Wymagany makeinfo z pakietu texinfo możemy pobrać z repozytorium PowerTools. Wymagane do kompilacji pakiety powinny zostać szybko instalowane – jest ich stosunkowo niewiele (Listing 1).

Następnie musimy sprawdzić wersje zainstalowane przez CentOS-a za pomocą niewielkiego skryptu: LFS v10.0 wymaga GCC w wersji 6.2 lub wyższej oraz GNU Make w wersji 4.0 lub wyższej, których nie znajdziemy w starszych dystrybucjach Linuksa, takich jak CentOS 7.

Jeśli do tej pory wszystko jest w porządku, dzielimy drugi dysk hosta kompilacji na partycje /swap i /home, tworzymy system plików Ext4 i definiujemy zmienną środowiskową $LFS, która jest niezbędna dla wszystkich kolejnych wywołań powłoki i wskazuje na główny punkt montowania. Zmienna ta musi zatem działać w każdych okolicznościach. Będziemy też chcieli uzupełnić ustawienia regionalne w CentOS-ie 8 i zamontować drugi dysk.

Ustawiamy rozruch dysku /dev/sda/ przez BIOS/MBR i dodajemy poszczególne partycje. Aby zapewnić wystarczająco dużo miejsca własnemu core.img. Gruba, pierwsza partycja dla / o rozmiarze 10 GB zaczyna się od 1 MB. Następnie tworzymy /swap o wielkości 2 GB, pozostawiając resztę dysku zarezerwowaną dla /home.

Listing 1: Instalacja pakietów wymaganych do kompilacji

$ dnf -y install yum-utils

$ yum config-manager –set-enabled powertools

dnf -y install bison byacc bzip2 gcc-c++ patch perl python3 tar texinfo wget

Listing 2: Pobieranie zestawu źródeł do kompilacji

$ wget http://lfs.linux-sysadmin.com/lfs/downloads/stable-systemd/wget-list

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

W tej konfiguracji /boot nie potrzebuje oddzielnej partycji – jądro i konfiguracja programu ładującego system znajdują się w zwykłym katalogu. Oddzielna partycja potrzebna jest tylko wtedy, gdy chcemy obsługiwać równoległe uruchamianie wielu różnych dystrybucji lub jeśli program ładujący nie ma już dostępu do głównego systemu plików. Brak dostępu do systemu plików może nastąpić w wyniku braku sterowników, szyfrowania dysku, programowej macierzy RAID lub LVM.

Ładowanie pakietów i łat

Rozdział 3 dokumentacji LFS definiuje LFS oraz funkcje, które będą się znajdowały w systemie. Oprócz narzędzi do budowania musimy pobrać żądane pliki źródłowe i wybrać pakiety z oprogramowaniem, które zdefiniują cały system. Twórcy LFS zadali sobie trud dokonania wstępnej selekcji, rozwiązania problemów z zależnościami różnych wersji i umieszczenia odnośników w pliku tekstowym, który można w wygodny sposób przekazać Wgetowi, a ten je pobierze (Listing 2).

Twórcy LFS dostarczają szereg łatek, które naprawiają błędy lub dostosowują pakiety do przyszłego systemu docelowego. Ponadto wyjaśniają wszystkie opcje wywołań configure. Dostarczają również listę sum kontrolnych MD5, dzięki której sprawdzimy integralność niemal 90 pobranych pakietów.

Zakończenie przygotować

W rozdziale 4 LFS użytkownik root tworzy struktury katalogów wymagane do kompilacji $LFS/{bin,etc,lib,lib64,sbin,tools,usr,var}, a także konto użytkownika lfs jako właściciela katalogów budowania. Pozostaje zatem kwestia przełączenia się na konto użytkownika lfs oraz opróżnienia i zoptymalizowania środowiska powłoki na tym koncie.

Ponieważ nowe środowisko jest powłoką bez logowania, będziemy potrzebowali pliku .bashrc, aby rozbudować środowisko powłoki i dostosować je do naszych potrzeb – np. ustawić zmienne środowiskowe, takie jak $LFSLC_ALL lub PATH. Kompilator skrośny znajdzie się później w katalogu $LFS/tools/.

Następnym krokiem jest ponowne uruchomienie hosta służącego do kompilacji, aby upewnić się, że wszystko działa jak należy. Jest to też dobry moment na utworzenie migawki maszyny wirtualnej.

Kompilacja skrośna

W rozdziale 5 podręcznika LFS pracujemy na koncie użytkownika lfs – i teraz zaczyna się główna praca: budowa kompilatora skrośnego i powiązanych narzędzi (Listing 3). Kompilator skrośny wraz z narzędziami są tymczasowo przechowywane w $LFS/tools/; możemy już od razu instalować biblioteki tam, gdzie będą musiały się ostatecznie znaleźć.

Proces tworzenia pakietów z oprogramowaniem niemal zawsze pozostaje taki sam. Najpierw przechodzimy do katalogu sources/, gdzie rozpakowujemy pliki źródłowe za pomocą tar xf. Następnie przechodzimy do nowego katalogu utworzonego w tym procesie i – jeśli to konieczne – tworzymy w nim podkatalog build/.

Możemy teraz skompilować i zainstalować pakiet, a następnie ponownie usunąć katalog z kodem źródłowym. Proces ten przeprowadzamy dla konsolidatora i asemblera, kompilatora skrośnego, nagłówków API jądra, glibc i libstdc++.

Budowanie narzędzi tymczasowych

Nadal pracując na koncie lfs, przechodzimy do kompilacji Basha, Grepa i natywnego LFS-GCC, używając między innymi narzędzi do kompilacji skrośnej, które utworzyliśmy w rozdziale 6 LFS. Aplikacje możemy zainstalować na podstawowym systemie plików LFS, ale nie można ich jeszcze używać – system hosta będzie nam nadal potrzebny do kilku zadań. Zwróćmy uwagę, że biblioteki zainstalowane w LFS są już wykorzystywane w procesie konsolidacji. Jednak w następnej sekcji będziemy używać aplikacji tylko w środowisku chroot.

Listing 3: Testowanie skompilowanego GCC

$ echo 'int main(){}’ > dummy.c

$ $LFS_TGT-gcc dummy.c

### Wyświetla informacje z nagłówków segmentów

### danego pliku

$ readelf -l a.out | grep '/ld-linux’

### Powinniśmy uzyskać wynik podobny do poniższego:

### [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]

Czeka nas wykonanie wielu czynności, do których będą nam potrzebne narzędzia tymczasowe. Musimy zatem skompilować procesor makr, konsolidator i asembler, natywny kompilator GCC, bibliotekę do obsługi TUI (tekstowego interfejsu użytkownika), a także Basha. Ponadto musimy utworzyć wiele innych przydatnych narzędzi, takich jak Awk, Chmod, Cp, Dd, Diff, File, Grep, Gzip, Make, Patch, Sed, Tar i Xz.

Dodatkowe narzędzia tymczasowe

Do tego momentu użytkownik lfs był właścicielem systemu plików LFS; w rozdziale 7 dokumentacji LFS właścicielem staje się użytkownik root. Następnie tworzymy na dysku urządzenia console i null, ponieważ jądro oczekuje tych urządzeń podczas rozruchu.

Rozwiązanie problemu z zależnościami cyklicznymi oznacza, że pracując po raz pierwszy jako użytkownik root, możemy teraz przełączyć się na środowisko chroot, które prawie całkowicie przejmuje zadania systemu operacyjnego hosta służącego do kompilacji. Wyjątkiem jest działające jądro: aby środowisko chroot mogło działać, komunikacja z jądrem jest konfigurowana za pośrednictwem wirtualnego systemu plików jądra (VFS).

VFS to systemy plików (takie jak tmpfs/), które nie zajmują miejsca na dysku i znajdują się w całości w pamięci głównej. Zwykle system montuje urządzenia w /dev jako wirtualne systemy plików, tworząc je za pomocą Udev tuż po wykryciu lub przy pierwszym dostępie podczas procesu rozruchu. Jednak na tym etapie Udev jeszcze nie istnieje, musimy więc ręcznie utworzyć wymagane urządzenia i zamontować je za pomocą bind-mount. Pułapka polega na tym, że po ponownym uruchomieniu hosta służącego do kompilacji LFS konieczne będzie ponowne uruchomienie poleceń montowania urządzeń wirtualnych.

Przy pierwszym przejściu do środowiska chroot pojawia się nietypowe ostrzeżenie Bash: brak /etc/passwd – możemy je zignorować i zająć się ostateczną struktura katalogów, uprawnieniami i plikami dziennika. Struktura katalogów jest zgodna ze standardem Filesystem Hierarchy Standard (FHS); tworzymy między innymi katalogi /boot, /home, /mnt, /opt /srv, pomijając te, których nie potrzeba, np. /usr/local/games.

Na tym etapie nadal brakuje standardowych użytkowników i grup. Ponieważ nie ma tu obowiązujących standardów, LFS korzysta z ustawień Udev i konfiguracji używanych w innych dystrybucjach. Następnie kompilujemy oprogramowanie do testowania innych programów (używając tymczasowo utworzonego konta tester) i instalujemy je. Ponadto nadal brakuje niektórych narzędzi. Zacznijmy od utworzenia Libstdc++ (drugi przebieg), pakietu do internacjonalizacji i obsługi lokalizacji, generatora parserów oraz języków programowania Perl i Python. W dalszej kolejności zajmiemy się narzędziami do obsługi stron podręcznika i innymi, które powinny się znaleźć w systemie, jak Blkid, Dmesg itp.

Zbudowany w ten sposób zestaw narzędzi działa teraz niezależnie od hosta kompilacji. Na końcu rozdziału dokumentacja LFS zajmuje się strippingiem, czyli odchudzaniem plików wykonywalnych, tworzeniem kopii zapasowych i przywracaniem systemu.

Instalacja podstawowego oprogramowania

Kolejny rozdział dokumentacji LFS zaczyna się od przedstawienia tematu zarządzania pakietami. Okazuje się jednak, że projekt nie korzysta z menedżera pakietów; cały sens LFS polega na nauce budowania rzeczy, więc menedżer pakietów po prostu nie pasowałby do koncepcji LFS.

Pora zatem na ciężką pracę. Na przykład w rozdziale 8 używamy configuremake i make install, aby zainstalować mnóstwo aplikacji i kilka ważnych bibliotek. Oprócz Basha potzrebne nam będą narzędzia do przetwarzania tekstu, takie jak Awk, Grep i Sed, a także programy do kompresji i archiwizacji, takie jak Bzip, Gzip, Tar i Xz. Dodajemy też GCC, menedżera uruchamiania Grub, a także inne narzędzia: Man i Mandb, OpenSSL, Perl i Python, Vim i Udev.

Kompilacja GCC jest zdecydowanie najbardziej czasochłonnym zadaniem w całym projekcie. Ten krok zajmuje prawie połowę całkowitego czasu kompilacji, głównie ze względu na uruchamianiu zestawów testowych. Ujrzymy mnóstwo komunikatów FAILED, ale nie musimy się nimi martwić, o ile grep w plikach dziennika generowanych przez zestaw testów daje oczekiwane wyniki. Możemy również bezpiecznie zignorować ostrzeżenia dotyczące składni C, które pojawiają się podczas procesu kompilacji.

Testy jednostkowe wywołują liczne wariacje polecenia make check lub make test, częściowo jako użytkownik tester (poprzez su tester -c). Jeśli pominiemy testy jednostkowe, zaoszczędzimy dużo czasu, ryzykujemy jednak, że nie zauważymy istotnych problemów, które mogą wystąpić podczas kompilacji.

Po zakończeniu pracy przychodzi pora na porządki. Usuwamy niepotrzebne już biblioteki i narzędzia, a także tymczasowego użytkownika tester. Jeśli utworzony LFS nie będzie używany do programowania i nie potrzebujesz funkcji debugowania, możemy zaoszczędzić 2 GB miejsca, usuwając symbole używane do debugowania.

Na koniec opuszczamy środowisko chroot i od razu wchodzimy do niego ponownie z włączonym haszowaniem ścieżki Basha [13].

Konfiguracja systemu

Rozdział 9 dotyczy konfiguracji stosu sieciowego. Jeśli chcesz, możesz wyłączyć przewidywalne nazwy urządzeń interfejsu sieciowego (Listing 4). Oznacza to, że LFS wykrywa pierwszą kartę sieciową w systemie jako klasyczne eth0; adres IP nadawany jest przez DHCP. Następnie przechodzimy do konfiguracji systemu rozpoznawania nazw i przypisania hostowi nazwy.

Na koniec wykonujemy drobne prace konfiguracyjne nad zegarem systemowym, konsolą systemu i ustawieniami regionalnymi. Jeśli mamy wątpliwości co do konfiguracji ustawień lokalnych, powinniśmy zajrzeć do plików /usr/share/keymaps i /usr/share/consolefonts.

Listing 4: Używanie klasycznych nazw interfejsów

# ln -s /dev/null /etc/systemd/network/99-default.link

Uruchamianie systemu

Pora na włączenie możliwości uruchamiania LFS. Rozdział 10 zaczyna się od utworzenia pliku /etc/fstab wskazującego na partycje LFS, sda1 (systemowa) i sda2 (wymiany). Następnie budujemy i instalujemy jądro Linuksa. Ponieważ późniejsze rozszerzenia, takie jak w BLFS, zawsze wymagają rekonfiguracji jądra, nie powinniśmy po zakończeniu kompilacji usuwać kodu źródłowego. Grub-install umieszcza program ładujący na dysku; możemy go następnie skonfigurować za pomocą Grub-mkconfig.

LFS używa make defconfig i konfiguruje jądro bez interakcji, za to z rozsądnymi wartościami domyślnymi. Jeśli chcemy, możemy zmienić te ustawienia i użyć opcji tekstowej konfiguracji jądra za pomocą make menuconfig, aby ręcznie ustawić wybrane parametry jądra. Ważne: twórcy Systemd zdecydowanie zalecają korzystanie z protokołu IPv6. Niektóre istotne funkcje, które należy włączyć lub wyłączyć, przedstawiliśmy na Listingu 5.

Ponowne uruchomienie

Na tym etapie dysponujemy już w pełni zainstalowanym systemem, możemy zatem uwiecznić tę chwilę, wpisując swoje imię w dwóch plikach, /etc/lsb-release i /etc/os-release. Wylogowujemy się z chroota, ustawiamy hasło administratora i odmontowujemy $LFS – po wykonaniu tych czynności możemy zrestartować system. Jeśli napotkamy problemy, wskazówki pomocne w ich rozwiązaniu znajdziemy w Tabeli 1.

Przedzierając się przez szczegóły procesu opisanego w tym artykule, szybko zauważymy, że budowanie Linuksa od podstaw wymaga dużo czasu, energii i uwagi. Czy wysiłek ten jest opłacalny? Społeczność skupiona wokół lidera projektu Gerarda Beekmansa uważa, że tak.

Przede wszystkim LFS zapewni nam praktyczną naukę budowania własnej dystrybucji. Poznamy jej wszystkie niezbędne komponenty i dowiemy się, jak ze sobą współpracują. Nabierzemy również doświadczenia w kompilowaniu oprogramowani. Jeśli chcemy, możesz użyć LFS jako punktu wyjścia do stworzenia własnego projektu.

Pod koniec całego procesu otrzymujemy aktualny, działający i bardzo lekki system linuksowy, zawierający niewiele więcej niż jądro i kilka narzędzi. Samodzielne budowanie dystrybucji pomaga zachować wyjątkową elastyczność. LFS to dom w stanie surowym, który możesz dostosować do własnych upodobań – od jednopokojowego mieszkania po luksusową willę. LFS można w razie potrzeby poddać pełnemu audytowi i, co ważniejsze, mamy pełną kontrolę nad wszystkimi poprawkami związanymi z bezpieczeństwem. Jest też kwestia subiektywna: zbudowanie własnego Linuksa od zera daje ogromną satysfakcję.

Z drugiej strony, LFS nie jest szczególnie wygodnym środowiskiem produkcyjnym. Brakuje demona SSH, podobnie jak Sudo, Wgeta i Parteda. Nie mamy do dyspozycji menedżera wolumenów LVM, zaś stos sieciowy nie jest kompletny. BLFS pomaga zaimplementować te funkcje, rozbudowując dokumentację o zaawansowane tematy. Po przeczytaniu ich można zyskać lepszą orientację, jaki ogrom pracy muszą wykonać twórcy oryginalnych dystrybucji.

Listing 5: Ważne funkcje jądra

  [ ] Auditing Support [CONFIG_AUDIT]

  [*] Control Group support [CONFIG_CGROUPS]

  [ ] Enable deprecated sysfs features to support old userspace tools [CONFIG_SYSFS_DEPRECATED]

  [*] Configure standard kernel features (expert users) [CONFIG_EXPERT] —>

    [*] open by fhandle syscalls [CONFIG_FHANDLE]

  Processor type and features  —>

    [*] Enable seccomp to safely compute untrusted bytecode [CONFIG_SECCOMP]

  Firmware Drivers  —>

    [*] Export DMI identification via sysfs to userspace [CONFIG_DMIID]

  Networking support  —>

    Networking options  —>

      <*> The IPv6 protocol [CONFIG_IPV6]

  Device Drivers  —>

    Generic Driver Options  —>

      [ ] Support for uevent helper [CONFIG_UEVENT_HELPER]

      [*] Maintain a devtmpfs filesystem to mount at /dev [CONFIG_DEVTMPFS]

  Firmware Loader —>

    [ ] Enable the firmware sysfs fallback mechanism [CONFIG_FW_LOADER_USER_HELPER]

  File systems  —>

    [*] Inotify support for userspace [CONFIG_INOTIFY_USER]

    Pseudo filesystems  —>

      [*] Tmpfs POSIX Access Control Lists [CONFIG_TMPFS_POSIX_ACL]

Tabela 1: Wskazówki dotyczące rozwiązywania problemów

ObjawPrzyczynaRozwiązanie
Komunikat podczas kompilacji libtool: warning: remember to run ‚libtool –finish /usr/lib’ (File-5.39)Spowodowane przez parametry prefiksu.Nie należy niczego uruchamiać, lecz zignorować ten komunikat.
The system has no more ptys. Ask your system administrator to create more. (Brak urządzeń pty systemie. Poproś administratora systemu, aby utworzył ich więcej.)Być może ponownie uruchomiłeś hosta kompilacji po kroku 7.3 i zapomniałeś ponownie zamontować węzły urządzeń przed chrootem.Należy powtórzyć procedury opisane w sekcji 7.3 i 7.4.
LFS zawiesza się po uruchomieniu i wyświetla komunikat Grub.Dysk LFS został skonfigurowany z BIOS/GPT.Przenosimy /boot na oddzielną partycję.
Podczas uruchamiania w LFS, Gub wyświetlanastępujący komunikat: error: hd1 cannot get C/H/S values.Dzieje się tak często, jeśli ręcznie utworzymy plik /boot/grub/grub.cfg.Dysk LFS jest drugim dyskiem w systemie, więc jeśli zdefiniujemy go jako pierwszy nośnik rozruchowy, plik musi mieć wpis set root=(hd0,1). Natomiast drugi nośnik startowy to set root=(hd1,1).
Kernel Panic — not syncing: VFS: Unable to mount root fs on unknown-block(0,0) („Panika jądra — brak synchronizacji: VFS: Nie można zamontować głównego systemu plików na nieznanym bloku(0,0)”)Wygląda na to, że brakuje niektórych sterowników dla używanego nośnika.Jeśli używamy dysków VirtIO, dodajmy odpowiednie sterowniki lub zmieńmy dyski na SATA.

Pamiętajmy, że jeśli chcemy korzystać z LSF na co dzień, będziemy musieli go regularnie aktualizować, pobierając i kompilując poprawki związane z bezpieczeństwem. Jak można sobie wyobrazić, robienie tego ręcznie byłoby bardzo żmudne. Dlatego w dokumentacji Linux from Scratch omówiony jest uproszczony proces zarządzania pakietami [15]. Ogólnie rzecz biorąc, w LFS nie korzysta się z menedżera pakietów, istnieje jednak możliwość rozbudowy LFS poprzez dodanie menedżera takiego jak Pacman lub GNU Stow [14]. Utworzonej przez nas dystrybucji będzie też brakowało takich funkcji, jak aktywna społeczność użytkowników, pakiety przetestowane przez zespół dbający o zapewnienie jakości, errata, rozbudowana sieć serwerów lustrzanych, programiści, z którymi można się kontaktować, i innych udogodnień, takich jak wiki, czat/IRC, listy mailingowe, fora, narzędzia do śledzenia błędów itp.

Na koniec istotna uwaga: LFS nie jest projektem dla początkujących użytkowników Linuksa. Innymi słowy, LFS nie nauczy nas podstaw, lecz raczej tajników i zakamarków systemu, do których w innych okolicznościach nie mielibyśmy szans dotrzeć. Poza tym LFS jest wspaniałą przygodą – i nawet jeśli nie będziemy używać zbudowanego przez siebie systemu, zdobyta podczas jego tworzenia wiedza pozwoli nam lepiej zrozumieć działanie dystrybucji, z której korzystamy na co dzień. 

Autor: Markus Frei od ponad 25 lat zajmuje się aplikacjami serwerowymi oraz interakcją między infrastrukturą a rozwojem oprogramowania. Jest współwłaścicielem firmy Linuxfabrik w Zurychu (­https://www.linuxfabrik.ch/), która oferuje serwis i wsparcie techniczne aplikacji linuksowych i open source, a także hosting zarządzany.

Info

[1] Linux From Scratch: http://www.linuxfromscratch.org/lfs

[2] Beyond Linux From Scratch: http://www.linuxfromscratch.org/blfs

[3] Yocto Project: https://www.yoctoproject.org

[4] Linux Target Image Builder: http://ltib.org

[5] OpenWrt: https://openwrt.org

[6] Scratchbox: http://www.scratchbox.org

[7] Posix: http://pubs.opengroup.org/onlinepubs/9699919799/

[8] File System Hierarchy Standard: http://refspecs.linuxfoundation.org/FHS_3.0/fhs/index.html

[9] Linux Standard Base: https://refspecs.linuxfoundation.org/lsb.shtml

[10] LFS with SysVinit: http://www.linuxfromscratch.org/lfs/view/stable

[11] LFS with Systemd: http://www.linuxfromscratch.org/lfs/view/stable-systemd

[12] Predictable Network Interface Names: https://www.freedesktop.org/wiki/Software/systemd/PredictableNetworkInterfaceNames/

[13] Bash Path Hashing: https://www.computerhope.com/unix/bash/hash.htm

[14] GNU Stow: https://www.gnu.org/software/stow

[15] Package-User approach: http://www.linuxfromscratch.org/hints/downloads/files/more_control_and_pkg_man.txt

Podziel się postem :)

Share on facebook
Share on linkedin
Share on twitter
Share on email

Najnowsze:

Bezpieczeństwo

Twój smartfon był szpiegowany? MVT pozwoli to sprawdzić!

Serwis Computerworld przypomniał o aplikacji Mobile Verification Toolkit (MVT), która została opracowana przez Amnesty International, organizację zajmującą się wszelkimi naruszeniami praw człowieka. Aplikacja w formie

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany.