23.4. Przebudowa “świata”

Kiedy już zsynchronizujemy nasze drzewo źródłowe z konkretną wersją FreeBSD (FreeBSD-STABLE, FreeBSD-CURRENT, itd.) możemy go użyć do przebudowania systemu.

Zróbmy kopię bezpieczeństwaNieocenione może się okazać wykonanie kopii bezpieczeństwa systemu zanim przystąpimy do działania. Podczas, gdy przebudowa świata jest (tak długo, jak długo stosujemy się do tych instrukcji) dość łatwym zadaniem, zawsze możemy popełnić jakąś pomyłkę lub pomyłka popełniona przez innych w drzewie źródłowym uczyni nasz system niemożliwym do uruchomienia.

Upewnijmy się, że zrobiliśmy kopię bezpieczeństwa i mamy w pobliżu rozruchowy CD-ROM lub naprawczą dyskietkę. Pewnie nigdy nie będziemy musieli z nich korzystać, niemniej jednak lepiej być przezornym i ubezpieczonym.

Subskrybujmy odpowiednie listy mailingoweGałęzie FreeBSD-STABLE i FreeBSD-CURRENT są z natury w ciągłym rozwoju a ludzie pracujący nad FreeBSD są tylko ludźmi, więc, niestety, błędy czasem się zdarzają.

Czasami są to niegroźne błędy powodujące np. wypisanie przez system nowego ostrzeżenia diagnostycznego a czasami mogą być katastrofalne w skutkach powodując niemożność uruchomienia systemu, zniszczenie systemów plików lub nawet gorzej.

Jeżeli pojawiają się takie problemy, do odpowiedniej listy mailingowej jest wysyłana tzw. “zapowiedź” (ang. heads up) wyjaśniająca naturę problemu a także to, których wersji systemu on dotyczy. Kiedy problem zostanie rozwiazany wysłane zostanie ogłoszenie “wszystko jasne” (ang. all clear).

Jeżeli podążamy za FreeBSD-STABLE lub FreeBSD-CURRENT i nie czytamy odpowiednio FreeBSD-STABLE mailing list ani FreeBSD-CURRENT mailing list, sami prosimy się o kłopoty.

Nie używajmy make worldWiększość wcześniejszych dokumentacji zaleca skorzystanie z make world w celu wykonania przebudowy. Komenda ta pomija jednak pewne ważne kroki i powinna być użyta jedynie pod warunkiem, że wiemy, co robimy. make world jest z wielu względów złym sposobem i zamiast niej powinna zostać użyta procedura opisana poniżej.

23.4.1. Kanoniczny sposób aktualizacji systemu

Aby zaktualizować system sprawdźmy /usr/src/UPDATING. Znajdziemy tam wszystkie niezbędne, dostosowane do naszej wersji źródeł kroki dla przygotowania przebudowy. Następnie wpiszmy kolejno:

# make buildworld
# make buildkernel
# make installkernel
# reboot

Notatka: Istnieje parę sytuacji, w których wymagane jest użycie mergemaster -p przed krokiem buildworld. Są one opisane w UPDATING. W większości przypadków można to pominąć jeśli nie aktualizuję się omijając kilka wersji FreeBSD.

Po tym, jak installkernel zakończy się sukcesem, powinniśmy uruchomić system w trybie awaryjnym (ang. single user mode) (np. wpisując boot -s na zachęcie startowej). Następnie wpiszmy:

# mergemaster -p
# make installworld
# mergemaster
# reboot

Przeczytajmy poniższe wyjaśnieniaOpisana powyżej sekwenja stanowi jedynie krótkie streszczenie, które ma pomóc nam zacząć. Niemniej jednak, powinniśmy przeczytać poniższe sekcje aby jasno zrozumieć każdy krok, zwłaszcza, jeśli zamierzamy użyć własnej konfiguraji jądra.

23.4.2. Przeczytajmy /usr/src/UPDATING

Zanim zaczniemy cokolwiek robić, przeczytajmy /usr/src/UPDATING (lub jego odpowiednik w miejscu, gdzie znajduję się kopia kodu źródłowego). Plik ten powininien zawierać ważne informacje dotyczące problemów, które możemy napotkać, lub porządek, w którym będziemy musieli uruchamiać poszczególne komendy. Jeśli UPDATING zaprzecza czemuś co przeczytaliśmy tutaj, UPDATING ma pierwszeństwo.

WAŻNE: Czytanie UPDATING nie jest akceptowalnym zamiennikiem subskrybowania odpowiednich list mailingowych, co zostało opisane wcześniej. Oba stanowią konieczne, uzupełniające się warunki.

23.4.3. Sprawdźmy /etc/make.conf

Zbadajmy plik /usr/share/examples/etc/make.conf i /etc/make.conf. Pierwszy zawiera standardowe definicje - z których większość jest zakomentowana. Aby wykorzystać je podczas przebudowywania systemu ze źródeł, dodajmy je do /etc/make.conf. Pamiętajmy jednak, że wszystko co dodajemy do /etc/make.conf jest także używane za każdym razem kiedy korzystamy z make, więc dobrym pomysłem jest ustawienie ich w rozsądny sposób dla naszego systemu.

Większość użytkowników zapragnie zapewne skopiować linie CFLAGS i NO_PROFILE, znalezione w /usr/share/examples/etc/make.conf do /etc/make.conf i usunąć ich komentarze.

Zbadajmy inne definicje (COPTFLAGS, NOPORTDOCS itd.) i zdecydujmy czy są dla nas odpowiednie.

23.4.4. Zaktualizujmy pliki z /etc

Folder /etc zawiera większą część informacji dotyczących konfiguracji naszego systemu, jak również skrypty uruchamiane podczas rozruchu. Większość tych skryptów jest różna w różnych wersjach FreeBSD.

Niektóre z plików konfiguracyjnych są także używane podczas codziennego użytkowania systemu. W szczególności /etc/group.

Zdarzały się sytuacje, kiedy instalacyjna część make installworld oczekiwała istnienia określonych nazw użytkowników czy grup. Podczas wykonywania aktualizacji prawdopodobne jest, że te grupy czy użytkownicy nie istniały. Powodowało to problemy podczas aktualizacji. W niektórych przypadkach make buildworld będzie sprawdzać czy istnieją odpowiedni użytkownicy bądź grupy.

Przykładem tego jest sytuacja, w której został dodany użytkownik smmsp. Proces instalacji zawodził kiedy mtree(8) starała się utworzyć /var/spool/clientmqueue.

Rozwiązaniem jest uruchomienie mergemaster(8) w trybie przed przebudowaniem (ang. pre-buildworld mode) korzystając z opcji-p. Porówna to tylko te pliki, które są kluczowe dla powodzenia się buildworld czy installworld. Jeżeli nasza stara wersja mergemaster'a nie obsługuje opcji -p, skorzystajmy z nowej wersji znajdującej się w drzewie źródłowym. Podczas pierwszego uruchomienia wpiszmy:

# cd /usr/src/usr.sbin/mergemaster
# ./mergemaster.sh -p

Podpowiedź: Jeżeli jesteśmy szczególnie przeczuleni, możemy sprawdzić w systemie, do jakiej grupy należą poszczególne zmieniane lub usuwane przez nas pliki:

# find / -group GID -print

pokaże nam wszystkie pliki, których właścicielem są członkowie grupy GID (może to być nazwa grupy lub jej numeryczny identyfikator - ID).

23.4.5. Wchodzenie w tryb awaryjny

Możemy chcieć skompilować swój system w trybie awaryjnym. Niezależnie od oczywistej korzyści delikatnego przyspieszenia procesu, reinstalacja systemu dotknie wielu istotnych plików systemowych; wszystkie standardowe binaria, biblioteki, pliki dołączone i tak dalej. Ich modyfikacja na pracującym systemie (zwlaszcza, jeśli w tym czasie znajdują się w systemie aktywni użytkownicy) jest proszeniem się o kłopoty.

Kolejną metodą jest kompilacja systemu w trybie wielu-użytkowników, i wejście w tryb awaryjny dla potrzeb instalacji. Jeżeli chcemy zrobić to w ten sposób, po prostu trzymajmy się poniższych kroków aż do zakończenia budowy. Możemy odwlec moment wejścia w tryb awaryjny do czasu, kiedy będziemy musieli wykonać installkernel lub installworld.

Jako superużytkownik, możemy uruchomić:

# shutdown now

z poziomu uruchomionego systemu, co wprowadzi nas w tryb awaryjny.

Alternatywnie, możemy uruchomić system ponownie i na zachęcie startowej wybrać opcję “single user”. System uruchomi wtedy tryb awaryjny. Następnie na zachęcie systemowej wpiszmy:

# fsck -p
# mount -u /
# mount -a -t ufs
# swapon -a

Sprawdzi to systemy plików, ponownie zamontuje / w trybie odczytu/zapisu, zamontuje wszystkie inne systemy plików UFS wpisane w /etc/fstab a następnie włączy tryb wymiany.

Notatka: Jeżeli nasz zegar CMOS nie jest ustawiony na czas GMT, a na czas lokalny (jest tak jeżeli wynik komendy date(1) nie pokazuje poprawnego czasu ani strefy czasowej), możemy potrzebować uruchomić poniższą komendę:

# adjkerntz -i

Zagwarantuje to poprawne ustawienie opcji naszej lokalnej strefy czasowej -- bez tego, możemy później napotkać pewne kłopoty.

23.4.6. Usuńmy /usr/obj

Podczas procesu przebudowy części systemu, umieszczane są one w folderach, które z kolei (standardowo) umieszczane są w /usr/obj. Foldery stamtąd "przesłaniają" te z /usr/src.

Możemy przyspieszyć proces make buildworld, jak również prawdopodobnie oszczędzić sobie wielu problemów z zależnościami usuwając ten katalog.

Niektóre pliki spod /usr/obj mogą mieć ustawioną flagę niezmienności (ang. immutable) (po więcej informacji zobacz chflags(1)), która musi być najpierw usunięta.

# cd /usr/obj
# chflags -R noschg *
# rm -rf *

23.4.7. Rekompilacja Systemu Bazowego

23.4.7.1. Zapisywanie wyników

Dobrym pomysłem jest zapisywanie wyników uruchomienia make(1) do innego pliku. Jeżeli coś pójdzie nie tak, będziemy mieć kopię wiadomości o błędzie. Nawet jeżeli nie pomoże nam to w zdiagnozowaniu co poszło nie tak, zawsze może pomóc innym jeżeli wyślemy opis naszego problemu do jednej z list malingowych FreeBSD.

Najprostszą metodą aby to zrobić jest użycie komendy script(1) z parametrem określającym nazwę pliku, do którego chcemy zapisać wynik komendy. Zróbmy to tuż przed przebydowywaniem świata, a następnie wpiszmy exit kiedy proces skończy pracę.

# script /var/tmp/mw.out
Script started, output file is /var/tmp/mw.out   
# make TARGET
... compile, compile, compile ...     
# exit
Script done, ...

Jeżeli to robimy, nie zapisujmy wyniku w /tmp. Ten folder może być opróżniony podczas następnego ponownego uruchomienia. Lepszym miejscem na przechowanie jest /var/tmp (jak w poprzednim przykładzie) lub katalog domowy root'a.

23.4.7.2. Kompilacja systemu bazowego

Z poziomu folderu /usr/src wpiszmy:

# cd /usr/src

(chyba, że nasz kod źródłowy znajduje się gdzieś indziej, wtedy musimy zmienić katalog na właściwy).

Aby przebudować świat użyjmy komendy make(1). Komenda ta czyta instrukcje zawarte w Makefile, które opisują sposób, w jaki programy składające się na FreeBSD powinny być przebudowane, porządek budowania i tak dalej.

Ogólny format komendy do wpisania wygląda następująco:

# make -x -DVARIABLE obiekt docelowy

W tym przykładzie, -x jest opcją, którą chcielibyśmy podać make(1). Zobaczmy stronę manuala make(1) po więcej przykładów opcji które możemy podać.

-DVARIABLE przekazuje zmienną do pliku Makefile. Zachowanie Makefile jest kontrolowane właśnie poprzez te zmienne. Są to te same zmienne umieszczone w /etc/make.conf a to jest po prostu inny sposób na ich ustawienie.

# make -DNO_PROFILE obiekt docelowy

jest kolejnym sposobem określenia, że profilowane biblioteki nie powinny być zbudowane, i odpowiada linijce

NO_PROFILE=    true    #    Avoid compiling profiled libraries

umieszczonej w /etc/make.conf.

obiekt docelowy mówi make(1) co chcemy zrobić. Każde Makefile okeśla liczbę różnych “obiektów docelowych” i od tego, które wybierzemy zalezy co się stanie.

Niektóre obiekty znajdują się w pliku Makefile ale nie są przeznaczone do używania ich przez nas. Zamiast tego, są one używane przez proces budowy do podzielenia kroków niezbędnych do przebudowy systemu na mniejsze.

W większości przypadków, nie będziemy musieli podawać żadnych parametrów make(1), więc nasza komenda będzie wyglądała następująco:

# make obiekt docelowy

Gdzie obiekt docelowy będzie jednym z wielu opcji budowy. Pierwszym obiektem docelowym powinien zawsze być buildworld.

Jak sugerują nazwy, buildworld buduje całkiem nowe drzewo w /usr/obj, a installworld, kolejny obiekt docelowy, instaluje owe drzewo na danym komputrze.

Rozdzielenie opcji jest bardzo przydatne z dwóch powodów. Po pierwsze pozwala na bezpieczną budowę, dając pewność, że nie wpłynie to na żadną część naszego pracującego systemu. Budowa jest więc “niezależna”. Z tego powodu, możemy bezpiecznie uruchomić buildworld na działającej w trybie wielu-użytkowników maszynie, nie martwiąc się o ujemne skutki. Nadal jednak zalecane jest abyśmy uruchomili installworld w trybie awaryjnym.

Po drugie, pozwala to na użycie zamontowanych systemów NFS aby naraz zaktualizować kilka komputerów z twojej sieci. Jeżeli posiadamy 3 maszyny: A, B, C i chcemy je zaktualizować musimy uruchomić make buildworld i make installworld na A. B i C powinny wtedy zamontować NFS /usr/src i /usr/obj z A, a my uruchomić make installworld aby zainstalować wyniki budowy na B i C.

Mimo tego, że obiekt world nadal istnieje, gorąco zaleca się jego nieużywanie.

Uruchom

# make buildworld

Możliwe jest określenie opcji -j dla make, która spowoduje jej rozmnożenie się na wiele równoczesnych identycznych procesów. Jest to przede wszystkim przydatne na komputerach wieloprocesorowych. Jednakże, podczas gdy większość procesu kompilacji ograniczona jest raczej wejściem-wyjściem niż procesorem, może to być również przydatne na jednoprocesorowych stacjach.

Na przeciętnym komputerze jednoprocesorowych powinniśmy wpisać:

# make -j4 buildworld

make(1) uruchomi wtedy do 4 jednoczesnych procesów. Empiryczne dowody wysyłane na listy mailingowe wskazują, że daje to generalnie najlepsze korzyści wydajnościowe.

Jeżeli posiadamy wieloprocesorową maszynę i używamy jądra skonfigurowanego z obsługą SMP, spróbójmy wartości od 6 do 10, i obserwujmy jak przyspieszą proces.

23.4.7.3. Czas budowy

Wiele czynników wpływa na czas budowy, ale dość nowe komputery radzą sobie z budową drzewa FreeBSD-STABLE w czasie godziny lub dwóch, bez stosowana żadnych trików lub skrótów podczas procesu. Budowa drzewa FreeBSD-CURRENT zajmie nieco dłużej.

23.4.8. Skompilujmy i zainstalujmy nowe jądro

Aby w pełni wykorzystać możliwości naszego nowego systemu, powinniśmy zrekompilować jądro. Jest to praktycznie konieczność, ze względu na to, że określone struktury pamięci mogły ulec zmianie i programy takie jak ps(1) czy top(1) nie będą działać dopóki wersje kodu źródłowego i jądra nie będą takie same.

Najłatwiejszym i najbezpieczniejszym sposobem zrobienia tego jest zbudowanie i zainstalowanie jądra bazującego na pliku GENERIC. Podczas, gdy GENERIC może nie posiadać wszystkich niezbędnych urządzeń dla naszego systemu, powinien zawierać wszystko co jest niezbędne w celu uruchomienia naszego systemu w trybie awaryjnym. Co stanowi dobry test na sprawdzenie czy nowy system działa jak należy. Po uruchomieniu z GENERIC i sprawdzeniu tego, że nasz system działa, możemy zbudować nowe jądro w oparciu o plik konfiguracyjny naszego normalnego jądra.

We FreeBSD ważne jest aby wykonać build world przed budową nowego jądra.

Notatka: Jeżeli chcemy zbudować własne jądro, i mamy już plik konfiguracyjny użyjmy po prostu KERNCONF=MYKERNEL w taki sposób:

# cd /usr/src
# make buildkernel KERNCONF=MYKERNEL
# make installkernel KERNCONF=MYKERNEL

Zauważmy, że jeżeli podnieśliśmy kern.securelevel powyżej 1 i ustawiliśmy, bądź to noschg, bądź inną podobną flagę dla binarki jądra niezbędne może się okazać wejście w tryb awaryjny w celu użycia installkernel. W przeciwnym razie będziemy mógli użyć obydwu tych komend z poziomu trybu wielo-użytkownikowego bez żadnych problemów. Zobaczmy init(8) po szczegóły dotyczące kern.securelevel i chflags(1) po szczegóły dotyczące różnych flag plików.

23.4.9. Wejdźmy w tryb awaryjny

powinniśmy wejść w tryb jednego awaryjny dla sprawdzenia, czy nowe jądro działa. Aby to zrobić, podążajmy za wskazówkami z Sekcja 23.4.5.

23.4.10. Zainstalujmy binaria nowego systemu

Jeżeli budujemy wystarczająco nową wersję FreeBSD aby korzystać z make buildworld powinniśmy teraz użyć installworld aby zainstalować binaria nowego systemu.

Wpiszmy

# cd /usr/src
# make installworld

Notatka: Jeżeli określiliśmy zmienne przy komendzie make buildworld, musimy określić te same zmienne przy make installworld. Nie jest to do końca prawdą jeśli chodzi o inne opcje; dla przykładu, -j nigdy nie może zostać użyta z installworld.

Przykładowo, jeśli wpiszemy:

# make -DNO_PROFILE buildworld

musimy zainstalować wynik z:

# make -DNO_PROFILE installworld

inaczej ostatnia komenda spróbuje zainstalować profilowane biblioteki, które nie zostały zbudowane podczas fazy make buildworld.

23.4.11. Zaktualizujmy pliki niezaktualizowane przez make installworld

Proces powtórnego tworzenia świata nie zaktualizuje niektórych folderów (w szczególności, /etc, /var i /usr) ani nie zmieni plików konfiguracyjnych, które one zawierają.

Najprostszym sposobem na zaktualizowanie tych plików jest użycie mergemaster(8), niemniej można to również zrobić ręcznie, jeśli tak uznamy. Niezależnie od sposobu, który wybierzemy, nie zapomnijmy zrobić kopii bezpieczeństwa /etc, na wypadek, gdyby coś poszło nie tak.

23.4.11.1. mergemaster

Napisał Tom Rhodes.

mergemaster(8) jest skryptem powłoki Bourne'a, który pomoże nam w określeniu różnic pomiędzy naszymi plikami konfiguracyjnymi z /etc, a plikami konfiguracyjnymi w drzewie źródłowym /usr/src/etc. Jest to zalecane rozwiązanie dla utrzymywania twoich plików konfiguracyjnych na bieżąco z tymi umieszczonymi w drzewie źródłowym.

Aby rozpocząć proces, wpiszmy po prostu mergemaster przy znaku zachęty powłoki i obserwujmy proces. Najpierw mergemaster zbuduje tymczasowe środowisko root'a, od / w dół i wypełni je różnymi plikami konfiguracyjnymi systemu. Następnie, pliki te będą porównane z tymi, które są obecnie zainstalowane w systemie. W tym miejscu, pliki, które będą się różnić zostaną pokazane w formacie diff(1), ze znakiem + oznaczającym dodane lub zmienione linie, ze znakiem - oznaczającym linie, które albo bedą całkiem usunięte, albo zasąpione nowymi liniami. Po więcej informacji odnośnie składni i sposobu wyświetlania różnic przez diff(1), zobaczmy diff(1).

mergemaster(8) pokaże nam każdy różniący się plik i w tym punkcie, będziemy mieć do wyboru: opcję usunięcia nowego pliku (oznaczonego jako plik tymczasowy), instalacji tymczasowego pliku w jego niezmienionym stanie, scalenie tymczasowego pliku z tym obecnie zainstalowanym albo ponownego zobaczenia wyników diff(1).

Wybór usunięcia tymczasowego pliku powie mergemaster(8)'owi, że chcemy zatrzymać obecny plik niezmieniony i usunąc jego nową wersję. Opcja ta nie jest rekomendowana, chyba, że nie dostrzegamy potrzeby zmiany obecnego pliku. W każdej chwili możemy uzyskać pomoc wpisując ? na zachęcie mergemaster(8)'a. Jeżeli użytkownik wybierze, aby ominąc plik, będzie on ponownie pokazany po uporaniu się ze wszystkimi pozostałymi.

Wybór opcji instalacji niezmienionego pliku tymczasowego spowoduje zamianę obecnego pliku na nowy. Dla większości niezmienionych plików jest to najlepszym rozwiązaniem.

Opcja scalenia pliku wprowadzi nas do edytora tekstu z zawartością obydwu plików. Będziemy mógli je wtedy scalić, przeglądając obydwa pliki umieszczone obok siebie na ekranie, wybierając z obydwu części do stworzenia ostatecznej wersji. Podczas porównywania znajdujących się obok siebie plików klawisz l będzie wybierał zawartość pliku z lewej strony a klawisz r zawartość pliku z prawej strony. Wynikiem końcowym będzie plik zawierający obie części, który można już będzie zainstalować. Opcja ta jest zazwyczaj używana dla plików, których ustawienia zostały wcześniej zmodyfikowane przez użytkownika.

Wybierając opcję ponownego zobaczenia wyników diff(1) pokaże nam różnicę miedzy plikami dokładnie tak jak wcześniej, kiedy mergemaster(8) prosił nas o wybranie opcji.

Po tym, jak mergemaster(8) skończy interakcję z plikami systemowymi możemy zostać zapytani o inne opcje. mergemaster(8) może spytać, czy chcemy przebudować plik zawierający hasła i zakończy na pytaniu o usunięcie pozostawionych plików tymczasowych.

23.4.11.2. Ręczna aktualizacja

Jeżeli chcemy dokonać aktualizacji ręcznie, nie możemy po prostu skopiować plików z /usr/src/etc do /etc i sprawić by działały. Niektóre z tych plików muszą najpierw zostać “zainstalowane”. Jest tak, ponieważ folder /usr/src/etc nie jest kopią odpowiadającą poprawnemu wyglądowi folderu /etc. W dodatku, są pliki, które powinny znaleźć się w /etc, a których nie ma w /usr/src/etc.

Jeżeli używamy mergemaster(8)'a (co jest zalecane), możemy odrazu przejść do następnej sekcji.

Najprostszą metodą na ręczne wykonanie tego jest zainstalowanie plików do nowego folderu a następnie ich przetworzenie szukając różnic.

Zróbmy kopię bezpieczeństwa naszego obecnego /etcMimo, że teoretycznie nic nie narusza tego folderu automatycznie, zawsze lepiej się zabezpieczyć. Skopiujmy więc nasz obecny folder /etc w bezpieczne miejsce. Przykładowo:

# cp -Rp /etc /etc.old

-R tworzy rekurencyjną kopię, -p zachowuje czasy, flagi własności plków itp.

Musimy zbudować sztuczny zestaw folderów do zainstalowania w nich nowego /etc i innych plików. /var/tmp/root jest rozsądnym wyborem, zawiera on również potrzebną liczbę podfolderów.

# mkdir /var/tmp/root
# cd /usr/src/etc
# make DESTDIR=/var/tmp/root distrib-dirs distribution

Polecenia te zbudują konieczną strukturę folderów i zainstalują pliki. Wiele z podfolderów, które zostały utworzone w /var/tmp/root jest pustych i powinny być usunięte. Najłatwiej można tego dokonać wpisując:

# cd /var/tmp/root
# find -d . -type d | xargs rmdir 2>/dev/null

Usunie to wszystkie puste foldery. (Standardowy błąd jest odsyłany do /dev/null aby zapobiec wypisywaniu ostrzeżeń o folderach, które nie są puste.)

/var/tmp/root zawiera teraz wszystkie pliki, które powinny zostać umieszczone w odpowiednich miejscach pod /. Musimy teraz przejrzeć wszystkie te pliki, określając jak różnią się one od tych obecnie przez nas posiadanych.

Zauważmy, że niektóre zainstalowane w /var/tmp/root pliki, poprzedzone są “.”. W czasie pisania jedynymi takimi plikami są pliki startowe powłoki w /var/tmp/root/ i /var/tmp/root/root/, chodziaż mogą być rownież inne (zależnie od tego, kiedy to czytamy). Upewnijmy się, że użyliśmy ls -a aby je wyłapać.

Najprostszą metodą aby porównać dwa pliki jest użycie diff(1):

# diff /etc/shells /var/tmp/root/etc/shells

Pokaże nam różnice pomiędzy naszym plikiem /etc/shells a nowym /var/tmp/root/etc/shells. Użyjmy tego do rozstrzygnięcia czy chcemy scalić pliki zachowując zamiany jakich dokonaliśmy, czy zastąpić stary plik nowym.

Użyjmy znacznika czasu w nazwie folderu domowego root'a (/var/tmp/root), abyśmy mogli łatwo porównać różnice pomiędzy wersjami: Częste przebudowywanie świata oznacza także częste aktualizowanie /etc, co może być trochę męczącym obowiązkiem.

Możemy przyspieszyć ten proces przechowując kopię ostatniego zestawu zmienionych plików, które scaliliśmy do /etc. Poniższa procedura pokazuje zasadę działania takiego pomysłu.

  1. Standardowo dokonajmy budowy świata (ang. make world). Podczas aktualizacji /etc i innych folderów, nadajmy docelowemu folderowi nazwę zawierającą obecną datę. Jeżeli robimy to 14 Lutego 1998 roku, możemy wpisać jak poniżej:

    # mkdir /var/tmp/root-19980214
    # cd /usr/src/etc
    # make DESTDIR=/var/tmp/root-19980214 \
        distrib-dirs distribution
    
  2. Scalmy zmiany z tego folderu, jak zarysowano powyżej.

    Nie usuwajmy folderu /var/tmp/root-19980214 po zakończeniu pracy.

  3. Jeśli pobraliśmy już ostatnią wersję źródeł i przetworzyliśmy ją, podążajmy za krokiem 1. Uzyskamy nowy folder, który może zostać nazwany /var/tmp/root-19980221 (jeżeli czekaliśmy tydzien aby dokonać nowej aktualizacji).

  4. Możemy teraz zobaczyć różnice powstałe w ciągu tego tygodnia używając diff(1) do stworzenia rekurencyjnego diff'a pomiędzy tymi dwoma folderami:

    # cd /var/tmp
    # diff -r root-19980214 root-19980221
    

    Zazwyczaj, będzie to znacznie mniejszy zestaw zmian niż ten powstały z pomiędzy /var/tmp/root-19980221/etc i /etc. A ponieważ zestaw zmian jest mniejszy, prościej jest nanieść te zmiany do plików w folderze /etc.

  5. Możemy teraz usunąć starszy z folderów /var/tmp/root-*:

    # rm -rf /var/tmp/root-19980214
    
  6. Powtarzajmy ten proces za każdym razem, kiedy musimy wprowadzić zmiany do /etc.

Możemy wykorzystać date(1) do zautomatyzowania generowania nazw folderów:

# mkdir /var/tmp/root-`date "+%Y%m%d"`

23.4.12. Ponowne uruchamianie

Skończyliśmy. Po zweryfikowaniu, że wszystko jest na swoim miejscu możemy ponownie uruchomić system. Zwykły shutdown(8) wystarczy:

# shutdown -r now

23.4.13. Koniec

Powinniśmy teraz mieć z powodzeniem zaktualizowany system FreeBSD. Gratulację.

Jeżeli coś poszło nie do końca dobrze, łatwo jest przebudować konkretną część systemu. Przykładowo, jeżeli przypadkowo usuneliśmy /etc/magic jako część aktualizacji lub scalania /etc, komenda file(1) przestanie działać. W tym przypadku, naprawa będzie wymagała wpisania:

# cd /usr/src/usr.bin/file
# make all install

23.4.14. Pytania

23.4.14.1. Czy dla każdej zmiany trzeba ponownie budować świat?
23.4.14.2. Kompilacja nie powiodła wypisując wiele błędów typu "sygnał 11" (lub inny numer sygnału). Co się stało?
23.4.14.3. Czy można usunąć /usr/obj po skończeniu?
23.4.14.4. Czy przerwany proces budowy może zostać wznowiony?
23.4.14.5. Jak można przyspieszyć proces tworzenia świata?
23.4.14.6. Co zrobić, jeżeli coś pójdzie nie tak?

23.4.14.1. Czy dla każdej zmiany trzeba ponownie budować świat?

Na to pytanie nie ma jednej prostej odpowiedzi, ponieważ zależy to od natury danej zmiany. Przykładowo, jeśli uruchomiliśmy CVSup, który pokazał, że poniższe pliki zostały zaktualizowane:

src/games/cribbage/instr.c
src/games/sail/pl_main.c
src/release/sysinstall/config.c
src/release/sysinstall/media.c
src/share/mk/bsd.port.mk

prawdopodobnie nie warto jest przebudowywać świat. Wystarczy, jeśli wejdziemy do odpowiednich podfolderów i wykonamy make all install. Ale jeżeli zmiana dotyczy czegoś istotnego, na przykład src/lib/libc/stdlib, wtedy powinniśmy albo zbudować cały świat od nowa, albo przynajmniej te jego części, które są statycznie połączone (ang. statically linked) (jak i wszystko inne co mogliśmy dodać i co jest statycznie połączone).

Ostatecznie, zależy to tylko od nas. Możemy być zadowoleni przebudowując świat co każde dwa tygodnie, przez które będą się zbierać zmiany. Albo, możemy chcieć przebudowywać tylko te części, które się zmieniły i być pewnymi, że możemy wyłapać wszystkie zależności.

I oczywiście, wszystko to zależy od tego jak często chcemy dokonywać aktualizacji i czy zamierzamy podążać za FreeBSD-STABLE czy FreeBSD-CURRENT.

23.4.14.2. Kompilacja nie powiodła wypisując wiele błędów typu "sygnał 11" (lub inny numer sygnału). Co się stało?

Oznacza to przeważnie problemy sprzętowe. (Prze)budowa świata jest skutecznym sposobem na sprawdzenie zachowania się naszego sprzętu w tzw. stresie, czyli pod obciążeniem i często skutkować będzie problemami z pamięcią. Zwykle objawiają się one tym, że nagle proces kompilacji tajemniczo kończy się, wypisując jednocześnie wiele dziwnych sygnałów.

Pewną oznaką tego jest, jeżeli ponownie uruchamiamy "make" i kończy się ona w innym miejscu procesu.

W tym przypadku, niewiele możemy zrobić poza zamianą komponentów w twoim komputerze w celu ustalenia który z nich zawodzi.

23.4.14.3. Czy można usunąć /usr/obj po skończeniu?

Krótka odpowiedź brzmi tak.

/usr/obj zawiera wszystkie pliki wynikowe powstałe podczas fazy kompilacji. Zwykle, jednym z pierwszych kroków w procesie make buildworld jest usunięcie tego folderu i rozpoczęcie od nowa. W tym przypadku, trzymanie /usr/obj po skończeniu pracy nie ma wielkiego sensu i będzie tylko zajmować spory kawałek miejsca na twardym dysku (obecnie ok 340 MB).

Jednakże, jeżeli wiemy co robimy, możemy sprawić by make buildworld ominął ten krok. Uczyni to późniejsze procesy budowy szybszymi, od kiedy większość źródeł nie będzie musiała być rekompilowana. Z drugiej strony, mogą się pojawić pewne niewielkie problemy z zależnościami powodując dziwne błędy przy procesie budowy. Często powoduje to szum na listach mailingowych FreeBSD, kiedy ktoś narzeka, że jego proces budowy zawiódł, nie zdając sobie sprawy z tego, że stało się tak ponieważ próbował iść na skróty.

23.4.14.4. Czy przerwany proces budowy może zostać wznowiony?

To zależy od tego jak daleko zaszliśmy w owym procesie, zanim napotkaliśmy ten błąd.

Generalnie (i nie jest to żadna żelazna reguła) proces make buildworld buduje nowe kopie niezbędnych narzędzi (jak np. gcc(1), czy make(1)) i biblioteki systemowe. Zarówno te narzędzia, jak i biblioteki są następnie instalowane. Nowe narzędzia i biblioteki są w dalszej kolejności używane do przebudowania się i ponownie instalowane. Cały system (teraz już włączając w to regularne programy użytkownika, takie jak ls(1) czy grep(1)) jest wtedy przebudowywany przy użyciu nowych plików systemowych.

Jeżeli jesteśmy na ostatnim etapie i wiemy o tym (ponieważ przejrzeliśmy wyniki procesu, które przechowujemy w pliku) wtedy możemy (względnie bezpiecznie) wykonać:

... fix the problem ...
# cd /usr/src
# make -DNO_CLEAN all

Co nie zmarnuje pracy poprzedniego make buildworld.

Jeżeli zobaczymy wiadomość:

--------------------------------------------------------------
Building everything..
--------------------------------------------------------------

w wyniku make buildworld, wtedy prawodpodobnie można to względnie bezpiecznie przeprowadzić.

Jeżeli nie zobaczymy tej wiadomości lub nie mamy pewności, zawsze lepiej jest się zabezpieczyć i zacząć od początku restartując proces budowy.

23.4.14.5. Jak można przyspieszyć proces tworzenia świata?

  • Uruchamiając go w trybie awaryjnym.

  • Umieśćmy foldery /usr/src i /usr/obj w oddzielnych systemach plików, na oddzielnych dyskach. Jeżeli to możliwe, umieśćmy te dyski na oddzielnych kontrolerach dysków.

  • Jeszcze lepiej, jeżeli umieścimy te systemy plików na wielu dyskach, używając ccd(4) (sterownik łączonego dysku).

  • wyłączmy profile (ustaw “NO_PROFILE=true” w /etc/make.conf). Prawie napewno nie będziemy tego potrzebować.

  • Również w /etc/make.conf ustawmy CFLAGS do -O -pipe. Optymalizacja -O2 jest dużo wolniejsza a różnica optymalizacyjna pomiędzy -O i -O2 jest zwykle nieistotna. -pipe pozwala kompilatorowi na użycie potoków zamiast tymczasowych plików w celach komunikacji, co oszczędza czas dostępu do dysku (kosztem pamięci).

  • Przekażmy make(1) opcję -jn aby uruchomić wiele paralelnych procesów. Zwykle pomaga to niezależnie od tego czy mamy jedno-, czy wielo- procesorową maszynę.

  • System plików zawierający /usr/src może zostać zamontowany (lub przemontowany) z opcją noatime. Zapobiegnie to przed zapisywaniem przez system plików czasu dostępu do plików. Prawdopodobnie i tak nie będziemy potrzebować tej informacji.

    # mount -u -o noatime /usr/src
    

    OstrzeżeniePrzykład zakłada, że /usr/src znajduje się w swoim własnym systemie plików. Jeżeli tak nie jest (jeżeli jest np. częścią /usr) musimy wtedy użyć punktu montowania dla tego systemu plików, nie /usr/src.

  • System plików zawierający /usr/obj może zostać zamontowany (lub przemontowany) z opcją async. Sprawi to, że zapisy dysku będą asynchroniczne. Innymi słowy, zapis będzie natychmiastowy a dane zostaną zapisane na dysku jedynie kilka sekund później. Pozwoli to, żeby zapisy były grupowane razem, co może drastycznie wpłynąc na wzrost wydajności.

    OstrzeżeniePamiętajmy jednak o tym, że opcja ta czyni nasz system bardziej kruchym. Opcja ta zwielokrotnia szansę na to, że nasz system będzie w stanie nie do odzyskania po ponownym uruchomieniu, jeżeli zasilanie wysiądzie.

    Jeżeli /usr/obj jest jedyną rzeczą w tym systemie plików, wtedy nie stanowi to problemu. Jeżeli posiadamy inne, cenne dane w tym samym systemie plików, upewnijmy się, że nasze kopie bezpieczeństwa są jak najświeższe, zanim włączymy tą opcję.

    # mount -u -o async /usr/obj
    

    OstrzeżenieJak powyżej, jeżeli /usr/obj nie znajduje się we własnym systemie plikówi, zamieńmy punkt montowania z przykładu na odpowiedni.

23.4.14.6. Co zrobić, jeżeli coś pójdzie nie tak?

Upewnijmy się, że w naszym środowisku nie ma żadnych nieistotnych pozostałości po wcześniejszych procesach budowy. Jest to dość proste.

# chflags -R noschg /usr/obj/usr
# rm -rf /usr/obj/usr
# cd /usr/src
# make cleandir
# make cleandir

Tak, make cleandir naprawdę powinna zostać użyta dwukrotnie.

Następnie, musimy ponownie uruchomić cały proces, zaczynając od make buildworld.

Jeżeli nadal pojawiają się problemy, wyślijmy błąd i wynik uname -a do Ogólna lista dyskusyjna FreeBSD. Bądźmy przygotowani do odpowiadania na pytania dotyczące naszych ustawień!

Ten i inne dokumenty można pobrać z ftp://ftp.FreeBSD.org/pub/FreeBSD/doc/.

W przypadku pytań o FreeBSD prosimy przeczytać dostępną dokumentację przed kontaktem z <questions@FreeBSD.org>.
W sprawie zapytań o tę dokumentację prosimy o kontakt z <doc@FreeBSD.org>.