Artykuł ten jest kopią wiadomości <slrn.pl.b0u1tv.32d.grzegorz@quatrin.pl> z naniesionymi drobnymi poprawkami. Regularnie użytkownicy szukają jakiegoś przyjaznego programu do zarządzania pakietami RPM. Instalowania, usuwania itp. Takie nakładki często potrafią jednak wywoływać kolejne błędy lub po prostu nie są zbyt ergonomiczne. Ja, jako etatowy wichrzyciel, postuluję wtedy powrót do korzeni - czyli używanie samego rpm. Znajomość tego narzędzia znacznie ułatwia pracę w niektórych bardziej złożonych przypadkach (a w tych prostszych nie musi wcale utrudniać). Na potrzeby artykułu nieco nagiąłem rzeczywistość, niektóre rzeczy robiłem też bardziej okrężną drogą niż jest to konieczne (np. sortowanie według daty instalacji można dużo prościej zrealizować za pomocą wbudowanej w RPM opcji '--last'), ale miał to być tekst propagandowo-dydaktyczny aby zainteresować początkujących, więc czuję się usprawiedliwiony.
<slrn.pl.b0u1tv.32d.grzegorz@quatrin.pl>:
(...) Naprawdę, rpm to bardzo fajne narzędzie. Jedne z pierwszych, które warto poznać. Mój system jest oparty o RPM, a nie mam w nim żadnego innego narzędzia do zarządzania pakietami jak tylko goły 'rpm' (głównie dlatego, że gnorpm wymagał zbyt wielu dodatkowych bibliotek by się skompilować, ale to, cicho sza, tajemnica ;)
Po pierwsze, można użyć mc do przejrzenia szybko kategorii zainstalowanych pakietów. Wystarczy w linii poleceń mc (tej którą widać pod panelami) wklepać
cd /#rpmsa pojawi się wirtualne drzewko katalogów, zawierające informacje o pakietach rpm podzielonych według klasy. Jeśli ktoś używa programu avfscoda, to taki "wirtualny katalog" może mieć dostępny w dowolnym filemanagerze, a nawet w gołym shellu.
A teraz krótkie omówienie najczęściej wykonywanych czynności:
Instalacja pakietu:
rpm -i xxx.rpm
Instalacja z paskiem postępu:
rpm -ivh xxx.rpm
Przy instalowaniu częstym problemem na jaki natykają się użytkownicy są tzw.
"circular (cyclic) dependencies" - w najprostszym wariancie wygląda to
tak, że mamy do zainstalowania dwa pakiety które są zależne od siebie
nawzajem. Pakiet A wymaga pakietu B, a pakiet B wymaga pakietu A.
I oczywiście żaden z nich nie daje się zainstalować, bo nie znajduje "tego
drugiego" w systemie. Ale rozwiązanie jest bardzo proste, należy
zainstalować je równocześnie:
rpm -ivh A.rpm B.rpm
Instalacja lub upgrade:
rpm -U xxx.rpm
Instalacja lub upgrade, ale z paskiem postępu:
rpm -Uvh xxx.rpm
Usunięcie pakietu:
rpm -e xxx
Trzeba zauważyć, że w tym wypadku używa się już nazwy pakietu.
To ważne. W poprzednich przypadkach rpm operował na plikach z pakietami,
więc podawało się jako argument kompletne nazwy plików, z rozszerzeniami
itp. Tutaj jednak akcja nie dotyczy jakiegoś pliku pakietu na dysku, ale
odwołuje się do pakietu zapisanego w bazie danych RPM-a. A w bazie danych
pakiety nie mają już rozszerzeń. Mają tylko nazwę, czyli np. "gpm", a nie
"gpm-1.20-3.i686.rpm". Ewentualnie można jeszcze podać wersję, ale to
zwykle nie będzie konieczne, bo RPM nie pozwala w normalnych warunkach na
współistnienie dwóch pakietów o tych samych nazwach (więc nazwa identyfikuje
jednoznacznie pakiet w bazie)
Wyświetlenie informacji o pakiecie: rpm -qi xxx Wyświetlenie spisu wszystkich pakietów: rpm -qa To w zasadzie to samo, co wyświetlenie informacji o pojedynczym pakiecie. Ale opcja '-a' mówi rpm-owi, aby przeprowadził jakąś operację na wszystkich pakietach w bazie. Dlatego RPM wyświetli spis wszystkich pakietów.
To samo, tylko ze szczegółowymi informacjami (nieczytelne IMO): rpm -qai To wygląda kryptycznie, ale jest w rzeczywistości bardzo proste. Wystarczy zapamiętać znaczenie poszczególnych literek, z których składa się opcje. 'U' to upgrade, 'i' to install, 'e' to erase, 'q' to query (odpytywanie informacji). To główne tryby pracy, po których można użyć dodatkowych opcji, zależnych od trybu. Pominąłem tylko tryb budowania nowych pakietów.
Jeśli robię upgrade czy instaluję jakiś pakiet, to mogę użyć opcji wymuszających np. ignorowanie zależności (--nodeps), albo pozwolić pakietom na konflikty pojedynczych plików (--replacefiles) czy też konflikty całych pakietów (--replacepkgs). Ale takie rzeczy rzadko się robi. To, co robi się chyba najczęściej i co sprawia najwięcej kłopotów, to zdobywanie informacji za pomocą rpm. Bo 'rpm -i' i 'rpm -e' to chyba wszyscy znają.
rpm ma tutaj jedną wielką przewagę nad wszelkimi nakładkami - oferuje dostęp do wszystkich możliwych danych i można je sobie zestawić w dowolny raport. Coś, co w nakładkach typu gnorpm jest niemożliwe.
Odpytywanie (query mode) jest słabo udokumentowane w manualu. Sam nie
wiem, jak i kiedy się tego nauczyłem... najważniejsze opcje to, oczywiście,
"-q" włączające tryb odpytywania. Do tego można dodać "-a" (czyli "all"
- wszystkie zainstalowane pakiety - wtedy nie podaje się nazwy pakietu do
odpytania, bo odpytywana jest cała baza), albo "-i" - złożony raport
zawierający dużo podstawowych informacji o pakiecie. Można też dodać "-p",
i wtedy można odpytać pakiet, który jeszcze nie jest zainstalowany (czyli
np. plik pakietu na płytkach z dystrybucją)
Np. 'rpm -qip /cdrom/RPMS/i686/gpm-1.20-i686-1.rpm' wyświetli info
dotyczące pakietu który znajduje się na płycie (można np. przeczytać
jego opis)
Z ciekawszych rzeczy: można sprawdzić do jakiego pakietu należy jakiś plik. Mamy np. plik /usr/bin/pstree i chcemy się dowiedzieć, skąd to draństwo się wzięło. Wystarczy wpisać 'rpm -qf /usr/bin/pstree'
Jakiś program nam szwankuje. Istnieje podejrzenie, że ma uszkodzone pliki. Zamiast go od razu reinstalować wystarczy zrobić 'rpm -V nazwa_pakietu', jeśli któryś z plików został usunięty albo się zmienił, to rpm nas o tym szybciutko powiadomi. W manualu jest dokładny opis jak oznaczana jest każda zmiana. Można zrobić 'rpm -Va' i od razu sprawdzić cały system. Ale bez paniki, niektóre zmiany w plikach są niegroźne, zwłaszcza gdy chodzi o pliki konfiguracyjne które samemu zmienialiśmy.
Czy jakiś plik jest potrzebny? Pytanie to dotyczy zwykle bibliotek. Wystarczy
zrobić 'rpm -q --whatrequires libgpm.so.1'.
Albo 'rpm -q --whatrequires /bin/bash'.
Przy bibliotekach warto zwrócić uwagę, że programy mogą wymagać biblioteki pod konkretną nazwą, jak np. 'gpm' (to akurat zależność nie od samej biblioteki, a od konkretnego pakietu), 'libgpm.so', czy 'libgpm.so.1.0.0'. Więc warto sprawdzić wszystkie symlinki do jakiejś biblioteki. I ważne są ścieżki - np. w biblioteki podaje się je zwyczajowo bez ścieżki dostępu (bo ścieżkami zajmuje się linker, dlatego nie są one zapisywane nigdzie na sztywno), ale już interpretery (np. shelle czy perl/python) podaje się ze ścieżką dostępu (bo tak zwykle jest to zrobione w samych skryptach). Aby wysnuć wnioski z '--whatrequires' albo '--whatprovides' trzeba już mieć trochę wiedzy o systemie.
Dlatego prościej jest zrobić np. rpm -e --test gpm Jeśli 'gpm' jest czemuś potrzebne, to rpm o tym powie i odmówi usunięcia pakietu. Jeśli nie jest jednak potrzebne, to i tak nie zostanie usunięte, bo opcja '--test' tylko symuluje działanie bez wprowadzania żadnych zmian w bazie czy na dysku.
Ale kluczem do zaawansowanego używania jest opcja '--queryformat', która pozwala nam powiedzieć co konkretnie nas interesuje, jakie informacje są nam potrzebne. Zadziwiające, jak mało osób z tego korzysta... A składnia wygląda np. tak: rpm -q --queryformat "magiczny_i_bardzo_hakerski_kod" nazwa_pakietu Tutaj najwięcej problemu sprawia "magiczny_i_bardzo_hakerski_kod". RPM obsługuje szeroką listę danych powiązanych z każdym pakietem. Listę wszystkich "pól" (w końcu rpm tworzy bazę danych) można zobaczyć po rpm --querytags Dużo tego będzie. Mój rpm obsługuje ponad setkę pól informacyjnych.
Mnie interesuje najpierw nazwa pakietu. To w końcu najważniejsze. Robię: rpm --querytags|grep NAME ...i otrzymuję 14 wyników, ale jedno pole wygląda wyjątkowo dobrze, bo nazywa się, po prostu, 'NAME'. Pola zawiera się w specjalną klamrę: %{...}. Zaś magiczny_i_bardzo_hakerski_kod składa się z potrzebnych nam pól, między które można dodatkowo wmieszać kody specjalne, jak np. '\n' (nowa linia), '\t' (tabulacja) i wiele innych, generalnie zgodnych z notacją funkcji printf().
Tutaj uwaga dla newbie. Jeśli kiedykolwiek będziecie chcieli zostać tzw. power-userem, to, choć byście nie mieli zamiaru programować, będziecie musieli znać składnie przynajmniej dwóch funkcji C. Funkcji printf() i strftime().
printf, bo kody formatujące są wykorzystywane w wielu programach, jak np. tutaj w rpm. A znajomość strftime też się przyda, bo w taki sposób zwykle określa się wyświetlanie daty w wielu programach (np. zegarek w IceWM). 'man 3 printf', 'man 3 strftime' - lektura dla ambitnych.
A więc złożę sobie najpierw format wyświetlający tylko nazwę pakietu. rpm -q --queryformat "%{NAME}" gpm I... nic. Zapomniałem dodać zakończenie linii i wynik jest zakrywany od razu przez prompt. rpm -q --queryformat "%{NAME}\n" gpm No. Od razu lepiej. Teraz dodam dodatkowe pole, rozmiar pakietu. rpm -q --queryformat "%{NAME} %{SIZE}\n" gpm Hej, to się może nawet przydać. Przypuśćmy, że brakuje nam miejsca na dysku. I chcemy usunąć jakieś pakiety. Większość ludzi zaczyna wtedy się zastanawiać "co też mam takiego wielkiego... (oprócz /home ;)". Mamy tutaj już format wyświetlający wielkość pakietów, teraz wystarczy je tylko posortować według wielkości, i już będziemy widzieć co też jest największymi pakietami. A, no i oczywiście przejść z odpytywania jednego pakietu na odpytywanie całej bazy: rpm -qa --queryformat "%{NAME} %{SIZE}\n" | sort -n +1 Wynik rpm po prostu puszczam rurką na 'sort', które z przełącznikiem '-n' sortuje numerycznie (a nie alfabetycznie), a z '+1' sortuje według drugiego pola (czyli tutaj rozmiaru). Teraz tylko wybrane, 'podejrzane' pozycje traktuję 'rpm -e --test' i po uprzednim rozważeniu usuwam. Proste. Skuteczne. Szybkie.
Podobnie można załatwić sobie listę ostatnio instalowanych pakietów. Np. instalowaliśmy, na próbę, Gnome. A mieliśmy wcześniej KDE. I teraz chcemy usunąć Gnome, bo się jednak nie sprawdził. Ale Gnome to mnóstwo pakietów, te główne pamiętamy, ale możemy pominąć któryś z tych drobniejszych... a jeśli będziemy mieć listę posortowaną chronologicznie, to oczywiście będzie nam dużo łatwiej. rpm -qa --queryformat "%{NAME} %{INSTALLTIME}\n" | sort -n +1 I już. Data jest co prawda w dziwnej, wewnętrznej notacji (ilość sekund które upłynęły od 1980?), ale dzięki temu dobrze się sortuje. Teraz od razu widać, co też ostatnio instalowaliśmy. Żeby to uczynić czytelniejszym, można ustalić wielkość pola NAME, przez co wynik będzie ładniej sformatowany. Ja proponuję limit długości 30 znaków, chyba wystarczy: rpm -qa --queryformat "%-30{NAME} %{INSTALLTIME}\n" | sort -n +1 Aaaa. Ślicznie. Jak ktoś bardzo chce, to może kazać RPM-owi dodatkowo pokazać datę w "ludzkim" formacie. Tyle że taki nie nadaje się do prostego sortowania. Więc zostawię stare pole z datą, i dodam nowe, ale "dla ludzi": rpm -qa --queryformat "%-30{NAME} %-15{INSTALLTIME} %{INSTALLTIME:date}\n"|sort -n +1 Jak widać, można dużo. Ma się też dostęp do dużo bardziej fantazyjnych pól, można np. sprawdzić, jaki kawałek softu na naszej maszynie jest nie-GPL: rpm -qa --queryformat "%-30{NAME} %{LICENSE}\n" Teraz wystarczy odrzucić GPL/LGPL: rpm -qa --queryformat "%-30{NAME} %{LICENSE}\n"|grep -v GPL A, i oczywiście format odpytywania nie musi zajmować tylko jednej linijki wynikowej, np.: rpm -qa --queryformat "^[\[1m%{NAME}^[\[0m\n%{DESCRIPTION}\nRozmiar: ^[\[1m%{SIZE}^[\[0m\n\n" (Uwaga: zbitki ^[ trzeba zamienić na pojedynczy kod Escape, najłatwiej wprowadzić go w shellu przez kombinację 'Control-v Escape')
RPM nie jest trudny w obsłudze. Nie ma "miliona" opcji, i kiedy rozumie się skąd się biorą te %{NAME} robi się to wszystko całkiem przejrzyste. Wymaga dużego nakładu chęci by nauczyć się nim wprawnie posługiwać, ale potem pozwala na naprawdę dużo. Na rzeczy które w graficznych nakładkach zwykle są niedostępne.