Rozdział 27. Dystrybucja aplikacji
W tym rozdziale omówimy skrótowo przygotowanie własnej aplikacji do rozpowszechniania, tworzenie źródłowych i binarnych pakietów dystrybucyjnych oraz sposób reakcji na błędy dostrzeżone przez użytkowników. Będziemy więc:
poznawać instalator pakietów RPM,
korzystać z poleceń autoconf i configure przy tworzeniu plików makefile specyficznych dla danej instalacji,
opisywać proces tworzenia pakietu RPM,
omawiać tworzenie i dystrybucję łatek,
poznawać śledzenie błędów zauważonych po wydaniu aplikacji.
Pisanie programów dla systemu Microsoft DOS jest bardzo proste, ponieważ program działający na jednej maszynie będzie prawdopodobnie działał także na innych. Windows wprowadza pewne ograniczenia, ponieważ trzeba pamiętać o różnych odmianach, takich jak CE (we wszelkiego rodzaju komputerkach podręcznych), NT, 9x i 2000. Pomimo tego, trzeba program skompilować dla każdej z tych platform i dostarczyć binarny plik wykonywalny.
Oprogramowanie o otwartych źródłach dostarcza nowych wyzwań, gdy dochodzi do dystrybucji ukończonych aplikacji. Ogólnie mówiąc, należy sprostać wymaganiom znacznie większej liczby platform sprzętowych i procesorów. Oprócz tego, po podjęciu decyzji o rozpowszechnianiu aplikacji jako wolnego oprogramowania należy udostępnić kod źródłowy.
Programując w systemie Linux, należy pamiętać o tym, że użytkownicy będą próbowali kompilować aplikacje na innych maszynach z systemami typu UNIX, np. FreeBSD, Solaris, HP-UX itp. Każdy z tych systemów czymś się różni od pozostałych. Często te różnice są tak duże, że uniemożliwiają skompilowanie dostarczonej aplikacji. Nawet różne dystrybucje Linuksa mają swoje pułapki, w które może wpaść nieuważny programista. Wystarczy powiedzieć, że Linux próbuje trafić na rynek i dlatego musi być adaptowany, używany i poszerzany przez innych. Dlatego właśnie należy dołożyć wszelkich starań, aby instalacja i aktualizacja utworzonej aplikacji przebiegała możliwie bez zakłóceń.
Jednym ze sposobów realizacji tego celu jest dostarczanie pakietów w postaci skompilowanej, które dają się łatwo zainstalować. Jeżeli dodatkowo dostarczony będzie pakiet źródłowy, to zainteresowani mogą przejrzeć i zmodyfikować kod. Wielu użytkowników Linuksa zna taki sposób dystrybucji oprogramowania w postaci pakietów. Jako przykład omówimy jedną z najpopularniejszych metod, a mianowicie pakiety RPM autorstwa firmy Red Hat. Przeanalizujemy te pakiety zarówno z punktu widzenia użytkownika, jak i z punktu widzenia programisty, który je musi utworzyć.
Możliwe, że opracowywana aplikacja jest budowana w sposób zależny od innych programów, na które programista nie ma wpływu. Na przykład interfejs graficzny dla debugera GDB będzie użyteczny tylko wtedy, gdy sam debuger zostanie zainstalowany. Nie tylko o to tutaj chodzi: może także wystąpić zależność od specyficznej wersji debugera.
Zamiast dołączać kopię GDB do swojej aplikacji, należy wprowadzić taką jawną zależność do pakietu binarnego. Dzięki temu użytkownik instalujący aplikację zostanie ostrzeżony, jeśli w jego systemie nie jest zainstalowany GDB lub jego wersja jest niedopasowana. W dalszej części tego rozdziału pokażemy, w jaki sposób rozwiązywane są takie zależności w pakietach RPM.
Instalowanie dostarczonej aplikacji może być tak proste i polegać np. na wstawieniu pliku binarnego do katalogu /usr/local/bin lub /opt. Musimy jednak pamiętać, że trzeba także uruchomić program konfiguracyjny, zainicjować bazę danych lub wykonać pewne czynności porządkujące przy instalacji pakietu lub przy jego usuwaniu. Pakiety w formacie RPM umożliwiają zautomatyzowanie tych wszystkich niezbędnych operacji.
Można nawet utworzyć własną dystrybucję systemu Linux, zbudowaną tak, aby pasowała i obsługiwała tylko rozpowszechnianą aplikację. Takie rozwiązanie spotyka się w praktyce w specjalistycznych aplikacjach, np. w serwerach komunikacyjnych.
Ponieważ spodziewamy się, że aplikacja rozprowadzana jako otwarte oprogramowanie będzie ulepszana przez społeczność użytkowników, to należy zastanowić się, jak wprowadzać takie modyfikacje, aby były zgodne z niezależnymi od producentów międzynarodowymi standardami, jak np. POSIX. Obsługa skomplikowanych wymagań narzucanych przez różnorodne platformy sprzętowe jest wspomagana przez dodatkowe narzędzia, dzięki którym program może działać na różnych maszynach — pokażemy tu więc zastosowanie poleceń configure i autoconf. Oczywiście, przestrzeganie standardów także może w tym wszystkim bardzo pomóc.
Istnieją wolne programy dla systemu Linux, które charakteryzują się nadzwyczaj wysoką jakością i z nimi należy konkurować. W rozdziale 2. przedstawiliśmy system CVS, który może być zastosowany w sieci do udostępniania kodu źródłowego. W tym rozdziale zapoznamy się z programem pomocniczym o nazwie patch, który może być użyty do dystrybucji poprawek kodu, zarówno niewielkich, jak i bardzo obszernych.
Popularne programy mogą budzić wielkie zainteresowanie objawiające się licznymi komentarzami na tematy ogólne, sugestiami ulepszeń i sygnalizowaniem kłopotów. Omówimy więc tu bardzo skrótowo system śledzenia błędów rozpowszechniany na zasadach GNU i noszący nazwę GNATS, wspomagający komunikację z użytkownikami.
Pakiety RPM
Pierwszy raz te pakiety zastosowano w dystrybucji Linuksa przygotowanej przez firmę Red Hat. Format RPM (skrót od Red Hat Package Manager) jest obecnie stosowany na szeroką skalę jako sposób rozprowadzania aplikacji, które mają być instalowane w systemie. RPM jest dostępny w różnych dystrybucjach, takich jak Red Hat (to oczywiste!), Mandrake (dystrybucja wywodząca się z Red Hat) i SuSE (dystrybucja niezależna). Ponieważ format RPM stał się znany i ma status wolnego oprogramowania, to można się spodziewać, że pewnego dnia będzie on obsługiwany w wielu innych dystrybucjach systemów Linux i UNIX.
Istnieją także pakiety o innych formatach, w szczególności należy tu wymienić pakiety DEB używane w dystrybucjach wywodzących się z dystrybucji Debian. Wiele z podanych w tym rozdziale reguł można odnieść także do pakietów DEB. W systemach korzystających z dystrybucji Debian należy wiec zapoznać się z dokumentacją programów dpkg i dselect. Jeżeli potrzeba, narzędzia RPM można także uruchomić w dystrybucji Debian.
Użytkownik RPM
Użytkownik Linuksa zazwyczaj spotyka się po raz pierwszy z pakietami RPM podczas instalacji systemu. Zarówno dystrybucja Red Hat, jak i SuSE rozpowszechniane są na płytach CD-ROM wypełnionych prawie całkowicie plikami w formacie RPM. Program instalacyjny zazwyczaj wyświetla menu z nazwami dostępnych pakietów (lub ich zbiorów) i instaluje wybrane z nich. Instalację pakietów RPM wykonuje program o nazwie rpm.
Po zakończeniu instalacji w wielu dystrybucjach można znaleźć graficzny instalator pakietów. W tej książce będziemy omawiać podstawowy instalator pakietów RPM, ponieważ można go stosować jeszcze przed instalacją i uruchomieniem X Window.
Program rpm jest stosowany wówczas, gdy trzeba zmodyfikować zainstalowany system, czyli w następujących okolicznościach:
usuwanie zbędnych pakietów,
dodawanie tych pakietów z dystrybucji, które nie były początkowo zainstalowane,
aktualizacja zainstalowanego pakietu (instalacja nowszej wersji),
dodawanie nowego pakietu pochodzącego z innych źródeł.
Powyższe zadania nie są na ogół skomplikowane, lecz wymagają posiadania uprawnień superużytkownika, ponieważ podczas instalacji trzeba korzystać z obszarów systemowych w systemie plików (wyjaśnimy to za chwilę). Istnieją jednak operacje, które może wykonać zwykły użytkownik korzystający z rpm i od nich właśnie rozpoczniemy.
Program rpm może na pierwszy rzut oka onieśmielać. Po wpisaniu polecenia:
$ rpm --help
pojawi się dwustronicowa lista wszystkich opcji tego programu, przeznaczonych zarówno dla użytkownika instalującego gotowe pakiety RPM, jak i dla programisty tworzącego dystrybucyjne pakiety źródłowe lub binarne. Opiszemy tu kilka prostszych opcji, które pomagają zrealizować najczęściej spotykane zadania.
Program rpm może być uruchomiony w kilku trybach, zależnie od potrzeb użytkownika. Są to:
tryb zapytań,
tryb instalacji i aktualizacji pakietów,
tryb budowania pakietów.
Do wyboru pakietu, który będzie używany jako przykład pokazujący instalację i aktualizację, użyjemy pierwszego z tych trybów. Tryb zapytań jest wywoływany za pomocą opcji -q.
Co naprawdę zostało zainstalowane?
Aby uzyskać listę wszystkich pakietów zainstalowanych przez program rpm, trzeba wywołać go w trybie zapytań z dodatkową opcją -a oznaczającą wszystkie pakiety:
$ rpm -q -a
aaa_base-99.11.11-2
aaa_dir-99.11.12-0
base-99.11.2-1
bash-2.03-26
bdflush-1.5-101
cpio-2.4.2-99
...
gnuchess-4.0.pl80-5
...
xboard-4.0.0-68
...
dia-0.81-1
pg_datab-6.5-21
pg_ifa-6.5.1-18
pg_iface-6.5.1-15
postgres-6.5.1-18
$
W dobrze wyposażonym systemie SuSE uzyskuje się w ten sposób listę zawierającą nazwy ponad tysiąca pakietów, które są zainstalowane. Kilka ostatnich podanych wyżej pozycji informuje, że baza danych PostgreSQL jest zainstalowana w najnowszej dostępnej wersji.
Nazwy pakietów mają następującą postać:
<nazwa_pakietu>-<wersja_pakietu>-<numer_wydania>
Nazwa pakietu jest zwykle nazwą głównej biblioteki lub programu zawartych w pakiecie. Wersja pakietu oznacza numer wersji aplikacji zawartej w tym pakiecie. Numer wydania jest powiększany za każdym razem przy budowie znowelizowanego pakietu RPM przeznaczonego do dystrybucji. Na przykład pakiet zawierający bazę danych PostgreSQL ma nazwę postgres-6.5.1-18. i jest osiemnastym kolejnym pakietem zawierającym bazę PostgreSQL w wersji 6.5.1.
Pakiety są przebudowywane z wielu powodów. Przeważnie decyduje o tym konieczność zmiany miejsca instalacji lub skryptów uruchamianych automatycznie podczas instalacji. Nowy pakiet zawierający nową wersję aplikacji zawsze ma numer wydania równy 1, tak jak w przykładowym pakiecie dia-0.81-1 na powyższej liście.
Baza danych RPM
Program rpm utrzymuje swoją bazę danych zawierającą informacje o pakietach, plikach znajdujących się w tych pakietach i ich wzajemnych zależnościach, aby zachować ślad wszystkich instalacji pakietów w systemie Linux. Baza ta jest na ogół przechowywana w katalogu /var/lib/rpm. Prawie wszystkie pliki w tym katalogu są plikami bazy danych (jest to baza typu dbm używana w systemach UNIX). Program rpm umożliwia obsługę tej bazy w różny sposób.
Na tym etapie wystarczy, aby Czytelnik zdawał sobie sprawę z tego, że każde dodanie, aktualizacja lub usunięcie pakietu powoduje aktualizację bazy danych.
Co znajduje się w pakiecie?
Kolejną informacją, którą może podać program rpm, jest lista plików zawartych w danym pakiecie. Użyjemy dwóch pakietów z podanej wcześniej listy: gnuchess i xboard (są to odpowiednio: program szachowy i jego interfejs graficzny).
$ rpm -q xboard gnuchess
xboard-4.0.0-68
gnuchess-4.0.pl80-5
$
Listę plików zawartych w pakiecie uzyskujemy, podając dodatkowo opcję -l:
$ rpm -q -l gnuchess
/usr/bin/game
/usr/bin/gnuan
/usr/bin/gnuchess
/usr/bin/gnuchessc
/usr/bin/gnuchessn
/usr/bin/gnuchessr
/usr/bin/gnuchessx
/usr/bin/postprint
/usr/lib/eco.pgn
/usr/lib/gnuchess.data
/usr/lib/gnuchess.eco
/usr/lib/gnuchess.lang
/usr/man/man6/game.6.gz
/usr/man/man6/gnuan.6.gz
/usr/man/man6/gnuchess.6.gz
/usr/man/man6/postprint.6.gz
$
Do wyszukania pakietu, w którym jest zawarty dany plik, należy w trybie zapytań użyć dodatkowej opcji -f:
$ rpm -q -f /usr/X11R6/bin/xboard
xboard-4.0.0-68
$
W zapytaniu można podać dowolną liczbę szukanych plików i wówczas rpm wyświetli listę wszystkich pakietów, w których są one użyte. Więcej informacji na temat użycia tych opcji można znaleźć na stronach podręcznika systemowego dotyczących programu rpm.
Usuwanie pakietu
Zmiany w instalacji systemu Linux może wprowadzać tylko superużytkownik. Korzystając z programu rpm jako superużytkownik, trzeba zachować wyjątkową ostrożność, ponieważ można bardzo łatwo zniszczyć działający system, usuwając przypadkowo jakiś pakiet. Przykładowo usuniemy więc program o mniejszym znaczeniu, czyli interfejs do programu szachowego o nazwie xboard.
Można podjąć próbę usunięcia pakietu, podając opcję -e (od słowa erase) w wywołaniu programu rpm i nazwę usuwanego pakietu. Długie nazwy pakietów RPM są często skracane i tutaj również należy podać tylko jej pierwszy człon, czyli samą nazwę bez numerów wersji i wydania. Można tak postąpić, ponieważ w systemie zazwyczaj nie mogą współistnieć dwie wersje tego samego pakietu. Takie skrócone nazwy były także używane w poprzednich przykładach pokazujących pracę w trybie zapytań.
$ su -
Password:
# rpm -e xboard
#
Przy próbie sprawdzenia obecności pakietu pojawi się komunikat, że nie jest on zainstalowany:
# rpm -q xboard
package xboard is not installed
#
Teraz spróbujemy usunąć sam program szachowy gnuchess:
# rpm -e gnuchess
error: removing these packages would break dependencies:
gnuchess is needed by glchess-0.10d-67
#
Komunikat wyświetlony w odpowiedzi oznacza, że istnieje jeszcze jeden zainstalowany pakiet o nazwie glchess, którego działanie zależy od obecności programu gnuchess. Możemy dokładnie sprawdzić, co to za pakiet.
Status pakietu
Informacje o pakiecie można uzyskać, podając w wywołaniu programu rpm w trybie zapytań dodatkową opcję -i (od słowa information):
$ rpm -q -i glchess
Name : glchess Relocation: (not relocateable)
Version : 0.10d Vendor: SuSE GmbH, Nuernburg, Germany
Release : 67 Build Date: Sat 13 Nov 1999 16:13:38 GMT
Install date: Sun 02 Jan 2000 17:50:14 GMT Build Host: stott.suse.de
Group : unsorted Source RPM: glchess-0.10d-67.src.rpm
Size : 171581 License: GPL
Packager : feedback@suse.de
Summary : 3D fronted for gnuchess
Description:
glchess is a fine 3D mesa fronted for gnuchess
Authors:
-------
Tomi.Sarvela@iki.fi
$
Widać więc, że pakiet glchess jest kolejnym interfejsem graficznym programu gnuchess wyświetlającym trójwymiarowy obraz. Przestanie on działać, jeśli usunęliśmy program gnuchess. Jeżeli trzeba usunąć z komputera wszystkie programy umożliwiające grę w szachy, to wśród nich musi się znaleźć także program glchess:
# rpm -e glchess gnuchess
#
Tym razem nie ma żadnych problemów. Przy jednym wywołaniu programu rpm usunięto jednocześnie dwa pakiety, podając ich nazwy w jednym poleceniu i nie spowodowało to wyświetlenia komunikatu o zakłóceniu zależności glchess od gnuchess.
Zagadnienie zależności między pakietami omówimy szerzej w dalszych częściach rozdziału.
Instalowanie pakietów
Jeżeli istnieje plik z pakietem RPM, który trzeba zainstalować, to należy użyć opcji -i (od słowa install) w wywołaniu programu rpm. W przypadku pakietów z dystrybucji Linuksa trzeba będzie zapewne znaleźć ten plik na płycie CD-ROM. Niestety, baza danych programu rpm nie zapisuje informacji o lokalizacji instalowanych pakietów.
Pokażemy tu sposób instalacji na przykładzie programów szachowych.
Najpierw należy odszukać pliki zawierające potrzebne pakiety. Ich lokalizacja zależy od wielu czynników, a głównie od dystrybucji i użytego nośnika danych. Jeżeli pakiet był pobrany ze strony internetowej, to do instalacji wystarczy podanie jego nazwy w poleceniu programu rpm. W naszym przykładzie będziemy instalować pakiet z płyty DVD dystrybucji SuSE:
# mount /cdrom
# cd /cdrom/suse/fun1
# ls
3d_chess.rpm figlet.rpm oonsoo.rpm xbl.rpm xpilot.rpm
3dpong.rpm fishtank.rpm pacman.rpm xblast.rpm xpinguin.rpm
INDEX flying.rpm pingus.rpm xboard.rpm xpuzzles.rpm
INDEX.english fortune.rpm pipeman.rpm xboing.rpm xracer.rpm
INDEX.german freeciv.rpm playone.rpm xbomb.rpm xroach.rpm
MD5SUMS frisk.rpm puzzle.rpm xbombs.rpm xrobots.rpm
TRANS.TBL frotz.rpm pysol.rpm xdemine.rpm xshogi.rpm
abuse.rpm glchess.rpm rockdiam.rpm xearth.rpm xskat.rpm
aleclone.rpm gnuchess.rpm sastroid.rpm xengine.rpm xsnow.rpm
anachron.rpm gnugo.rpm space.rpm xfact.rpm xsok.rpm
antipoli.rpm gshogi.rpm spellc.rpm xgammon.rpm xsol.rpm
asclock.rpm hextris.rpm tf.rpm xgas.rpm xspringi.rpm
astrolog.rpm imaze.rpm tfhelp.rpm xjewel.rpm xtacy.rpm
batalion.rpm lincity.rpm thrust.rpm xlife.rpm xtartan.rpm
battball.rpm maelstr.rpm tux_aqfh.rpm xlyap.rpm xteddy.rpm
bsdgames.rpm manix.rpm tuxeyes.rpm xmahjong.rpm xtetris.rpm
bzflag.rpm meltflip.rpm vgacard.rpm xmemory.rpm xthing.rpm
craft.rpm mirrma.rpm x3d.rpm xmine.rpm xtron.rpm
crafty.rpm moontool.rpm xabacus.rpm xmines.rpm xvier.rpm
crosfire.rpm net3d.rpm xancur.rpm xmaounts.rpm yahtzee.rpm
daliclck.rpm nethack.rpm xaos.rpm xmris.rpm
emiclck.rpm netmaze.rpm xball.rpm xpat2.rpm
empire.rpm oneko.rpm xbill.rpm xphoon.rpm
#
Widzimy tu bardzo wiele pakietów RPM, a wśród nich także gnuchess i xboard. Jeżeli spróbujemy zainstalować pojedynczo pakiet xboard, to tak jak należy oczekiwać, pojawi się komunikat o niespełnionych zależnościach:
# rpm -i xboard.rpm
error: failed dependencies:
gnuchess is needed by xboard-4.0.0-68
#
Można instalować wiele pakietów równocześnie (i tak trzeba postępować, jeśli są one od siebie nawzajem zależne), podając ich nazwy w tym samym wierszu poleceń:
# rpm -i xboard.rpm gnuchess.rpm
#
Aktualizacja pakietu
Jeżeli jest zainstalowana wcześniejsza wersja pakietu i chcemy ją zaktualizować, to w programie rpm zamiast opcji -i należy użyć opcji -U (od słowa upgrade). Opcja ta działa prawie tak samo jak opcja instalacyjna, z tą różnicą, że pliki są zastępowane ich nowszymi wersjami. Opcja -i nie pozwala na zainstalowanie innej wersji pakietu, jeżeli jakąś jego wersję zainstalowano już wcześniej.
Instalatory graficzne
Ponieważ instalacja pakietów RPM jest operacją wykonywaną dość często, powstało wiele programów pomocniczych wspomagających tę czynność. W środowisku GNOME jest stosowany program gnorpm, który umożliwia graficzny wybór pakietów, a następnie ich instalację lub usunięcie. W środowisku KDE można znaleźć podobne narzędzie o nazwie kpackage (wygląd okna tego programu pokazano na rysunku niżej). Starsze dystrybucje Red Hat zawierały program o nazwie glint. Poza systemem X Window spotyka się tego rodzaju programy z interfejsem znakowym, jak np. YaST z dystrybucji SuSE.
|
Takie narzędzia mogą być bardzo przydatnej w codziennych pracach utrzymaniowych, ale do dnia dzisiejszego żadne z nich nie zawiera pełnej funkcjonalności programu rpm.
Sprawdzanie zależności
Aby sprawdzić zależności istniejące między zainstalowanymi pakietami, należy w trybie zapytań programu rpm użyć dodatkowej opcji -R (lub --requires):
$ rpm -q -R xboard
gnuchess
/bin/sh
/usr/bin/perl
ld-linux.so.2
libICE.so.6
libSM.so.6
libX11.so.6
libXaw.so.6
libXext.so.6
libXmu.so.6
libXt.so.6
libc.so.6
libc.so.6(GLIBC_2.0)
$
Łatwo tu zauważyć, że pakiet xboard wymaga pakietu gnuchess i kilku innych elementów (czyli bibliotek X Window, programu perl oraz powłoki sh).
Każda z pozycji powyższej listy określa pewne właściwości. Każdy pakiet RPM zapewnia jedną lub więcej takich właściwości i przy instalacji może wymagać, aby w systemie były dostępne także inne właściwości. Sam plik RPM przechowuje te właściwości. Wzajemne zależności pakietów są po prostu odzwierciedleniem tych właściwości, których nie zawiera dany pakiet. Można sprawdzić, jakimi właściwościami dysponuje pakiet, podając w trybie zapytań dodatkową opcję --provides.
Zastosujemy teraz te opcje do zbadania biblioteki XML. Dzięki tej bibliotece (opisywanej w rozdziale 23.) programy mogą odczytywać i tworzyć pliki w formacie XML, coraz częściej stosowanym w wymianie danych.
Oto przykład sprawdzenia wersji:
$ rpm -q libxml
libxml-1.7.3-5
$
Następnie sprawdzamy, jakich właściwości dostarcza pakiet:
$ rpm -q --provides libxml
libxml
libxml.so.1
libxml.so.1(GCC.INTERNAL)
$
Możemy się przekonać, że badany pakiet udostępnia kilka możliwości. Na liście znajdują się zarówno właściwości ogólne, jak i właściwości specyficzne dla tego pakietu. Pakiet zawiera bibliotekę XML (libxml) w specyficznej wersji dzielonej (libxml.so.1).
Należy bardzo uważnie sprawdzać zależności między pakietami, ponieważ niektóre z nich wymagają specyficznych wersji jakichś właściwości (sama właściwość ogólna nie wystarcza).
Możemy odszukać pakiety, które dysponują określonymi właściwościami, używając w trybie zapytań dodatkowej opcji --whatprovides:
$ rpm -q --whatprovides libxml
libxml-1.7.3-5
$
Można szukać zależności odwrotnych i sprawdzać, który zainstalowany pakiet wymaga danej właściwości. Służy do tego dodatkowa opcja --whatrequires podana w trybie zapytań:
$ rpm -q --whatrequires libxml
libglad-0.7-5
libxmld-1.7.3-5
$
Widzimy, że kilka pakietów także wymaga obecności libxml, ale co można powiedzieć na temat aplikacji? Wymagają one zazwyczaj specyficznej wersji dzielonej biblioteki, co sprawdzamy w następujący sposób:
$ rpm -q --whatrequires libxml.so.1
gnorpm-0.9-3
gnprint-0.10-5
gnumeric-0.41-5
libglad-0.7-5
$
Widzimy tu, że instalator pakietów dla środowiska GNOME o nazwie gnorpm oraz kilka innych aplikacji jawnie wymagają obecności dzielonej biblioteki libxml w wersji 1.
Pomijanie zależności
Czasami dany pakiet jest zależny od innego pakietu, który nie został zainstalowany, albo zainstalowano go w odmienny sposób. Aby poradzić sobie w takiej sytuacji, można pominąć sprawdzanie zależności pakietów przez program rpm, podając w trybie instalacyjnym dodatkową opcję --nodeps:
# rpm -i xboard.rpm
error: failed dependencies:
gnuchess is needed by xboard-4.0.0-68
# rpm -i --nodeps xboard.rpm
#
Jeżeli chcemy zainstalować pakiet, który jest już zainstalowany, to program rpm na to nie pozwoli. Można ominąć takie zachowanie programu za pomocą dodatkowej opcji --force podanej w trybie instalacyjnym. Opcja ta bywa przydatna przy instalacji wcześniejszej wersji pakietu w sytuacjach, gdy została zainstalowana jego nowsza wersja.
Inne opcje
Istnieje kilka innych opcji przydatnych dla użytkowników pakietów RPM. Można np. wyświetlić skrypt uruchamiany przy instalacji lub usuwania pakietu, podając dodatkową opcję --scripts:
$ rpm -q --scripts postgres
postinstall script (through /bin/sh):
if [ -x bin/fillup ] ; then
bin/fillup -q -d = etc/rc.config var/adm/fillup-templates/rc.config.postgres
else
echo "ERROR: fillup not found. This should not happen. Please compare"
echo "etc/rc.config and var/adm/fillup-templates/rc.config.postgres and"
echo "update by hand."
fi
touch var/log/postgresl.log
if [ "$UID" = "0" ] ; then
chown postgres.daemon var/log/postgresl.log
fi
preuninstall script (through /bin/sh):
if [ -x sbin/init.d/postgres ] ; then
sbin/init.d/postgres stop
sleep
fi
$
W powyższym przykładzie można np. odczytać, że skrypt uruchamiany przed usunięciem pakietu PostgreSQL zatrzymuje przed wykonaniem tej operacji usługę postgres.
Jeżeli trzeba zapobiec uruchamianiu skryptów przy instalacji (-i) lub usuwaniu (-e) pakietu, należy użyć dodatkowo opcji --noscripts.
Sprawdzanie, czy instalacja pakietu odbędzie się poprawnie, odbywa się dla opcji --test. Wówczas nastąpi sprawdzenie zależności, lecz nie odbędzie się faktyczna instalacja plików z pakietu.
Dodatkowa opcja -v (od słowa verbose) powoduje wyświetlanie obszerniejszych komunikatów przy niektórych opcjach trybu zapytań.
# rpm -i -v -h xboard.rpm gnuchess.rpm
xboard ##############################################
gnuchess ########################
#
Opcje o nazwach jednoliterowych można ze sobą łączyć, więc -ivh oznacza to samo, co trzy oddzielnie podane opcje -i -v -h w powyższym przykładzie.
Program rpm może również instalować pakiety bezpośrednio z Internetu za pomocą protokołu FTP lub HTTP. Wystarczy wtedy jako nazwę pakietu podać jego pełny adres internetowy. Więcej informacji na temat użycia niestandardowych portów i serwerów pośredniczących w instalacji poprzez sieć można znaleźć na stronach podręcznika systemowego do programu rpm.
Baza danych RPM umożliwia sprawdzenie poprawności zainstalowanych pakietów. Jeżeli przypadkowo zostaną usunięte jakieś pliki i trzeba sprawdzić, co zostało zniszczone, należy posłużyć się opcją -V (od słowa verify).
# rm /usr/bin/gnuchess
# rpm -V gnuchess
missing /usr/bin/gnuchess
W powyższym przykładzie można stwierdzić, że zniszczona jest instalacja gnuchess, ponieważ brakuje głównego pliku programu.
Można zweryfikować (-V) poprawność instalacji wszystkich (-a) pakietów jednocześnie (przy dużych instalacjach trochę to potrwa). Każdy zainstalowany plik jest wówczas poddawany kilku testom. Wyświetlane są nazwy tych plików, które nie przejdą pomyślnie wszystkich testów, łącznie z wynikami testów:
# rpm -V -a
S.5....T c /etc/modules.conf
S.5....T c /etc/hosts
.....U.. /var/spool/fax
Unsatisfied dependencies for shlibs5-99.11.10-1: libgif.so
missing /var/catman
$
W każdym wierszu wyjściowym podawany jest ośmioznakowy wyniku testu — wskaźnik, czy dany plik jest lub nie jest plikiem konfiguracyjnym (c). Podawane są także niespełnione zależności i brakujące pliki. Wynik testu jest po prostu wynikiem porównania faktycznych atrybutów danego pliku z atrybutami zapamiętanymi w bazie danych RPM. Różniące się atrybuty są oznaczane w następujący sposób:
. |
(kropka) pomyślny wynik testu |
S |
rozmiar pliku |
M |
uprawnienia do pliku |
U |
użytkownik |
G |
grupa |
5 |
suma kontrolna MD5 |
T |
data modyfikacji |
L |
dowiązanie symboliczne |
D |
urządzenie |
Komunikaty pojawiające się podczas weryfikacji należy traktować z pewną rezerwą, ponieważ nie wszystkie nieudane testy oznaczają jakiś problem. Wiele plików zmienia się zgodnie z zasadami sztuki podczas użytkowania systemu, np. pokazany w powyższym przykładzie plik /etc/hosts, do którego zostały dopisane adresy komputerów z sieci lokalnej.
Pakiety, które nie są zainstalowane
Większość z dotychczas omówionych operacji przeprowadzanych w trybie zapytań dotyczyła pakietów, które są zainstalowane. Czasami jednak trzeba się dowiedzieć, które pakiety powinny zostać zainstalowane, aby uzyskać wymagane właściwości lub pliki. Aby uzyskać taką informację, należy użyć opcji -p.
Jeżeli musimy znaleźć pakiet, który zawiera specyficzny plik (np. /usr/bin/gnuchess) i nie mamy takiego pliku zainstalowanego, to tryb zapytań nie dostarczy takiej informacji. Zapytanie o właściwość gnuchess także nic nie da:
$ rpm -q -f /usr/bin/gnuchess
file /usr/bin/gnuchess: No such file or directory
$ rpm -q --whatprovides gnuchess
no package provides gnuchess
$
Musimy więc spowodować, aby pliki z pakietami RPM same dostarczały informacje o sobie. Można sprawdzać wersję, posiadane właściwości, pliki zawarte w pakiecie, skrypty oraz zależności:
$ cd <katalog z pakietami rpm>
$ rpm -q -p gnuchess.rpm
gnuchess-4.0.p180-5
$ rpm -q --provides -p gnuchess.rpm
gchess
gnuchess
$ rpm -q -l -p gnuchess.rpm
/usr/bin/name
/usr/bin/gnuan
/usr/bin/gnuchess
...
Niestety, nie jest możliwe użycie opcji --whatprovides lub --whatrequires dla grupy pakietów, które nie są zainstalowane. W takim wypadku trzeba więc sprawdzać oddzielnie każdy niezainstalowany pakiet:
$ for p in *.rpm
> do
> rpm -q -R -p $p | grep -s gnuchess
> if [ "$?" = "0" ]
> then
> echo $p
> fi
> done
glchess.rpm
xboard.rpm
$
Dopiero na podstawie powyższych komunikatów można stwierdzić, że spośród pakietów znajdujących się w danym katalogu jedynie glchess i xboard wymagają obecności gnuchess. Teraz można zlokalizować gnuchess i naprawić uszkodzoną instalację, instalując pakiet gnuchess — co wynikało z weryfikacji przeprowadzonej za pomocą opcji -V.
Anatomia pakietu RPM
Przyjrzymy się teraz typowemu pakietowi RPM. Oto postgres.rpm wzięty z dystrybucji SuSE:
$ ls -ls postgres.rpm
2844 -rw-r--r-- 1 neil users 2905041 Apr 16 13:09 postgres.rpm
$ file postgres.rpm
postgres.rpm: RPM v3 bin i386 postgres-6.5.1-18
$
Typ pliku jest rozpoznawany za pomocą polecenia file, ponieważ struktura tego pliku została dodana do bazy danych /etc/magic. Plik jest rozpoznawany dlatego, że rozpoczyna się od określonego nagłówka zawierającego informację, że jest to właśnie pakiet RPM. Nagłówek zawiera także magiczną liczbę (ang. magic number) oznaczającą, czy jest to plik binarny lub czy zawiera kod źródłowy. W przypadku plików binarnych odnotowany jest także rodzaj sprzętu użytego do kompilacji. Umieszczony jest tu również napis zawierający nazwę pakietu oraz numery wersji i wydania. Te wszystkie atrybuty nagłówka są wyświetlane za pomocą polecenia file.
W rzeczywistości każdy plik z pakietem RPM stanowi archiwum (podobnie jak tar lub cpio) zawierające pliki, które trzeba zainstalować. Pliki RPM są skompresowane i zwierają sumę kontrolną umożliwiającą sprawdzenie ich integralności.
Aby lepiej poznać wewnętrzną strukturę pakietu RPM, przekształćmy go na archiwum cpio za pomocą programu rpm2cpio. Program ten wymaga podania nazwy pakietu RPM jako argumentu w wierszu poleceń (lub ze standardowego wejścia), a następnie zapisuje archiwum cpio na standardowe wyjście:
$ rpm2cpio postgres.rpm > postgres.cpio
$
Listę plików zawartych w archiwum można uzyskać za pomocą polecenia cpio:
$ cpio -t <postgres.cpio
etc/profile.d/postgres.csh
etc/profile.d/postgres.sh
sbin/init.d/postgres
sbin/init.d/rc2.d/K15postgres
sbin/init.d/rc.2/S25postgres
sbin/init.d/rc3.d/K15postgres
sbin/init.d/rc3.d/S25postgres
usr/doc/packages/postgres
usr/doc/packages/postgres/COPYRIGHT
usr/doc/packages/postgres/CVS
...
Tę metodę przekształcania na archiwum cpio można nawet zastosować do uzyskiwania pojedynczych plików z pakietu RPM bez przeprowadzania instalacji całego pakietu.
Pakiety źródłowe
Niezależnie od tego, że wiele aplikacji rozprowadza się w postaci binarnej między innymi jako pakiety RPM, to czasem należy koniecznie zbudować program z plików źródłowych. Najnowsze wersje aplikacji nie zawsze są od razu udostępniane w postaci pakietów, a czasem trzeba także dopasować aplikację do lokalnego środowiska — a to wymaga kompilacji.
Możliwe jest utworzenie pakietu RPM zawierającego kod źródłowy. Często takie pakiety nazywane są skrótowo SRPM (od słów Source RPM) lub spm. Kody źródłowe są najczęściej rozprowadzane w postaci archiwum tar. Takie archiwum nazywane bywa potocznie tarball i przeważnie jest skompresowane. Oprócz kodu źródłowego może ono także zawierać specyfikację, którą można wykorzystać do budowy binarnego pakietu RPM. Źródłowe pakiety RPM zazwyczaj zawierają takie skompresowane archiwum z kodem źródłowym.
Użytkownicy posługujący się źródłowymi skompresowanymi archiwami przeprowadzają często kompilację i instalację w następujący sposób:
$ tar zxvf application.tar.gz
$ cd application
$ ./configure
$ make
$ su -
# make install
Czasami występuje jeszcze etap sprawdzania (make check), jeśli aplikacja została wyposażona w testujące programy lub skrypty.
Każdy, kto chociaż raz instalował oprogramowanie objęte nadzorem Free Software Foundation, od razu rozpozna powyższą sekwencję poleceń. Jest to standard opracowany dla projektu GNU, który znalazł wielu naśladowców. Celem tego standardu jest jak największe ułatwienie kompilacji i umożliwienie jej przeprowadzenia na wielu różnorodnych platformach sprzętowych. Przyjrzymy się teraz bliżej poszczególnym etapom.
Najpierw odbywa się rozpakowanie archiwum tar do bieżącego katalogu. Najczęściej przy tej okazji tworzony jest nowy podkatalog zawierający kod aplikacji.
W drugim etapie (po przejściu do nowego podkatalogu, jeśli taki powstał) jest uruchamiany skrypt configure. Głównym zadaniem tego skryptu jest utworzenie pliku makefile przystosowanego do maszyny, na której odbywa się kompilacja. Często jest także tworzony plik dołączany (zwykle o nazwie config.h) zawierający opcje kompilacji, który aplikacja dołączy za pomocą dyrektywy include. Jako przykład można podać makrodefinicje, które zależą od dostępności bibliotek w systemie lub od charakterystyki systemu (np. bajtowy rozmiar liczby typu integer).
W trzecim etapie następuje kompilacja, w której wykorzystuje się dostrojone pliki makefile i pliki include.
Jeżeli wszystko przebiegnie pomyślnie, to ostatnim etapem jest instalowanie aplikacji. W normalnych okolicznościach są wymagane do tego uprawnienia superużytkownika.
Jeżeli spojrzymy na zawartość katalogu z aplikacją, przeważnie znajdziemy tam kilka pomocnych plików. Stanowią one części standardu budowania aplikacji i obejmują:
COPYING |
Zawiera szczegóły licencyjne oraz warunki kopiowania |
ChangeLog |
Opisy ostatnich zmian |
FAQ |
Często zadawane pytania i udzielane odpowiedzi |
INSTALL |
Opis sposobu instalowania aplikacji |
NEWS |
Opis nowych właściwości |
README |
Opis aplikacji i jej zadania |
TODO |
Plany na przyszłość |
Użycie tego rodzaju plików w aplikacji pomaga użytkownikowi znaleźć odpowiedzi na jego wątpliwości bez potrzeby wysyłania raportu o błędach.
configure, autoconf i automake
Istnieje kilka narzędzi wspomagających tworzenie standardowego katalogu z kodem źródłowym gotowego do dystrybucji. Są to configure, autoconf i automake. Pełny zakres zastosowań tych programów narzędziowych wykracza, niestety, poza ramy tego rozdziału. Wielu ekspertów może stwierdzić, że najlepszą metodą użycia tych narzędzi jest skopiowanie jakiejś działającej konfiguracji. Omówimy tu w skrócie niektóre pliki używane podczas tworzenia katalogu z kodem źródłowym oraz opiszemy konfigurację umożliwiającą utworzenie przenośnej aplikacji. Dalsze informacje można znaleźć na stronie info programów autoconf i automake.
Jak już wspomniano wcześniej, skrypt powłoki o nazwie configure stanowi ważną część standardowej dystrybucji źródeł aplikacji. Jest to elegancki skrypt, który może sprawdzić wersję aplikacji oraz obecność bibliotek i skonfigurować opcje używane przy tworzeniu pliku makefile.
Najczęściej używaną opcją podczas uruchamiania skryptu configure jest prawdopodobnie opcja --prefix. Definiuje ona katalog najwyższego poziomu dla instalacji aplikacji, która jest konfigurowana i dzięki temu pozwala użytkownikowi na podjęcie decyzji o zaakceptowaniu lub odrzuceniu wartości domyślnych. Zwykle skrypt konfiguracyjny konfiguruje wszystko w taki sposób, aby wynikowa aplikacja rezydowała gdzieś w katalogu /usr/local, binarne pliki programów były umieszczane w /usr/local/bin, zaś strony podręcznika systemowego w /usr/local/man itd. Zastosowanie opcji --prefix umożliwia zmianę domyślnej lokalizacji katalogu najwyższego poziomu (/usr/local) na coś innego (np. /opt lub coś związanego z numerem wersji, jak /usr/local/app-1.0). Inne aplikacje mogą mieć zdefiniowane własne skrypty konfiguracyjne umożliwiające np. budowę fragmentu całego zestawu aplikacji.
Sam skrypt configure przeważnie nie jest pisany ręcznie, ponieważ zawiera wiele powtarzalnych elementów, jest on natomiast generowany przez program autoconf. Skrypt utworzony za pomocą programu autoconf nie wymaga obecności tego programu podczas uruchamiania, ponieważ jest skryptem powłoki (zazwyczaj dosyć długim). Program autoconf tworzy taki skrypt na podstawie szablonu zawierającego informację o właściwościach lub innych pakietach wymaganych przez aplikację.
Zajmijmy się przykładem prostego użycia programu autoconf. Omawiany w książce testowy program dla aplikacji obsługującej wypożyczalnię płyt DVD korzysta z biblioteki GNU o nazwie readline obsługującej wprowadzane danych wejściowych. Jeżeli spróbujemy skompilować taką aplikację w systemie nie dysponującym biblioteką readline, to kompilacja się nie uda. Jest to wielka szkoda, ponieważ program testowy korzystający z readline nie zależy tylko od tej biblioteki. Jest ona używana tylko przy edycji wiersza poleceń i jej brak nie zmniejsza właściwości użytkowych samego programu. Najprostszym sposobem na uniknięcie takich kłopotów jest napisanie kodu w taki sposób, aby wywołania funkcji z biblioteki readline odbywały się warunkowo, np. za pomocą dyrektywy #define.
Najpierw należy utworzyć plik wejściowy, który będzie używany przez program autoconf. Plik ten nazywa się configure.in. Jeżeli dołączane są testy sprawdzające np. dostępność jakichś narzędzi lub bibliotek, można je włączyć w postaci skryptów powłoki, zapisywanych zazwyczaj w pliku o nazwie aclocal.m4. Program autoconf bardzo intensywnie korzysta z procesora makropoleceń m4, więc trzeba szerzej się z nim zapoznać, studiując jego strony info. Jeżeli potrzebny jest plik dołączany w języku C sterujący wykorzystaniem różnych właściwości przez aplikację, to trzeba utworzyć plik o nazwie config.h.in.
Program autoconf obsługuje bardzo wiele makropoleceń służących do testowania i prawdopodobnie wystarczą one dla zaspokojenia większości wymagań. Szczegóły można znaleźć w dokumentacji do tego programu.
Korzystając ze skryptu configure chcemy osiągnąć w naszej aplikacji dwa cele. Po pierwsze, chcemy wygenerować konfiguracyjny plik nagłówkowy, który będzie mógł przełączać nasz kod zależny od biblioteki readline. Po drugie — chcemy utworzyć plik makefile, który będzie wykorzystany do skonsolidowania aplikacji z odpowiednimi bibliotekami.
Plik nagłówkowy jest tworzony na podstawie następującego szablonu o nazwie config.h.in:
/*
config.h
Ustawienie opcji kompilacji
*/
/* Włączenie tej definicji, jeśli jest dostępna biblioteka readline */
#define HAVE_READLINE 0
Zmienna HAVE_READLINE zostanie przedefiniowana przez skrypt configure po jego uruchomieniu. Zbudujemy ten skrypt tak, aby zmiennej HAVE_READLINE nadawał wartość 1 albo 0, zależnie od tego, czy plik dołączany readline jest obecny w systemie, czy nie.
Oto przykład prostego pliku configure.in:
dnl Przetworzenie tego pliku przez autoconf daje skrypt configure.
AC_INIT(dvdstore.c)
AC_CONFIG_HEADER(config.h)
dnl Sprawdzenie obecności programów.
AC_PROG_CC
dnl Sprawdzenie obecności bibliotek.
dnl Sprawdzenie obecności plików nagłówkowych.
AC_HEADER_STDC
AC_CHECK_HEADERS(readline/readline.h, AC_DEFINE(HAVE_READLINE)
dnl Sprawdzenie definicji typów, struktur i charakterystyki kompilatora.
dnl Sprawdzenie obecności funkcji bibliotecznych.
AC_OUTPUT()
Wiersze rozpoczynające się od oznaczenia dnl są komentarzami, które makroprocesor m4 usuwa podczas pracy (dnl jest skrótem od „delete to new line”, czyli „usuń tekst aż do końca wiersza”). W pliku jest kilka wywołań makropoleceń, które mogą być umieszczane praktycznie w dowolnej kolejności. Jedynie wywołania AC_INIT i AC_CONFIG_HEADER muszą być umieszczone na początku, zaś AC_OUTPUT na końcu pliku. Pozostałe pokazane tu sekcje są w większości puste; ilustrują jedynie zalecaną kolejność testów. Testy mogące sprawić jakieś kłopoty zwykle są umieszczane wcześniej.
Makropolecenie AC_INIT jest używane przez skrypt configure do inicjacji. Przekazuje on nazwę pliku, który musi istnieć w katalogu zawierającym dane źródłowe. Skrypt sprawdza, czy ten plik istnieje i czy dzięki temu może dalej pracować we właściwej lokalizacji.
Makropolecenie AC_CONFIG_HEADER deklaruje nazwę konfiguracyjnego pliku nagłówkowego — w naszym przypadku jest to config.h.
Test AC_PROG_CC jest pierwszym testem uruchamianym przez skrypt configure. Sprawdza on obecność kompilatora języka C. Potem następuje test sprawdzający obecność standardowych plików nagłówkowych biblioteki języka C. Następnie dochodzimy do pierwszego zadania, które ma wykonać skrypt configure, czyli sprawdzenia obecności pliku nagłówkowego biblioteki readline. Jeżeli ten plik zostanie znaleziony, zdefiniowana zostanie zmienna HAVE_READLINE.
Na zakończenie makropolecenie AC_OUTPUT powoduje, że skrypt configure zaktualizuje swoje pliki wyjściowe (w tym przypadku będzie to plik config.h), wprowadzając do niego wymagane wyniki testów.
Przejdźmy teraz do praktyki. Najpierw uruchamiamy program autoconf, aby utworzyć skrypt konfiguracyjny:
$ autoconf
$
Następnie uruchamiamy ten skrypt w celu utworzenia pliku nagłówkowego:
$ ./configure
creating cache ./config.cache
checking how to run the C preprocessor... cc -E
checking for ANSI C header files... yes
checking for readline/readline.h... yes
updating cache ./config.cache
creating ./config.status
creating config.h
$
Przeglądając plik nagłówkowy, możemy dostrzec zmianę dyrektywy #define, odzwierciedlającą fakt, że w naszym systemie jest zainstalowana biblioteka readline:
/* config.h. Generated automatically by configure. */
/*
config.h
Ustawienie opcji kompilacji
*/
/* Włączenie tej definicji, jeśli jest dostępna biblioteka readline */
#define HAVE_READLINE 1
Inne wstępnie zdefiniowane makropolecenia skryptu konfiguracyjnego umożliwiają sprawdzenie obecności samego kodu biblioteki (a nie tylko jej pliku nagłówkowego) oraz tego, czy w tym kodzie istnieją funkcje wymagane przez naszą aplikację. Zakładamy tutaj, że jeśli istnieje plik nagłówkowy, to biblioteka readline także jest prawidłowa!
Można także sprawdzić, czy utworzony plik makefile poradzi sobie z brakiem biblioteki readline. W tym celu można utworzyć zmienną w skrypcie konfiguracyjnym, która umożliwi edycję pliku makefile w taki sam sposób, jak to się stało z plikiem config.h.
Musimy więc utworzyć szablon pliku makefile, który będzie modyfikował skrypt konfiguracyjny. W opisywanym przykładzie w pliku o nazwie Makefile.in używamy nazw zmiennych otoczonych znakami „@”:
RLIB = @RLIB@
dvdstiore: dvdstore.o
$(CC) -o dvdstore dvdstore.o dvd_pg.a $(RLIB)
Jest to bardzo prosty plik makefile utworzony tylko dla celów pokazowych. Chcemy, aby skrypt configure ustawiał zmienną RLIB, jeżeli istnieje możliwość skonsolidowania aplikacji z biblioteką readline, albo pozostawiał ją pustą, jeżeli biblioteka nie jest dostępna.
Musimy więc wprowadzić pewne zmiany do pliku configure.in, aby działało to w pożądany sposób:
...
dnl Sprawdzenie obecności funkcji bibliotecznych.
AC_CHECK_LIB(readline, rl_bind_key,
RLIB="-lreadline -lncurses",
[],
-lncurses)
AC_SUBST(RLIB)
AC_OUTPUT(Makefile)
Makropolecenie AC_CHECK_LIB sprawdza, czy można skonsolidować testowy program wywołujący funkcję rl_bind_key (jest to jedno z wywołań użyte w programie). Makropolecenie to używa następujących parametrów:
<biblioteka>, <funkcja>, <działanie-jeśli-znaleziona>, <działanie-jeśli-nie-znaleziona>, <inne-biblioteki>
Jeżeli kompilacja programu testowego z opcją -lreadline przebiega poprawnie, to makropolecenie ustawia zmienną powłoki RLIB. W opisywanym przypadku potrzebna jest także konsolidacja z biblioteką curses, na co wskazuje obecność członu <inne-biblioteki>. Puste nawiasy kwadratowe oznaczają, że nie jest podejmowane żadne działanie, jeżeli ta biblioteka nie zostanie znaleziona.
Przy wyszukiwaniu błędów w skrypcie configure warto oczyścić bufor konfiguracyjny. Jest to plik o nazwie config.cache, używany przez configure do przechowywania zmiennych między uruchomieniami kolejnych testów. Można usunąć go bez żadnych skutków ubocznych, wymuszając w ten sposób ponowne uruchomienie wszystkich testów przez skrypt configure. Takie postępowanie jest zalecane po zmianie pliku configure.in i ponownym uruchomieniu programu autoconf.
$ rm config.cache
$ autoconf
$ ./configure
creating cache ./config.cache
checking how to run the C preprocessor... cc -E
checking for ANSI C header files... yes
checking for readline/readline.h... yes
checking for rl_bind_key in -lreadline... yes
updating cache ./config.cache
creating ./config.status
creating Makefile
creating config.h
config.h is unchanged
Widzimy teraz, że plik makefile o nazwie Makefile został utworzony po wywołaniu AC_OUTPUT(Makefile) i zawiera odpowiednie definicje bibliotek:
# Generated automatically from Makefile.in by configure.
RLIB = -lreadline -lncurses
dvdstore: dvdstore.o
$(CC) -o dvdstore dvdstore.o dvd_pg.a $(RLIB)
Podobnie jak program autoconf, program automake także generuje standardowy plik Makefile.in na podstawie szablonu Makefile.am. Celem takiego podejścia jest stworzenie możliwości zastosowania standardowych makroinstrukcji i reguł w plikach makefile. Więcej informacji na temat szczegółów można znaleźć na stronach info programu automake.
Dzięki zastosowaniu programów autoconf i automake można utworzyć przenośny kod źródłowy, który może być dostarczany użytkownikom z nadzieją, że będą oni mogli posługiwać się aplikacją w wielu odmiennie skonfigurowanych systemach.
Pakiety źródłowe RPM
Jak już wspomniano wcześniej, źródłowy pakiet RPM jest szczególnym rodzajem pakietu zawierającym kod źródłowy aplikacji, poprawki wprowadzone przez twórcę pakietu podczas jego konfiguracji oraz specyfikację pozwalającą zbudować aplikację i utworzyć binarny pakiet RPM.
Podczas instalacji źródłowego pakietu RPM kod źródłowy (na ogół w postaci skompresowanego archiwum) jest umieszczany przeważnie w katalogu /usr/src/packages/SOURCES, zaś plik ze specyfikacją w /usr/src/packages/SPECS. Dokładna lokalizacja zależy od rodzaju dystrybucji i często spotyka się np. lokalizację /var/lib/rpm i podrzędne katalogi.
Jako przykład źródłowego pakietu RPM pokażemy aplikację XBoard przygotowaną dla dystrybucji SuSE 6.3. Pakiet ten ma nazwę xboard.spm.
Jeśli sprawdzimy zawartość pakietu za pomocą programu rpm, zobaczymy kod źródłowy, łatki i specyfikację:
$ rpm -q -l -p xboard.spm
xboard-4.0.0.dif
xboard-4.0.0.tar.gz
xboard.spec
$
Te pliki można rozpakować (np. do /usr/src/packages/SOURCES lub tam, gdzie wskazuje konfiguracja programu rpm), instalując po prostu pakiet:
$ rpm -i xboard.spm
Budowanie pakietu RPM
Pakiet RPM jest idealnym rozwiązaniem dla użytkowników chcących rozprowadzać swoją aplikację. Mając taki pakiet, można z łatwością zainstalować aplikację, odinstalować ją, korzystać z trybu zapytań i sprawdzać zależności. Opiszemy więc, w jaki sposób utworzyć własny pakiet RPM.
Najprostszą metodą utworzenia własnego pakietu RPM jest małe oszustwo. Twórca pakietu RPM ma do dyspozycji bardzo wiele opcji, ale większość z nich rzadko jest używana. Zgodnie z ideą otwartego oprogramowania można „pożyczyć” specyfikację i metody używane w innym pakiecie i zastosować je w swoim.
Ponieważ tworzenie pakietu RPM może być zadaniem bardzo skomplikowanym (można na ten temat napisać całą książkę), w tym rozdziale podamy tylko prosty przykład. Powinien on wystarczać do rozpowszechniana niewielkiej aplikacji w postaci źródłowej lub binarnej. Bardziej egzotyczne opcje i obsługę łatek w pakiecie pozostawiamy bardziej dociekliwym Czytelnikom. Pomocne mogą być tu strony podręcznika systemowego dla programu rpm oraz plik RPM HOWTO (znajdujący się przeważnie w katalogu /usr/doc).
Utworzymy pakiet RPM dla naszej aplikacji dvdstore obsługującej wypożyczalnię płyt DVD.
Motorem operacji tworzenia pakietu RPM jest plik spec, który nazwiemy dvdstore.spec. Plik specyfikacji składa się z wielu sekcji opisujących sposób budowy aplikacji, jej instalowanie oraz zależności z innymi plikami.
W pracy programu rpm podczas tworzenia pakietu można wyróżnić kilka etapów, które można w pewien sposób kontrolować. Wykorzystamy do tego poszczególne sekcje w pliku specyfikacji.
Ogólnie mówiąc, do przeprowadzania swoich operacji program rpm korzysta z drzewa katalogów /usr/src/packages (lub /var/lib/rpm). Skompresowane archiwa z kodem źródłowym będą przechowywane w katalogu SOURCES, pliki specyfikacji w SPECS, źródłowe pakiety RPM będą tworzone w SRPMS, zaś binarne pakiety RPM w katalogu RPM. Zbudowane aplikacje będą umieszczane w podkatalogach BUILD.
Dla danego pliku specyfikacji program rpm będzie szukał skompresowanych źródeł w katalogu SOURCES, rozpakuje je do podkatalogu w BUILD, przejdzie do tego podkatalogu, zbuduje aplikację, zainstaluje ją i utworzy pakiety RPM.
Pokażemy, w jaki sposób ten cały proces jest kontrolowany przez plik specyfikacji.
Pierwsza część tego pliku zawiera pozycje opisujące aplikację, czyli to, co ona zapewnia i czego wymaga do swojego działania:
#
# spec file for package dvdstore (Version 1.1)
#
Vendor: Wrox Press
Distribution: Any
Name: dvdstore
Release: 1
Packager: neil@tilde.co.uk
Copyright: 2000 by Wrox Press
Group: Applications/Media
Provides: dvdstore
Requires: postgres-6.5
Autoreqprov: on
Version: 1.1
Summary: DVD Rental Store Application
Source: dvdstore-1.1.tar.gz
Większość pozycji z powyższej listy jest zrozumiała sama przez się. Pakiety RPM mają nazwy w następującej postaci:
Nazwa-Wersja-Wydanie.architektura.rpm
Jako architektura występuje src dla źródłowych pakietów RPM, noarch dla pakietów binarnych, które nie są zależne od platformy lub i386 dla pakietów binarnych przygotowanych dla komputerów z procesorami firmy Intel. W systemach Linux działających na innych platformach sprzętowych używane są inne oznaczenia, np. sparc dla procesorów SPARC firmy Sun. Niektóre pakiety zawierają aplikacje skompilowane specjalnie dla jakiegoś rodzaju procesora i wówczas może się tu znaleźć wyróżniające się oznaczenie. Jako przykład można podać jądro skompilowane dla procesora Pentium firmy Intel, dla którego pakiety będą oznaczane jako i586.
Pozycja Group jest używana przez graficzne instalatory pakietów. Umożliwia ona grupowanie aplikacji o określonych właściwościach.
Pozycja Autoreqprov umożliwia programowi rpm dodawanie swoich własnych zależności, jeżeli jest to konieczne. Przykład zastosowania tej właściwości będzie pokazany dalej.
Następna (obowiązkowa) część specyfikacji zawiera opis aplikacji podawany w swobodnym formacie. Często podaje się tutaj dane o autorze.
%description
DVD Rental Store Application
An application to manage a DVD rental store, including membership, rental and return of titles and reservations.
This version requires PostgreSQL 6.5.
Authors: Neil Matthew and Richard Stones
Kolejna sekcja zawiera polecenia używane przez proces build programu rpm, mające za zadanie przygotowanie kodu źródłowego do kompilacji, kompilację i następnie instalację aplikacji:
%prep
%b
%build
make
%install
make install
Sekcja %prep służy do przygotowania kodu źródłowego do kompilacji. Może się tu także odbywać wprowadzanie poprawek (łatek). Istnieje makropolecenie (%setup), które rozpakowuje skompresowane archiwum z kodem źródłowym — ta informacja jest wystarczająca do zbudowania naszej przykładowej aplikacji.
Sekcja %build zawiera instrukcje dotyczące budowania aplikacji. W przypadku naszej przykładowej aplikacji wystarcza tu zwykłe polecenie make. Przy aplikacjach bardziej skomplikowanych można wywołać skrypt configure z odpowiednimi parametrami (jeżeli np. mamy zamiar budować binarny pakiet RPM ze specjalnym zestawem opcji).
Sekcja %install zawiera instrukcje dotyczące lokalnej instalacji.
Każda z sekcji %prep, %build oraz %install jest właściwie skryptem powłoki i dlatego może zawierać dowolne polecenie powłoki, łącznie z poleceniami warunkowymi.
Jeżeli zażyczymy sobie zbudowania pakietu RPM, to program rpm będzie uruchamiał kolejno poszczególne sekcje. Nazwy opcji kontrolujących budowanie pakietu zaczynają się od litery -b.
-bp |
Uruchomienie sekcji %prep |
-bc |
Uruchomienie sekcji %build |
-bi |
Uruchomienie sekcji %install |
-bs |
Budowa pakietu źródłowego (po %prep, %build i %install) |
-bb |
Budowa pakietu binarnego (po %prep, %build i %install) |
-ba |
Budowa zarówno pakietu źródłowego, jak i pakietu binarnego |
Do utworzenia binarnego pakietu RPM program rpm wymaga informacji o tym, które pliki będą instalowane w procesie instalacji. Pliki te trzeba wskazać w sekcji %files w pliku specyfikacji:
%files
/usr/local/lib/dvd_pg.a
/usr/local/include/dvd.h
/usr/local/man/man3/dvd3
Aby sprawdzić, czy podane na tej liście pliki istnieją, stosujemy w programie rpm opcję -bl (sprawdzenie listy):
$ rpm -bl dvdstore.spec
Processing files: dvdstore
File not found: /usr/local/man/man3/dvd3
Provides: dvdstore
Requires: postgres-6.5
$
Po upewnieniu się, że nasza aplikacja będzie zbudowana i zainstalowana z plików źródłowych, oraz sprawdzeniu poprawności listy plików można przystąpić do budowy pakietów RPM. Oczywiście, do instalacji wymagane są odpowiednie uprawnienia superużytkownika. Podane niżej komunikaty pojawiające się podczas tych operacji są skrócone z powodu braku miejsca:
$ rpm -ba dvdstore.spec
Executing: %prep
+ umask 022
+ cd /usr/src/packages/BUILD
+ cd /usr/src/packages/BUILD
+ rm -rf dvdstore-1.1
+ /bin/gzip -dc /usr/src/packages/SOURCES/dvdstore-1.1.tar.gz
+ tar -xvvf -
drwxr-xr-x neil/users 0 2000-04-25 10:54 dvdstore-1.1/
-rw-r--r-- neil/users 1093 2000-04-25 10:54 dvdstore-1.1/Makefile
-rw-r--r-- neil/users 5391 2000-04-08 20:23 dvdstore-1.1/pg_disk.pgc
-rw-r--r-- neil/users 6889 2000-04-08 20:23 dvdstore-1.1/p_title.pgc
...
+ STATUS=0
+ '[' 0 -ne 0 ']'
+ cd dvdstore-1.1
++ /usr/bin/id -u
+ '[' 500 = 0 ']'
++ /usr/bin/id -u
+ '[' 500 = 0 ']'
+ /bin/chmod -Rf a+rX,g-w,o-w .
+ exit 0
Executing: %build
+ umask 022
+ cd /usr/src/packages/BUILD
+ cd dvdstore-1.1
+ make
gcc -Wall -g -I/usr/lib/pgsql/include -c dvd_gen.c -o dvd_gen.o
ecpg -t -I/usr/lib/pgsql/include pg_util.pgc
gcc -Wall -g -I/usr/lib/pgsql/include -c pg_util.c -o pg_util.o
ecpg -t -I/usr/lib/pgsql/include pg_functional.pgc
gcc -Wall -g -I/usr/lib/pgsql/include -c pg_functional.c -o pg_functional.o
ar -r dvd_pg.a dvd_gen.o pg_util.o pg_functional.o pg_member.o pg_lookup.o
pg_title.o pg_disk.o
+ exit 0
Executing: %install
+ umask 022
+ cd /usr/src/packages/BUILD
+ cd dvdstore-1.1
+ make install
cp dvd.h /usr/local/include
cp dvd_pg.a /usr/local/lib
+ exit 0
Processing files: dvdstore
Finding provides...
Finding requires...
Provides: dvdstore
Requires: postgres-6.5
Wrote: /usr/src/packages/SRPMS/dvdstore-1.1-1.src.rpm
Wrote: /usr/src/packages/RPMS/i386/dvdstore-1.1-1.i386.rpm
$
Tak utworzone źródłowe i binarne pakiety RPM można już rozsyłać do użytkowników.
Jeżeli w momencie instalowania lub usuwania aplikacji należy uruchomić jakiś skrypt, to można go dodać do pliku specyfikacji. Szczegółowe informacje na ten temat można znaleźć w pliku HOWTO. Jako przykład podamy tu prosty skrypt wysyłający wiadomość do superużytkownika po instalacji pakietu. Skrypt ten powinien być umieszczony w sekcji %post (od słów post-install) pliku specyfikacji:
%post
mail root -s "DVD installed - please register" </dev/null
Teraz przy budowaniu pakietu RPM można zauważyć, że program rpm dodaje swoje własne zależności, czyli /bin/sh, ponieważ są one wymagane do uruchomienia skryptu „poinstalacyjnego”, który został ostatnio dodany:
$ rpm -bb dvdstore.spec
...
Finding requires...
Provides: dvdstore
Prereqs: /bin/sh
Requires: postgres-6.5
Wrote: /usr/src/packages/RPMS/i386/dvdstore-1.1-1.i386.rpm
$
Zbudowany pakiet RPM można sprawdzić w trybie zapytań, aby się upewnić, czy po instalacji zostanie uruchomiony dodany skrypt:
$ rpm -q --scripts -p /usr/src/packages/RPMS/i386/dvdstore-1.1-1.i386.rpm
postinstall script (through /bin/sh):
mail root -s "DVD installed - please register" </dev/null
$
W podobny sposób można dodawać inne skrypty, które mają być uruchamiane w wybranych momentach czasu.
Łatki
Decydując się na rozpowszechnianie kodu źródłowego w postaci spakowanego archiwum (lub źródłowego pakietu RPM), można także rozpowszechniać niewielkie poprawki do tego kodu (zwane łatkami). Łatka (ang. patch) jest po prostu różnicą dwóch wersji pliku lub zestawu plików. Jeżeli kod był tworzony np. pod kontrolą CVS, to można mieć pewność, że każde wydanie było oznaczone. Dzięki temu można dokładnie wiedzieć, które wersje kodu źródłowego (i innych plików) wchodzą do każdego wydania aplikacji.
Aby nie zmuszać użytkowników do pobierania kompletnego zestawu kodów źródłowych przy każdym wydaniu nowej wersji, można publikować łatki, dzięki którym będzie można aktualizować posiadane kopie plików.
Program patch (opracowany przez Larry'ego Walla i stanowiący obecnie część standardu POSIX) umożliwia automatyczne dodawanie łatek do kodu źródłowego. Mechanizm ten jest szeroko wykorzystywany w kodzie źródłowym jądra Linuksa, ponieważ cały kod ma rozmiar większy niż dziesięć megabajtów. Typowe poprawki związane ze zmianą podrzędnego numeru wersji jądra liczą zaledwie kilkadziesiąt kilobajtów nowego kodu. Łatki stanowią bardzo efektywny sposób rozpowszechniania poprawek i aktualizacji plików wśród programistów.
Tworzenie łatki
Łatka najczęściej powstaje w wyniku działania programu diff wywołanego z kilkoma specjalnymi opcjami wspomagającymi wykrywanie błędów.
Przede wszystkim należy utworzyć podkatalogi zawierające ostatnio wydaną wersję (starą wersję) i najnowszy kod (nową wersję). Następnie należy uruchomić program diff porównujący zawartości tych katalogów i tworzący listę wykrytych różnic.
Należy zwrócić szczególną uwagę na to, aby punkt wyjściowy (czyli stara wersja) był taki sam, jak wersja posiadana przez użytkowników, którzy będą stosowali łatkę. Natychmiast po operacji tworzenia różnic należy zachować nową wersję jako kolejne wydanie, aby stała się ona odniesieniem dla przyszłych łatek.
Strona podręcznika systemowego programu patch zawiera zalecaną procedurę postępowania, dzięki której z największym prawdopodobieństwem można uzyskać pomyślny wynik. Program diff przy tworzeniu łatki należy wywoływać z następującymi opcjami:
$ LC_ALL=C TZ=GMT0 diff -Naur old new
Zmienna środowiskowa LC_ALL ustawia środowisko językowe dla programu diff. Wartość tej zmiennej w powyższym przykładzie zabrania stosowania lokalnych tłumaczeń formatów daty, czasu, komunikatów itd., ponieważ nie muszą one występować w komputerze użytkownika.
Zmienna TZ uzyskuje wartość GMT0, co oznacza, że czasy i daty używane w danych wyjściowych programu diff są odniesione do czasu UTC (co ułatwia w razie konieczności kontrolę łatek).
W wywołaniu programu diff dozwolone jest użycie następujących opcji:
-N |
Traktowanie plików znalezionych tylko w jednym z katalogów jako istniejące, zaś w innym — jako puste. Spowoduje to, że powstanie łatka tworząca nowe pliki, jak jest to wymagane, ponieważ różnicą będzie po prostu cała zawartość istniejącego pliku. |
-a |
Traktowanie wszystkich plików jako tekstowych i porównywanie ich wiersz po wierszu. |
-u |
Generacja danych wyjściowym w zunifikowanym formacie zawierającym pewne informacje na temat kontekstu różnic, co pomaga programowi patch znaleźć odpowiednie miejsce do zastosowania poprawek. Ta opcja może nie być dostępna we wszystkich wersjach programu diff w systemach nielinuksowych. Jeśli opcja nie występuje w danej wersji, to należy spróbować opcji -c dla utworzenia różnic kontekstowych programu diff lub zainstalować GNU diff! |
-r |
Podczas porównywania katalogów stosowane jest rekurencyjne przeszukiwanie podkatalogów. |
Sprawdźmy to wszystko w działaniu, tworząc łatkę dla wersji 1.0 naszej aplikacji dla wypożyczalni płyt DVD, zmieniającą ją w wersję 1.1. Najpierw utworzymy katalogi zawierające tylko źródłowe pliki każdej wersji.
Często przydaje się użycie polecenia distclean w pliku „makefile” w celu usunięcia wszystkich przejściowych plików powstałych w procesie budowania aplikacji. Takie polecenie usuwa pliki obiektowe, biblioteki, kopie zapasowe plików utworzone przez edytor oraz pliki binarne aplikacji. Pozostawiane są jedynie pliki tekstowe i kod źródłowy, które są gotowe do dystrybucji lub wykonania łatki.
$ ls -F
dvd_app_1.0/ dvd_app_1.1
Utwórzmy teraz łatkę opisującą różnice dwóch wersji aplikacji. Pokazany niżej wynik działania programu diff został skrócony z powodu braku miejsca:
$ LC_ALL=C TZ=GMT0 diff -Naur dvd_app_1.0 dvd_app_1.1
diff -Naur dvd_app_1.0/makefile dvd_app_1.1/Makefile
--- dvd_app_1.0/Makefile Sat Apr 8 14:09:21 2000
+++ dvd_app_1.1/Makefile Tue Apr 25 07:42:49 2000
@@ -39,3 +44,7 @@
rm -f *~
rm -f core
+distclean:
+ rm -f *.o *~ core test_pg dvd_pg.a dvd_app final_file
+ rm -f pg_member.c pg_util.c pg_functional.c
+ rm -f pg_lookup.c pg_title.c pg_disk.c
diff -Naur dvd_app_1.0/pg_lookup.pgc dvd_app_1.1/pg_lookup.pgc
--- dvd_app_1.0/pg_lookup.pgc Sat Apr 8 19:23:56 2000
+++ dvd_app_1.1/pg_lookup.pgc Tue Apr 25 07:43:14 2000
@@ -135,7 +135,7 @@
sprintf(db_text, "Unknown Error: %d", err_number);
pg_print_debug(__FILE__, __LINE__, sqlca, "Bad err code");
}
- strcpy(*message_to_show, db_text);
+ *message_to_show = db_text;
exec sql COMMIT WORK;
} /* pg_get_err_text */
...
$
Widzimy, że został zmieniony plik Makefile (dodano polecenie distclean) oraz poprawiono błąd w pliku pg_lookup.pgc w pobliżu wiersza 135.
Aby opublikować tę łatkę, trzeba przechwycić wynik działania programu diff, poddać go kompresji i udostępnić użytkownikom:
$ LC_ALL=C TZ=GMT0 diff -Naur dvd_app_1.0 dvd_app_1.1 | gzip > patch-1.0-1.1.gz
Skompresowany plik zawierający łatkę ma rozmiar ok. 1000 bajtów, a więc niewiele w porównaniu z pełnym kodem o długości ponad 100 kilobajtów.
Użycie łatki
Gdy użytkownik otrzyma naszą łatkę, będzie mógł dokonać aktualizacji swojej kopii kodu źródłowego. Służy do tego polecenie patch, ale należy przy tym pamiętać o kilku sprawach.
Każda różnica w utworzonej łatce odnosi się do plików umieszczonych w podkatalogach dvd_app_1.0 oraz dvd_app_1.1. Użytkownik może przetrzymywać pliki źródłowe w innych katalogach niż katalogi stosowane podczas tworzenia łatki.
Program patch umożliwia zignorowanie jednego lub więcej członów nazwy pliku podczas aplikowania łatki. Najczęściej właściwość ta jest wykorzystywana w przypadku problemów z nazwą katalogu najwyższego poziomu. Należy poinstruować użytkownika, aby przeszedł do katalogu z kodem źródłowym aplikacji i użył polecenia:
$ patch -Np1
Jako dane wejściowe musi być wówczas użyty nieskompresowany plik z łatką. Można to wszystko uzyskać w następujący sposób:
$ ls -F
dvd_app/ patch-1.0-1.1.gz
$ cd dvd_app
$ gzip -dc ../patch-1.--1.1.gz | patch -Np1
patching file Makefile
patching file dvd_gen.c
patching file pg_lookup.pgc
patching file pg_util.pgc
$
Opcje programu patch są następujące:
-p<numer> |
Odcięcie pierwszego członu nazwy pliku zarejestrowanego w łatce. W naszym przykładzie zamiast dvd_app_1.0/Makefile pojawiłoby się więc Makefile, co da prawidłowy wynik, jeśli polecenie patch jest uruchamiane w katalogu najwyższego poziomu. |
-N |
Wskazanie, że łatka jest normalna (a nie odwrotna). Program patch umożliwia wycofanie wprowadzonych łatek (czyli użycie tzw. łatek odwrotnych), jeśli wykryje, że dana łatka była już użyta. Opcja -N blokuje takie działanie, dzięki czemu przypadkowe powtórne użycie łatki nie spowoduje cofnięcia wprowadzonych poprawek. |
GNATS
Po wydaniu aplikacji trafi ona do rąk wielu różnych użytkowników, zyska wiele zastosowań i spowoduje wiele problemów. Niektórzy użytkownicy będą sygnalizowali problemy autorom, prosząc o pomoc w ich pokonaniu. Jeżeli aplikacja stanie się popularna, to autorzy mogą otrzymywać bardzo wiele żądań poprawek, aktualizacji i wprowadzenia nowych właściwości.
Aplikacja GNATS jest bazą danych śledzącą błędy i warto się jej bliżej przyjrzeć. Pakiet instalacyjny tej bazy i wiele informacji na jej temat można znaleźć na stronie firmy Cygnus pod adresem http://www.cygnus.com/projects.html.
System GNATS korzysta z bazy danych do rejestracji stanu śledzonych błędów. Proces serwera oczekuje na nadchodzące raporty o błędach, które mogą docierać kilkoma drogami. System przyjmuje raporty nasyłane jako:
wiadomości poczty elektronicznej,
wiadomości przesyłane ze strony WWW,
raporty wysyłane bezpośrednio przez aplikację.
Razem z nadzorowaną aplikacją rozsyłany jest prosty program o nazwie send-pr przeznaczony dla systemu UNIX. Konfiguruje on wysyłanie raportów do systemu GNATS. Jeżeli problemy mają być zgłaszane za pomocą poczty elektronicznej, to należy także skonfigurować proces, który będzie te wiadomości odbierał i przetwarzał. Sygnalizacja błędów może być przypisana do programistów, mogą być także generowane raporty o awariach.
Opracowano także interfejs WWW dla systemu GNATS (o nazwie WebGNATS). Jest on rozpowszechniany razem z kodem źródłowym GNATS.
Podsumowanie
W tym rozdziale przedstawiono dość szeroko program RPM służący do zarządzania pakietami. Pokazano sposób użycia tego programu do kontroli pakietów oprogramowania w systemie Linux na przykładzie instalacji, usuwania i trybu zapytań. Pokazano także sposób tworzenia własnych pakietów RPM zawierających wersję źródłową i binarną aplikacji.
Omówiono także zastosowanie łatek zamiast dystrybucji kompletnego kodu źródłowego.
Podano skrótową informację o systemie GNATS służącym do śledzenia błędów i wspomagającym kontrolę problemów pojawiających się w aplikacji.
2 Część I ♦ Podstawy obsługi systemu WhizBang (Nagłówek strony)
2 D:\1-dokumenty\Word\Zaawansowane programowanie w systemie Linux\R-27-05.doc