____ _ _ _ _ | _ \ ___ __| | | | | __ _| |_ | |_) / _ \/ _` | |_| |/ _` | __| | _ < __/ (_| | _ | (_| | |_ |_| \_\___|\__,_|_| |_|\__,_|\__|
☠ morketsmerke ☠
1. Wstęp
Chcąc zmienić coś w swoim życiu postanowiłem, że zacznę od pracy. Dalej chciałem pracować w IT, tylko na innym stanowisku (praca szkolnego administratora jest porównywalna z pracą technika IT, tu ma ktoś problem z systemem, tu trzeba podłączyć rzutnik, szczerze to znudziła się praca tego typu). Dobrze czułem się pracując z Linuksem, to była moja pasja. Znałem dwa stanowiska na których mógłbym pracować: Linux System Administrator lub Linux System Engineer. Teraz na rynku pracy jeśli chodzi o IT ważniejsze są uzyskane certyfikaty i odbyte kursy niż wykształcenie akademickie. Szukając certyfikatów, które spowodują większe szanse na zatrudnienie, znalazłem dwa. Linux Fundation oraz Red Hat. Po przeczytaniu postu a na Reddit doszedłem do wniosku, że lepszym wyborem będzie Red Hat. Jeśli chodzi o produkcyjne wykorzystanie Linuksa to większość używa Red Hat Enterprise Linux lub jego darmowego odpowiednika. Kiedyś CentOS ale obecnie może być to zarówno Rocky lub Alma Linux, oba są oparte na tym systemie. Szukając jakiś materiałów w internecie, które pomogły by mi się przygotować natrafiłem na Amazonie na książke Asghara Ghori pt. RHCSA Red Hat Enterprise Linux 8 (UPDATED): Training and Exam Preparation Guide (EX200), Second Edition zamówiłem ją na swojego Kindla i zacząłem przygotowywać się do egzaminu.
1.1. Egzamin
Egzamin EX200 dający uprawnienia Red Hat Certified System Administrator jest egzaminem praktycznym sprawdzającym umiejętność instalacji, konfiguracji oraz rozwiązywania podstawowych problemów administracyjnych na dystrybucji Red Hat. Egzamin będzie odbywać się w postaci elektronicznej i zdający będzie mięć do dyspozycji dwie maszyny wirtualne do wykonania zadań egzaminacyjnych. Takie też środowisko przygotujemy sobie do nauki. Na dzień 11 listopada 2020 (tak jak podaje książka) egzamin obejmuje 69 zagadnień jednak ta liczba, ze względu na rozwój technologii jak i samego RHEL-a mogła ulec już zmianie.
1.2. Zagadnienia
Zagadnienia używane na egzaminie mogą cały czas ewoluować. Odnośnik obok przedstawia aktualne zagadnienia egzaminacyjne: http://www.redhat.com/training/courses/ex200/examobjective. Obecnie egzamin zadawany jest na RHEL 9, wydanym 17 maja 2022. Dość istotną zmianą w produkcji tego systemu jest zmiana upstreamu. Ta wersja Red Hat nie jest już oparta na dystrybucji Fedora tak jak wszystkie do tej pory, ale na CentOS Stream (nowa wersja non-stream tej dystrybucji nie jest już dostępna stąd rozbicie społeczonościowych dystrybucji do zastosowań produkcyjnych na Rocky oraz Alma Linux) i tej wersji będziemy używać na maszynach wirtualnych.
1.3. Przygotowania
Kiedy uznałem, że chce zdobyć RHCSA, uzyskałem Red Hat na zasadzie Non-cost RHEL Individual Developer Subscription, gdzie istotne informacje znajdują się w odnośniku obok: https://developers.redhat.com/articles/faqs-no-cost-red-hat-enterprise-linux. Przy użyciu tej subskrypcji uzyskamy dostęp do Red Hat przez rok na 16 instalacji (bez znaczenia czy to fizyczny komputer, czy maszyna wirtualna). Po tym czasie należy zalogować się ponownie, zakceptować warunki umowy i do około 30 minut powinnimy uzyskać ponowny rok subskrypcji i tak co roku. Wszystko jest opisane na powyższej stronie. System w wersji 9 zainstalowałem na komputerze przeznaczony do codziennego użytku. Najlepszym sposobem na nauczenie się administracji systemem jest jego używanie na co dzień, a że jest entuzajstą a nie profesjonalistą, mój kontakt z systemami tego typu jest raczej dość mocno ograniczony. Dlatego też przesiadłem się na RHEL, póki co to ten system poprostu działa, wcześniej korzystałem z Fedory 35 oraz Debiana 11. Do celów dydaktycznych potrzebujemy peceta lub laptopa z min. dwurdzeniowym procesorem z możliwością wirtualizacji 64-bitowych systemów, 8GB pamięci operacyjnej oraz min. 40GB wolnej przestrzeni na dysku na potrzeby utworzenia maszyn wirtualnych z wymagną przez ćwiczenia przestrzenią dyskową. Do tego celu możemy użyć dowolnego środowiska wirtualizacji, które znamym. Jeśli nie mieliśmy wcześniej żadnego kontatku z tego typu oprogramowaniem, to najlepiej jest użyć oprogramowania Oracle VirtualBox, dającego najprostszy interfejs do interakcji z maszynami, gdyż przy późniejszych zagadnieniach będziemy musieli zmienić jej ustawienia lub dodać kilka urządzeń. Czy ktoś zainstaluje na swoim komputerze RHEL czy nie to, już indywidualna sprawa i nie wypłynie ona wykonanie ćwiczeń. Nie mniej jednak, w podpunkcie odnośnie maszyn wirtualnych tego rodziału przedstawie skrypt powłoki, który po uruchomieniu utworzy automatycznie maszyny wymagane do wykonania ćwiczeń. Ale póki co przedstawie teraz instalacje Oracle VirtualBox na RHEL 9.
1.3.1. Instalacja Oracle VirtualBox na RHEL 9.0
Pierwszą czynnością jest uruchomienie przeglądarki i przejście pod adres: https://www.virtualbox.org/wiki/Linux_Downloads, na samym dole strony znajdują się pliki repozytorium dla kilku dystrybucji Linuksa. Kopiujemy adres odnośnika do pliku konfiguracyjnego repozytorium. Następnie możemy wydać polecenia:
[xf0r3m@primeb450 ~]$ sudo wget https://download.virtualbox.org/virtualbox/rpm/el/virtualbox.repo -O /etc/yum.repos.d/virtualbox.repo [xf0r3m@primeb450 ~]$ sudo dnf update Updating Subscription Management repositories. Red Hat Enterprise Linux 9 for x86_64 - AppStream (RPMs) 6.3 kB/s | 4.1 kB 00:00 Red Hat Enterprise Linux 9 for x86_64 - BaseOS (RPMs) 10 kB/s | 4.1 kB 00:00 Oracle Linux / RHEL / CentOS-9 / x86_64 - VirtualBox 99 B/s | 181 B 00:01 Oracle Linux / RHEL / CentOS-9 / x86_64 - VirtualBox 1.9 kB/s | 1.7 kB 00:00 Importowanie klucza GPG 0x98AB5139: Identyfikator użytkownika: „Oracle Corporation (VirtualBox archive signing key) <info@virtualbox.org>” Odcisk : 7B0F AB3A 13B9 0743 5925 D9C9 5442 2A4B 98AB 5139 Z : https://www.virtualbox.org/download/oracle_vbox.asc W porządku? [t/N]: t Oracle Linux / RHEL / CentOS-9 / x86_64 - VirtualBox 8.6 kB/s | 7.8 kB 00:00 Rozwiązano zależności. Nie ma nic do zrobienia. Ukończono. [xf0r3m@primeb450 ~]$ sudo dnf install VirtualBox-6.1 kernel-devel Updating Subscription Management repositories. Ostatnio sprawdzono ważność metadanych: 0:04:10 temu w dniu sob, 13 sie 2022, 10:12:38. Rozwiązano zależności. ...
Po instalacji restartujemy komputer.
[xf0r3m@primeb450 ~]$ sudo reboot
Teraz Oracle VirtualBox jest gotów do działania.
Jeśli chcemy możemy użyć RPMFusion. Po załadowaniu tych repozytoriów do swojego systemu możemy od razu wydać polecenie:
[user@centos9 ~]$ sudo dnf install VirtualBox kernel-devel ... [user@centos9 ~]$ sudo su [root@centos9 user]# akmods Checking kmods exist for 5.14.0-142.el9.x86_64 [ OK ] [root@centos9 user]# sudo systemctl restart vboxdrv.service [root@centos9 user]# sudo systemctl status vboxdrv.service ● vboxdrv.service - Linux kernel module init script Loaded: loaded (/usr/lib/systemd/system/vboxdrv.service; enabled; vendor preset: enabled) Active: active (exited) since Mon 2022-08-15 16:13:27 CEST; 6s ago Process: 62653 ExecStart=/sbin/modprobe vboxdrv (code=exited, status=0/SUCCESS) Process: 62657 ExecStart=/sbin/modprobe vboxnetflt (code=exited, status=0/SUCCESS) Process: 62658 ExecStart=/sbin/modprobe vboxnetadp (code=exited, status=0/SUCCESS) Main PID: 62658 (code=exited, status=0/SUCCESS) CPU: 133ms ...
1.3.2. Pozyskanie obrazu ISO z Red Hat Enterprise Linux 9
Aby pobrać potrzebny nam obraz musimy zarejestrować się w subskrypcji dla indywidualnych deweloperów. Przechodzimy na stronę https://developers.redhat.com/register i rejestrujemy się. Następnie logujemy i po zalogowaniu przechodzimy na stronę: https://developers.redhat.com/products/rhel/download. w sekcji All Downloads znajdują się wszystkie dostępne wersje RHEL objęte jeszcze wsparciem. Nas będzie interesować wyłącznie wersja 9 i tą też pobieramy, oczywiście dla architektury x86_64 w wersji DVD.
1.3.3. Tworzenie maszyn wirtualnych z RHEL
Tworzenie maszyn wirtualnych, nie jest zaganieniem egzaminacyjnym. Na egzaminie dostaniemy dostęp do dwóch zdalnych maszyn. Teoretycznie można by użyć fizycznych maszyn o ile ktoś ma do takowych dostęp, jednak do drugiej maszyny trzeba dodać aż 8 dysków, więc użycie wirtualnej maszyny, to chyba jedyne efektywne rozwiązanie. Poniżej znajdują się wymagania jakie powinna spełniać każda z nich:
- RHEL9-VM1:
- 64-Bitowy Red Hat Enterprise Linux 9.0,
- 1 wirtualny procesor,
- 1024 MB pamięci operacyjnej,
- 10GB dysk twardy, wyłącznie na instalacje systemu,
- Karta sieciowa ustawiona na bridged.
- Nazwa hosta ustawiona na server1.example.com
- Stały adres IP, pozwalający na swobodną komunikację w sieci
- RHEL9-VM2:
- 64-bitowy Red Hat Enterprise Linux 9.0,
- 1 wirtualny procesor
- 2048 MB pamięci operacyjnej
- 10 GB dysk twardy, na instalacje systemu
- 4 x 250 MB dysk twardy, dla ćwiczeń z LVM
- 2 x 10 GB dysk twardy, dla ćwiczeń z VDO
- 1 x 1 GB dysk twardy, dla ćwiczeń ze Stratis
- Nazwa hosta ustawiona na server2.example.com
- Stały adres IP, pozwalający na swobodną komunikację w sieci
Maszyny możemy utworzyć ręcznie, zgodnie z wtycznymi dla używanego przez nas środowiska wirtualizacji. Jeśli jednak korzystamy z VirtualBox możemy wykorzystać poniższe skrypty. W przypadku drugiej maszyny dodatkowe dyski trzeba będzie dodać z poziomu ustawień maszyny.
- RHEL9-VM1:
#!/bin/bash vboxmanage=$(which vboxmanage); vmname="RHEL9-VM1"; bridged_if=""; $vboxmanage createvm --name $vmname --ostype RedHat_64 --register; $vboxmanage createhd --filename "$HOME/VirtualBox VMs/${vmname}/OS.vdi" --size \ 10240 --format VDI --variant Standard; $vboxmanage storagectl $vmname --name SATA0 --add sata; $vboxmanage modifyvm $vmname --memory 1024; $vboxmanage modifyvm $vmname --graphicscontroller vmsvga; $vboxmanage modifyvm $vmname --nic1 bridged; $vboxmanage modifyvm $vmname --bridgeadapter1 $bridged_if; $vboxmanage storageattach $vmname --storagectl SATA0 --port 0 --type hdd --medium \ "$HOME/VirtualBox VMs/${vmname}/OS.vdi"; $vboxmanage storageattach $vmname --storagectl SATA0 --port 1 --type dvddrive \ --medium "$HOME/Pobrane/rhel-baseos-9.0-x86_64-dvd.iso";
- RHEL9-VM2:
#!/bin/bash vboxmanage=$(which vboxmanage); vmname="RHEL9-VM2"; bridged_if=""; $vboxmanage createvm --name $vmname --ostype RedHat_64 --register; $vboxmanage createhd --filename "$HOME/VirtualBox VMs/${vmname}/OS.vdi" --size \ 10240 --format VDI --variant Standard; $vboxmanage createhd --filename "$HOME/VirtualBox VMs/${vmname}/VDO1.vdi" --size \ 10240 --format VDI --variant Standard; $vboxmanage createhd --filename "$HOME/VirtualBox VMs/${vmname}/VDO2.vdi" --size \ 10240 --format VDI --variant Standard; $vboxmanage createhd --filename "$HOME/VirtualBox VMs/${vmname}/Stratis.vdi" \ --size 1024 --format VDI --variant Standard; $vboxmanage storagectl $vmname --name SATA0 --add sata; $vboxmanage modifyvm $vmname --memory 2048; $vboxmanage modifyvm $vmname --graphicscontroller vmsvga; $vboxmanage modifyvm $vmname --nic1 bridged; $vboxmanage modifyvm $vmname --bridgeadapter1 $bridged_if; $vboxmanage storageattach $vmname --storagectl SATA0 --port 0 --type dvddrive \ --medium "$HOME/Pobrane/rhel-baseos-9.0-x86_64-dvd.iso"; $vboxmanage storageattach $vmname --storagectl SATA0 --port 1 --type hdd --medium \ "$HOME/VirtualBox VMs/${vmname}/OS.vdi"; i=2; while [ $i -le 5 ]; do $vboxmanage createhd --filename "$HOME/VirtualBox VMs/${vmname}/LVM${i}.vdi" --size \ 250 --format VDI --variant Standard; $vboxmanage storageattach $vmname --storagectl SATA0 --port $i --type hdd --medium \ "$HOME/VirtualBox VMs/${vmname}/LVM${i}.vdi"; i=$((i + 1)); done $vboxmanage storageattach $vmname --storagectl SATA0 --port 6 --type hdd --medium \ "$HOME/VirtualBox VMs/${vmname}/VDO1.vdi"; $vboxmanage storageattach $vmname --storagectl SATA0 --port 7 --type hdd --medium \ "$HOME/VirtualBox VMs/${vmname}/VDO2.vdi"; $vboxmanage storageattach $vmname --storagectl SATA0 --port 8 --type hdd --medium \ "$HOME/VirtualBox VMs/${vmname}/Stratis.vdi";
Powyższe skrypt są również dostępne na moim profilu na github-ie. Pod poniższymi linkami.
- RHEL9-VM1:https://github.com/xf0r3m/docs/raw/main/RHCSA/RHEL9-VM1.sh
- RHEL9-VM2:https://github.com/xf0r3m/docs/raw/main/RHCSA/RHEL9-VM2.sh
Korzystając ze skryptów należy pamiętać o zmianie intefejsu
sieciowego wykorzystywanego do mostkowania. Zmienna
bridge_if
.
Po utworzeniu maszyn przyszedł czas na instalację.
1.3.4. Instalacja Red Hat Enterprise Linux 9.0
Zaraz po uruchomieniu maszyny rozpocznie się proces ładowania zawartości płyty. Menu bootowania płyty zawiera trzy opcje.
- Install Red Hat Enterprise Linux 9.0
- Test this media & install Red Hat Enterprise Linux 9.0
- Troubleshooting
Domyślnie zaznaczoną jest opcja numer 2. Mamy minutę na zmianę decyzji. Naciśnięcie dowolnego klawisza zatrzymuje odliczanie. Dając nam czas do namysłu, jednak na ten moment nie ma co za bardzo rozmyślać dlatego też wybieramy opcję numer 1. Po wybraniu tej opcji nastąpi uruchomienie systemu oraz instalatora. Instalator używany przez RHEL oraz dystrybucje z nim związane nazywa się Anaconda. Swoje działanie rozpoczyna jeszcze w trybie tekstowym, następnie domyślnie uruchamia tryb graficzny, gdzie odbywa się konfiguracja instalcji a następnie już właściwa instalacja. Nie mniej jednak instalacja w trybie tekstowym jest również możliwa. Podczas instalacji, poza głównym instalatorem będziemy mieć do dyspozycji multipekser terminala, który do momentu uruchomienia właściwego instalatora (w wersji graficznej) był główną konsolą. W multiplekserze będzie my mieć dostęp do komunikatów diagnostyczny, które w wersji 8 RHEL był wyświetlane na oddzielnych konsolach; kilka powłok z uprawnieniami superużytkownika (uruchomione na konsolach 2, 3 i 5) oraz konsolę z komunikatami przechwytywanymi przez główny rejestrator systemu rsyslog. Udostępnienie tych funkcjonalności podczas instalacji systemu, może pomóc w ewentualnym diagnozowaniu i naprawie problemów z instalacją. Pliki z komunikatami na czas instalacji przechowywane są w katalogu /tmp, po instalacji zostaną one przeniesione do katalogu /var/log/anaconda. Według mnie jest dość przydatna funkcjonalność, ponieważ na podstawie czasu modyfikacji tych plików możemy dowiedzić się kiedy system został zainstalowany. Poniżej znajduje się lista, opisująca za co odpowiada konkretna konsola (kolejny ekran, dostępny po naciśnięciu klawiszy Ctrl + Alt + F1 - F6).
- CTLR + ALT + F1 - multiplekser terminala,
- CTRL + ALT + F2 - powłoka z dostępem do root,
- CTRL + ALT + F3 - powłoka z dostępem do root,
- CTRL + ALT + F4 - komunikaty diagnostyczne rejestratora syslog.
- CTRL + ALT + F5 - powłoka z dostępem do root,
- CTRL + ALT + F6 - tryb graficzny.
Instalacja Red Hat Enterprise Linux rozpoczyna się od wyboru języka procesu instalacji. Chcąc pracować już w takim prawowitym IT, należy posługiwać się językiem angielskim i to technicznym. Systemy z którymi zderzmy się w potencjalnej pracy raczej będą systemami o zasięgu międzynarodowym, prawdopodobnie już o tym wspominałem ale egzamin pozwalający uzyskać certyfikacje RHCSA również będzie po angielsku. Dlatego też instalować jak i korzystać z systemu będziemy w języku angielskim, na pierwszym ekranie wybieramy English pozostawiając wariant English (United States). Następnym ekranem jest Installation Summary (lewy górny róg), jest tak jakby pulpit programu instalacyjnego, na nim występują komponenty, które możemy skonfigurować. W wersji 9.0, te komponenty są podzielone na 4 sekcje: Localization, Software, System oraz User Settings. W pierwszym procesie instalacji, przejdziemy przez wszystkie z nich.
Zwróć my uwagę na to, iż system sam dokonał wstępnej konfiguracji instalatora, na pozostało jedynie sprawdzić oraz skonfigurować tylko te opcje oznaczone znakiem ostrzegawczym oraz czerwoną podpowiedzią. Po ich konfiguracji program umożliwi nam zainstalowanie systemu.
W sekcji lokalizacyjnej do ustawienia są takie opcje, układ klawiatury, język, oraz data i czas. Podczas ładowania pierwszego okna (moment wybrania języka instalacji), instalator na podstawie informacji GeoIP postara się określić naszą przybliżoną lokalizację, o ile posiada on na tym momencie połączenie z internetem. Dlatego też możemy spotkać się z samoinstnie wybranym języku instalacji ustawionym na Polski. Język został zmieniony, ale wybrana strefa czasowa może pozostać, wręcz powinna. Dzięki tej funkcji możemy zaoszczędzić czas, i przejść do kolejnej sekcji.
Kolejną sekcja dotyczy oprogramowania, tutaj konfigurowane będzie na przykład połączenie z firmą Red Hat. RHEL jest system licencjonowanym i jeśli chcemy skorzystać z oficjalnych repozytoriów należy "podłączyć" system do naszego konta założonego w celu pozyskania obrazu płyty. Jednak na razie nie trzeba tego, będzie to do zrobienia na późniejszych etapach nauki administracji systemem. Kolejną opcją jest Installation Source (Źródło instalacji), konfigurąc tę opcję możemy wybrać czy będziemy korzystać pod czas instalacji z obrazu płyty lub sieciowego repozytorium lub Red Hat CDN. Z racji tego, iż ściągneliśmy pełny obraz ważący kilka gigabajtów, nie ma sensu używać instalacji sieciowej. Tego typu źródło instalacji należy wybrać w momencie gdy pobraliśmy minimalistyczną wersję obrazu, dlatego też zostaniemy przy standardowym wyborze Local media. Ta opcja pozwala też na dodanie podczas instalacji dodatkowego repozytorium, jednak na tym etapie nie będziemy się tym zajmować. Ostanią opcją z tej sekcji jest Software selection, ta opcja daje nam możliwość, wyboru rodzaju instalacji. Na potrzeby nauki, wybierzemy opcję Server with GUI, jeśli będziemy instalować RHEL na naszym komputerze do codziennego użytku możemy wybrać Workstation. Wybierając rodzaj instalacji po lewej stronie, po prawej wyświetają się dodatkowe pakiety lub warianty do zainstalowania.
Sekcja System, służy głównie do wyboru docelowego miejsca dla instalacji. W opcji Instalation Destination, wskazujemy docelowy dysk do instalacji, możemy go spartycjonować ręcznie lub automatycznie możemy również zaszyfrować partycje, jeśli jest taka potrzeba. W przypadku szyfrowania danych bardzo ważny jest układ klawiatury. Innymi opcjami póki co dla nas ważnymi jest Network & Host name, w założeniach zadania, może być wymagane ustawienie odpowiedniego adresu oraz nazwy dla maszyny, to te opcje ustawiamy właśnie tam. Pozostałe opcje tej sekcji, poki co nie są dla nas istotne.
Ostatnia sekcja ustawia hasło dla superużytkownika oraz tworzy konto dla pierwszego użytkownika. Nie musi on posiadać uprawnień administratora i nie będzie ich miał. Opcja utworzenia użytkownika może się nie mieścić na ekranie, podczas instalacji systemu maszynie witualnej, dlatego nie należy przejmować, że jej nie ma. Wystarczy przewinąć wyświetlany oraz paskiem przewiajania po prawej stronie.
Teraz kiedy wszyskie (te istotne dla instalacji) opcje zostały opisane możemy zainstalować system zgodnie założeniami pierwsze maszyny i powtorzyć to na drugiej. I to jest pierwsze ćwiczenie.
Ćwiczenie 1: Instalacja Red Hat Enterprise Linux 9
Stwórz zgodnie założeniami podanymi w podrozdziale Tworzenie maszyn wirtualnych z RHEL maszynę RHEL-VM1. Następnie korzystając z sugestii podanych podczas opisu procesu instalacji zainstaluj na niej Red Hat Enterprise Linux 9. Powtórz tę czynność na drugiej maszynie przeznaczonej do laboratorium. Pamiętaj, że założenia dla drugiej maszyny różnią się.
Ćwiczenie 2: Logowanie zdalne do RHEL
Wykorzystując program do obsługi protokołu SSH dla twoje systemu operacyjnego zaloguj się na superużytkownika. Pamiętaj o tym, że bezpośrednie logowanie na superużytkownika wymagało zaznaczenia opcji w trakcie ustawiania hasła dla niego podczas instalacji.
Podsumowanie
W tym rozdziale przeszliśmy przez proces instalacji RHEL. Dowiedzielśmy się, że możliwa jest instalacja w trybie tekstowym oraz oraz, że nie należy ona do najtrudniejszych. Warto zwrócić uwagę na to iż jeśli do tej pory korzystaliśmy z jakiś materiałów to dotyczą one wersji 8 RHEL, my będziemy korzystać z wersji 9, bo to na niej w 2022 roku będziemy przeprowadzany egzamin, a między tymi wersjami jest kilka zmian. W następnym rozdziale zapoznamy się z środowiskiem graficznym, strukturą katalogów oraz podstawowym narzędziami do pracy w powłoce.
2. Poruszanie się po systemie RHEL 9
Wykonując ćwiczenia z pierwszego rozdziału, zainstalowaliśmy sobie Red Hat w wersji 9 na maszynie wirtualnej. Jako wariant wyboru oprogramowania wybraliśmy Server with GUI i od drobnego omówienia środowiska graficznego rozpocznę ten rodział.
2.1. Środowisko graficzne RHEL 9
Red Hat jest dystrybucją Linuksa przeznaczoną do zastosowań produkcyjnych, więc system tego typu musi wykazywać się dużą stabilnością. Znaczące zmiany są wprowadzane raczej w dużych wydania jak RHEL 9, takim znaczącym przeskokiem jest zmiana linii jądra z 4.18 (w przypadku RHEL 8) na 5.14 (w przypadku RHEL 9) oraz zastąpienie klasycznego serwera X Window protokołem Wayland, to jednak nastąpiło z wydaniem RHEL 8. Zmiany w RHEL 9, odnośnie środowiska graficznego to przejście z Gnome 3.38 na Gnome 40, ta zmiana przyniosła również odświerzenie menedżera wyświetlania lub menedżera logowania czym w przypadku środowiska Gnome jest GDM. Większość elementów pozostała taka sama na górnej belce mamy datę oraz czas w prawyn górnym rogu do wyboru opcje ułatwień dostępu, wskaźnik połączenia sieciowego oraz porozwinięciu możliwość regulacji głośności i jasności ekranu oraz wyłączenia komputera. Wiecej opcji w tym miejscu będzie dostępne dopiero po zalogowaniu. Będzie można zmienić kilka ustawień jak np. sieć bezprzewodwą. Zmianie uległ również sposób prezentacji kont użytkownika. Z racji tego iż root nie jest zwykłym użytkownikiem nie będzie pojawiać się na liscie, ale zalogowanie na niego jest możliwe za pomocą kliknięcia w Not Listed? pod listą użytkowników, wówczas będzie mogli ręcznie podać nazwę użytkownika oraz hasło. Ekranem startowym po zalogowaniu jest ekran Activities, który pozwala na podgląd wykonywanych czynności, rozpoczęcie nowych (wybierając aplikacje z doka lub z pełnej listy aplikacji, która jest dostępna po kliknięciu na ikonę 9 kropek w doku) oraz przełacznie się między obszarami roboczymi. Domyślnie GNOME daje dostęp do dwóch przestrzeni roboczych, gdy tylko przeniesiemy aplikację do na nowy obszar, GNOME udostępni nam kolejny i tak dalej. Wyszukiwarka nad podgląd obszaru roboczego daje możliwość wyszukiwania nie tylko aplikacji ale także ustawień co jest normą w GNOME od wersji 3. Na doku znajdują się ulubione aplikacje, które możemy usuwać i dodawać za pomocą PPM i następnie wybierając dodaj lub usuń z ulubionych.
2.2. Struktura katalogowa w Uniksach
Zanim jednak przejedziemy do obsługi wiersza poleceń omówimy sobie hierachiczną strukturę katalogów, która występuje nie tylko w RHEL ale i w innych Uniksach, ponieważ HFS (ang. Hierarchy File System) jest ogólnym standardem. Na Uniksach możemy spotkać się z trzema typami systemów plików.
- Disk-based - dyskowe - są to klasyczne pliki i katalogi przechowywane bezpośrednio na dysku.
- Network-based - sieciowe - są to udziały podmontowane w naszych systemach za pomocą róznych protokołów, nie tylko SMB. Plik network-based są plikami disk-based, ale na innych komputerach.
- Memory-based - wirtualne - te systemy plików są tworzone przez procesy na potrzeby działania systemu, takim systemem może być katalog /dev lub /proc. Ich trwałość często zależy od tego jak długo system pozostaje włączony lub od wewnętrznych ustaleń samego systemu.
Struktura plików i katalogów na Uniksach ma postać odwróconego drzewa. Korzeń (katalog główny) znajduje się na szczycie struktury i od niego rozchodzą się poszczególne gałęzie (podkatalogi), gałęzię mogą zawierać kolejne rozgałezienia, tworząc całe struktury. Na gałęziach znajdują się również liscie czyli pliki i na liściach struktura się kończy.
Dostęp do konkretnych plików i katalogów w strukturze określany jest za pomocą ścieżek. Scieżki określają położenie plików i katalogów wewnątrz HFS. Separatorem elementów ścieżki (posczególnych podkatalogów), jest ukośnik, slash (/).
Podczas pracy z elementami jak foldery oraz pliki możemy używać scieżek bezwzględnych zaczynające się od katalogu głównego, lub ścieżek względnych zaczynających się od elementu znajdującego w obecnym katalogu robocznym (tym katalogu, w którym się obecnie znajdujemy).
Katalog główny jest miejscem do przechowywania wszystkich plików, jakie znajdują się w systemie, jest pierwszym element znajdujący się na ścieżce (bezwzględnej) i oznaczny jest on poprostu ukośnikiem (/), od tego katalogu zaczyna się cała struktura. Poniżej znajduje się lista najważniejszych podkatalogów katalogu głównego, każdy z nich ma swoje znaczenie w systemie.
- /boot (disk-based) - katalog ten przechowuje jądro, initramfs oraz konfiguracje programu rozruchowego.
- /dev (memory-based) - katalog ten przechowuje pliki urządzeń służące do komunikacji z sprzętowymi komponentami komputera. Pliki te są tworzone przez usługę udevd podczas podłączania urządzenia oraz rozruchu systemu.
- /etc (disk-based) - skrót etc możemy rozwinąć do ang. etcetera lub ang. extended text configration. Jest to miejsce do przechowywania plików konfiguracyjnych różnych programów.
- /home (disk-based) - ten katalog przechowuje, katalogi domowe użytkowników.
- /opt (disk-based) - katalog przeznaczony na dodatkowe oprogramowanie instalowane w systemie.
- /proc (memory-based) - wirtualna struktura podkatalogów, zawierająca informacje o procesach oraz różne informacje o systemie, np. informacje o procesorze.
- /run (memory-based) - katalog przechowywujący pliki wykorzystywane przez procesy podczas wykonywania ich czynności. W tym katalogu znajduje się również podkatalog media zawierący punkty montowania podłączanych do systemu dysków wymiennych.
- /sys (memory-based) - katalog przechowuje informacje o urządzeniach, sterownikach. Pewne funkcjonalności jądra również są zawarte w tym katalogu. Dane z tego katalogu są używane przez jądro do obsługi urządzeń.
- /tmp (disk-based) - miejsce przechowywania plików tymczasowych, pliki złożone w tym katalogu przetrwają ponowne uruchomienie komputera. Okres przechowywania tych plików to 10 dni.
- /usr (disk-based) - skrót usr,
należy rozwinąć jako ang. UNIX System Resources. Ten
katalog jest kolejną dużą strukturą katalogów w systemie. W tym
katalogu przechowywane są wszystkie programy, więc wiekszość
systemu. Na poniższej liście znajdują się rozpisane podkatalogi
tego katalogu:
- /usr/bin - katalog przechowuje większosć plików binarnych, wykorzystywanych w systemie, programów oraz poleceń.
- /usr/sbin - narzędzia administracyjne niedostępne dla zwykłych użytkowników, poza kilkoma programami. Ten katalog często nie jest ujęty podczas wyszukiwania poleceń.
- /usr/lib, /usr/lib64 - biblioteki współdzielone oraz pliki statyczne, niektórych programów typu init.
- /usr/include - pliki nagłówkowe języka C
- /usr/local - miejsce przechowywania zewnętrznych programów instalowanych i wykorzystywanych przez administatorów, ten katalog zawiera w sobie podobną strukturę katalogową jak sam /usr.
- /usr/share - miejsce przechowywania stron podręcznika, dokumentacji czy przykładowych plików konfiguracyjnych.
- /var (disk-based) - katalog na zmienne
dane, katalog podobnie do /usr ma wewnątrz wiele znaczący
podkatalogów, takich jak:
- /var/log - katalog na pliki dzienników, zbierane nie tylko z głównego rejestratora, ale i funkcji rejestrowania samych usług.
- /var/opt - katalog na zmienne dane oprogramowania instalowanego w katalogu /opt
- /var/spool - katalog ten przechowuje dane zanim zostaną przekazane lub pobrane przez właściwe komponenty, na przykład poczta elektronicza w przypadku serwerów pocztowych.
- /var/tmp - katalog przechowuje duże pliki tymczasowe. Pliki złożone w tym katalogu przetrwają ponowne uruchomienie systemu. Czas ich istnienia w tym katalog to 30 dni.
Za pomocą polecenia tree, możemy wyświetlić strukturę katalogą w postaci drzewa, jednak najpierw nauczymy się korzystać z poleceń w RHEL.
2.3. Obsługa wiersza poleceń i najprostsze polecenia
Obsługa wiersza poleceń zależy w znacznym stopniu od powłoki, ponieważ to ona zajmuje się jego interpretacją i koniec końców wykonaniem programu, którego nazwę podaliśmy chcąc wykonać polecenie. Aby móc skorzystać w RHEL z wiersza poleceń musimy albo uruchomić w środowisku graficznym aplikację Terminal, lub zalogować się zdalnie za pomocą protokołu SSH. Uruchomienie terminala lub zalogowanie się przez SSH uruchomi powłokę, która swoją gotowość na otrzymywanie poleceń obwieści wyświetleniem znaku zachęty.
Znak zachęty jest wskaźnikiem za kursorem po którym możemy wprowadzać do systemu polecenia. Kiedyś znaki zachęty były pojedynczymi znakmi informującymi o uprawnieniach z jakimi działa proces powłoki (o tym za chwilę). Teraz znaki zwracają nazwę użytkownika, nazwę komputera oraz obecny katalog roboczy wewnątrz nawiasu kwadratowego, następnie zanim znajduje się znak krzyżyka (#) mówiący, że powłoka działa uprawnieniami użytkownika root lub symbol dolara ($) mówiący, że połoka działa z uprawnieniami zwykłego użytkownika. Poniżej przedstawiłem oba znaki:
[root@server1 ~]# [user@server1 ~]$
W różnych dystrybucjach, znak zachęty może różnorako wyglądąć. Możemy dostować go do własnych potrzeb, wiele osób korzysta z jak najmniejszych znaków zachęty, aby zaoszczedzić miejsce w wierszu polecenia. Teraz możemy już wydawać polecenia.
Kazde polecenie w jakimkolwiek Uniksie, składa się z nazwy polecenia, ewentualnych opcji oraz ewentualnych argumentów. Nie wszystkie polecenia do uzyskania żądanych przez nas efektów wymagają opcji czy argumentów.
$ nazwa_polecenia [opcje] [argumenty]
Każde polecenie przed zatwierdzeniem możemy edytować, za pomocą strzałek lub skrótów klawiszowych dostarczanych przez bibliotekę GNU Readline. Więcej na ten temat znajdziemy w internecie.
Przez cały kurs będziemy poznawać jakieś polecenia ale w tym momencie nauczymy się najprostszych z nich.
2.3.1. Listowanie zawartości katalogu
Aby wyświetlić zawartość katalogu w powłoce, możemy użyć polecenia ls. Polecenie bez podania argumentu w postaci katalogu wyświetli zawartość folderu, w którym się znajdujemy. Najważniejszymi opcjami między innymi są:
- -a - wyświetlanie wszystkich, elementów w katalogu także tych, które normalnie nie są wyświetlane (plik i foldery, których nazwa rozpoczyna się od kropki).
- -l - wyświetlenie szczegółowych informacji na temat elementów. Informacja zwracana przez polecenie jest wówczas podzielona na 9 pól, które kolejno oznaczają: typ pliku oraz uprawnienia; liczbę dowiązań; nazwę użytkownika (właściciela pliku); nazwę grupy do której należy ten plik; rozmiar w bajtach; czas modyfikacji oraz nazwę elementu.
- -ld - wyświetla szczegółową informacje na temat podanego jak argument katalogu, bez wyświetlania jego zawartości. Jeśli nie podamy argumentu polecenie wyświetli informacje na temat bierzącego katalogu.
- -lh - wyświetli szczegółowo informacje na temat elementów w katalogu, wyświetlając ich rozmiar w przeskalowanych wartościach, co ułatwi odczytanie go przez człowieka.
- -lt - wyświetli szczegółową listę elementów posortową względem czasu modyfikacji od najnowszego pliku.
- -ltr - działanie podobne do -lt, ale odwrócone, elementy zostaną wyświetlone od najstarszego.
- -R - wyświetlenie elementów w sposób rekurencyjny. Polecenie z tą opcją wyświetli zawartość katalogów wraz z zawartością ich podkatalogów itd.
Poniżej znajduje się przykład najczęściej wykorzystywanego polecenia ls wraz z opcjami:
[root@server1 ~]# ls -al total 10576 dr-xr-x---. 17 root root 4096 Jun 16 18:49 . dr-xr-xr-x. 18 root root 235 Jun 9 19:46 .. -rw-------. 1 root root 1197 Jun 9 19:59 anaconda-ks.cfg -rw-------. 1 root root 3908 Jun 16 18:50 .bash_history -rw-r--r--. 1 root root 18 Aug 10 2021 .bash_logout -rw-r--r--. 1 root root 141 Aug 10 2021 .bash_profile -rw-r--r--. 1 root root 429 Aug 10 2021 .bashrc drwxr-xr-x. 3 root root 17 Jun 16 18:14 bzipped drwx------. 8 root root 120 Jun 13 10:55 .cache -rw-r--r--. 1 root root 11 Jun 16 13:10 catfile1 drwx------. 9 root root 4096 Jun 13 13:42 .config -rw-r--r--. 1 root root 100 Aug 10 2021 .cshrc drwxr-xr-x. 2 root root 6 Jun 13 10:55 Desktop drwxr-xr-x. 4 root root 30 Jun 16 16:44 dir20 drwxr-xr-x. 2 root root 6 Jun 13 10:55 Documents drwxr-xr-x. 2 root root 6 Jun 13 10:55 Downloads drwxr-xr-x. 3 root root 55 Jun 16 11:34 etc -rw-r--r--. 1 root root 4986788 Jun 16 18:13 etc-bzipped.tar.bz2 -rw-r--r--. 1 root root 5772869 Jun 16 18:12 etc-gzipped.tar.gz -rw-r--r--. 2 root root 0 Jun 16 17:26 file10 -rw-r--r--. 2 root root 0 Jun 16 17:26 file20 -rw-r--r--. 1 root root 579 Jun 16 11:07 fstab drwxr-xr-x. 3 root root 17 Jun 16 18:14 gzipped -rw-------. 1 root root 42 Jun 16 18:22 .lesshst drwx------. 3 root root 19 Jun 13 10:55 .local drwxr-xr-x. 2 root root 6 Jun 13 10:55 Music drwxr-xr-x. 2 root root 6 Jun 13 10:55 Pictures drwxr-xr-x. 2 root root 6 Jun 13 10:55 Public lrwxrwxrwx. 1 root root 6 Jun 16 17:30 soft10 -> file10 -rw-r--r--. 1 root root 129 Aug 10 2021 .tcshrc drwxr-xr-x. 2 root root 6 Jun 13 10:55 Templates drwxr-xr-x. 2 root root 6 Jun 13 10:55 Videos -rw-------. 1 root root 8264 Jun 16 18:38 .viminfo -rw-r--r--. 1 root root 464 Jun 16 18:38 vipractice
Podczas korzystania z wielu programów możemy natknąć się na wiele opcji. Dzielą się one na długie i krótkie, opcje krótkie występują w postaci pojedynczego znaku poprzedzonego jednym myślnikiem (-). Opcje długie występuje w postaci pojedynczego (najczęsciej, ponieważ to zależy od programu) słowa poprzedzonego dwoma myślnikami (--). W przypadku tak prostych poleceń jak ls również możemy użyć długich opcji np. zamiast -a możemy użyć --all.
2.3.2. Wyświetlenie bieżącego katalogu roboczego
Na pierwszy rzut oka mogłoby się wydawać po co nam to polecenie, skoro w znaku zachęty na RHEL jest wyświetlona nazwa bieżącego katalogu. Polecenie pwd wyświetla ścieżkę bezwzględną do bieżącego katalogu, a po drugie to polecenie ma bardzo ważną cechę związaną z dowiązaniami, ale o tym będzie przy dowiązaniach. Do normalnych zastosowań pwd nie potrzebuje żadnej opcji, ani żadnego argumentu.
[root@server1 ~]# pwd /root
2.3.3. Poruszanie się wśrod katalogów
Generalnie, do zmiany bierzącego katalogu czy przejścia z/do innego katalogu służy polecenie cd. Pozwala ono na kilka sztuczek.
- Powrót do katalogu domowowego nie wymaga przy tym poleceniu żadnego argumentu ani opcji, wystarczy wydać polecenie cd.
- Polecenie zapamiętuje poprzedni katalog roboczy i powrót do niego wymaga podania po poleceniu cd myślnika (-) jako argumentu
- W ścieżkach chcąć skrócić sobie pisanie, możemy użyć tyldy (~) jako zamiennika katalogu domowego.
- Chcąc przenieść się do katalogu nadrzędnego względem bierzącego nie musimy znać jego nazyw wystarczy że poleceniu cd podamy dwie kropki (..)
Poniżej zamieściłem przykłady kilku z nich.
[root@server1 ~]# cd - /home/user [root@server1 user]# cd .. [root@server1 home]# cd
2.3.4. Identyfikacja urządzenia terminala
Czasmi może zajść potrzeba zidentyfikowania własnego urządania terminalowego służy do tego polecenie tty. Jeśli wynikiem działania tego polecenie będzie /dev/pts* oznacza to, że korzystamy z emulatora terminala np. programu Terminal w środowisku GNOME lub połączenia zdalnego za pomocą protokołu SSH. Jeśli naszę urządzenie to /dev/tty* oznacza to, że korzystamy z jednej wirtualnych konsol dostępnych w systemie.
[root@server1 ~]# tty /dev/pts/0
2.3.5. Czas systemowy oraz załadowanie procesora
Większości dostępnych Uniksów zapewne zawierać będzie polecenie uptime. To niepozorne polecenie zawraca dużą ilość informacji.
- Czas systemowy,
- Ilość czasu jaka upłyneła od uruchomienia systemu (tzw. uptime),
- Ilość zalogowanych do systemu użytkowników,
- Średnie załadowanie procesora w przeciągu minuty, 5 i 15 minut, ta wartość pokazuje zużycie procesora, podając wartości ułamkowe jeśli np. w ciągu jednej minuty jeden z wątków procesora był wykorzystany w 50% otrzymamy wynik 0.50. Jeśli posiadamy procesor wielordzeniowy, ten wskaźnik może wskazywać wartości powyżej 1, oznacza to że procesy wykorzystują już więcej niż jeden wątęk/rdzeń.
[root@server1 ~]# uptime 13:28:40 up 8 min, 1 user, load average: 0.00, 0.12, 0.12
2.3.6. Czyszczenie ekranu powłoki
Do czyszczenia terminala ze zbędnego wyjścia poleceń służy polecenie clear lub kombinacja klawiszy Ctrl+l.
[root@server1 ~]# clear
2.3.7. Określanie ścieżki polecenia
Czasami w pewnych konfiguracjach lub też w skryptach powłoki niezbędne będzie podanie ścieżki do konkretnego programu kryjącego się za nazwą polecenia, w RHEL możemy zrobić to na trzy sposoby wykorzystując do tego różne polecenia. Polecenia podałem w przykładzie w raz z informacją zwracaną przez polecenie.
[user@rhel90 ~]$ which ls alias ls='ls --color=auto' /usr/bin/ls [user@rhel90 ~]$ whereis ls ls: /usr/bin/ls /usr/share/man/man1/ls.1.gz /usr/share/man/man1p/ls.1p.gz [user@rhel90 ~]$ type ls ls jest aliasem do ls --color=auto'
Które z tych poleceń będzie właściwe to już zależy, do czego będą nam potrzebne tego typu informacje. Polecenie whereis wydaje się szczególnie pomocne.
2.3.8. Wyświetlenie informacji o systemie
Polecenie uname należy do poleceń, które są dość niepozorne, ale za pomocą jego opcji możemy otrzymać wersję użytego jądra, architekturę systemu i tym podobne informacje. Polecenie bez podania żadnej z opcji zwraca wyłącznie nazwę systemu i jest to Linux. Aby otrzymać wszelkie zwracane przez to polecenie informacje możemy użyć opcji -a. Resztę opcji znajdziemy na stronach podręcznika (o tym będzie w dalszej części materiału).
[user@rhel90 ~]$ uname -a Linux latitude-e5270 5.14.0-70.13.1.el9_0.x86_64 #1 SMP PREEMPT Thu Apr 14 12:42:38 EDT 2022 x86_64 x86_64 x86_64 GNU/Linux
2.3.9. Wyświetlanie informacji o procesorze
W RHEL możemy łatwo sprawdzić informacje na temat zainstalowanego w naszym komputerze procesora w przystępny sposób. Do dyspozycji mamy bowiem polecenie lscpu. Wyświetla ono wszystkie dostępne informacje jakie może znaleźć w systemie na temat tego komponentu.
[root@server1 ~]# lscpu Architecture: x86_64 CPU op-mode(s): 32-bit, 64-bit Address sizes: 39 bits physical, 48 bits virtual Byte Order: Little Endian CPU(s): 1 On-line CPU(s) list: 0 Vendor ID: GenuineIntel Model name: Intel(R) Core(TM) i5-6300U CPU @ 2.40GHz CPU family: 6 Model: 78 Thread(s) per core: 1 Core(s) per socket: 1 Socket(s): 1 Stepping: 3 BogoMIPS: 5004.62 Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx rdtscp lm constant_tsc rep_good nopl xtopology nonstop_tsc cpuid tsc_known_freq pni pclmulqdq monitor ssse3 cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt aes xsave avx rdrand hypervisor lahf_lm abm 3dnowpre fetch invpcid_single pti fsgsbase avx2 invpcid rdseed clflushopt md_clear flush _l1d Virtualization features: Hypervisor vendor: KVM Virtualization type: full Caches (sum of all): L1d: 32 KiB (1 instance) L1i: 32 KiB (1 instance) L2: 256 KiB (1 instance) L3: 3 MiB (1 instance) NUMA: NUMA node(s): 1 NUMA node0 CPU(s): 0 Vulnerabilities: Itlb multihit: KVM: Mitigation: VMX unsupported L1tf: Mitigation; PTE Inversion Mds: Mitigation; Clear CPU buffers; SMT Host state unknown Meltdown: Mitigation; PTI Spec store bypass: Vulnerable Spectre v1: Mitigation; usercopy/swapgs barriers and __user pointer sanitization Spectre v2: Mitigation; Retpolines, STIBP disabled, RSB filling Srbds: Unknown: Dependent on hypervisor status Tsx async abort: Not affected
2.4. Uzyskiwanie pomocy
2.4.1. Strony podręcznika
W dystrybucjach Linuksa nie tylko w RHEL możemy znaleźć duża bazę zawierającą opisy poleceń, plików konfiguracyjnych oraz innych komponentów takich jak biblioteki. Służą temu strony podręcznika. Aby uzyskać do nich dostęp wystarczy wydać polecenie man podając jako argument interesujący nas komponent. Nie zawsze musi być to polecenie. Strony podręcznika są podzielone na rozdziały czy też sekcje ich opisy oraz numery sa zawarte na (o ironio) stronie podręcznika polecenia man. Wydajmy poniższe polecenie aby zapoznać się z nim oraz z ich organizacją.
[xf0r3m@hp-z600 ~]$ man man
Różne komponenty na Linuksie mogą mieć takie same nazwy. Polecenie
man zwraca pierwsze znalezione wystąpienie, jeśli wpiszemy
polecenie man passwd
to otrzymamy
informacje na temat polecenia, ale jeśli interesowałoby nas poznanie
szczegółów pliku /etc/passwd musimy podać przed jego nazwą,
numer rozdziału odpowiedzialny za pliki konfiguracyjne.
[xf0r3m@hp-z600 ~]$ man 5 passwd
Strony podręcznika, możemy przeszukiwać pod kątem występowania słów kluczowych, w przypadku kiedy znamy zagadnienie ale nie znamy odpowiedniego polecenia. Do tego celu możemy użyć opcji -k polecenia man lub polecenia apropos. Wynik działania tych programów jest taki sam.
[user@rhel90 ~]$ apropos dos dos2unix (1) - DOS/Mac to Unix and vice versa text file format converter dosfsck (8) - check and repair MS-DOS FAT filesystems dosfslabel (8) - set or get MS-DOS filesystem label or volume ID fatlabel (8) - set or get MS-DOS filesystem label or volume ID filesystems (5) - Linux filesystem types: ext, ext2, ext3, ext4, hpfs, iso9660, JFS, minix, msdos, ncpfs nfs, ntfs, proc, Reiserfs, smb, sysv, umsdos, vfat, XFS, xiafs fs (5) - Linux filesystem types: ext, ext2, ext3, ext4, hpfs, iso9660, JFS, minix, msdos, ncpfs nfs, ntfs, proc, Reiserfs, smb, sysv, umsdos, vfat, XFS, xiafs fsck.fat (8) - check and repair MS-DOS FAT filesystems fsck.msdos (8) - check and repair MS-DOS FAT filesystems fsck.vfat (8) - check and repair MS-DOS FAT filesystems mac2unix (1) - DOS/Mac to Unix and vice versa text file format converter mkdosfs (8) - create an MS-DOS FAT filesystem mkfs.fat (8) - create an MS-DOS FAT filesystem mkfs.msdos (8) - create an MS-DOS FAT filesystem mkfs.vfat (8) - create an MS-DOS FAT filesystem unix2dos (1) - DOS/Mac to Unix and vice versa text file format converter unix2mac (1) - DOS/Mac to Unix and vice versa text file format converter vdosetuuid (8) - sets a new uuid for the vdo volume stored on a backing store vdostats (8) - Display configuration and statistics of VDO volumes
W pierwszej kolumnie znajduje się nazwa komponentu, w drugiej (w nawiasie) numer rozdziału a następnie krótki opis.
Szukając opisu polecenia możemy posiłkować się poleceniem whatis. Polecenie to poszukuje konkretnego komponentu na stronach podręcznika, a nie słowa kluczowego.
[user@rhel90 ~]$ whatis xdg-open xdg-open (1) - opens a file or URL in the user's preferred application
Polecenie whatis, zachowuje się identycznie jak polecenie man z opcją -f.
2.4.2. Pomoc w samym poleceniu
Inny sposobem niż wertowanie stron podręcznika w celu znalezienia odpowiedniej opcji jest po prostu wywołanie polecenia a opcją --help.
[user@rhel90 ~]$ ranger --help Usage: ranger [options] [path] Options: --version show program's version number and exit -h, --help show this help message and exit -d, --debug activate debug mode -c, --clean don't touch/require any config files. --logfile=file log file to use, '-' for stderr --cachedir=dir change the cache directory. (/home/xf0r3m/.cache/ranger) -r dir, --confdir=dir change the configuration directory. (/home/xf0r3m/.config/ranger) --datadir=dir change the data directory. (/home/xf0r3m/.local/share/ranger) --copy-config=which copy the default configs to the local config directory. Possible values: all, rc, rifle, commands, commands_full, scope --choosefile=OUTFILE Makes ranger act like a file chooser. When opening a file, it will quit and write the name of the selected file to OUTFILE. --choosefiles=OUTFILE Makes ranger act like a file chooser for multiple files at once. When opening a file, it will quit and write the name of all selected files to OUTFILE. --choosedir=OUTFILE Makes ranger act like a directory chooser. When ranger quits, it will write the name of the last visited directory to OUTFILE --selectfile=filepath Open ranger with supplied file selected. --show-only-dirs Show only directories, no files or links --list-unused-keys List common keys which are not bound to any action. --list-tagged-files=tag List all files which are tagged with the given tag, default: * --profile Print statistics of CPU usage on exit. --cmd=COMMAND Execute COMMAND after the configuration has been read. Use this option multiple times to run multiple commands.
Posiadanie tej opcji nie jest standardem, wiec nie wszystkie polecenia będą ją mieć.
2.4.3. Dokumentacja texinfo
Projekt GNU, zaproponował zmianę formatu dokumentacji programów, z suchych stron podręcznika do dokumentów przypominających ksiązkę lub inne dokumenty. Strony podręcznika nadal są podstawowym i wybudowanym (w większość dystrybcji) źródłem wiedzy na temat systemu i jego komponentów. Nie mniej jednak jeśli uznamy, że zawartość strony podręcznika nie jest dla zadowalająca może spojrzeć też tam, o ile ten format jest zainstalowany w naszym systemie. Dostęp do niego uzyskujemy za pomocą polecenia info lub pinfo, następnie podając nazwę polecenia jako argument. Wydając samo polecenie info, możemy zobaczyć ile dokumentacji w formacie texinfo znajduje się w systemie.
2.4.4. /usr/share/doc
Innym miejscem przechowującym jakieś informacje na temat poleceń czy też programów może być katalog /usr/share/doc. Możemy w nim znaleźć na przykład domyślne plik konfiguracyjne wielu usług (oczywiście zależy to czy zostaną one dodane do paczek z oprogramowaniem). Nie należy jednak od razu skreślać tego katalogu, często mogą znajdować się tam informacje, których nie znajdziemy na stronach podręcznika czy w formacie info np. tutoriale lub gotowe konfiguracje.
2.4.5. Dokumentacja Red Hat Enterprise Linux
Innym źródłem informacji na temat obsługi systemu jest dokumentacja Red Hat dostępna w internecie (dla RHEL 9) pod tym adresem: https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/9
Każdy zebranych tam tematów możemy pobrać w formacie HTML, PDF oraz ePub (czytniki e-booków).
Odnośnie egzaminu:
Na egzaminie możemy korzystać ze wszystkiego co jest dostępne w systemie
warto pamiętać o tym. Jeśli będziemy mieć problemy z poleceniem
man, warto wydać polecenie mandb odświeży
to bazę danych stron podręcznika.
Ćwiczenie 1: Nawigacja pośród katalogów Linuksa
Jako zwykły użytkownik na maszynie wirtualnej server1, wyświetl ścieżkę na której się znajdujesz. W tym samym katalogu wyświetl wszystkie pliki. Przjedź do katalogu /etc następnie wyświetl ścieżkę, na której się znajdujesz, następnie powróć do poprzedniego katalogu i jeszcze raz wyświetl ścieżkę.
Ćwiczenie 2: Rożne zadania
Jako zwykły użytkownik na maszynie server1 w terminalu polecenie tty. Następnie uruchom kilka kart terminala wydaj w nich to samo polecenie i porównaj zwracane wartości. Wyświetl czas pracy systemu oraz średnie obciążenie procesora. Za pomocą trzech poznanych poleceń wyświetl lokalizacje polecenia vgs.
Ćwiczenie 3: Informacje o systemie
Jako zwykły użytkownik na maszynie server1 za pomocą poznanego polecenia wyświetl wszystkie informacje o systemie (oczywście w miarę możliwości polecenia). Następnie użyj innego polecenia aby sprawdzić informacje na temat zainstalowanego w komputerze procesora.
Ćwiczenie 4: Używanie pomocy
Jako zwykły użytkownik na maszynie server1
Wyświetl stronę podręcznika polecenia uname oraz stronę
podręcznika dla pliku /etc/shadow. Wykonaj trzy polecenia:
apropos ext4
,
man -k ext4
,
whatis group
. Czym różnią się
informacje zwracane przez te polecenia?
Podsumowanie
W tym rozdziale skupiliśmy się na podstawach obsługi systemu, poznaliśmy środowisko graficzne. Odświerzyliśmy sobie informacje na temat hierachicznego systemu plików wykorzystywanego w Uniksach. Zapoznaliśmy się z terminalem i podstawowymi poleceniami. Na koniec dowiedzieliśmy się gdzie możemy szukać pomocy na temat poleceń, plików konfiguracyjnych i tego typu rzeczy.
3. Operacje na plikach
W poprzedni rodziale poznaliśmy podstawy poruszania się po systemie, przejrzeliśmy środowisko graficzne, zapoznaliśmy się z wierszem polecenia oraz z najbardziej podstawowymi poleceniami. Było to swoiste zapoznanie się z systemem operacyjny. Teraz pora w nim trochę popracować. Ludzie zazwyczaj kiedy wspomagają swoją prace komputerem, pracują na danych. Te dane są zazwyczaj zebrane w pliki i od omówienia rodzajów plików dostępnych na Linuksie rozpoczniemy ten rozdział.
3.1. Rodzaje plików
W Uniksach możemy wymienić 7 rodzajów różnych plików. W tych systemach nie jest istotne rozszerzenie oraz zawartość tych plików. Dla systemu zawsze będzie to zwykły plik. Wszystkie pliki niewymienione na poniższej liście, które przyjdą nam do głowy są plikami zwykłymi.
Zatem w Uniksach możemy wyróżnić takie rodzaje plików jak:
- Plik zwykły - plik zwykłe przechowywują dane, są to wszelkiej maści pliki tekstowe, pliki binarne z programami oraz inne.
- Katalog - jest struktura organizacyjna systemu plików, stosowana w celach porządkowych zwykłych plików w systemie plików.
- Plik urządzenia znakowego - w przypadku określenia znakowy stosuje się także określenie surowy (ang. raw). Pliki te wykorzystywane są do komunikacji z urządzaniami wykorzysującymi interfejs szeregowy.
- Pliki urządzeń blokowych - Plików tych używa się są do komunikacji z urządzeniami wykorzystującymi interfejs równoległy. Głównie są to dyski.
- Dowiązania symboliczne - przypominają skróty znane z innych systemów operacyjnych. Jest to plik wskazujący na inny plik lub katalog.
- Nazwane potoki, gniazda - są to pliki, które służą do komunikacji miedzyprocesowej. Omawianie ich tutaj wychodzi poza ramy tego materiału.
Nie ma się też za bardzo co rozwodzić nad każdym z tych typów plików. Rodzaju pliku możemy ustalić podczas wyświetlania zawartości katalogu. Wskaźnikiem jest pierwszy znak w pierwszej kolumnie informacji zwracanej przez polecenie ls -l. Informacje zwracane dla poszczególnych typów wyglądają następująco:
#Zwykły plik: [root@server1 ~]# ls -l anaconda-ks.cfg -rw-------. 1 root root 1197 Jun 9 19:59 anaconda-ks.cfg #Katalog: [root@server1 ~]# ls -ld bzipped/ drwxr-xr-x. 3 root root 17 Jun 16 18:14 bzipped/ #Urządzenie znakowe: [root@server1 ~]# ls -l /dev/console crw--w----. 1 root tty 5, 1 Jun 17 15:20 /dev/console #Urządzenie blokowe: [root@server1 ~]# ls -l /dev/sda1 brw-rw----. 1 root disk 8, 1 Jun 17 15:20 /dev/sda1 #Dowiązanie symboliczne: [root@server1 ~]# ls -l soft10 lrwxrwxrwx. 1 root root 6 Jun 16 17:30 soft10 -> file10
Pierwsze znaki, pierwszej kolumny róznią się od siebie w zależności od typu plików. Jest jeszcze kilka róznic. Pliki urządzeń nie posiadają rozmiaru, tylko dwie liczby oddzielone od siebie przecinkiem. Te liczby to numer główny oraz numer poboczny. Numer główny określa rodzaj urządzenia (użyty sterownik urządzenia), z kolei numer poboczny jest jego unikalny identyfikatorem w systemie. Innym rodzajem, jest dowiązanie symboliczne, które nazwa wskazuje na ścieżke innego pliku, ale do tego typu plików wrócimy poźniej.
Te informacje które są zwracane oprócz nazwy pliku przez polecenie, ls z odpowiednią opcją to tak zwane metadane. Większą ich ilość możemy wyświetlić za pomocą polecenia stat. Na poniższym przykładzie zamieszczono więcej metadanych zwykłego pliku z poprzedniego przykładu:
[root@server1 ~]# stat anaconda-ks.cfg File: anaconda-ks.cfg Size: 1197 Blocks: 8 IO Block: 4096 regular file Device: fd00h/64768d Inode: 6126703 Links: 1 Access: (0600/-rw-------) Uid: ( 0/ root) Gid: ( 0/ root) Context: system_u:object_r:admin_home_t:s0 Access: 2022-06-16 10:37:11.765639347 +0200 Modify: 2022-06-09 19:59:42.592326645 +0200 Change: 2022-06-09 19:59:42.592326645 +0200 Birth: 2022-06-09 19:59:42.237318552 +0200
Zwykłe pliki na Uniksach nie muszą mieć rozszerzenia, więc aby przed uruchomieniem pliku upewnić się co to jest, mamy do dyspozycji takie narzędzie jak program file, który zbada zawartość podanego mu w argumencie pliku.
[root@server1 ~]# file test test: Bourne-Again shell script, ASCII text executable
Plik nie ma rozszerzenia .sh a mimo to pozostaje skryptem powłoki.
3.2. Kompresja i archiwizowanie
Kompresja pozwala na zmniejszenie objętości plików za pomocą zaawansowanych algorytmów, dzięki czemu możemy zaoszczędzić miejsce na dysku. Wadą takiego przechowywania danych jest dłuższy czas oczekiwania na ich gotowość do pracy, ponieważ dane przed tym należy zdekompresować. Archizowanie może służyć do zebrania wielu małych plików w jeden duży. Na Uniksach możemy wymienić dwa natywne narzędzia służące do kompresji i jedno do archiwizowania.
3.2.1. gzip
Natywnym i dostępnym na każdym systemie sposobem na kompresje danych jest gzip. Algorytmy zawarte w tym narzędziu kompresują dane, powodując zmniejszenie ich objętość. Narzędzie do każdego skompresowanego pliku dodaje rozszerzenie .gz. Aby skompresować plik wystarczy podać jego nazwę lub ścieżkę do niego jako argument poleceniu gzip.
#Plik przed kompresją [root@server1 ~]# ls -l fstab -rw-r--r--. 1 root root 579 Jun 16 11:07 fstab #Kompresja [root@server1 ~]# gzip fstab #Plik po kompresji [root@server1 ~]# ls -l fstab.gz -rw-r--r--. 1 root root 350 Jun 16 11:07 fstab.gz
Jak możemy zauważyć rozmiar pliku zmniejszył się. Zwróćmy uwagę na to iż narzędzie nie działa na kopii pliki tylko kompresuje bezpośrednio podany plik. Aby plik zdekompresować możemy użyć polecenia gunzip
[root@server1 ~]# gunzip fstab.gz
Dla plików skompresowanych za pomocą polecenia gzip, możemy podejrzeć listę skompresowanych plików (w przypadku jednego pliku może być to użyteczne do wyświetlenia statystki kompresji) wykorzystując opcje -l i podając jako argument skompresowany plik.
[root@server1 ~]# gzip -l fstab.gz compressed uncompressed ratio uncompressed_name 350 579 43.7% fstab
3.2.2. bzip2
Program bzip2 jest obecnie standardem kompresji wśród wielu Uniksów. Jest wolniejszy od gzip, ale skompresowane przez niego pliki są mniejsze. Więc pozostaje w naszej gestii, który z nich będziemy stosować. Do skompresowanych przez bzip2 plików dodawane jest rozszerzenie .bz2. A kompresja za pomocą tego narzędzia wygląda następująco:
[root@server1 ~]# ls -lh test -rw-r--r--. 1 root root 250M Jun 17 17:21 test [root@server1 ~]# bzip2 test [root@server1 ~]# ls -lh test.bz2 -rw-r--r--. 1 root root 210 Jun 17 17:23 test.bz2
Dekompresja takiego pliku takiego pliku wyglada analogicznie do narzędzia gunzip.
[root@server1 ~]# bunzip2 test.bz2 [root@server1 ~]# ls -lh test -rw-r--r--. 1 root root 250M Jun 17 17:25 test
W przypadku polecenia bzip2 nie mamy możliwośći wyświetlenia listy skompresowanych plików (statystyk kompresji).
3.2.3. tar
Program tar nie służy do kompresji, a do archiwizcji. Jego zadaniem jest stworzenie jednego pliku z wielu innych plików lub z całego katalogu. Na początku program swojego istnienia program tar domyślnie tworzył archiwa na napędach taśmowych, dlatego też jeśli ma on tworzyć archiwum do pliku potrzebna będzie odpowiednia opcja, i ta funkcjonalność pozostała po dziś dzień.
Opcje tego programu możemy podawać na trzy różne sposoby, wpisując z myślnikami każdą opcje po kolei, wypisując opcje pod jednym myślnikiem, lub nie używać myślnika w ogóle. Do stworzenia archiwum potrzebujemy dwóch opcji, pierwszej -c - tworzącej archiwum oraz drugiej -f - nakazujące stworzenie archiwum w podanym jako argument opcji pliku. Poniżej znajdują się opisane wyżej użycia polecenia tar do stworzenia archiwum.
[root@server1 ~]# tar -c -f etc_tarred.tar /etc tar: Removing leading `/' from member names [root@server1 ~]# tar -cf etc_tarred1.tar /etc tar: Removing leading `/' from member names [root@server1 ~]# tar cf etc_tarred2.tar /etc tar: Removing leading `/' from member names
Zwróćmy uwagę na komunikat programu, który usuwa ze scieżek wskazujących pliki (ponieważ użyłem ścieżki bezwzględnej) początkowy ukośnik, aby przy wypakowywaniu nie nadpisać ważnych plików systemowych. Warto dodać, iż ja tworzyłem te archiwa jako superużytkownik, w momencie gdy root używa polecenia tar, używana jest domyślnie opcja -p, która powoduje zachowanie wszystkich atrybutów plików, w przypadku zwykłego użytkownika ta opcja musi zostać jawnie podana.
Rozpakowanie archiwum wymaga podania opcji -x oraz opcji -f ze wskazaniem pliku archiwum.
[root@server1 ~]# tar -xf etc_tarred1.tar -C /tmp [root@server1 ~]# ls -ld /tmp/etc drwxr-xr-x. 132 root root 8192 Jun 17 15:20 /tmp/etc
W tym przykładzie użyłem jeszcze jednej ważnej opcji -C, która nakazuje poleceniu tar zmianę katalogu przed wypakowaniem archiwum.
Za pomocą opcji -t, możemy podejrzeć zawartość archiwum. Opcja -v powoduje wyświetlanie komunikatów przez program.
[root@server1 ~]# tar -tvf etc_tarred2.tar drwxr-xr-x root/root 0 2022-06-17 15:20 etc/ lrwxrwxrwx root/root 0 2022-06-09 19:47 etc/mtab -> ../proc/self/mounts -rw-r--r-- root/root 579 2022-06-09 19:44 etc/fstab -rw------- root/root 0 2022-06-09 19:44 etc/crypttab drwxr-xr-x root/root 0 2022-06-09 19:47 etc/lvm/ drwxr-xr-x root/root 0 2022-06-09 19:44 etc/lvm/devices/ -rw-r--r-- root/root 286 2022-06-09 19:44 etc/lvm/devices/system.devices drwx------ root/root 0 2022-06-09 20:48 etc/lvm/archive/ -rw------- root/root 1891 2022-06-09 20:48 etc/lvm/archive/rhel_00000-557804270.vg drwx------ root/root 0 2022-06-09 20:48 etc/lvm/backup/ -rw------- root/root 1890 2022-06-09 20:48 etc/lvm/backup/rhel drwx------ root/root 0 2022-02-16 13:01 etc/lvm/cache/ -rw-r--r-- root/root 111694 2022-02-16 13:01 etc/lvm/lvm.conf -rw-r--r-- root/root 2299 2022-02-16 13:01 etc/lvm/lvmlocal.conf ...
Chcąc dodać plik do archiwum, wystarczy użyć opcji -r nie trzeba go rozpakowywać i dodawać tych plikiów wystarczy wskazać archiwum a następnie pliki, które chce się dodać. Plik zostanie dodany na koniec archiwum.
[root@server1 ~]# tar -rvf etc_tarred2.tar vipractice.bz2 vipractice.bz2 [root@server1 ~]# tar -tvf etc_tarred2.tar ... -rw-r--r-- root/root 208 2022-06-09 19:46 etc/.updated -rw-r--r-- root/root 307 2022-06-16 18:38 vipractice.bz2
Dodawaniu plików do archiwum nie służy wyłącznia opcja -r, ale również -u, która dodaje nowsze pliki na końcu archwium. Wyświetlając zawrtość takiego archiwum, możemy zobaczyć pliki o tych samych nazwach. Te nazwy oczywiście odpowiadają różnym wersjom tych plików.
[root@server1 ~]# tar -uvf etc_tarred.tar /etc/nanorc tar: Removing leading `/' from member names /etc/nanorc tar: Removing leading `/' from hard link targets [root@server1 ~]# tar -tvf etc_tarred2.tar ... -rw-r--r-- root/root 208 2022-06-09 19:46 etc/.updated -rw-r--r-- root/root 10373 2022-06-19 09:47 etc/nanorc
Po zebraniu wszystkich plików do archiwum, może okazać się że jest to sporych rozmiarów plik. Polecenie tar, pozwala na zastosowanie poznanych wcześniej algorytmów kompresji podczas tworzenia archwium.
- gzip: opcja -z
[root@server1 ~]# tar -czf etc-gzipped.tar.gz /etc
- bzip2: opcja -j
[root@server1 ~]# tar -cjf etc-bzipped.tar.bz2 /etc
Rozpakowując skompresowane archiwa w RHEL możemy rozpakować podając takie same opcje jak w przypadku nie skompresowanych archiwów.
[root@server1 ~]# tar -xf etc-gzipped.tar.gz -C /tmp
Program rozpozna po zawartości pliku algortym kompresji. Wiecej informacji na temat polecenia tar znajduje na stronie podręcznika.
Odnośnie egzaminu:
Na egzaminie będziemy mieć określną ilość czasu na wykonanie zadań
egzaminacyjnych, dlatego też operacje kompresji czy archiwizacji
plików będą przeprowadzane na małych plikach, aby nie tracić czasu.
3.3. Edycja plików za pomocą edytora Vim
Podczas wykonywania zadań związanych z administracją systemem, niezbędna może być edycja jakiegoś pliku. Edytor Vim jest standardem jeśli chodzi o edycję plików. Ten edytor w wersji podstawowej jaką jest program Vi jest dostępny w większości Uniksów. W przypadku w wielu dystrybucji Linuksa preinstalowany jest Vim, ze względu na to ten edytor jest jednym z podstawowych narzędzi. Lepiej jest nauczyć się rozwiązania, które możemy zastosować domyślnie bez zbędnej ingerencji w system (bez instalacji ulubionego edytora, który znamy).
Edytor Vim może działać w trzech trybach:
- tryb poleceń - domyślny tryb pracy programu, Vim oczekuje na wprowadzenie polecenia. Ten tryb jest uruchamiany w momencie uruchomienia programu. Polecenia są przypisane do poszczególnych znaków na klawiaturze.
- tryb wprowadzania - tryb ten służy do edycji tekstu, uruchamiany za pomocą polecenia i lub a.
- tryb ostatniej lini - ten tryb możemy również nazwać wierszem polecenia lub poprawnie trybem ex. Uruchamiany jest poprzez wciśnięcie dwukropka (:) w trybie poleceń. Po tym znaku podajemy polecenie.
3.3.1. Podstawy obsługi Vim
Edytor Vim uruchamiamy, jak każde inne polecenie. Podając jego nazwę w wierszu polecenia. Podczas uruchamiania możemy podać plik jako argument lub też użyć polecenia trybu ostatniej linii :o po czym podać ścieżkę do pliku.
[root@server1 ~]# vim test.txtPoruszanie po tekscie odbywa się w trybie poleceń za pomocą klawiszy:
- h - przesunięcie kursora w lewo
- j - przesunięcie kursora w dół
- k - przesunięcie kursora w górę
- l - przesunięcie kursora w prawo
Przejście do edycji tekstu, wymaga użycia polecenia i co spowoduje rozpoczęcie edycji w pozycji kursora lub polecenia a, które spowoduje przesunięcie kursora o jedną pozycję i rozpoczęcie edycji, polecenie a możemy tłumczyć jako dopisywanie (ang. append), a i jako wprowadzanie (ang. insert).
Opuszczenie trybu wprowadzania i powrót do trybu polecenia wymaga naciśnięcia klawisza Esc (ang. escape). Przjście do trybu polecenia jest wymagane, aby przenieść kursor w inne miejsce. W tym trybie również poprzez polecenia ostatniej linii zapisujemy zmiany w pliku oraz opuszczamy edytor. Zmiany w tekscie również możemy porzućić, nie musimy ich zapisywać. Poniżej umieściłem kilka poleceń trybu ostatniej linii, służacych od zapisywania i opuszczania edytora.
- :w - zapisanie zmian w pliku oraz pozostanie w w edytorze
- :x - zapisanie zmian w pliku oraz opuszczenie Vim
- :q - opuszczenie Vim.
Każdej z tych opcji może towarzyszyć wykrzyknik (!), więc jeśli chcielibyśmy porzucić zmiany w pliku i wyjść należy użyć polecenia :q!. Możemy czasami spotkać się z uprawnieniami, które nie pozwolą nam zapisać zmian w pliku. Rozwiązać tego typu problem możemy na dwa sposoby, wymusić zapisanie zamian za pomocą wykrzyknika (działa to tylko w przypadku, gdy superużytkownik chce zapisać zmiany w pliku tylko odczytu), lub podać ścieżkę do nowego pliku poleceniu :w, poźniej skopiować w plik w docelowe miejsce.
3.3.2. Pozostałe polecenia Vim
Vim posiada bogatą kolekcję komend trybu poleceń oraz trybu ostatniej linii, na poniższej liście znajdują się część z nich, możemy wykorzystać je do sprawniejszego używania edytora Vim.
Komendy trybu poleceń:
- ^ - Shift + 6 - przeniesie kursora na początek linii.
- $ - Shift + 4 - przeniesie kursora na koniec linii.
- Ctrl + f - przewinięcie tekstu o jedną stronę w przód.
- Ctrl + b - przewinięcie tekstu o jedną stronę w tył.
- x - usunięcie znaku wskazywanego przez kursor, znak tak naprawdę zostaje wycięty i poźniej może zostać wklejony.
- dd - usunięcie/wycięcie całej linii, linia podobnie jak znak może zostać wklejona.
- v - przejście Vim w tryb wizualny (tutaj nie omawiany), pozwala zaznaczać tekst co ułatwia kopiowanie oraz wycinanie.
- y - kopiowanie zaznaczenia w trybie wizualnym.
- d - wycinanie/usuwanie w trybie wizualnym.
- p - wklejanie.
- u - cofnięcie się o jedną zmianę, odpowiednik Ctrl+z.
- Ctrl+r - tzw. redo, powrót do stanu przed cofnięciem zmiany. Czasami bardzo przydatna funkcja.
- . - kropka - powtórzenie ostatniego polecenia. Jeśli ostatnim poleceniem było wprowadzanie, to polecenie wklei cały wprowadzony tekst do momentu zmiany polecenia.
- / - slash - przeszukiwanie tekstu w przód.
- ? - znak zapytania - przeszukiwanie tekstu w tył.
- n - następne wystąpienie frazy w tekście
- N - poprzednie wystąpienie frazy w tekscie. W przypadku przeszukiwania w tył, działanie poleceń n oraz N jest odwrócone.
W przypadku trybu poleceń, możemy zwielokrotnić działanie tych poleceń, wprowadzając liczbę wykonywania tego polecenia przed poleceniem. Na przykład jeśli chcemy usunąć 3 linie to zamiast wydawać trzykrotnie polecenie dd, możemy nacisnąć 3 następnie dd i trzy linie spod kursora zostaną usunięte/wycięte.
Polecenia trybu ostatniej linii:
- :set number - włącza numerowanie linii.
- :o - otwiera plik, jako argument podajemy ścieżkę do pliku.
- :%s/old/new - zamiana pierwszego wstąpienia słowa old słowem new.
- :%s/old/new/g - zamiana wszystkich wystąpień słowa old słowem new.
- :6,11co4 - polecenie kopiuje zawartość linii od 6 do 11 i wkleja ją po 4 linii.
- :3,5m6 - polecenie przenosii linię od 3 do 5 na miejsce po linii numer 6.
- :6,8d - polecenie usuwa linie od 6 do 8.
- :r - polecenie wprowadza w miejscu kursora zawartość pliku podanego jako argument.
Podczas korzystania Vim istotna jest praktyka. Dlatego trzeba przesiąść się na niego i zacząć tworzyć w nim pliki.
Odnośnie egzaminu:
Podczas egzaminu, możemy spotkać się z zadaniem w którym trzeba
zmienić jakiś plik. Dostępność Vim na maszynie
egzaminacyjnej jest niemal pewna, dlatego też nauczenie się jego
obsługi jest dość istotne.
3.4. Pliki i katalogi
Jaka kolwiek praca z komputerem prędzej czy poźniej będzie wymagać operacji na plikach i katalogach. Poniżej przedstawiam najprostsze czynności jakie możemy wykonywać na tych elementach.
3.4.1. Tworzenie plików i katalogów
Tworzenie plików może zrealizować na kilka sposób. Jednym z nich jest wykorzystanie polecenia touch, które służy generalnie do uaktualnienia czasów dostępu oraz modyfikacji, jednak kiedy podany plik nie istnieje to zostanie on utworzony przez to polecenie.
[root@server1 ~]# touch plik1 [root@server1 ~]# ls -l plik1 -rw-r--r--. 1 root root 0 Jun 19 14:52 plik1
Jak widać na powyższym przykładzie został utworzony plik, którego wielkość to całe 0 bajtów. Innym sposobem na utworzenie pliku jest wykorzystanie polecenia Vim, w którym zapisując zmiany w nowym pliku, tworzymy go mimochodem. Ostanim ze sposobów jest utworzenie plików ze strumienia (stumienie będą opisywane w dalszej części tego materiału), za pomocą polecenia cat, które omówimy sobie w następnym podrozdziale. Wydając następujące polecenie:
[root@server1 ~]# cat > plik2 test1 test2 test3 test4 test5
Uruchamiając to polecenie przełączymy strumienie tak, aby wszystko co zostanie wpisane do terminala trafi do pliku (w dużym skrócie). Taką edycję pliku możemy zakończyć naciskając kombinacje klawiszy Ctrl+d.
Za tworzenie katalogów odpowiedzialne jest polecenie mkdir. Polecenie to utworzy katalog o nazwie podanej jako argument. Ważną opcją tego polecenia jest -p, za pomocą którego jesteśmy wstanie tworzyć z poziomu pojedynczego polecenia całe struktury katalogów. Opcja ta powoduje utworzenie katalogów podanych na ścieżce, które nie istnieją.
[root@server1 ~]# mkdir dir1
3.4.2. Wyświetlanie zawartości pliku
Na Uniksach do wyświetlania zawartości plików mamy kilka rozwiązań pierwszym z nich jest wspomnianie już polecenie cat. Polecenie wyświetli zawartość pliku podanego jako argument w terminalu.
[root@server1 ~]# cat plik2 test1 test2 test3 test4 test5
Na Uniksach, obok polecenia cat występuje polecenie tac, które ma takie samo zastosowanie jak to wyżej wymienione, wyświetlając jednak zawartość pliku odwrotnie od końca. Poniższy przykład zaraz to zobrazuje:
[root@server1 ~]# tac plik2 test5 test4 test3 test2 test1
Podczas wyświetlania dużych plików ich zawartość może nie mieścić się na ekranie, czy też w oknie terminala. Do wyświetlania tego typu plików wykorzystuje się takie polecenia jak more czy less. Oba dzielą wyświetloną treść plików na strony wielkości ekranu bądź terminala. Program more nie jest za bardzo zaawansowanym narzędziem. Wyświetlając pliki za jego pomocą nie mamy zbyt dużego pola manewru. Możemy przesuwać stronę po stronie, do końca pliku. Dlatego też znacznie lepszym rozwiązaniem jest wykorzystanie polecenia less, który pozwala poruszać się po tekscie w góre i w dół, ale również pozwala na wyszukiwanie fraz w tekscie, możemy również nawigować po za pomocą klawiszy znanych z programu Vim. Program less uruchomi się szybciej niż, program more, ponieważ nie musi on załadować całego pliku od razu.
[root@server1 ~]# less /var/log/messages
Ostatnim już sposobem na wyświetlenie zawartości plików jest, użycie polecenia head oraz tail, ich zadaniem jest wyświetlenie kilku początkowych (domyślnie 10) linii z podanego jako argument pliku - polecenie head lub kilku ostatnich (również 10) linii z podanego pliku - polecenie tail.
[root@server1 ~]# tail /var/log/messages Jun 19 13:59:33 server1 systemd[1]: Finished dnf makecache. Jun 19 14:18:23 server1 cupsd[964]: REQUEST localhost - - "POST / HTTP/1.1" 200 182 Renew-Subscription successful-ok Jun 19 15:16:43 server1 cupsd[964]: REQUEST localhost - - "POST / HTTP/1.1" 200 182 Renew-Subscription successful-ok Jun 19 15:28:22 server1 systemd[1]: Starting dnf makecache... Jun 19 15:28:23 server1 dnf[2173]: Updating Subscription Management repositories. Jun 19 15:28:23 server1 dnf[2173]: Unable to read consumer identity Jun 19 15:28:23 server1 dnf[2173]: This system is not registered with an entitlement server. You can use subscription-manager to register. Jun 19 15:28:23 server1 dnf[2173]: Metadata cache refreshed recently. Jun 19 15:28:23 server1 systemd[1]: dnf-makecache.service: Deactivated successfully. Jun 19 15:28:23 server1 systemd[1]: Finished dnf makecache.
Domyślną ilość wypisywanych linii możemy regulować poprzez podanie po myślniku (-) żądanej liczby.
[root@server1 ~]# tail -5 /var/log/messages Jun 19 15:28:23 server1 dnf[2173]: Unable to read consumer identity Jun 19 15:28:23 server1 dnf[2173]: This system is not registered with an entitlement server. You can use subscription-manager to register. Jun 19 15:28:23 server1 dnf[2173]: Metadata cache refreshed recently. Jun 19 15:28:23 server1 systemd[1]: dnf-makecache.service: Deactivated successfully. Jun 19 15:28:23 server1 systemd[1]: Finished dnf makecache.
Polecenie tail ma jedną bardzo istoną opcję, która pozwala śledzić na bierząco zmiany w pliku, ta opcja to -f.
Poleceniem związanym z zawartością plików, ale nie z jej wyświetlaniem może być polecenie wc, które domyślnie wyświetla ilość linii, liczbę słów oraz bajtów.
[root@server1 ~]# wc /var/log/messages 639 7503 61333 /var/log/messages
3.4.3. Kopiowanie i przenoszenie plików i katalogów
Pracując z plikami, być może wystąpić potrzeba skopiowania bądź przeniesienia danych w inne miejsce. Za operację kopiowania odpowiedzialnie jest polecenie cp. Jako pierwszy argument przyjmuje ono ścieżkę lub plik źródłowy, jako drugi ścieżkę lub plik docelowy.
[root@server1 ~]# cp plik2 plik3
W przypadku gdy dany plik już istnieje w podanym katalogu polecenie zapyta się czy nadpisać docelowy plik, ale tylko w przypadku superużytkownika, bowiem on w konfiguracji swojej powłoki posiada alias (nazwę zastępczą) cp dla polecenia cp -i, opcja -i włącz tryb interaktywy, czyli właśnie takie pytania.
[root@server1 ~]# cp plik1 plik3 cp: overwrite 'plik3'? n
Za pomocą polecenia cp możemy kopiować całe katalogi z podkatalogami przy użyciu opcji -r, która włącza kopiowanie rekurencyjne. Jeśli atrybuty plików są dla nas ważne, to żeby nie nadpisać ich należy użyć opcji -p.
Za przenoszenie plików odpowiedzialne jest polecenie mv, które ma jeszcze jedną ważną cechę ukrytą w mechanice swojego działa. Otóż jeśli będzie przenosić plik lub katalog w ramach tego samego katalogu, to zmieni on tylko swoją nazwę.
Polecenie mv w przypadku superużytkownika, posiada podobny alias co w przypadku polecenia cp, polecenie jest uruchamiane domyślnie z opcją pytającą o nadpisanie elementu docelowego.
[root@server1 ~]# mv plik1 plik3 mv: overwrite 'plik3'? n
Polecenie mv nie potrzebuje żadnej opcji, aby przenieść cały katalog wraz z podkatalogami.
[root@server1 ~]# mv gzipped /tmp [root@server1 ~]# ls -ld /tmp/gzipped/ drwxr-xr-x. 3 root root 17 Jun 16 18:14 /tmp/gzipped/
3.4.4. Usuwanie plików i katalogów
Zbędne plik i katalogi możemy usunąć, za pomocą polecenia rm. Polecenie do usunięcia katalogu wymaga podania nazwy pliku jako argumentu.
[root@server1 ~]# rm plik1 rm: remove regular empty file 'plik1'? y
Polecenie rm również jest aliasem, z tą samą opcją co cp czy mv. Aby usunąć cały katalog wraz podkatalogami, należy użyć kolejno opcji -r - uruchamiającej usuwanie rekurencjne oraz opcji -f, wymuszające odpowiedź y na wszystkie pytania.
[root@server1 ~]# rm -rf /tmp/etc
Usuwanie plików i katalogów posiadając uprawnienia superużytkownika, może skończyć się katastrofą. Pomyłka w tym poleceniu może uszkodzić system. Dlatego też należy zachować szczególną ostrożność przy korzystaniu z tego polecenia, a w szcególności w połączeniu z nazwami wieloznacznymi (będzie o tym przy okazji omawiania powłoki BASH).
Do usuwania pustych katalogów, możemy użyć polecenia rmdir, jak i opcji -d polecenia rm.
[root@server1 ~]# rm -d dir1/ rm: remove directory 'dir1/'? y [root@server1 ~]# rmdir dir2
Odnośnie egzaminu:
Polecenia manipulacji plikami są podstawowymi czynnościami związnymi
z administracją każdego Uniksa, więc warto przyswoić wiedzę zebraną
w tym podrozdziale.
3.5. Dowiązania
Wśród systemów uniksowych, możemy w kategoriach manipulacji plikami wyróżnić takie elementy jak dowiązania. Dowiązania są najprościej rzecz biorąc są elementami, które wskazują na inne pliki. Dowiązania możemy podzielić na twarde oraz symboliczne.
3.5.1. Dowiązania twarde
Twarde dowiązania nie są same w sobie stricte plikami. Pliki bowiem znajdują na urządzeniach służacych do przechowywania danych. Systemy plików przechowują metadane plików, ich atrybuty oraz informacje w jakich obszarch, której z pamięci masowych należy szukać zawartości pliku, aby ludzie mogli się nimi posługiwać używa się nazw plików. Taką własnie nazwą jest twarde dowiązanie. Dla eksperymentu utworzymy pusty plik, o nazwie hard1, oto jego artybuty
[root@server1 ~]# ls -li hard1 6043841 -rw-r--r--. 1 root root 0 Jun 19 17:31 hard1
Pierwsza kolumna zawiera numer i-node jest to
identyfikator
wpisu w bazie danych systemu plików, ktory zawiera metadane na
temat pliku. W trzeciej kolumnie atrybutów znajduje się wartość
1
. Ta kolumna przedstawia ilość
dowiązań twardych. Każdy zwykły plik posiada co najmniej jedno
dowiązanie - identyfikującą bezpośrednio plik nazwę. Tworząc kolejne
twarde dowiązanie, podłączamy kolejną nazwę tego pliku. Teraz utwórzmy
dowiązanie o nazwie hard2 do pliku hard1. Dowiązania
tworzymy za pomocą polecenia ln.
[root@server1 ~]# ln hard1 hard2 [root@server1 ~]# ls -li hard* 6043841 -rw-r--r--. 2 root root 0 Jun 19 17:31 hard1 6043841 -rw-r--r--. 2 root root 0 Jun 19 17:31 hard2
Zwróć my uwagę na to, iż hard2
wskazuje na ten sam numer i-node, czyli wskazuje na ten sam
pliki. Liczba dowiązań uległa zmianie tak samo w przypadku
hard1
jak i
hard2
, ponieważ na ten sam plik
wskazują dwa dowiązania. Zawartość pliku możemy zmieniać odwołując
czy to do hard1 czy hard2, tak samo jest
z atrybutami, ponieważ obie nazwy wskazują na ten sam węzeł
i-node (wpis w bazie danych systemu plików), jeśli usuń my
teraz plik hard1, to tak naprawdę usuniemy jedno z dowiązań.
[root@server1 ~]# rm hard1 rm: remove regular empty file 'hard1'? y [root@server1 ~]# ls -li hard* 6043841 -rw-r--r--. 1 root root 0 Jun 19 17:31 hard2
Dowiązania twarde mogą powodować bałagan w plikach, ponieważ mimo usunięcia on dalej istnieje pod inną nazwą. Dopiero usunięcie wszystkich dowiązań, ostatecznie kończy egzystencje pliku w pamięci masowej, ponieważ systemy plików, pliki bez dowiązań uznają za nie potrzebne i realokują miejsce przechowania zawartości tego pliku.
3.5.2. Dowiązania symboliczne
Innym rodzajem dowiązań jest dowiązanie symboliczne. Często są one porównywane do skrótów znanych z systemów Windows i tak na prawdę taka jest ich rola. Dowiązania symboliczne mają wskazywać na inne pliki. W przeciwieństwie do dowiązań twardych, te dowiązania są jednak odrębnymi plikami (tak jakby), posiadają one bowiem wpis w bazie danych systemu plików, ale w miejscu przeznaczonym na adres przechowywania danych pliku na dysku lub innej pamięci znajduje się scieżka do pliku źródłowego, na który wskazuje dowiązanie. Zatem tego rodzaju elementy mają własne atrybuty. Wielkość dowiązania symbolicznego zależy od ilość znaków na ścieżce do pliku źródłowego. Dowiązania symboliczne tworzymy za pomocą tego samego narzędzia co dowiązania twarde, dodając tylko opcję -s.
[user@server1 ~]$ ln -s symfile symlink1 [user@server1 ~]$ ls -l symlink1 lrwxrwxrwx. 1 user user 7 Jun 20 19:28 symlink1 -> symfile
Dowiązania symboliczne mogłoby wydawać się, że są w wstanie zastąpić kopiowanie. Kopiując plik, odwzrowywuje się jego zawartość w innym miejscu na pamięci masowej, tworząc odrębny nienaruszony plik. Tworząc dowiązanie, podłączamy się pod istniejący już plik, który może być zmieniony nie tylko przez użytkowników, ale też programy. Dowiązania symbolicznego możemy użyć jak wymienionego wcześniej skrótu, chcąc zaoszczędzić sobie pisania długich ścieżek do głęboko osadzonych katalogów w systemie ewentualnie ułatwić pisanie ścieżek w skryptach oraz programach.
Przechodząc do folderu wskazywanego przez dowiązanie symboliczne jeśli wyświetlimy scieżkę obecnego katalogu roboczego, zobaczymy ścieżkę z uwzględeniem tego dowiązania. Aby odkryć prawdziwą ścieżkę należy polecenia pwd z opcją -P.
Ćwiczenie 1: Archiwa
Na maszynie server1 jako superużytkownik, utwórz skompresowane za pomocą programu gzip archiwum z zawartością katalogu /etc. Powtórz czynność tym razem z użyciem programu bzip2. Porównaj wielkość tych archiwów. Na koniec rozpakuj oba archiwa bez zaznaczania algorytmu kompresji (bez podawania odpowiedniej opcji).
Ćwiczenie 2: Praktyka z Vim-a
Na maszynie server1 jako zwykły użytkownik, utworz przepisując treść ćwiczenia nr. 1, każde zdanie w odrębnej linii, zapisz zmiany w pliku o nazwie vimpractice i zamknij edytor. Otwórz plik w edytorze ponownie, wyświetl numery linii. Skopiuj linię 2 i 3 na koniec pliku, tak aby było łącznie 6 linii. Przenieś linię nr. 3 w miejsce pierwszej. Przejdź na koniec pliku i dodaj do niego zawartośc w pliku .bash_profile (znajdziesz go w katalogu domowym użytkownika). Zamień wszystkie wszystkie wystąpienia słowa profile na pro file. Usuń linię od 5 do 8, zapisz zmiany w pliku i opuść edytor. Na koniec wyświetl podsumowanie pliku za pomocą polecenia wc.
Ćwiczenia 3: Manipulacja plikami
Na maszynie server1 jako zwykły użytkownik, utwórz jeden dowolny plik oraz jeden katalog, wyświetl ich atrybuty, sprawdź uprawnienia, nazwę właściciela oraz grupę do której ten plik należy. Co się stanie gdy spróbujesz przenieść utworzony wcześniej plik do katalogu /var/log. Przenieś plik oraz katalog do katalogu /tmp. Utwórz duplikat pliku i zmień jego nazwę na jakąkolwiek inną. Usuń wszystkie pliki utworzone na potrzeby tego ćwiczenia.
Podsumowanie
W tym rozdziale zapoznaliśmy się, z typowymi zadaniami związanymi z administracją plikami w systemie. Poznaliśmy edytor Vim, którego nauka wymaga zachodu, aczkolwiek nie pójdzie ona na marne. Ten edytor w uboższej podstawowej wersji w postaci programu Vi spotkamy w każdym Uniksie, zatem będzie potrafili sprawnie edytować pliki w każdym systemie, niezależnie od tego czy nasz ulubiony edytor jest dostępny. Ciekawszą rzeczą w tym rodziale z pewnością były dowiązania symboliczne. W następnym rodziale skupimy się na uprawnieniach plików i katalogów, oraz przekonamy się jak potężnym narzędziem jest polecenie find.
4. Zaawansowane zarządzanie plikami
W Uniksach możemy zabezpieczyć pliki i katalogi przed ingerencją innych użytkowników. Służą temu specjalny rodzaj zabezpieczeń jakim są uprawnienia.
4.1. Uprawnienia podstawowe
Uprawnienia przypisywane są w trzech klasach, klasie użytkownika (u) nazwywanego również właścicielem elementu; grupie (g), do której należy ten plik oraz oraz innym użytkownikom systemu (o), ta klasa uprawnień jest również oznaczna jako uprawnienia publiczne.
Każdej z tych klas możemy przypisać odpowiednie uprawnienia takie jak: prawo do odczytu (r), prawo do zapisu (w) oraz prawo do wykonania (x).
Za nim zaczniemy zmieniać uprawnienia, nauczymy się je identyfikować. Uprawnienia do pliku możemy wyświetlić za pomocą polecenia ls -l lub polecenia stat.
[user@server1 ~]$ ls -l file1 -rw-r--r--. 1 user user 0 Jun 21 14:21 file1
Uprawnienia znajdują się w pierwszej kolumnie:
-rw-r--r--.
, łącznie 11 znaków, ale
nas będzie interesować tylko 9 w środku. Pierwszy znak oznacza typ
pliku, natomiast kropka związana jest z kontekstem SELinux,
nie będziemy się teraz tym zajmować. Te dziewięć pól są to miejsca
przeznaczone na uprawnienia poszczególnych klas. Pierwsze trzy pola
z lewej to uprawnienia użytkownika (właściciela), kolejne trzy pola
to uprawnienia grupy do której należy ten plik natomiast pozostałe
trzy to uprawnienia publiczne, stosowane wobec użytkowników nie
związanych z tym elementem. Uprawnienia przypisane każdej z klas
układają się kolejno w rwx, myślnik na którymś z tych miejsce
oznacza brak takiego prawa w danej klasie.
Każde z określonych praw pozwala nam, na wykonanie innych czynności związanych z tym elementem. Prawo read pozwala na odczyt zawartości pliku oraz jego skopiowanie, w przypadku katalogów pozwala na wyświetlenie jego zawartości. Prawo write pozwala na modyfikowanie elementu, wraz z jego usunięciem. Ostatnie prawo execute pozwala na uruchomienie pliku o ile jest to plik wykonywalny, w przypadku katalogów to prawo jest niezbędne aby użytkownik mógł przejść do niego (za pomocą polecenia cd).
Zatem w przypadku pliku z powyższego przykładu, właściciel może czytać i pisać, a grupa oraz wszyscy inni mogą tylko czytać, dla nich wówczas ten plik jest plikiem tylko do odczytu.
Prawdopodobnie kiedyś bedziemy chcieli ukryć jakieś pliki lub będziemy musieli dać uprawnienia jednemu z użytkowników do innych plików w systemie, wówczas wymagana będzie zmiana uprawnień.
Poszczególnym klasom (u, g, o) możemy nadać (+), obebrać (-) lub przypisać (=) odpowiednie uprawnienia. Do manipulacji uprawnieniami służy polecenie chmod, jako pierwszy argument przyjmuje on sekwencje zmiany uprawnień (uprawnienia) a jako drugi plik lub katalog, którego mają się tyczyć uprawnienia.
Załóżmy, że plik z powyższego przykładu jest skryptem i musimy nadać użytkownikowi prawo do wykonania, grupie prawo do zapisu i wykonania a pozostałym użytkownikom zabrać uprawnienia, ponieważ ten plik nie powinien być stosowany poza grupą. Aby zrealizować tę zmianę uprawnień należy wydać poniższe polecenie:
[user@server1 ~]$ chmod u+x,g+wx,o-r file1
Po zmianie, uprawnienia do tego pliku prezentują się w następujący sposób:
[user@server1 ~]$ ls -l file1 -rwxrwx---. 1 user user 0 Jun 21 14:21 file1
Zapis uprawnień w tej postaci, który swoją drogą nazwa się zapisem symbolicznym, wymaga dużo pisania. Uprawnienia można zmieniać łatwiej jednak wymagać to będzie więcej myślenia.
Każde z omówionych wcześniej praw posiada swoją wagę, te wagi sumują się dając uprawnienia dla konkretnej klasy. A więc: prawo do odczytu (r) posiada wagę 4, prawo do zapisu (w) posiada wagę 2 a prawo do wykonania (x) posiada wagę 1. Brak prawa (-) ma wagę 0. Tak złożone razem sumy tych wag dają uprawnienia do pliku czy katalogu. Chcąc określić uprawnienia pliku z pierwszego przykładu jescze przed zmianą uprawnień, będą one wynosić: 644.
[user@server1 ~]$ ls -l file1 -rw-r--r--. 1 user user 0 Jun 21 14:21 file1 ---------------------------------------------- u = rw- = 4 + 2 + 0 = 6 g = r-- = 4 + 0 + 0 = 4 o = r-- = 4 + 0 + 0 = 4 ugo = 644
Natomiast uprawnienia po zmianie bedą wynosić:
[user@server1 ~]$ ls -l file1 -rwxrwx---. 1 user user 0 Jun 21 14:21 file1 ---------------------------------------------- u = rwx = 4 + 2 + 1 = 7 g = rwx = 4 + 2 + 1 = 7 o = --- = 0 + 0 + 0 = 0 ugo = 770
W ten sposób przeliczonymi uprawnieniami (tzw. uprawnieniami bezwględnymi, ponieważ przypisują one uprawnienia każdej z klas) możemy posługiwać się podczas ich zmiany przy użyciu polecenia chmod
[user@server1 ~]$ chmod -v 644 file1 mode of 'file1' changed from 0770 (rwxrwx---) to 0644 (rw-r--r--) [user@server1 ~]$ chmod -v 770 file1 mode of 'file1' changed from 0644 (rw-r--r--) to 0770 (rwxrwx---)
Na powyższym przykładzie zastosowałem opcję -v, która wyświetla jak zmieniają się uprawnienia oraz przedstawia je w obu formach. W przypadku wyświetlonej wartości liczbowej, pierwsze zero z lewej strony jest miejscem na uprawnienia specjalne o których będzie za chwilę, w przypadku standardowych uprawnienień nie ma ono znaczenia.
Zapis uprawnień bezwzględnych w zapisie symbolicznym wyglądał by następująco:
[user@server1 ~]$ chmod -v u=rw,g=r,o=r file1 mode of 'file1' changed from 0770 (rwxrwx---) to 0644 (rw-r--r--)
Definiując uprawnienia bezwzględne, posługujemy się cyframi od 0 do 7. Są to wszystkie cyfry systemu liczbowego o podstawie 8 (tzw. ósemkowy lub oktalny) dlatego też często nazwa się takie ustalanie uprawnień trybem oktalnym.
Podczas ustalania uprawnień dla plików lub katalogów, nie ma znaczenia jakiego trybu użyjemy, nie ma lepszego i gorszego. Jest tryb czytelniejszy oraz szybszy do zapisania.
Na koniec jako ciekawostke podam iż istnieje czwarta dodatkowa klasa oznaczająca wszystkie klasy (a), za jej pomocą można nadawać, odbierać i przypisywać takie same uprawnienia dla wszystkich klas.
[user@server1 ~]$ chmod -v a=rwx file1 mode of 'file1' changed from 0644 (rw-r--r--) to 0777 (rwxrwxrwx)
4.1.1. Uprawnienia domyślne
Każdy nowoutworzony plik czy katalog Uniksie ma już z góry przypisane uprawnienia i są nimi 666 dla plików oraz 777 dla katalogów. Uprawnienia te są korygowane za pomocą wartości umask.
Wartość umask (ang. user mask) jest maską uprawnień stosowaną na tworzonych przez użytkowników nowych plikach i katalogach. Każdy użytkownik ma swoją indywidualną maskę i może ją dowolnie zmieniać. Maska ma za zadanie usunięcie tych praw, których nie życzymy sobie widzieć w poszczególnych klasach. Aby wyświetlić maskę użytkownika należy wydać poniższe polecenie:
[user@server1 ~]$ umask 0022
Maska w przypadku RHEL 9 wygląda tak jak na powyszym przykładzie. Ta wartość usunie z klasy grupy oraz z klasy pozostałych użytkowników prawo do zapisu. Rachunek uprawnień jest bardzo prosty.
#W przypadku plików: 0666 0022 - ------ 0644 #W przypadku katalogów: 0777 0022 - ------ 0755
Chcąc zmienić maskę wystarczy wydać polecenie:
[user@server1 ~]$ umask 002 [user@server1 ~]$ umask 0002
Tak zdefiniowana maska usunie tylko prawo do zapisu w klasie pozostałych użytkowników dla każdego nowego pliku i katalogu. Maska o tej wartości była domyślną maską dla zwykłych użytkowników w RHEL 8. Wartość maski zdefiniowanej z poziomu wiersza poleceń, utrzyma się tylko przez czas trwania otwartej sesji terminala. Po jego zamknięciu lub wylogowaniu się maska wróci do poprzedniej wartości. Jeśli chcemy aby wartości tej maski została zapisana na stałe, należy umieść polecenie umask w jednym z plików uruchomieniowych powłoki, będzie o tym w dalszej części tego materiału.
4.1.2. Zmiana właściciela oraz grupy pliku
Do zmiany właściciela pliku oraz grupy, do której on należy służy polecenie chown, które przyjmuje jako pierwszy argument trzy możliwe wersje: parę właściciel:grupa; samego właściela lub nazwę grup poprzedzoną dwukropkiem (:) a następnie pliki. Poniższy przykład obrazuje wszystkie trzy możliwe zmiany właściciela oraz grup, do której należy plik.
[root@server1 tmp]# chown user100:user100 acluser [root@server1 tmp]# ls -l acluser -rw-rw-r--. 1 user100 user100 9 Jun 22 18:25 acluser [root@server1 tmp]# chown user acluser [root@server1 tmp]# ls -l acluser -rw-rw-r--. 1 user user100 9 Jun 22 18:25 acluser [root@server1 tmp]# chown :user acluser [root@server1 tmp]# ls -l acluser -rw-rw-r--. 1 user user 9 Jun 22 18:25 acluser
4.2. Uprawnienia specjalne
Poza podstawowym rodzajem uprawnień w Uniksach istnieją dodatkowe uprawnienia, których zadaniem może być podniesienie uprawnień w systemie, zaoszczędzenie czasu lub ochrona przed skasowaniem pliku w miejscach gdzie wszyscy mają uprawnienia zapisu. Teraz omówimy sobie każdy z nich.
4.2.1. Uprawnienia bitu setuid
Każde z podstawowych praw, możemy określić mianej bitu, z uprawnieniami specjalnymi jest podobnie, każde z nich jest kolejnym bitem (prawem) o szczególnym znaczeniu. Tak jest i tym przypadku. Bit setuid służy do podniesienia uprawnień. Jest on oznaczany małą lub wielką literą s w klasie użytkownika/właściciela. Ma on zastosowanie głównie na plikach wykonywalnych. Kiedy uruchomimy program z ustawionym takim bitem, program ten będzie działać z uprawnieniami właściciela tego pliku. Bit ten jest wykorzystywany najczęściej do uruchomienia programu z uprawnieniami root przez zwykłego użytkownika. Takim przykładem może być program su, który służy przełączaniu się miedzy użytkownikami, bez tego bitu przelogowanie nie było by możliwe. Dla eksperymentu możemy usunać ten bit, następnie spróbować jako zwykły użytkownik przelogować na kogoś innego.
[root@server1 ~]# chmod -v u-s /usr/bin/su mode of '/usr/bin/su' changed from 4755 (rwsr-xr-x) to 0755 (rwxr-xr-x) [user@server1 ~]$ su user100 Password: su: Authentication failure
Jak widać przełączanie na użytkownika
user100
nie powiodło się
mimo iż polecenie zapytało o hasło (polecenie su nie pyta o
hasło tylko superużytkownika). Zwróćmy również uwagę na to jak wygląda
bit setuid w oktalnym zapisie uprawnień. Do wskazywania
uprawnień specjalnych wykorzystywana jest nieużywana przy zwykłych
uprawnieniach czwarta liczba całkiem z lewej strony. Teraz przywrócimy
setuid temu programowi.
[root@server1 ~]# chmod -v +4000 /usr/bin/su mode of '/usr/bin/su' changed from 0755 (rwxr-xr-x) to 4755 (rwsr-xr-x) [user@server1 ~]$ su user100 Password: [user100@server1 user]$
Podczas przywracania uprawnień, nie naruszyłem tych podstawowych
używając wartości +4000
, nie
potrzeba wskazywać klasy, ponieważ program sam wie, że ten bit należy
nadać w klasie właściciela.
Czasami bit setuid może występować w postaci wielkiej litery S, oznacza to tyle iż w klasie właściciela nie występuje prawo do wykonywania (bit x).
4.2.2. Uprawnienia bitu setgid
Zastosowania bitu setgid, mogą być dwa jedno podobne do bitu setuid, ale tyczące się grupy, drugie zaś dotyczy się katalogów współdzielonych. Bit setgit oznaczany jest małą lub wielką literą s w klasie grupy.
Kiedy katalog posiada ustawiony bit setgid, to grupa, która jest właścicielem takiego katalogu będzie przypisywana jako grupa każdemu nowemu elementowi utworzonemu w tym katalogu.
[user2000@server1 sdir]$ ls -ld /sdir drwxrws--T. 3 root sgrp2 65 Jun 21 17:31 /sdir [user2000@server1 sdir]$ mkdir user2000dir [user2000@server1 sdir]$ ls -l total 4 -rw-rw-r--. 1 user1000 sgrp2 5 Jun 20 16:00 user1000file drwxrwsr-x. 2 user2000 sgrp2 6 Jun 21 17:30 user2000dir [user2000@server1 sdir]$ touch user2000file [user2000@server1 sdir]$ ls -l total 4 -rw-rw-r--. 1 user1000 sgrp2 5 Jun 20 16:00 user1000file drwxrwsr-x. 2 user2000 sgrp2 6 Jun 21 17:30 user2000dir -rw-rw-r--. 1 user2000 sgrp2 0 Jun 21 17:31 user2000file
Katalog /sdir jest własnością grupy sgrp2 oraz posiada ustawiowiony bit setgid (bit s w miejscu x w klasie grupy). Utworzyłem katalog oraz plik, oba elementy odziedziczyły grupę sgrp2 właśnie dzięki tym uprawnieniom. Zwróćmy uwagę również na fakt iż nowoutworzony katalog odziedziczył również bit setgid. Tego typu funkcjonalność możemy wykorzystać tworząc katalogi do pracy grupowej, aby zaoszczędzić użytkownikom grupy zmianę uprawnień przy każdym nowym pliku lub podkatalogu w tego typu folderach.
Innym przykładem jest wykorzystanie pliku wykonywalnego z ustawionym bitem setgid. Weźmy pod lupe taki plik jak program write, ten program służy do przesyłania wiadomości między użytkownikami (między terminalami).
[user@server1 ~]$ ls -l /usr/bin/write -rwxr-sr-x. 1 root tty 24472 Feb 24 11:25 /usr/bin/write
Posiada on bit setgid, którym pozwoli mu w tym przypadku skorzystać z uprawnień grupy na plikach urządzeń. Pierwsza konsola wirtualna w systemie:
[user@server1 ~]$ ls -l /dev/tty0 crw--w----. 1 root tty 4, 0 Jun 21 15:13 /dev/tty0
Grupa tty posiada prawo do zapisu na tym urządzeniu. Sprawdźmy jeszcze pierwsze urządzenie pseudoterminala (okno programu Terminal lub połączenie przez SSH).
[user@server1 ~]$ ls -l /dev/pts/0 crw--w----. 1 user tty 136, 0 Jun 21 17:51 /dev/pts/0
Tutaj grupa również posiada prawo zapisu. Usuwanie i przypisywanie tego bitu jest analogiczne do bitu setuid, wymaga tylko zmiany kilku wartości
[root@server1 ~]# chmod -v g-s /usr/bin/write mode of '/usr/bin/write' changed from 2755 (rwxr-sr-x) to 0755 (rwxr-xr-x) [root@server1 ~]# chmod -v +2000 /usr/bin/write mode of '/usr/bin/write' changed from 0755 (rwxr-xr-x) to 2755 (rwxr-sr-x)
Przeglądając atrybuty plików i katalogów możemy natknąć sie na bit setgid zapisany wielką literą, jest to ten sam bit, tylko że w klasie grupy brakuje prawa do wykonania (bitu x).
4.2.3. Uprawnienia bitu sticky
Bit sticky ma za zadanie zabezpieczyć pliki i katalogi przed nieuprawnionym usunięciem w ogólodostępnych katalogach (tam gdzie wszyscy mają prawo do zapisu). Jeśli katalog ma ustawiony taki bit, to wówczas tylko właściciel pliku bądź podkatalogu będzie mógł go usunąć. Bit sticky oznaczany jest za pomocą małej lub wielkiej litery t w klasie publicznej (pozostałych użytkowników).
Usunięcie lub przypisanie tego bitu może odbywać się tak jak w przypadku poprzednich bitów.
[root@server1 ~]# chmod -v -o-t /sdir mode of '/sdir' changed from 3770 (rwxrws--T) to 2770 (rwxrws---) [root@server1 ~]# chmod -v +1000 /sdir mode of '/sdir' changed from 2770 (rwxrws---) to 3770 (rwxrws--T)
Tutaj zwróćmy uwagę na to, iż bit sticky jest zapisany wielką literą, otóż działanie tego bitu się nie zmienia, jest jedynie informacja, że klasie publicznej brakuje prawa do wykonania (x). Wszystkie bity specjalne umieszczane w poszczególnych klasach, rezydują w miejscu prawa do wykonywania.
4.3. Polecenie find
Polecenie find, jak sama nazwa wskazuje służy do wyszukiwania plików i katalogów. Najczęściej jest ono wykorzystywane przez użytkowników w podstawowym zakresie, zwracając gigantyczną ilość danych. Często korzystając z tego narzędzia nie wykorzystuje się w pełni jego potencjału, który ukrywa się w dużej ilości opcji zawężających wyniki poszukiwania oraz możliwości wykonania akcji w wyszukanych plikach.
Najprostszy sposób na użycie polecenia find znajduje się poniżej:
[root@server1 user]# find / -name network /run/systemd/network /tmp/gzipped/etc/sysconfig/network /tmp/gzipped/etc/vmware-tools/scripts/vmware/network /etc/sysconfig/network /etc/vmware-tools/scripts/vmware/network /root/bzipped/etc/sysconfig/network /root/bzipped/etc/vmware-tools/scripts/vmware/network /usr/lib/systemd/network
Polecenie przeszukało cały główny system plików pod kątem plików
o nazwie network
. Sama opcja
-name
jest zawężeniem wyników
wyszukiwania, bez tej opcji polecenie zwróciłoby wszystkie pliki
znalezione w podanym katalogu czyli w tym przypadku minimum kilka
tysięcy.
Poniżej zamieszczam najważniejsze opcje służące do bardziej szczegółowego wyszukiwania plików.
- -iname - wyszukuje pliki o nazwie podanej jako
argument tej opcji, ignorując przy tym wielkość znaków.
[root@server1 user]# find . -iname do* ./Downloads ./Documents ./.cache/mozilla/firefox/r7fvuapl.default-default/cache2/doomed
- -size - wyszukiwanie plików na podstawie rozmiaru.
Jeśli chcemy aby program znalazł pliki mniejsze niż podana
wartość stawiamy przed nią myślnik (-), a jeśli
większe to plus (+). Poniższy przykład zaprezentuje
wyszukiwanie plików powyżej 1G w moim katalogu domowym:
[xf0r3m@latitude-e5270 ~]$ find ~ -size +1G -exec ls -ldh {} \; -rw-r--r--. 1 xf0r3m xf0r3m 2,1G 06-18 18:12 /home/xf0r3m/Pobrane/Fedora-MATE_Compiz-Live-x86_64-35/Fedora-MATE_Compiz-Live-x86_64-35-1.2.iso -rw-r--r--. 1 xf0r3m xf0r3m 1,4G 06-18 19:44 /home/xf0r3m/Pobrane/Fedora-LXDE-Live-x86_64-35-1.2.iso -rwxr-xr-x. 1 xf0r3m xf0r3m 11G 2017-01-25 /home/xf0r3m/Pobrane/rhel-8.6-x86_64-dvd.iso -rwxr-xr-x. 1 xf0r3m xf0r3m 8,0G 2017-02-11 /home/xf0r3m/Pobrane/rhel-baseos-9.0-x86_64-dvd.iso -rwxr-xr-x. 1 xf0r3m xf0r3m 2,9G 06-21 19:50 /home/xf0r3m/Dokumenty/RHEL9-VM1_21.06.ova -rwxr-xr-x. 1 xf0r3m xf0r3m 2,3G 06-21 19:54 /home/xf0r3m/Dokumenty/RHEL9-VM2_21.06.ova -rwxr-xr-x. 1 xf0r3m xf0r3m 2,6G 06-21 20:00 /home/xf0r3m/Dokumenty/RHEL8-VM1_21.06.ova -rw-------. 1 xf0r3m xf0r3m 6,2G 06-22 16:06 '/home/xf0r3m/VirtualBox VMs/RHEL9-VM1/RHEL9-VM1_21.06-disk001.vmdk' -rw-------. 1 xf0r3m xf0r3m 4,8G 06-21 22:26 '/home/xf0r3m/VirtualBox VMs/RHEL9-VM2/RHEL9-VM2_21.06-disk001.vmdk' -rw-------. 1 xf0r3m xf0r3m 6,3G 06-21 22:28 '/home/xf0r3m/VirtualBox VMs/RHEL8-VM1/RHEL8-VM1_21.06-disk001.vmdk'
Opcję-exec
, omówimy pod koniec tego podrozdziału. - -user, -group - wyszukiwanie plików na podstawie
nazwy właściciela oraz grupy do której plik należy. W przykładzie
przedstawie polecenie, które wyszuka wszystkie pliki należące do
użytkownika user, ale i nie należące do grupy sgrp2:
[root@server1 user]# find / -user user -not -group sgrp2 /dev/pts/0 /proc/1688 /proc/1688/task /proc/1688/task/1688 /proc/1688/task/1688/fd /proc/1688/task/1688/fd/0 /proc/1688/task/1688/fd/1 /proc/1688/task/1688/fd/2 ...
Aby zanegować, któreś z kryteriów należy poprzedzić je opcją -not lub wykrzyknikiem (!). - -maxdepth, -mindepth - te opcje wskazują poleceniu
find, jak głęboko w strukturę katalogów ma sięgać polecenie
podczas wyszukiwania (-maxdepth) lub od którego poziomu
podkatalogów ma zacząć wyszukiwanie (-mindepth).
[root@server1 user]# find / -maxdepth 3 -name network /run/systemd/network /etc/sysconfig/network [root@server1 user]# find / -mindepth 4 -name network /tmp/gzipped/etc/sysconfig/network /tmp/gzipped/etc/vmware-tools/scripts/vmware/network /etc/vmware-tools/scripts/vmware/network /root/bzipped/etc/sysconfig/network /root/bzipped/etc/vmware-tools/scripts/vmware/network /usr/lib/systemd/network
Zwróćmy uwagę na to, iż te opcje są opcjami globalnymi, nie mają bezpośredniego wpływu na wyszukiwanie, dlatego też należy je umieszczać przed opcjami mającymi zawęzić kryteria. - -type - wyszukiwanie na podstawie typu
plików. Poniższy przykład pokazuje również jak zapisać różne
wartości przy jednej opcji:
[root@server1 user]# find / -type p,s -exec ls -ld {} \; srwxr-xr-x. 1 chrony chrony 0 Jun 22 2022 /run/chrony/chronyd.sock srwxr-xr-x. 1 root root 0 Jun 22 2022 /run/mcelog-client srw-rw-rw-. 1 root root 0 Jun 22 2022 /run/.heim_org.h5l.kcm-socket srw-rw-rw-. 1 root root 0 Jun 22 2022 /run/avahi-daemon/socket srw-rw-rw-. 1 root root 0 Jun 22 2022 /run/lsm/ipc/simc srw-rw-rw-. 1 root root 0 Jun 22 2022 /run/lsm/ipc/sim srw-rw-rw-. 1 root root 0 Jun 22 2022 /run/cups/cups.sock prw-------. 1 root root 0 Jun 22 2022 /run/initctl prw-------. 1 root root 0 Jun 22 2022 /run/dmeventd-client prw-------. 1 root root 0 Jun 22 2022 /run/dmeventd-server
Polecenie wyszukuje w systemie wszystkie gniazda i nazwane potoki (typy plików, nieomawiane w tym materiale). Jak widać inną wartość dla tej opcji należy podać po przecinku. - -mtime, -mmin - wyszukiwanie pliku na podstawie
ilości czasu upłyniętego od daty ostatniej modyfikacji, z czego
opcja -mtime przyjmuje wartości w liczbie dni, która upłynęła
od ostatniej modyfikacji, a -mmin w minutach.
[xf0r3m@latitude-e5270 ~]$ find ~ -maxdepth 2 -mtime -7 /home/xf0r3m /home/xf0r3m/.mozilla/firefox /home/xf0r3m/.local/share /home/xf0r3m/Pobrane /home/xf0r3m/Pobrane/Fedora-MATE_Compiz-Live-x86_64-35.torrent /home/xf0r3m/Pobrane/Fedora-MATE_Compiz-Live-x86_64-35 /home/xf0r3m/Pobrane/Fedora-LXDE-Live-x86_64-35.torrent /home/xf0r3m/Pobrane/Fedora-LXDE-Live-x86_64-35-1.2.iso /home/xf0r3m/Pobrane/Fedora-Workstation-Live-x86_64-35.torrent [xf0r3m@latitude-e5270 ~]$ find ~ -maxdepth 3 -mmin -360 /home/xf0r3m /home/xf0r3m/.mozilla/firefox /home/xf0r3m/.mozilla/firefox/qlw3f0ci.default-default /home/xf0r3m/.local/share /home/xf0r3m/.local/share/gnome-shell /home/xf0r3m/.local/share/gvfs-metadata /home/xf0r3m/.local/share/recently-used.xbel /home/xf0r3m/.local/share/ranger /home/xf0r3m/.local/state/wireplumber /home/xf0r3m/Dokumenty/docs/.git /home/xf0r3m/Dokumenty/docs/angielski
Powyższe polecenia przedstawiają pliki, które były modyfikowane w przeciągu ostatnich 7 dni, oraz ostatnich 6 godzin. Użyłem tutaj również modyfikatorów głębokości. - -perm - wyszukiwanie plików na podstawie uprawnień.
Chcąc wyszukać pliki po konkretnych uprawnieniach pliku, podajemy je w
wersji oktalnej po opcji. Możemy również skorzystać z innych opcji
wprowadzania
uprawnień: uprawnienień minimalnych podanych po myślniku
(-), wówczas każdy z podanych tam praw będzie musiało
wystąpić w danej klasie lub uprawnień dowolnych podanych po ukośniku
(/), wówczas przypasowany zostanie plik, który będzie
posiadać, minimum jedno z praw, z minimum jednej klasy.
[root@server1 user]# find / -perm 111 -exec ls -ld {} \; ---x--x--x. 1 root root 87168 Aug 26 2021 /usr/bin/sudoreplay [root@server1 user]# find /dev -type c -perm -222 -exec ls -ld {} \; crw-rw-rw-. 1 root kvm 10, 241 Jun 22 2022 /dev/vhost-vsock crw-rw-rw-. 1 root kvm 10, 238 Jun 22 2022 /dev/vhost-net crw-rw-rw-. 1 root root 10, 196 Jun 22 2022 /dev/vfio/vfio crw-rw-rw-. 1 root root 10, 200 Jun 22 2022 /dev/net/tun crw-rw-rw-. 1 root render 226, 128 Jun 22 2022 /dev/dri/renderD128 crw-rw-rw-. 1 root root 10, 229 Jun 22 2022 /dev/fuse crw-rw-rw-. 1 root tty 5, 2 Jun 22 17:28 /dev/ptmx crw-rw-rw-. 1 root tty 5, 0 Jun 22 2022 /dev/tty crw-rw-rw-. 1 root root 1, 9 Jun 22 2022 /dev/urandom crw-rw-rw-. 1 root root 1, 8 Jun 22 2022 /dev/random crw-rw-rw-. 1 root root 1, 7 Jun 22 2022 /dev/full crw-rw-rw-. 1 root root 1, 5 Jun 22 2022 /dev/zero crw-rw-rw-. 1 root root 1, 3 Jun 22 2022 /dev/null [root@server1 user]# find /dev -type c -perm /222 -exec ls -ld {} \; crw-rw----. 1 root dialout 4, 64 Jun 22 17:30 /dev/ttyS0 crw-rw-rw-. 1 root tty 5, 2 Jun 22 17:30 /dev/ptmx crw-r--r--. 1 root root 10, 235 Jun 22 17:30 /dev/autofs
Powyżej przedstawiłem wymienione sposoby na zapis uprawnień w przy opcji -perm. Tej opcji możemy również przekazać uprawnienia w postaci symbolicznej na przykład:[root@server1 user]# find /usr -perm -u=s -exec ls -ld {} \; -rwsr-xr-x. 1 root root 36880 Feb 16 15:46 /usr/bin/fusermount3 -rwsr-xr-x. 1 root root 74880 Dec 3 2021 /usr/bin/chage -rwsr-xr-x. 1 root root 78744 Dec 3 2021 /usr/bin/gpasswd -rwsr-xr-x. 1 root root 42448 Dec 3 2021 /usr/bin/newgrp -rwsr-xr-x. 1 root root 36872 Jan 12 18:21 /usr/bin/fusermount -rwsr-xr-x. 1 root root 49152 Feb 24 11:25 /usr/bin/mount -rwsr-xr-x. 1 root root 36784 Feb 24 11:25 /usr/bin/umount -rwsr-xr-x. 1 root root 57616 Feb 24 11:25 /usr/bin/su -rwsr-xr-x. 1 root root 32608 Mar 11 16:34 /usr/bin/pkexec -rwsr-xr-x. 1 root root 53704 Aug 9 2021 /usr/bin/crontab -rwsr-xr-x. 1 root root 32648 Aug 10 2021 /usr/bin/passwd ---s--x--x. 1 root root 185456 Aug 26 2021 /usr/bin/sudo -rwsr-xr-x. 1 root root 16240 Oct 15 2021 /usr/bin/vmware-user-suid-wrapper -rws--x--x. 1 root root 32712 Feb 24 11:25 /usr/bin/chfn -rws--x--x. 1 root root 24464 Feb 24 11:25 /usr/bin/chsh -rwsr-xr-x. 1 root root 57920 Aug 9 2021 /usr/bin/at -rwsr-xr-x. 1 root root 16128 Dec 2 2021 /usr/sbin/pam_timestamp_check -rwsr-xr-x. 1 root root 24544 Dec 2 2021 /usr/sbin/unix_chkpwd -rwsr-xr-x. 1 root root 15608 Mar 10 18:18 /usr/sbin/grub2-set-bootflag -rws--x--x. 1 root root 45232 Dec 9 2021 /usr/sbin/userhelper -rwsr-xr-x. 1 root root 20416 Mar 11 16:34 /usr/lib/polkit-1/polkit-agent-helper-1 -rwsr-x---. 1 root sssd 119512 Jan 17 20:47 /usr/libexec/sssd/krb5_child -rwsr-x---. 1 root sssd 53240 Jan 17 20:47 /usr/libexec/sssd/ldap_child -rwsr-x---. 1 root sssd 28536 Jan 17 20:47 /usr/libexec/sssd/proxy_child -rwsr-x---. 1 root sssd 32656 Jan 17 20:47 /usr/libexec/sssd/selinux_child -rwsr-x---. 1 root dbus 36848 Aug 9 2021 /usr/libexec/dbus-1/dbus-daemon-launch-helper -rwsr-xr-x. 1 root root 16104 Feb 10 11:13 /usr/libexec/Xorg.wrap -rwsr-x---. 1 root cockpit-wsinstance 57600 Mar 3 13:28 /usr/libexec/cockpit-session
Powyższe polecenie szuka wszystkich programów z ustawionym bitem setuid.
4.3.1. Opcje akcji polecenia find
Na powyższych przykładach stosowałem wielkrotnie dodatkową opcję -exec. Jest to opcja akcji podejmowana na pliku gdy tylko zostanie znaleziony. Składania opcji -exec może wyglądać następująco:
$ find ... -exec ls -ld {} \;
Po opcji -exec podajemy zwykłe polecenie, tak jak gdybyśmy
wpisywali je do wiersza polecenia. Odniesieniu do znalezionego pliku
służy zapisana para nawiasów klamrowych
{}
każde polecenie wydawane za pomocą
opcji -exec czy innej musi zostać za terminowane
zacytowanym średnikiem (\;), ponieważ jest koniec
polecenia wprowadzonego do tej opcji, a nie koniec polecenia
find. Wynik działania przykładowego użycia opcji
-exec znajduje się w przykładach na początku tego
podrozdziału.
Poza poleceniem -exec, istnieją jeszcze dwa polecenia akcji -delete, które usuwa pliki oraz -ok, które różni się tym od -exec, że pyta sie użytkownika czy wykonać podane polecenie na pliku.
Odnośnie egzaminu:
Polecenie find, wydaje się bardzo pomocne, posiada masę opcji
część znich znajduje się tutaj, pozostałe są rozpisane na stronach
podręcznika. Powinniśmy umieć się posługiwać tym narzędziem, zarówno
zaweżać obszar poszukiwania jak i prawidłowo używać opcji
-exec.
4.4. Lista kontroli dostępu
Oprócz klasycznego zestawu uprawnień w Uniksach oraz określenia właściciela i grupy do której należy plik bądź katalog, w RHEL możemy dodatkowo wskazać innych użytkowników oraz grupy i przypisać im uprawnienia nieżależne od tych klasycznych (standardu ugo/rwx). Temu właśnie służy lista kontroli dostępu. Ten mechanizm obsługiwany jest za pomocą dwóch poleceń, pierwszym z nich jest getfacl i służy ono do wypisania listy kontroli dostępu. Stwórzmy w katalogu /tmp plik o nazwie aclfile, następnie wykonajmy polecenie getfacl podając ten plik jako argument.
[user@server1 ~]$ cd /tmp [user@server1 tmp]$ touch acluser [user@server1 tmp]$ getfacl acluser # file: acluser # owner: user # group: user user::rw- group::rw- other::r-- [user@server1 tmp]$ ls -l acluser -rw-rw-r--. 1 user user 9 Jun 22 18:25 acluser
Kiedy plik niema zdefiniowanych żadnych dodatkowych użytkowników oraz grup, jego lista kontroli dostępu jest równoznaczna z klasycznymi uprawnieniami Uniksa i te listy oznaczają kolejno właściciela, grupę do której należy ten plik oraz pozostałych użytkowników. Listy kontroli dostępu możemy modyfikować za pomocą polecenia setfacl. Zanim jednak poznamy jak należy modyfikować ACL, poniżej znajduje się lista najważniejszych opcji tego polecenia. Są one dość istotne, ponieważ pozwalają na manipulowanie listami elementu.
- -b - usuwa wszystkie listy dostępowe,
- -d - ustawia listy jako domyślne,
- -k - usuwa wszystkie listy domyślne,
- -m - modyfikuje lub ustawia listy,
- -n - chroni przed automatycznym przeliczaniem maski,
- -R - ustawia listy rekurencyjnie, listy katalogu są stosowane na elementy w nim zawarte,
- -x - usuwa pojedynczą listę.
Listy kontroli możemy zastoswać dla trzech podmiotów:
- użytkownika:
u[ser]:nazwa/uid:uprawnienia
- grupy:
g[roup]:nazwa/gid:uprawnienia
- innych:
o[ther]:uprawnienia
To co zostało ujęte w nawiasach kwadratowych, jest zapisem opcjonalnym. Identyfikator podmiotu możemy zapisać albo za pomocą numerów UID oraz GID, lub za pomocą nazw. Jeśli nazwa lub UID/GID zostaną pominiete to listy user oraz group będą tyczyć się właściciela oraz grupy, do której należy dany element. Uprawnienia mogą być podane za pomocą symboli lub sumy wag dla pojedynczej klasy. Ustawię teraz listę dla jednego z użytkowników w systemie.
[user@server1 tmp]$ setfacl -m u:user100:rw acluser [user@server1 tmp]$ ls -l acluser -rw-rw-r--+ 1 user user 9 Jun 22 18:25 acluser
Pierwsze polecenie ustawia prawo do czytania oraz pisania użytkownikowi
user100
za pomocą list dostępu.
Wyświetliłem szczegóły pliku. Zwróćmy uwagę na to, iż kropka na końcu
uprawnień została zastąpiona plusem (+), taki zapis
informuje użytkowników, że uprawnienia tego pliku są rozszerzone za
pomocą ACL. Teraz przyjrzymy sie jak wyglądają listy pliku:
[user@server1 tmp]$ getfacl -c acluser user::rw- user:user100:rw- group::rw- mask::rw- other::r--
W tym przykładzie użyłem opcji -c, która nie wyświetla
wcześniej pokazywanego nagłówka. Nie jest on nam potrzebny. Nowy wpis
pojawia się pod wpisem właśiciela. Mówi on wprost, że użytkownik
user100
posiada prawo do czytania oraz
modyfikowania pliku acluser
, mimo iż
na podstawie klasycznych uprawnień oraz praw własności nie jest on
nijak związany z tym plikiem.
Poza uprawnienia dla użytkownika pojawi się wpis oznaczony słowem
mask
. Jest to maska list kontroli
i wyznacza ona maksymalne uprawnienia jakie można dać danemu
podmiotowi. Przy każdej zmianie list kontroli dostosowuje się ona do
najwyższych uprawnień na liście. Dodam teraz drugiego użytkownika z
wyższymi od user100 uprawnieniami, bedziemy mogli wówczas
zaobserowować jak zmienia się maska.
[user@server1 tmp]$ setfacl -m u:user200:7 acluser [user@server1 tmp]$ getfacl -c acluser user::rw- user:user100:rw- user:user200:rwx group::rw- mask::rwx other::r--
Maska została ponownie przeliczona i wskazuje teraz uprawnienia o sumie wag równej 7 (rwx). Teraz wymuszę inną wartość dla maski:
[user@server1 tmp]$ setfacl -m m:4 acluser [user@server1 tmp]$ getfacl -c acluser user::rw- user:user100:rw- #effective:r-- user:user200:rwx #effective:r-- group::rw- #effective:r-- mask::r-- other::r--
Na powyższym przykładzie za pomocą selektora (u: - user, itd.)
m:
wskazuje uprawnienia dla maski
ACL.
Teraz przy zdefiniowanych przez nas listach użytkowników, pojawił się
komentarz #effective:r--
. Oznacza to,
iż uprawnienia zostały zmniejszone ponieważ, przekraczają nałożoną na
plik maskę list kontroli. Zrócmy uwagę, ze to ograniczenie
uprawnień maską dotknęło grupę, do której należy plik. Aby wyłączyć
automatyczne przeliczanie maski, należy użyć opcji -n. Usunę
teraz
jedną z list, aby zaprezentować jak można to zrobić kiedy listy dla
poszczególnych użytkowników nie będą nam potrzebne:
[user@server1 tmp]$ getfacl -c acluser user::rw- user:user100:rw- user:user200:rwx group::r-- mask::rwx other::r-- [user@server1 tmp]$ setfacl -x u:user200 acluser [user@server1 tmp]$ getfacl -c acluser user::rw- user:user100:rw- group::r-- mask::rw- other::r--
Teraz oczyszcze plik z list, ponieważ nie są nam już one potrzebne.
[user@server1 tmp]$ setfacl -b acluser [user@server1 tmp]$ getfacl -c acluser user::rw- group::r-- other::r--
Po usunięciu list z tak rygorystczną maską możemy zaobserwować, że zostały zmodyfikowane uprawnienia grupy. Przed usunięciem list należy ustawić maskę aby odzworowywała wcześniejsze uprawnienia.
4.4.1. Domyślne listy kontroli dostępu
Domyślne listy kontroli dostępu są stosowane w udostępnionych katalogach, aby zapewnić spójny zestaw uprawnień dla elementów w nim zawartych. Listy kontroli zdefiniowane dla takiego katalogu są dzieczone przez elementy, które się w nim znajdują. Dzięki czemu nie trzeba poprawiać uprawnień przy każdym nowym pliku lub katalogu. Dziedziczenie nieco różni się w przypadku plików i podkatalogów:
- Pliki otrzymują domyślne listy katalogu nadrzędnego jako zwykłe listy kontoli dostępu (access ACL, poznaliśmy je na początku tego podrozdziału).
- Podkatalogi przyjmują od katalogu nadrzędnego zarówno, zwykłe jak i domyślnie listy kontroli.
Domyślnie listy definiuje się tak samo jak zwykłe, jednak robi się to tylko na katalogach za pomocą polecenia setfacl z dodatkową opcją -d. Utworzę teraz podkatalog o nazwie projekty w katalogu /tmp, następnie nadam mu dwie domyślnie listy dając dwóm użytkownikom systemu pełne uprawnienia do niego.
[user@server1 tmp]$ mkdir projekt [user@server1 tmp]$ setfacl -dm u:user100:7,u:user200:7 projekt/ [user@server1 tmp]$ getfacl -c projekt/ user::rwx group::r-x other::r-x default:user::rwx default:user:user100:rwx default:user:user200:rwx default:group::r-x default:mask::rwx default:other::r-x
Następnie utworzę plik o nazwie zalozenia_projektu.txt, poniżej znajdują sie jego szczegóły:
[user@server1 projekt]$ touch zalozenia_projektu.txt [user@server1 projekt]$ ls -l total 0 -rw-rw-r--+ 1 user user 0 Jun 23 15:56 zalozenia_projektu.txt
Jak widzimy posiada on już jakieś zdefiniowane listy. Są to listy odziedziczone po katalogu nadrzędnym. Oto listy tego pliku:
[user@server1 projekt]$ getfacl -c zalozenia_projektu.txt user::rw- user:user100:rwx #effective:rw- user:user200:rwx #effective:rw- group::r-x #effective:r-- mask::rw- other::r--
Zauważmy, że wpływ na listy mają uprawnienia domyślne elementów (plików i katalogów) oraz wartość umask. Maska ACL przyjmuje wartość najwyższych zdefiniowanych uprawnień, w przypadku plików jest 6 (odczyt oraz zapis). Następnie odziedziczone listy są konfrontowane z maską i zdefiniowane w nich uprawnienia albo pozostają bez zmian, albo ustawiane są tylko te bity występujące na masce, dlatego też efektywne listy kontroli są takie a nie inne. Teraz do zwykłych list katalogu projekty dodam listy dwóch użytkowników dodanych jako listy domyślnie i utworze podkatalog.
[user@server1 tmp]$ setfacl -m u:user100:7,u:user200:7 projekt [user@server1 tmp]$ getfacl -c projekt/ user::rwx user:user100:rwx user:user200:rwx group::r-x mask::rwx other::r-x default:user::rwx default:user:user100:rwx default:user:user200:rwx default:group::r-x default:mask::rwx default:other::r-x [user@server1 tmp]$ cd projekt/ [user@server1 projekt]$ mkdir commonfiles [user@server1 projekt]$ getfacl -c commonfiles/ user::rwx user:user100:rwx user:user200:rwx group::r-x mask::rwx other::r-x default:user::rwx default:user:user100:rwx default:user:user200:rwx default:group::r-x default:mask::rwx default:other::r-x
Jak możemy zauważyć, listy kontroli są identyczne. Teraz dwaj pozostali użytkownicy posiadają możliwości zapisywania oraz odczytywania, w przypadku katalogów i plików stworzonych przeze mnie. Jednak ja jako user będę chciał zapisać coś w plikach innych użytkowników to nie mam takich uprawnień, ponieważ listy dotyczą tylko tych dwóch użytkowników zdefiniowanych na listach.
4.4.2. Dziwny problem z listami kontroli dostępu
Odnośnie egzaminu:
Zapoznając się ze zwykłymi listami dostępu po zdefiniowaniu list o
uprawnieniach
dających pełne prawa jednemu z użytkowników nie mogłem
(jako on) zapisać nic do pliku znajdującego się w katalogu
/tmp za pomocą jakiego kolwiek edytora. Dane
mogłem zapisać natomiast przekierowując strumień na przykład z
polecenia echo. Ten problem zauważyłem w RHEL 9, w
wersji 8.6
nie występował. Problem nie występuje na RHEL 9, gdy plik
odziedziczy listy
od katalogu, a uprawnienia zostaną zmniejszone przez maskę, wówczas
użytkownicy z mogą zapisywać zmiany za pomocą edytorów.
Ćwiczenie 1: Manipulowanie uprawnieniami pliku
Jak zwykły użytkownik na maszynie server1, stwórz dwa pliki file11 oraz dir11. Uruchom polecenie umask aby określić obecną maskę użytkownika. Używając zapisu symbolicznego ustaw maskę użytkownika na wartość 0035. Utwórz plik o nazwie file22 oraz katalog o nazwie dir22 w katalogu domowym. Sprawdź i porównaj uprawnienia plików i katalogów utworzonych na potrzeby tego ćwiczenia. Używając polecenia chmod zmień uprawnienia pliku file11 aby były takie jak uprawnienia pliku file22 oraz zmień uprawnienia katalogu dir22 tak aby identyczne jak uprawnienia folderu dir11. Nie usuwaj jeszcze tych plików.
Ćwiczenie 2: Konfiguracja katalogu do pracy grupowej
Jako superużytkownik na maszynie server1, utwórz katalog /sdir następnie utwórz grupę (groupadd) sgrp oraz dwóch użytkowników user1000 oraz user2000 (useradd). Dodaj tych dwóch użytkowników do wcześniej utworzonej grupy. Ustaw właściela katalogu na użytkownika root oraz sgrp jako grupę do której należy, następnie ustaw odpowiednie uprawnienia: grupa=rwx; inni=--- poza tym ustaw bity setgid oraz sticky. Zaloguj się jako user1000 i utwórz w wyżej wspomnianym katalogu plik, następnie zaloguj się jako user2000 dokonaj zmian w utworzonym przez user1000 pliku. Na koniec spróbuj go usunąć. Zapisanie zmian powinno się zakończyć się sukcesem, ale próba usunięcia już nie.
Ćwiczenie 3: Wyszukiwanie plików
Jako superużytkownik na maszynie server1, wyszukaj wszystkie pliki w całej strukturze katalogu głównego, które zostały zmodyfikowane w ciągu ostatnich 300 minut i wyświetl ich typ. Wyszukaj w całej strukturze katalogu głównego pliki nazwanych potoków oraz gniazd.
Ćwiczenie 4: Zaawansowane wyszukiwanie plików
Jak superużytkownik na maszynie server1, wyszukaj katalogu /usr zwykłe pliki z czasem dostępu starszym niż 100 dni oraz rozmiarem nie przekraczającym 5 MB, których właścicielem jest root.
Ćwiczenie 5: Ustawianie list dostępu
Jako superużytkownik na maszynie server1, utwórz plik testfile w katalogu /tmp. Utwórz uzytkowników user3000 oraz user4000. Stwórz na wszcześniej utworzonym pliku listy kontroli, ustawiając użytkownikowi user2000 uprawnienia równe 7, dla user3000 uprawnienia równe 6, a dla użytkownika user4000 uprawnienia równe 4. Usuń listę użytkownika user2000 i wyświetl pozostałe listy. Następnie oczyść plik z list dostępu oraz sprawdź czy nie pozostały żadne listy.
Podsumowanie
W tej części materiału zapoznaliśmy się z podstawowymi uprawnieniami plików i katalogów, nauczyliśmy się je ustawiać w dwóch różnych formach zapisu. Poznaliśmy uprawnienia specjalne oraz jak je przypisywać. Dowiedzielśmy się jak ważnym narzędziem jest polecenie find. Na koniec poznaliśmy sposób na rozszerzenie uprawnień poza standard ugo/rwx za pomocą list kontroli dostępu. W następnym rozdziale zajmiemy się użytkownikami.
5. Podstawy zarządzania użytkownikami
Użytkownik jest encją, czyli odwzrowaniem rzeczywistego elementu. Obecność użytkowników w systemie ma jeden cel - wyznaczać granice, bowiem każdy z użytkowników posiada swój katalog domowy, w którym przechowuje swoje pliki osobiste oraz programy. W tym rozdziale nauczymy się tworzyć użytkowników oraz modyfikować ich podstawowe informacje, jak np. położenie katalogu domowego czy zmianę numeru UID. Na początku jednak zapoznamy się z metodami sprawdzenia aktywności użytkowników w systemie, prześledzimy ich próby uzyskania dostępu do systemu.
5.1. Kto jest zalogowany do systemu i co robi
Za pomocą polecenia who, możemy sprawdzić kto jest zalogowany w systemie, na jakim terminalu pracuje, o której się zalogował, jeśli jest połączenie zdalne wówczas po czasie zalogowania zobaczymy adres IP w nawiasie. W moim systemie obecnie zalogowanych jest dwóch użytkowników:
[user@server1 ~]$ who root pts/0 2022-06-25 15:06 (192.168.8.192) user pts/1 2022-06-25 15:06 (192.168.8.192)
Innym poleceniem zwracającym bieżącą aktywność użytkowników systemie jest polecenie w. Poniżej znajduje się wynik uruchomienia polecenia na jednym z moich systemów.
user@server1 ~]$ w 15:09:43 up 4 min, 2 users, load average: 0.11, 0.23, 0.12 USER TTY LOGIN@ IDLE JCPU PCPU WHAT root pts/0 15:06 7.00s 0.10s 0.09s /usr/bin/python3 -s /usr/bin/ranger user pts/1 15:06 1.00s 0.00s 0.00s w
Pierwsza linia informacji zwracanych przez to polecenie jest identyczna
z informacjami, które zwraca polecenie uptime. Następnie
zwraca ono tabele z nazwą użytkownika
(USER
), nazwą terminala
(TTY
), czasem zalogowania się
(LOGIN@
), czasem bezczynności
(IDLE
), czasem procesora zużytym na
wykonanie wszystkich zadań po podłączeniu się do terminala wraz z
zadaniami wykonywanymi w tle (JCPU
),
czasem procesora zużytym na wykonanie bieżącego procesu
(PCPU
) oraz nazwę procesu, która jest
obecnie wykonywana (WHAT
).
5.1.1. Monitorowanie prób logowania się do systemu
Monitorując aktywność systemu nie należy zapominać o sprawdzaniu prób zalogowania się do niego. W dystrybucjach Linuksa istnieją trzy polecenia przeznaczone do tego celu. Pierwszym z nich jest polecenie last, które zwraca listę ostatnio zalogowanych użytkowników.
[root@server1 ~]# last user pts/1 192.168.8.192 Sat Jun 25 15:06 still logged in root pts/0 192.168.8.192 Sat Jun 25 15:06 still logged in reboot system boot 5.14.0-70.13.1.e Sat Jun 25 17:05 still running user pts/0 192.168.8.182 Fri Jun 24 14:20 - 17:14 (02:53) reboot system boot 5.14.0-70.13.1.e Fri Jun 24 16:19 - 17:14 (00:54) root pts/1 192.168.8.182 Thu Jun 23 15:54 - 17:27 (01:32) user pts/0 192.168.8.182 Thu Jun 23 14:18 - 17:27 (03:08) user pts/0 192.168.8.182 Thu Jun 23 11:04 - 14:17 (03:13) ...
Polecenie poza tym kto się zalogował, do jakiego terminala, czy
zdalnie czy lokalnie, zwraca również informacje, o której system
został uruchomiony - wpisy rozpoczynające się od
reboot
. Nieścisłości czasowe
wynikają z tego iż, zegar RTC na serwerze ustawiony jest z
uzględniem strefy czasowej oraz zmian czasu lokalnego (powinien
wskazywać na czas UTC), poźniej te dane są skorygowane po
skomunikowaniu się z serwerami czasu. Chcąc wyświetlić tylko listę,
kiedy dokonano startu systemu wydajemy to polecenie z
argumentem reboot, ten argument jest tak naprawdę nazwą
użytkownika.
[root@server1 ~]# last reboot reboot system boot 5.14.0-70.13.1.e Sat Jun 25 15:42 still running reboot system boot 5.14.0-70.13.1.e Sat Jun 25 17:05 - 15:42 (-1:23) reboot system boot 5.14.0-70.13.1.e Fri Jun 24 16:19 - 17:14 (00:54) reboot system boot 5.14.0-70.13.1.e Thu Jun 23 11:23 - 17:27 (06:03) reboot system boot 5.14.0-70.13.1.e Wed Jun 22 17:30 - 00:17 (06:47) reboot system boot 5.14.0-70.13.1.e Tue Jun 21 15:13 - 18:14 (03:00) reboot system boot 5.14.0-70.13.1.e Mon Jun 20 21:11 - 19:47 (-1:23) reboot system boot 5.14.0-70.13.1.e Mon Jun 20 11:54 - 16:18 (04:24) ...
Dane wyświetlane przez to polecenie przechowywane są w pliku /var/log/wtmp.
Alternatywnie do listy ostatnio zalogowanych użytkowników, możemy przejrzeć listę prób logowania się do systemu, które się nie powiodły. Temu służy polecenie lastb.
[root@server1 ~]# lastb user ssh:notty 192.168.8.182 Thu Jun 23 14:18 - 14:18 (00:00) user ssh:notty 192.168.8.182 Thu Jun 23 14:18 - 14:18 (00:00) user1000 pts/0 Tue Jun 21 17:28 - 17:28 (00:00) user ssh:notty 192.168.8.182 Mon Jun 20 19:27 - 19:27 (00:00) user100 pts/1 Mon Jun 20 13:00 - 13:00 (00:00) user ssh:notty 192.168.8.182 Mon Jun 20 10:44 - 10:44 (00:00) root pts/0 Fri Jun 10 17:59 - 17:59 (00:00)
W przypadku połączeń SSH oznaczenie
notty
, mówi nam że nie przydzielono
terminala z powodu niepowodzenia logowania. Kiedy w drugiej kolumnie
zobaczymy oznaczenie pts/X (X oznacza numer urządzenia), to
możemy stwierdzić, że nie powiodło się przełączenie na wskazanego w
pierwszej kolumnie użytkownika. Na serwerach, które mają otwarty port
22 oraz pozwalają na zalogowanie się za pomocą hasła polecenie będzie
zwracać zazwyczaj bardzo długą listę. Wiele automatów na całym świecie
próbuje zalogować się na serwer poprzez zagdywanie użytkownika i hasła.
Plikiem, który przechowuje informacje zwracane przez to polecenie jest /var/log/btmp.
Ostanim narzędziem pozwalającym na sprawdzenie kto logował się do systemu jest polecenie lastlog, wyświetla ono ostatnie logowanie na podstawie listy użytkowników.
[root@server1 ~]# lastlog ... user pts/1 192.168.8.192 Sat Jun 25 15:06:16 +0200 2022 vboxadd **Never logged in** user100 pts/1 Thu Jun 23 15:55:01 +0200 2022 user200 pts/0 Fri Jun 24 16:55:08 +0200 2022 user1000 pts/0 Tue Jun 21 17:28:44 +0200 2022 user2000 pts/0 Tue Jun 21 17:28:50 +0200 2022 user3000 **Never logged in** user4000 **Never logged in** user3 pts/0 Thu Jun 23 12:13:34 +0200 2022 user4 pts/0 Thu Jun 23 12:33:09 +0200 2022 user4100 **Never logged in** user4200 **Never logged in** user4300 pts/0 Thu Jun 23 13:01:04 +0200 2022
Napis **Never logged in**
oznacza, że
użytkownik nie logował się do systemu. Informacje zwracane przez to
polecenie są przechowywane w pliku /var/log/lastlog.
5.1.2. Informacje o użytkowniku
Podczas pracy z użytkownikami, możemy potrzebować informacji na jego temat. Równie dobrze moglibyśmy sprawdzić go w pliku /etc/passwd, ale jest lepszy sposób. Na Linuksach dostępne jest polecenie id, które zwraca UID, GID podstawowej grupy oraz grup, do których należy użytkownik podany jak argument tego polecenia:
[root@server1 ~]# id user100 uid=1001(user100) gid=1001(user100) groups=1001(user100),9999(sgrp)
Wówczas jeśli jako my sami potrzebuje wyświetlić, grupy do których należymy możemy użyć polecenia groups.
[user100@server1 ~]$ groups user100 sgrp
5.2. Pliki autentykacji użytkowników
Każdy użytkownik, chcący skorzystać z systemu musi się uwierzytelnić za pomocą tylko jemu znanych poświadczeń, wówczas zostaje on autoryzowany do wykonywania różnych czynności w systemie. Sam system do uwierzytelniania użytkowników stosuje kilka plików.
5.2.1. Pliki /etc/passwd
Ten plik jest swoistą bazą danych o użytkownikach w systemie. Każdy jeden wpis to jeden użytkownik.
[root@server1 ~]# tail -5 /etc/passwd user:x:1000:1000:user:/home/user:/bin/bash user100:x:1001:1001::/home/user100:/bin/bash user200:x:1002:1002::/home/user200:/bin/bash user1000:x:1003:1003::/home/user1000:/bin/bash user2000:x:1004:1004::/home/user2000:/bin/bash
Każdy z tych wpisów zawiera kilka pól oddzielonych od siebie dwukropkiem (:). Natomiast same pola oznaczają kolejno:
- Nazwę użytkownika -
user
. Nazwy użytkowników na Linuksie nie powinny przekraczać 255 znaków oraz zawierać innych znaków specjalnych niż podkreślnik (_) lub myślnik (-) i niepowinny zawierać wielkich liter, - Hasło -
x
, w tym przypadku x oznacza, że hasło jest zaszyforwane w pliku /etc/shadow, w tym polu może znajdować się również gwiazdka (*), która oznacza że konto jest wyłączone. - UID -
1000
, jest identyfikator użytkownika, jądro odwołując się do użytkowników używa tych identyfikatorów. W systemie istnieją zakresy UID, które są przypisywane poszczególnym użytkownikom. Identyfikator 0, jest zarezerwowany dla root, identyfikatory do 1 do 999 są przeznaczone dla użytkowników systemowych (przeważnie tworzonych na potrzeby usług, w RHEL istnieje podział, na UID-y od 1 do 200 są przeznaczone dla użytkowników przypisanych do wewętrznych usług systemowych a UID-y od 201 do 999 dla pozostałych). - GID -
1000
, jest to identyfikator grupy podstawowej użytkownika (podczas tworzenia użytkownika, tworzona jest także grupa o takiej samej nazwie jak użytkownik i jest ona nazywana podstwową grupą użytkownika. Istnienie takiej grupy zapewnia spójność uprawnień plików). - Komentarz -
user
, Komentarz, dawniej pole GECOS, jest miejscem na dodatkowe informacje o użytkowniku, np. numer telefonu lub adres e-mail. - Katalog domowy -
/home/user
, to pole zawiera ścieżkę do katalogu domowego. - Powłoka -
/bin/bash
, miejsce dla domyślnego programu uruchamianego zaraz po zalogowaniu najczęsciej jest to jedna z dostępnych w systemie powłok.
5.2.2. Plik /etc/shadow
Plik /etc/shadow, koreluje z plikem /etc/passwd ich wspólnym kluczem jest nazwa użytkownika. Plik ten zamiast ogólnych informacji o użytkowniku zawiera jego hasło oraz zasady związane z hasłami. Tak jak w przypadku pliku passwd każdy wpis odpowiada jedemu użytkownikowi.
[root@server1 ~]# tail -5 /etc/shadow user:$6$bNlZFNZV/wWKGQU8$DgIHeUdALGWs7bZ7Foet2UeHFSANSvYcEtLmn6aLm5QxLcx10jZNkUg.dphdmizej/k5Xe.oEqSCeHAf5/7Gv0::0:99999:7::: user100:$6$N3norXlohg0yE1pi$FyeKcBNl4mj/nLbNRlx7KaAQnddG0y/kXpQ9pbgjTV9ti3dQ5q3pIpXm1poa85oxFHFVT9HPTyBmaRNkrSJPX.:19163:0:99999:7::: user200:!!:19163:0:99999:7::: user1000:!!:19163:0:99999:7::: user2000:!!:19163:0:99999:7:::
Każdy z tych wpisów zawiera kilka pól oddzielonych od siebie dwukropkiem (:). Natomiast same pola oznaczają kolejno:
- Nazwę użytkownika -
user
, odpowiadającą nazwie użytkownika z pliku /etc/passwd. - Zaszyfrowane hasło -
$6$bNlZFNZV/wWKGQU8$DgIHeUdALGWs7bZ7Foet2UeHFSANSvYcEtLmn6aLm5QxLcx10jZNkUg.dphdmizej/k5Xe.oEqSCeHAf5/7Gv0
, utworzone na podstawie hasła wpisanego przez użytkownika. RHEL w przypadku przesłonionych haseł używa algorytmu SHA-512. Jeśli to pole zawiera wykrzyknik (!), to wówczas użytkownik nie może zalogować się do systemu za pomocą hasła. Puste pole oznacza, że uzytkownik może zalogować się bez wprowadzania hasła. - Ostatnia zmiana hasła -
19163
, to pole zawiera liczbę dni, która upłyneła od północy 1 stycznia 1970r. (początku czasu Uniks) do momentu zmiany hasła. To pole można uznać za liczbową datę. - Minimalny wiek hasła -
0
, wyznacza liczbę dni, która musi upłynąć przed następną zmianą hasła. Puste pole lub zero oznacza iż, nie ustalono minimalnego wieku dla hasła tego użytkownika. - Maksymalny wiek hasła -
99999
, wyznacza liczbę dni, po której należy zmienić hasło. Hasła, których ważność osiągnie tę wartość mogą być dalej ważne, jednak system przy następnym logowaniu będzie wymagał jego zmiany. - Okres ostrzegania -
7
, określa ilość dni, w których użytkownik będzie informowany o tym, że mija termin ważności jego hasła i musi je zmienić, aby dalej móc się logować do systemu. - Okres nieaktywności hasła - określa ilość dni, przez które przeterminowane hasło będzie jescze akceptowane. Po zalogwaniu system będzie żądać zmiany hasła. W przypadku naszego przykładu, to pole jest puste, a więc nie ma zdefiniowanego tego okresu.
- Data wygaśnięcia konta - określa ilość dni od północy 1 stycznia 1970r., po których nie będzie można używać konta do logowania się. Zero bądź puste pole (tak jak na przykładzie) oznacza iż konto nigdy nie wygaśnie.
- Pole zarezerowane - pole zarezerowowane do użycia w przyszłości.
W przypadku pól od zaszyfrowanego hasła do pola zarezerowanego, puste pole lub 0 wyłącza przeznaczone im właściwości. Część z tych opcji ustawiana jest w pliku /etc/login.defs i nazwane są zasadami ważności haseł lub ang. pasword aging. Na koniec zwróćmy uwagę na szczegóły tego pliku:
[root@server1 ~]# ls -l /etc/shadow ----------. 1 root root 2012 Jun 25 18:53 /etc/shadow
Nikt nie ma żadnych uprawnień do tego pliku. Możliwa jest jego modyfikacja za pomocą specjalnego mechanizmu, który będzie omawiany przy okazji SELinux.
5.2.3. Plik /etc/group
Plik /etc/group jest odpowiednikiem dla pliku /etc/passwd tylko, że dla group. Ten plik ma podobną budową do plików /etc/passwd lub /etc/shadow posiada jednak mniejszą ilość pól.
[root@server1 ~]# tail -5 /etc/group user:x:1000: user100:x:1001: user200:x:1002: sgrp:x:9999:user100,user200 sgrp2:x:8888:user1000,user2000
A każde z pół przechowuje kolejno:
- Nazwę grupy -
sgrp
. - Hasło grupy -
x
oznacza, że hasło jest zaszyfrowane w pliku /etc/gshadow. Hasła grupy służą zablokowaniu przełączania się między grupami za pomocą polecenia newgrp, aby użytkownicy nie mogli uzyskać dostępu plików innych grup. - GID -
9999
, identyfikator grupy. - Lista członków grupy -
user100,user200
, lista użytkowników oddzielonych przecinkami przypisanych do tej grupy. W przypadku podstawowych grup użytkowników (nazwa grupy jest identyczna z nazwą użytkownika), a członek jest domyślny i nie widnieje na liście.
5.2.4. Plik /etc/gshadow
Grupy jak i użytkownicy również mają swoje hasła. W opisie pola hasła przy okazji pliku /etc/group wyjaśniłem dlaczego tak jest. Te hasła muszą być gdzieś składowane i to w bezpieczny sposób. Hasła grup również są przesłonione jak hasła użytkowników. Miejscem składowania haseł grup jest jest plik /etc/gshadow, zawiera on podobne wpisy jak plik /etc/group i jest z nim powiązany wspólnym kluczem jakim jest nazwa grupy.
[root@server1 user]# tail /etc/gshadow user:!:: user100:!:: user200:!:: dba:!:: user1000:!:: user2000:!:: dbagrp:!:: user90:!:: g1:!::
Plik /etc/gshadow zawiera 4 pola tak jak plik /etc/group, każde z tych pól oznacza kolejno:
- Nazwa grupy -
user
, identyczna z nazwą zawartą w we wpisach w pliku /etc/group. - Zaszyforwane hasło, jeśli tym polu pojawia się
inny znak taki jak
!
lub gwiazdka (*) oznacza to, że użytkownicy nie mogą za pomocą hasła uzyskać dostępu do grupy. - Administratorz grupy, lista użytkowników mogących zarządzać grupą, mogą oni dodawać i usuwać członków przy użyciu polecenia gpasswd.
- Członkowie grupy, oddzielona przecinkami lista użytkowników należąca do tej grupy.
5.3. Podstawy zarządzania użytkownikami
W tym podrozdziale poznamy podstawy zarządzania użytkownikami. Będziemy tworzyć użytkowników, zmieniać informacje o nich oraz ich usuwać. Tworząc nowego użytkownika wydajemy proste polecenie i podajemy jego nazwę. Taki użytkownik tworzony jest z domyślnymi wartościami. Zanim zaczniemy tworzyć użytkowników poznamy dwa miejsca, skąd mogą brać się te domyślne wartości.
5.3.1. Domyślnie informacje użytkowników
Informacje o tym jaką przydzielić użytkownikowi powłokę, czy między jakimi wartościami powinien znajdować się jego UID są w systemie z góry określone. Takimi miejscami, w których możemy szukać domyślnych wartości jest plik /etc/default/useradd, którego zawartość dostępna jest po wydaniu poniższego polecenia:
[user@server1 ~]$ useradd -D GROUP=100 HOME=/home INACTIVE=-1 EXPIRE= SHELL=/bin/bash SKEL=/etc/skel CREATE_MAIL_SPOOL=yes
Z tych informacji możemy wynioskować początkowy GID
(GROUP
), jednak
ta opcja używana jest gdy opcja USERGROUPS_ENAB, w pliku
/etc/login.defs (drugim z plików) jest ustawiona na NO.
Poza tym znamy domyślną lokalizację tworzenia katalogów domowych
(HOME
), czas nieaktywność
(INACTIVE
), który określa liczbę dni
pomiędzy wygaśnięciem hasła a trwałym zablokowaniem konta, domyślną
datę wygaśnięcia konta (EXPIRE
),
domyślną powłokę (SHELL
), lokalizację
katalogu szkieletowego (SKEL
) -
katalog ten przechowuje pliki kopiowane do każdego katalogu domowego
nowego użytkownika w momencie jego utworzenia. Ostatnią wartością jest
zmienną określająca czy tworzyć pliki skrzynki mailowej każdemu
użytkownikowi
(CREATE_MAIL_SPOOL
). Nie które z tych
wartości możemy modyfikować używając tego samego polecenia, więcej
informacji na ten temat znajduje się na stronie podręcznia polecenia
useradd.
Innym źródłem wartości domyślnych wykorzystywanych podczas tworzenia użytkowników jest plik /etc/login.defs. Zawartość tego pliku najlepiej jest wyświetlić za pomocą poniższego polecenia, które odfiltruje komentarz i puste linie:
[user@server1 ~]$ grep -v ^# /etc/login.defs | grep -v ^$ MAIL_DIR /var/spool/mail UMASK 022 HOME_MODE 0700 PASS_MAX_DAYS 99999 PASS_MIN_DAYS 0 PASS_WARN_AGE 7 UID_MIN 1000 UID_MAX 60000 SYS_UID_MIN 201 SYS_UID_MAX 999 SUB_UID_MIN 100000 SUB_UID_MAX 600100000 SUB_UID_COUNT 65536 GID_MIN 1000 GID_MAX 60000 SYS_GID_MIN 201 SYS_GID_MAX 999 SUB_GID_MIN 100000 SUB_GID_MAX 600100000 SUB_GID_COUNT 65536 ENCRYPT_METHOD SHA512 USERGROUPS_ENAB yes CREATE_HOME yes HMAC_CRYPTO_ALGO SHA512
Wewnątrz tego pliku znajdują się definicje takich wartości jak
maska użytkownika (umask
), elementy
polityki haseł (PASS_...
) czy zakresy
wartości UID oraz GID. W tym pliku również znajduje
się nazwa algorytmu używanego do przesłaniania haseł. Opisy
poszczególnych wartości zawartych w tym pliku znajdują się na
stronie podręcznika.
5.3.2. Tworzenie użytowników
Do tworzenia użytkowników systemie służy polecenie useradd, domyślnie wymaga on wyłącznie podania nazwy użytkownika. Podczas tej czynności zostaną dodane wpisy do plików autentykacyjnych, które omwialiśmy wcześniej, zostanie utworzony katalog domowy i przekopiowane zostaną do niego pliki z katalogu szkieletowego (/etc/skel). Utworzymy sobie teraz testowego użytkownika.
[root@server1 user]# useradd user1
To polecenie utworzy użytkownika z domyślnymi wartościamy identyfkatora, powłoki oraz innymi. Polecenie to daje możliwość zmiany tych wartości podczas tworzenie nowego użytkownika. Poniżej znajduje się lista opcji, na której zawarto najważniejsze z nich:
- -d, pozwala na podanie ścieżki do katalogu domowego użytkownika.
- -g, pozwala na podanie GID-u lub nazwy podstawowej grupy użytkownika.
- -G, pozwala na wprowadzenie grup, do których ma należeć użytkownik, nazwy podajemy po przecinku (o ile więcej niż jedna).
- -o, każdy identyfikator czy to użytkownika czy grupy musi być unikatowy. Ta opcja pozwala na współdzielenie (w tym przypadku) UID-u, choć konieczność użycia tej opcji zachodzi tylko w specyficznych przypadkach.
- -s, pozwala na ustalenia domyślnego programu, który uruchamiany jest zaraz po zalogowaniu się użytkownika. Tym programem najczęściej jest powłoka.
- -u, pozwala na podanie identyfikatora użytkownika UID, identyfikator powinien być unikatowy w cały systemie, chyba że podano opcję -o.
Chcąc użyć tych opcji podaje się je po nazwie polecenia przed nazwą użytkownika. W ramach ćwiczeń możemy utworzyć kilku użytkowników z losowymi wartościami opcji podanych powyżej. W tym rozdziale poznamy narzędzie, które służy do usuwania użytkowników, ale za nim to zrobimy poznamy polecenie, dzięki któremu będziemy mogli zmienić opcje już utworzonych użytkowników.
Tak utworzonym użytkowników pozostało tylko nadać hasło, przy użyciu polecenia passwd.
Tutaj podano tylko część opcji tego polecenia, więcej znajduje się na stronie podręcznika. Nie uczmy się także opcji na pamięć, raczej zawsze będziemy mieć dostęp do stron podręcznika.
5.3.3. Zmiana informacji użytkownika
Zmianie informacji użytkownika służy polecenie usermod, ma ono prawie identyczne opcje jak polecenie useradd. Poza kilkoma wyjątkami.
- -l - opcja pozwala na podanie nowej nazwy użytkownika.
- -d - opcja pozwala na zmianę katalogu domowego. Nie było by tej opcji na tej liście gdyby nie fakt, iż aby katalog został utworzony na podanej ścieżce, ta opcją musi zostać użyta w raz z opcją -m, której zadaniem jest przeniesienie danych z poprzedniego katalogu.
Na poniższym przykładzie pokazano zmianę katalogu domowego użytkownika user90:
[root@server1 ~]# tail /etc/passwd ... user90:x:5003:5003::/home/user90:/bin/bash [root@server1 ~]# usermod -d /usr/home90 -m user90 [root@server1 ~]# tail /etc/passwd ... user90:x:5003:5003::/usr/home90:/bin/bash [root@server1 ~]# ls -al /usr/home90 total 12 drwx------. 3 user90 user90 78 Jun 26 16:06 . drwxr-xr-x. 13 root root 158 Jun 27 14:31 .. -rw-r--r--. 1 user90 user90 18 Nov 5 2021 .bash_logout -rw-r--r--. 1 user90 user90 141 Nov 5 2021 .bash_profile -rw-r--r--. 1 user90 user90 492 Nov 5 2021 .bashrc drwxr-xr-x. 4 user90 user90 39 Jun 26 13:48 .mozilla
Pozostałe opcje, które znajdują się na stronie podręcznika tego polecenia możemy używać w ten sam sposób jak w przypadku useradd.
5.3.4. Usuwanie użytkowników
Kiedy użytkownicy przestają być potrzebni, ze względów bezpieczeństwa można, albo ich zablokować albo usunąć. W tym rodziale zajmiemy się wyłącznie usuwaniem. Polecenie do usuwania użytkowników to userdel. Jest ono prostolinijne i niewymaga dodatkowych opcji, wystarczy podać nazwę użytkownika jako argument polecenia i użytkownik zostanie usunięty, jednak jego dane pozostaną w systemie. Użytkownika wraz z danymi możemy usunąć za przy użyciu opcji -r.
[root@server1 ~]# userdel -r user90 [root@server1 ~]# tail /etc/passwd chrony:x:986:981::/var/lib/chrony:/sbin/nologin dnsmasq:x:985:980:Dnsmasq DHCP and DNS server:/var/lib/dnsmasq:/sbin/nologin tcpdump:x:72:72::/:/sbin/nologin systemd-oom:x:978:978:systemd Userspace OOM Killer:/:/usr/sbin/nologin user:x:1000:1000:user:/home/user:/bin/bash user100:x:1001:1001::/home/user100:/bin/bash user200:x:1002:1002::/home/user200:/bin/bash user5000:x:5000:7000::/home/user5000:/bin/bash user1000:x:5001:5001::/home/user1000:/bin/bash user2000:x:5002:5002::/home/user2000:/bin/bash [root@server1 ~]# ls -al /usr/home90 ls: cannot access '/usr/home90': No such file or directory
5.3.5. Użytkownicy bez możliwości logowania
Tak jak na początku powiedzieliśmy sobie, że użytkownicy w systemie istnieją, po to aby wyznaczać granice. Takim użytkownikami są najczęściej są użytkownicy systemowi, którzy są związani z róznego rodzaju usługami. Cechą która ich wyróżnia jest fakt, iż nie mają oni możliwości logowania do systemu, inaczej mówiac są użytkownikami nieinteraktywnymi. Użytkownicy tego typu w miejscu powłoki mają wskazany program /sbin/nologin. Ten mały program przy próbie zalogowania zwróci informacje o tym, że to konto jest obecnie niedostępne. Treść tego komunikatu możemy zmieniać, wpisująć nasz komunikat do pliku /etc/nologin.txt. Użytkownikiem bez możliwości logowania może być każdy, kto ma zamiast powłoki ustawiony właśnie ten program. Poniżej znajduje się polecenie, które zmieni użytkownika user2000 w użytkownika nieinteraktywnego.
[root@server1 ~]# usermod -s /sbin/nologin user2000 [root@server1 ~]# tail /etc/passwd chrony:x:986:981::/var/lib/chrony:/sbin/nologin dnsmasq:x:985:980:Dnsmasq DHCP and DNS server:/var/lib/dnsmasq:/sbin/nologin tcpdump:x:72:72::/:/sbin/nologin systemd-oom:x:978:978:systemd Userspace OOM Killer:/:/usr/sbin/nologin user:x:1000:1000:user:/home/user:/bin/bash user100:x:1001:1001::/home/user100:/bin/bash user200:x:1002:1002::/home/user200:/bin/bash user5000:x:5000:7000::/home/user5000:/bin/bash user1000:x:5001:5001::/home/user1000:/bin/bash user2000:x:5002:5002::/home/user2000:/sbin/nologin
Kiedy spróbuje się na niego zalogować otrzymam wspomniany komunikat.
[root@server1 ~]# su - user2000 This account is currently not available.
Odnośnie egzaminu:
Jeśli w systemie użytkownik, który teoretycznie nie powinien mieć
możliwości logowania, zaloguje się do systemu to znaczy, że mamy
poważny problem z bezpieczeństwem. Wówczas należy sprawdzić
w pliku /etc/passwd czy wszyscy użytkownicy nieinteraktywni
mają ustawiony domyślny program na /sbin/nologin.
Ćwiczenie 1: Sprawdzenie prób logowania użytkowników
Jako superużytkownik na maszynie server1. Zapisz przy użyciu polecenia Vim ostaniego użytkownika, któremu udało się zalogować oraz ostatniego którego logowanie nie powiodło się. Zapisz ostatnie uruchomienie systemu, poza obecnym włączniem oraz listę użytkowników, którzy nigdy się nie logowali do systemu.
Ćwiczenie 2: Weryfikacja użytkownika oraz grupy
Jako superużytkownik na maszynie server1, uruchom polecenie who oraz w porównaj wyniki ich działania. Uruchom polecnia id oraz groups następnie omów informacje zwracane przez nie.
Ćwiczenie 3: Tworzenie użytkowników
Jak superużytkownik na maszynie server1, utwórz użytkownika o nazwie user4100, o identyfikatorze 4100, katalogu domowym znajdującym się katalogu /usr. Następnie utworz użytkownika user4200 z domyślnymi ustawieniami. Przypisz obu hasło. Następnie wyświetl dotyczące ich wpisy w plikach autentykacji (/etc/{passwd,shaddow,group,gshadow}).
Ćwiczenie 4: Tworzenie użytkowników nieinteraktywnych
Jako superużytkownik na maszynie server1, utwórz użytkownika user4300, następnie zmień informacje o nim tak, aby stał sie użytkownikiem nieinterkatywnym. Ustaw mu hasło i spróbuj się zalogować na niego. Jaki komunikat został wyświetlony? Wyświetl wpis użytkownika w pliku /etc/passwd. Co spowodowało, że użytkownik nie może się zalgować?
Podsumowanie
W tym rozdziale dowiedzieliśmy się w jaki sposób możemy sprawdzić próby logowania się do systemu, kto jest zalgowany i co robi. Poznaliśmy zestaw plików odpowidzialnych za autentykacje, a także nauczyliśmy w podstawowym stopniu zarządzać użytkownikami. W następnym rozdziale skupimy się na zasadach haseł i przełączaniu użytkowników.
6. Zaawansowane zarządzanie użytkownikami
W poprzednim rozdziale nauczyliśmy się tworzyć, usuwać użytkowników oraz edytować informacje o nich. Poznaliśmy plik uwierzytelniania, którym między innymi jest plik /etc/shadow, w nim przechowywane są przesłonione hasła, zasady ważności haseł oraz kont i tym zajmiemy sie na początku.
6.1. Zasady ważności hasła
Każdy administrator w systemie, który wykorzystuje intensywnie użytkowników, powinien wdrożyć zasady bezpieczeństwa z nimi związane. Może wymusić na osobach korzystających z kont ich zabezpieczenie po przez regularną zmianę hasła, zablokować nieużywane konta czy utworzyć dla użytkowników tylko konta tymczasowe, które po upływie określonego czasu zostaną automatycznie zablokowane. Te zasady mieszczą w się w dziedzinie ustawień ważności hasła i są realizowane w dystrybucjach Linuksa za pomocą dwóch poleceń: chage oraz passwd. Poniżej w tabeli skumulowałem opcje tych dwóch poleceń odpowiadające za konkrentą czynność.
chage | passwd | |
---|---|---|
Data ostatniej modyfikacji hasła | -d | X |
Data wygaśnięcia konta | -E | X |
Czas nieaktywności hasła | -I | -i |
Informacje o zasadach użytkownika | -l | -S |
Minimalna ważność hasła | -m | -n |
Maksymalna ważność hasła | -M | -x |
Okres ostrzegania | -W | -w |
Po za tymi wspólnymi cechami, polecenie passwd, jest wstanie:
- usunąć hasło - -d, takie konto, wówczas staje się kontem bez hasła.
- wymusić utratę ważności hasła - -e, po zalogowaniu na takie konto, wymagana będzie zmiana hasła. Ustawienie opcji -d polecenia chage, daje ten sam efekt.
- zablokować konto - -l, użytkownik nie będzie mieć możliwości zalogowania się do systemu.
- odblokować konto - -u, przywraca możliwość logowania się zablokowanemu kontu.
Stosując chage lub passwd nazwę użytkownika podajemy po opcjach i ich wartościach. Na poniższym przykładzie za prezentowałem w jaki sposób możemy ustawić wszystkie pozostałe pola we wpisie w pliku /etc/shadow za pomocą powyższych poleceń.
#chage: [root@server1 ~]# chage -m 7 -M 28 -W 5 -I 7 -E 2022-12-31 user3000 [root@server1 ~]# chage -l user3000 Last password change : Jun 28, 2022 Password expires : Jul 26, 2022 Password inactive : Aug 02, 2022 Account expires : Dec 31, 2022 Minimum number of days between password change : 7 Maximum number of days between password change : 28 Number of days of warning before password expires : 5 [root@server1 ~]# grep 'user3000' /etc/shadow user3000:$6$AjNe9ajpYrZ1Sjld$NN36zAMKPlnJElCvuUX1UM0fc6Ymc5pLY4medoHRMCWJhnsoiuKSpjbo7uwTZVkVlv.swqQJ5Dxoa2QZyjsXO.:19171:7:28:5:7:19357: #passwd: [root@server1 ~]# passwd -n 5 -x 28 -w 5 -i 7 user4000 Adjusting aging data for user user4000. passwd: Success [root@server1 ~]# passwd -S user4000 user4000 PS 2022-06-28 5 28 5 7 (Password set, SHA512 crypt.) [root@server1 ~]# grep 'user4000' /etc/shadow user4000:$6$29yZ7yqj2lWdSoQE$AMp2ZXAqxa.wWMA88dINDdogjych/Yshnip1whwaqymLTS4ALW9UGx9406tZmsghOTXptBIFrq4UvDF/.sl2f0:19171:5:28:5:7::
Za pomocą polecenia passwd, nie możemy dodać daty wygaśnięcia konta. Jednak to polecenie wraz z poleceniem, które znamy z poprzednie rozdziału usermod, może blokować i odblokowywać konta. Zablokujemy i odblokumjemy oba wcześniej wykorzystwane konta.
Blokowanie kont za pomocą polecenia passwd:
[root@server1 ~]# passwd -l user3000 Locking password for user user3000. passwd: Success [root@server1 ~]# grep 'user3000' /etc/shadow user3000:!!$6$AjNe9ajpYrZ1Sjld$NN36zAMKPlnJElCvuUX1UM0fc6Ymc5pLY4medoHRMCWJhnsoiuKSpjbo7uwTZVkVlv.swqQJ5Dxoa2QZyjsXO.:19171:7:28:5:7:19357: [root@server1 ~]# passwd -u user3000 Unlocking password for user user3000. passwd: Success [root@server1 ~]# grep 'user3000' /etc/shadow user3000:$6$AjNe9ajpYrZ1Sjld$NN36zAMKPlnJElCvuUX1UM0fc6Ymc5pLY4medoHRMCWJhnsoiuKSpjbo7uwTZVkVlv.swqQJ5Dxoa2QZyjsXO.:19171:7:28:5:7:19357:
Jak możemy zauważyć po zablokowaniu konta przed przesłonionym hasłem zostały umieszczone dwa wykrzykniki, które po odblokowaniu konta zostały usunięte. Poniżej znajdują się te same czynności wykonane przy użyciu polecenia usermod.
[root@server1 ~]# usermod -L user4000 [root@server1 ~]# grep 'user4000' /etc/shadow user4000:!$6$29yZ7yqj2lWdSoQE$AMp2ZXAqxa.wWMA88dINDdogjych/Yshnip1whwaqymLTS4ALW9UGx9406tZmsghOTXptBIFrq4UvDF/.sl2f0:19171:5:28:5:7:: [root@server1 ~]# usermod -U user4000 [root@server1 ~]# grep 'user4000' /etc/shadow user4000:$6$29yZ7yqj2lWdSoQE$AMp2ZXAqxa.wWMA88dINDdogjych/Yshnip1whwaqymLTS4ALW9UGx9406tZmsghOTXptBIFrq4UvDF/.sl2f0:19171:5:28:5:7::
W przypadku polecenia usermod, umieszczony został tylko jeden wykrzyknik przed hasłem, jednak nie ważne czy został umieszczony jeden czy dwa, wykrzyknik przed przesłonionym hasłem oznacza, że konto jest zablokowane.
6.2. Zarządzanie grupami
Podobnie tak jak w przypadku użytkowników, w poprzednim rozdziale tak i grupami możemy zarządać w podobny sposób. Możemy je dodawać z dostosowanymi do potrzeb informacjami, zmieniać ich informacje oraz usuwać.
6.2.1. Tworzenie nowych grup
Do tworzenia nowych grup służy polecenie groupadd, które do utworzenia grupy z domyślnymi wartościami wymaga jedynie jej nazwy. Poniżej znajdują się najważniejsze opcje tego polecenia:
- -g, pozwala na podanie własnego identyfikatora grupy GID, identyfikator powinien być unikatowy, chyba że podano opcję -o.
- -o, pozwala na współdzielenie identyfikatora z inną grupą.
- -r, tworzy grupę systemową z identyfikatorem w zakresie podanym w pliku /etc/login.defs, przeważnie między 201 a 999.
- -U, pozwala podać listę użytkowników, którzy będą należeć do grupy, nazwy użytkowników są oddzielone od siebie przecinkiem.
[root@server1 ~]# groupadd -g 9999 sgrp [root@server1 ~]# grep 'sgrp' /etc/group sgrp:x:9999:
Na powyższym przykładzie utworzyłem grupę z niestandardowym identyfikatorem, następnie wyświetliłem jej wpis w pliku /etc/group.
6.2.2. Zmiana informacji grupy
Polecenie groupmod, posiada takie samo zastosowanie dla grup, jak polecenie usermod dla użytkowników. Część opcji groupmod odpowiada opcjom z polecenia groupadd. Na wyszczególnienie zasługuje opcja -n, która pozwala na zmianę nazwy grupy.
[root@server1 ~]# groupmod -g 8888 -n sysadm sgrp [root@server1 ~]# grep 'sgrp' /etc/group [root@server1 ~]# grep 'sysadm' /etc/group sysadm:x:8888:
Jak możemy zobaczyć na przykładzie grupie
sgrp
został zmieniony identyfikator
oraz nazwa. Teraz ta grupa widnieje pod GID-em
8888
oraz pod nazwą
sysadm
.
6.2.3. Usuwanie grup
Jeśli grupa nie jest już potrzebna w systemie możemy ją usunąć. Do usuwania grup służy polecenie groupdel. Polecenie jest bardzo proste w użyciu. Jedyny wymagany argument to nazwa grupy.
[root@server1 ~]# groupdel sysadm [root@server1 ~]# grep 'sysadm' /etc/group
Grupa została usunięta. Polecenie grep
nie mogło odnaleźć wzorca sysadm
w
pliku /etc/group.
6.3. Przełączanie użytkowników oraz uruchamianie poleceń jako superużytkownik
Wykonywanie zadań administracyjnych najczęściej będzie wymagać podniesienia uprawnień do poziomu superużytkownika - root. Do tej pory wszystkie polecenia w tym materiale wykonywałem z poziomu konta root (wyjątkowowo kilka poleceń zostało wykonanych jako zwykły użytkownik), więc aby wykonywać zadania administracyjne należy się zalogować jak superużytkownik. Logowanie bezpośrednie na to konto nie jest dobrą praktyką. A do dyspozycji mamy dwa rozwiązania. Pierwszym z nich jest przełączenie użytkownika.
6.3.1. Przełącznie użytkownika
Pierwszą z metod jest zalogowanie się na nasze konto (konto dostępowe, zwykły użytkownik), a następnie przełącznie się na konto root za pomocą polecenia su. To polecenie pozwala na przełączenie się na dowolne konto, jeśli jako pierwszy argument podamy myślnik (-) przed nazwą użytkownika podczas przełączania zostaną uruchomione skrypty startowe, które stworzą nam środowisko jak najbardziej zbliżone do bezpośredniego logowania.
[user@server1 ~]$ su - root Password: [root@server1 ~]#
Za pomocą tego polecenia możemy przełączyć się na dowolne konto, jeśli zwykli użytkownicy przełączają się między kontami wymagane będzie podanie hasła dla docelowego konta, wyjątkiem tutaj jest superużytkownik, który nie musi podawać żadnych haseł.
Aby korzystać z tej metody nie trzeba nawet otwierać sesji powłoki jako przełączony użytkownik, możemy po prostu wykonać polecenie jako on za pomocą opcji -c.
[user@server1 ~]$ su root -c 'vgs' Password: VG #PV #LV #SN Attr VSize VFree rhel 1 2 0 wz--n- <19.00g 0
Korzystanie z polecenia su, nie jest zbyt elastycznym rozwiązaniem, daje pełen dostęp do superużytkownika gdzie nie jest to konieczne. Ten rodzaj podniesienia uprawnień w systemie używany jest przez kilka dystrybucji w jednym celu aby pobrać i skonfigurować to drugie rozwiązanie.
6.3.2. Polecenie sudo
Użycie polecenia sudo jest znacznie lepszym rozwiązaniem. Głównym argumentem jest fakt, iż możemy skonfigurować to polecenie w taki sposób, aby dać użytkownikom dostęp tylko do tych poleceń których naprawdę potrzebują. Jednak na początku zajmiemy się prostszą konfiguracją, czyli stworzeniem lokalnego administratora, którego konto dalej będzie zwykłym użytkownikiem.
Do konfiguracji tego narzędzia służy plik /etc/sudoers oraz
katalog /etc/sudoers.d, w którym wystarczy umieścić plik z
konfiguracją. Plik /etc/sudoers, możemy edytować dowolnym
edytorem, jednak pakiet sudo posiada specjalne polecenie
visudo, które stworzy kopie tymczasową pliku, na
której
będziemy dokonywać zmian (polecenie samoczynnie uruchomi edytor),
następnie polecenie nadpisze oryginalny plik i usunie plik tymczasowy.
Najprostszą konfiguracją jaką możemy
wykonać jest nadanie zwykłemu użytkownikowi uprawnień do wszystkich
funkcji administracyjnych. Zmian możemy dokonać w dowolnym miejscu w
pliku, jednak nalepiej
znaleźć odpowiednie do tego miejsce. Możemy je namierzyć wyszukując
linię root ALL=(ALL) ALL
, skopiować
ją, wkleić pod nią i zmienić tylko nazwę użytkownika na początku linii:
user ALL=(ALL) ALL
Ten wpis zapewni użytkownikowi user
dostęp do wszystkich funkcji administracyjnych w systemie. Oprócz
użytkownikom, dostęp do wszystkich lub określonych funkcji możemy nadać
grupie. Kiedy zajdzie taka potrzeba wystarczy dopisać użytkownika do
grupy i nie trzeba już edytować pliku. Konfiguracja grupy różni się od
konfiguracji użytkownika tym, że nazwę grupy poprzedza się znakiem
procentu (%):
%sysadms ALL=(ALL) ALL
We wpisach konfiguracyjnych znajdują się aż trzy słowa
ALL
, każde z nich ma oddzielne
znacznie. Pierwsze słowo ALL po nazwie użytkownika oznacza
nazwę komputera (lub adres IP), ponieważ plik /etc/sudoers
może być współdzielony między innymi komputerami, jednak ten plik
będzię dotyczyć tylko tego systemu dlatego też może pozostać
ALL. Drugie słowo ALL w nawiasie oznacza jako kto
będzie wykonywać te polecenie, ta lista pozwala wybrać
użytkownika (po zastosowaniu opcji -u) do wykonania polecenia.
W nie których systemach możemy spotkać się z zapisem
(ALL:ALL), zapis ALL po dwukropku oznacza listę grup.
Grupę możemy wybrać z pomocą opcji -g. Ostanie ALL
jest listą programów do których użytkownik poprzedzający polecenie
narzędziem sudo będzie mieć dostęp. Poniżej przykładowe użycie
polecenia sudo.
[user@server1 ~]$ sudo vgs [sudo] password for user: VG #PV #LV #SN Attr VSize VFree rhel 1 2 0 wz--n- <19.00g 0
Podczas uruchamia programu vgs
,
sudo, po prosiło o hasło - hasło użytkownika, który wydaje
to polecenie.
Narzędzie sudo możemy skonfigurować w taki sposób aby nie
wymagało hasła podczas uruchamiania programu. We wcześniejszej
dyrektywie, konfigurującej użytkownika przed ostatnim słowem ALL
dopisujemy NOPASSWD:.
user ALL=(ALL) NOPASSWD:ALL
Najczęściej naszym zadaniem związanym z poleceniem sudo będzie przypisanie konkretnym użytkownikom dostępu do określonych poleceń. Jeśli do skonfigrowania mamy wiele takich elementów za równo poleceń jak i użytkowników, to aby zrobić to jak najefektywniej należy użyć aliasów. Sudo swojej konfiguracji wyróżnia aliasy przeznaczone dla użytkowników jak i dla poleceń. Alias z listą użytkowników tworzymy tak jak na przykładzie:
User_Alias PKGADM = user1, user100, user200
Po słowie User_Alias
zapisujemy nazwę
aliasu, w tym przypadku jest PKG_ADM
po znaku równości (=) podajemy listę użytkowników
tak jak na przykładzie powyżej. Ze zbiorem poleceń jest podobnie ale
zmienia się dyrektywa inicjująca alias.
Cmnd_Alias PKGCMD = /usr/bin/yum, /usr/bin/rpm
Po zdefiniowaniu obu aliasów, możemy przejść do przypisnia aliasowi
PKGADM
(określonym użytkownikom)
dostępu do poleceń zapisanych w
PKGCMD
.
PKGADM ALL = PKGCMD
Teraz użytkownicy zdefiniowani w aliasie
PKGADM
będą mogli użyć tylko i
wyłącznie poleceń zdefiniowanych w PKGCMD
Podczas pracy będziemy zazwyczaj definiować aliasy użytkowników, ponieważ jeśli rozejrzymy się po pliku /etc/sudoers, definicje aliasów z pogrupowanymi poleceniami są już zapisane w komentarzach wystarczy usunąć znak komentarza oraz przypisać ten alias określonej grupie użytkowników.
Użycie polecenia sudo jest rejestrowane. Wpisy zapisywane są do pliku /var/log/secure ich odczyt wymaga uprawnień superużytkownika. We wpisach znajduje się nazwa użytkownika, który wywołał to polecenie jak i samo polecenie.
Więcej informacji na temat tego narzędzia znajduje się na stronie podręcznika samego polecenia jak i pliku /etc/sudoers. Jak ćwiczenie, nadajmy uprawnienia do pełnych funkcji administracyjnych zwykłemu użytkownikowi, którego tworzyliśmy podczas instalacji systemu na maszynie. Od tego momentu na wszystkich przykładach będę używać tego konta, a uprawnienia administracyjne będę wymuszać za pomocą polecenia sudo.
6.4. Zmiana praw własności plików i katalogów
Polecenie chown, omówiliśmy sobie podczas omawiania uprawnień plików. Polecenie to służy do zmiany właściciela oraz ewentualnie grupy, do której należy element.
[user@server1 ~]$ ls -l file1 -rw-r--r--. 1 user user 0 Jun 26 15:30 file1 [user@server1 ~]$ sudo chown user100 file1 [sudo] password for user: [user@server1 ~]$ ls -l file1 -rw-r--r--. 1 user100 user 0 Jun 26 15:30 file1
Jednak w systemie istnieje inne polecenie, dzięki któremu możemy zmienić grupę. Jest nim chgrp. Składania polecenia identyczna do składni chown.
[user@server1 ~]$ sudo chgrp user100 file1 [sudo] password for user: [user@server1 ~]$ ls -l file1 -rw-r--r--. 1 user100 user100 0 Jun 26 15:30 file1 [user@server1 ~]$
Jak możemy zauważyć grupa, do której należy plik została zmieniona w porównaniu do szczegółów z poprzedniego przykładu.
Polecenia chown możemy również używać rekurencyjnie, aby zmieniać prawa własności całych struktur katalogowych wraz z plikami. Tej czynności służy opcja -R.
[user@server1 ~]$ sudo chown -R root:root /tmp/etc
Na powyższym przykładzie zmieniłem właściciela oraz grupę do wszystkim
elementom w katalogu /tmp/etc
.
Ćwiczenie 1: Utwórz użytkowników oraz skonfiguruj zasady haseł
Na maszynie server1 utwórz grupę lnxgrp o numerze GID 6000. Utwórz użytkownika user5000 o numerze UID 5000 oraz numerze GID 6000. Przypisz mu hasło, a następnie ustaw minimum 4 dni do następnej zmiany hasła, ważność hasła na 30 dni oraz okres ostrzegania na 10 dni. Konto tego użytkownika powinno wygasnąć 20 grudnia 2022 roku.
Ćwiczenie 2: Zablokuj i odblokuj użytkownika
Na maszynie server1 zablokuj użytkownika user5000 za pomocą polecenia passwd. Sprawdź jak zmienił się jego wpis w pliku /etc/shadow. Spróbuj się zalogować na użytkownika. Odblokuj go za pomocą polecenia usermod zweryfikuj jego odblokowanie na podstawie wpisu z pliku powyżej.
Ćwiczenie 3: Zmień dane grupy
Na maszynie server1 zmień GID grupy lnxgrp z 6000 na 7000, dodaj do niej użytkowników user1000 oraz user2000 (jeśli nie istnieją utwórz ich), na koniec zmień nazwę grupy na dbagrp i zweryfikuj zmiany.
Ćwiczenie 4: Konfiguracja dostępu do sudo
Na maszynie server1, skonfiguruj polecenie sudo dla użytkownika user5000, tak aby miał dostęp do wszystkich funkcji administracyjnych bez podawania hasła. W celu sprawdzenia wydaj polecenie sudo vgs.
Ćwiczenie 5: Zmiana praw własności do plików i katalogów
Na maszynie server1, utwórz w katalogu /tmp plik f6 oraz katalog d6. Utwórz użytkownika user90. Za pomocą polecenia chown ustaw właściciela pliku f6 na user90. Za pomocą polecenia chgrp ustaw grupę na dbagrp. Utwórz grupę g1, następnie ustaw rekrencyjnie prawa własności dla katalogu d6, na user90:g1.
Podsumowanie
Tym rodziałem zakończyliśmy zarządzanie użytkownikami. Zapoznaliśmy się z narzędziami do ustalania zasad haseł w praktyce, poznaliśmy narzędzia do zarządzania grupami oraz efektywne sposoby na bezpieczne podnoszenie uprawnień za pomocą polecenia sudo. Na koniec odświerzyliśmy informacje na temat praw własności plików i katalogów. W następnym rozdziale poznamy podstawy powłoki BASH.
7. Powłoka BASH
Powłoka jest to program odpowiedzialny za możliwość wprowadzania poleceń do systemu i ich interpretowanie. Powłoka jest domyślnym interfejsem użytkownika w różnych wariantach systemów uniksopodobnych. To właśnie proces połoki jest uruchamiany po uruchomieniu okna terminala.
Na przestrzeni lat wraz z kolenymi odłamami oryginalnego Uniksa powstawało wiele powłok, każda z nich miała swoje wady i zalety. Obecnie najpowszechniejszą wersją z nich jest BASH, jej główną zaletą jest zebranie większości funkcjonalność różnych powłok, poprawienie ich działa oraz dostosowanie do obecnych czasów. Ten rodzaj powłoki również domyślnie jest instalowany w wielu dystrybucjach Linuksa i Red Hat nie jest w tym temacie wyjątkiem. W tym rodziale chciałbym omówić najważnejsze funkcje tej powłoki oraz jej skrypty startowe, dzięki którym będziemy mogli dostować ją do swoich potrzeb.
7.1. Funkcje powłoki BASH
BASH w swojej kolekcji posiada masę funkcjonalności, których próżno szukać w innych powłokach. Dla przykładu w nowszych dystrybucjach, skrypt powłoki zastępują podstawowe narzędzia systemowe, będące kiedyś pełnoprawnymi programami.
7.1.1. Zmienne
Korzystając z powłoki możemy używać zmiennych, czyli opisanych miejsc alokowanych w pamięci do przechowywania dowolnych wartości. Do dyspozycji mamy dwa rodzaje zmiennych - zmienne lokalne oraz zmienne środowiskowe.
Zmienne lokalne są dostępne tylko w obecnej sesji powłoki. Tego typu zmienne nie będą widoczne dla uruchomionych w tej sesji skryptów czy programów, gdyż są przechowywane tylko i wyłącznie w obszarze pamięci należącym do tego procesu powłoki. Taka zmienną możemy zdefiniować podając w wierszu polecenia jej nazwę, następnie znak równości oraz wartość. Warto dodać aby nie było między tymi elementami żadnej spacji. Poniższy przykład na pewno to rozświetli.
[user@server1 ~]$ zmienna=2137
Po wykonaniu takiego polecenia, powłoka utworzy zmienną i nada jej podaną wartość, po czym zwróci znak zachęty.
Do takiej zmiennej możemy odwołać się podczas pisania polecenia wystarczy poprzedzić nazwę znakiem dolara ($).
[user@server1 ~]$ echo $zmienna 2137
Polecenie echo
wypisuje wszystko co
do zostanie mu podane jako argument na standardowe wyjście (o tym
będzie w dalszej częsci materiału). Jak widzimy polecenie wypisało
zawartość zmiennej.
Innymi zmiennymi są zmienne środowiskowe przechowują one różnego rodzaju wartość, które mogą wpływać na działanie programów. Każdy program uruchomiony na Linuksie dostaje od procesu nadrzędnego obszar pamięci zmiennych środowiskowych, które może wykorzystywać do sobie tylko znanych celów. Definicja takich zmiennych, różni się tym, że poprzedza się ją poleceniem export, którego zadaniem jest przeniesienie zmiennej lokalnej do pamięci zmiennych środowiskowych.
[user@server1 ~]$ export ZMIENNA=2137
Nazwy zmiennych środowiskowych zapisujemy za pomocą wielkich liter aby odróżnić je od zmiennych lokalnych. Dostęp do takiej zmiennej możemy uzyskać, kiedy uruchomimy jakiś program w tej powłoce, aby otrzymał on od powłoki, w której został uruchomiony (procesu nadrzędnego) obszar zmiennych środowiskowych. Najlepiej by było aby takim programem była kolejna powłoka (podpowłoka).
[user@server1 ~]$ bash [user@server1 ~]$ echo $ZMIENNA 2137
Po uruchomieniu podpowłoki wydałem polecenie, które wyświetliło mi zawartość zmiennej, którą zdefiniowałem jako zmienną środowiskową w poprzednim przykładzie.
Wszystkie zmienne środowiskowe w systemie możemy wypisać za pomocą polecenia env lub polecenia printenv. Oto fragment listingu zmiennych środowiskowych z mojego systemu:
[user@server1 ~]$ env ... TERM=xterm-256color LESSOPEN=||/usr/bin/lesspipe.sh %s USER=user SELINUX_USE_CURRENT_RANGE= ZMIENNA=2137 SHLVL=2 XDG_SESSION_ID=7 XDG_RUNTIME_DIR=/run/user/1000 SSH_CLIENT=192.168.122.1 34956 22 which_declare=declare -f ...
Natomiast za pomocą polecenia set możemy wypisać wszystkie zmienne dostępne w systemie, łącznie z lokalnymi zmiennymi powłoki.
[user@server1 ~]$ set ... SHLVL=1 SSH_TTY=/dev/pts/0 TERM=xterm-256color UID=1000 USER=user XDG_DATA_DIRS=/home/user/.local/share/flatpak/exports/share:/var/lib/flatpak/exports/share:/usr/local/share:/usr/share XDG_RUNTIME_DIR=/run/user/1000 XDG_SESSION_CLASS=user XDG_SESSION_ID=7 XDG_SESSION_TYPE=tty ZMIENNA=2137 _=set _backup_glob='@(#*#|*@(~|.@(bak|orig|rej|swp|dpkg*|rpm@(orig|new|save))))' colors=/home/user/.dircolors new_dirs=/home/user/.local/share/flatpak/exports/share:/var/lib/flatpak/exports/share which_opt=-f which_shell=bash zmienna=2137 zmienna1=2137 ...
Zmienne, które nie są już potrzebne możemy usunąć za pomocą polecenia unset.
[user@server1 ~]$ set | grep 'zmienna1' zmienna1=2137 [user@server1 ~]$ unset zmienna1 [user@server1 ~]$ echo $zmienna1
Przy odwołaniu się do zmiennej, polecenie echo zwróciło pusty wiersz.
Manipulując zmiennymi w powłoce może zmienić znak zachęty, ponieważ jego definicja jest przechowywana w zmiennej PS1:
[user@server1 ~]$ echo $PS1 [\u@\h \W]\$
Te poprzedzone lewym ukośnikiem \ litery są kolejnymi elementami znaku zachęty. Opis tych elementów znajduje się na stronie podręcznika polecenia/powłoki BASH w rozdziale PROMPTING.
7.1.2. Podstawienie polecenia
Często wykorzystywaną funkcją wraz z zmiennymi jest podstawienie polecenia. Polega ono na uruchomieniu, przez podpowłokę polecenia ujętego albo w okrągły nawias poprzedzony znakiem dolara ($()) albo w ukośny cudzysłów (``). Informacja zwracana przez polecenie trafia albo do zmiennej albo bezpośrednio jako argument polecenia.
[user@server1 ~]$ export KERNEL_VERSION=$(uname -r) [user@server1 ~]$ echo $KERNEL_VERSION 5.14.0-70.13.1.el9_0.x86_64
Poniżej znajduje się przykład użycia podstawienia polecenia w innym poleceniu:
[user@server1 ~]$ sudo find / -name *`uname -r` -print 2> /dev/null /boot/vmlinuz-5.14.0-70.13.1.el9_0.x86_64 /boot/System.map-5.14.0-70.13.1.el9_0.x86_64 /boot/config-5.14.0-70.13.1.el9_0.x86_64 /usr/lib/firmware/5.14.0-70.13.1.el9_0.x86_64 /usr/lib/modules/5.14.0-70.13.1.el9_0.x86_64 /usr/share/doc/kernel-keys/5.14.0-70.13.1.el9_0.x86_64
Gwiazdka (*) w tym przypadku oraz
2>
, również są elementami połoki,
które sobie omówimy.
7.1.3. Przekierowanie strumieni
Na Uniksach mamy doczynienia z trzema rodzajami strumieni danych, owe strumienie łączą ze sobą np. urządzenia z programami, dlatego pisząc na klawiaturze możemy wprowadzać tekst do programu, albo programy mogą wypisać wynik swojego działnia do okna terminala. Pierszy strumień to strumień standardowegp wejścia źródłem jego danych jest najczęściej klawiatura. Jego identyfikatorem jest 0 (programy używają identyfikatorów do korzystania ze strumieni, my też będziemy podłaczając jeden strumień do drugiego). Drugi strumień danych, to strumień standarowego wyjścia źródłem jego danych jest najczęściej program (jądro podczas uruchamiania programu przekazuje mu kopie strumieni), jego identyfikatorem jest 1, a podłączony jest on do terminala. Ostatnim strumieniem jest strumień błędów jego źródłem danych są komunikaty diagnostyczne programów, jest on najczęciej podłączony razem ze strumieniem wyjścia do terminala. Identyfikatorem strumienia błędów jest 2.
Przekierowania strumienia standardowego wyjścia dokonujemy w wierszu polecenia poprzez podanie znaku większości (>) a następnie podajemy miejse docelowe na dane. Na przykład wynik listowania katalogu /etc możemy umieścić w pliku.
[user@server1 ~]$ ls -l /etc > ls.out [user@server1 ~]$ head -5 ls.out total 1320 drwxr-xr-x. 3 root root 28 Jun 26 13:50 accountsservice -rw-r--r--. 1 root root 16 Jun 26 14:01 adjtime -rw-r--r--. 1 root root 1529 Jun 23 2020 aliases drwxr-xr-x. 3 root root 65 Jun 26 13:54 alsa
Użycie pojedynczego znaku większości przekieruje strumień w tym przypadku do pliku oraz nadpisze informacje zawarte w nim. Jeśli plik nie istnieje to zostanie on utworzony.
Nadpisywanie danych za pomocą przekierowania strumieni nazywane jest
clobberingiem. Możemy zablokować tę funkcję za pomocą
polecenia set -o noclobber
, wówczas
gdy plik będzie istnieć pokaże nam się taki komunikat jak na poniższym
przykładzie.
[user@server1 ~]$ ls -l /etc > ls.out -bash: ls.out: cannot overwrite existing file
Funkcję można włączyć z powrotem za pomocą polecenia
set +o noclobber
.
Chcąc dopisać do zawartości pliku, zawartość strumienia możemy użyć podwójnego znaku większości (>>). Na przykład:
[user@server1 ~]$ ls -l /var >> ls.out [user@server1 ~]$ cat ls.out total 4 drwxr-xr-x. 2 user4000 g1 6 Jun 26 16:06 d6 srwxrwxrwx. 1 gdm gdm 0 Jun 30 13:59 dbus-aIxoyUxXnM srwxrwxrwx. 1 gdm gdm 0 Jun 30 09:38 dbus-JRmt27fCi0 drwxr-xr-x. 2 user200 dba 6 Jun 26 15:33 dir10 -rw-r--r--. 1 user4000 dba 0 Jun 26 16:06 f6 -rw-r--r--. 1 user200 user100 0 Jun 26 15:33 file10 -rw-r--r--. 1 user user 2400 Jun 30 14:57 ioerror ... total 16 drwxr-xr-x. 2 root root 19 Jun 26 13:54 account drwxr-xr-x. 2 root root 6 Aug 10 2021 adm drwxr-xr-x. 18 root root 4096 Jun 26 14:12 cache drwxr-xr-x. 2 root root 6 Mar 7 04:37 crash drwxr-xr-x. 3 root root 18 Jun 26 13:50 db drwxr-xr-x. 2 root root 6 Aug 10 2021 empty ...
Z racji tego, iż znak większości służy do przekierowania jedynie wyjścia to aby przekierować strumień błedów, należy podać przez znakiem jego identyfikator.
[user@server1 ~]$ ls -l /dvd 2> err.out [user@server1 ~]$ cat err.out ls: cannot access '/dvd': No such file or directory
Czasami może się zdarzyć, iż będzie potrzeba przekierowania obu tych strumieni, wówczas trzeba skorzystać z podłączenia jednego strumienia do drugiego.
[user@server1 ~]$ ls -l /tmp /sdir > ls2.out 2>&1 [user@server1 ~]$ cat ls2.out ls: cannot access '/sdir': No such file or directory /tmp: total 4 drwxr-xr-x. 2 user4000 g1 6 Jun 26 16:06 d6 srwxrwxrwx. 1 gdm gdm 0 Jun 30 13:59 dbus-aIxoyUxXnM srwxrwxrwx. 1 gdm gdm 0 Jun 30 09:38 dbus-JRmt27fCi0 drwxr-xr-x. 2 user200 dba 6 Jun 26 15:33 dir10 -rw-r--r--. 1 user4000 dba 0 Jun 26 16:06 f6 -rw-r--r--. 1 user200 user100 0 Jun 26 15:33 file10 -rw-r--r--. 1 user user 2400 Jun 30 14:57 ioerror ...
To polecenie można zapisać również w inny sposób. Na przykład:
ls -l /tmp /sdir &> ls2.out
.
Obie formy są poprawne i obie robią to samo, która będzie dla nas
lepsza musimy zdecydować sami.
Odnośnie egzaminu:
Jednym z zadań egzaminacyjnych może być wykonanie polecenia z
przekierowaniem wyjścia lub/i strumienia błędów do pliku.
Kolejnym rodzajem przekierowania jest przekierowanie wejścia, jednak jest ono dość rzadko stosowane. Do tego rodzaju przekierowania stosuje się znak mniejszości (<). Jednym z przykładów jest polecenie użycie polecenia tar, jednak nie ma ono sensu, ponieważ istnieje opcja -f, która pozwala na podanie ścieżki do pliku.
[user@server1 ~]$ tar -x -C /tmp < etc.tar [user@server1 ~]$ ls -l /tmp total 16 drwxr-xr-x. 2 user4000 g1 6 Jun 26 16:06 d6 srwxrwxrwx. 1 gdm gdm 0 Jun 30 13:59 dbus-aIxoyUxXnM srwxrwxrwx. 1 gdm gdm 0 Jun 30 09:38 dbus-JRmt27fCi0 drwxr-xr-x. 2 user200 dba 6 Jun 26 15:33 dir10 drwxr-xr-x. 132 user user 8192 Jun 30 09:38 etc ...
Ostatni rodzaj przekierowania, to potok, o potoku jeszcze będzie w tym rozdziale.
7.1.4. Historia poleceń
Dość istotną funkcją powłoki BASH jest historia poleceń. Pozwala ona zaoszczędzić pisania w szczególności długich poleceń czy poleceń potokowych (ang. pipelines). Posiada ona funkcję wyszukiwania oraz swobodny dostęp do poleceń umieszczonych w historii.
Aby wyświetlić polecenia z historii, należy użyć polecenia history, wyświetli ono listę poleceń z numerami na początku, każde polecenie to jedna linia. Numer porządkowy pomoże nam się odwołać do polecenia podczas jego wywoływania, ponieważ nie potrzeba szukać polecenia czy przebierać ich wszystkich za pomocą niżej opisanych klawiszy. Wystarczy znać jego numer. Poniżej znajduje się fragment listy historii poleceń z mojego systemu:
[user@server1 ~]$ history 1 id 2 groups 3 su 4 su - 5 cat /etc/sudoers 6 su - root 7 sudo cat /etc/sudoers 8 su - root 9 sudo cat /etc/sudoers 10 su - root 11 sudo yum update 12 su - root 13 touch file1 ...
Wyświetlenie listy poleceń w historii możemy ograniczyć podajac w jako argument ilość wyświetlanych linii. Polecenie wyświetli wówczas polecenia od końca listy (ostatnio dodane).
[user@server1 ~]$ history 10 266 rm etc.tar 267 sudo tar -cvf etc.tar /etc 268 tar -x -C /tmp < etc.tar 269 ls -al /tmp 270 ls -l /tmp 271 history 272 touch file1 273 sudo poweroff 274 touch file1 275 history 10
Za pomocą opcji -d możemy usunać wybrane polecenie z historii.
[user@server1 ~]$ history 10 266 rm etc.tar 267 sudo tar -cvf etc.tar /etc 268 tar -x -C /tmp < etc.tar 269 ls -al /tmp 270 ls -l /tmp 271 history 272 touch file1 273 sudo poweroff 274 touch file1 275 history 10 [user@server1 ~]$ history -d 271 [user@server1 ~]$ history 10 267 sudo tar -cvf etc.tar /etc 268 tar -x -C /tmp < etc.tar 269 ls -al /tmp 270 ls -l /tmp 271 touch file1 272 sudo poweroff 273 touch file1 274 history 10 275 history -d 271 276 history 10
Na informacji zwracanej przez wcześniejsze wywołanie polecenia
history 10
w linii
271
widnieje polecenie
history
, natomiast na drugim wywołaniu
po usunięciu tego polecenia pod tym numerem widnieje już inne.
Wśród poleceń w historii możemy poruszać się za pomocą strzełek w górę oraz w dół lub kombinacji klawiszy (co jest bardziej zalecene) Ctrl+p (poprzednie polecenie) oraz Ctrl+n (następne polecenie). Możemy je również wyszukiwać po przez wciśnięcie kombinacji klawiszy Ctrl+r i podanie fragmentu polecenia. Czasmi wyszukiwanie może nie przynieść skutku, wówczas należy nacisnać Ctrl+c i spróbować ponownie.
Do poleceń w historii odnosimy się wprowadzając w wierszu polecenia
wykrzyknik (!) następnie możemy podać numer z listy.
Dla przykładu użyje polecenia numer 13
z fragmentu listy z pierwszego przykładu.
[user@server1 ~]$ !13 touch file1 touch: cannot touch 'file1': Permission denied
Możemy również podać litery rozpoczynające polecenie na przykład:
[user@server1 ~]$ !tou touch file1 touch: cannot touch 'file1': Permission denied
Ta instrukcja podstawi najczęstsze wystąpienie polecenia rozpoczynającego się o tych liter. Podobną metodą jest podanie fragmentu polecenia zawierającego jakiś ciąg znaków, na przykład:
[user@server1 ~]$ !?file? touch file1 touch: cannot touch 'file1': Permission denied
To polecenie podstawi najczęściej występujące polecenie z historii
zawierające ciąg znaków file
.
Za pomocą polecenia wykrzyknika możemy odwołać się do ostatniego polecenia podając drugi wykrzyknik. Tą metodę możemy zastosować w przypadku gdy zapomnimy o sudo przy wydawaniu poleceń administracyjnych.
[user@server1 ~]$ cat /var/log/secure cat: /var/log/secure: Permission denied [user@server1 ~]$ sudo !! sudo cat /var/log/secure [sudo] password for user: Jun 26 14:12:08 server1 polkitd[725]: Loading rules from directory /etc/polkit-1/rules.d Jun 26 14:12:08 server1 polkitd[725]: Loading rules from directory /usr/share/polkit-1/rules.d Jun 26 14:12:08 server1 polkitd[725]: Finished loading, compiling and executing 12 rules Jun 26 14:12:08 server1 polkitd[725]: Acquired the name org.freedesktop.PolicyKit1 on the system bus ...
Historię możemy wyłączyć używając polecenia
set -o history
. Włączenie historii
wymaga polecenia set +o history
.
Historia kontrolowana jest za pomocą trzech zmiennych
HISTSIZE, której wartość jest równoznaczna z ze zmienną
HISTFILESIZE oraz HISTCONTROL. Ich opisy znajdują
się na stronie podręcznika polecenia bash. Natomiast ścieżka
do pliku zawierającego historie z poprzednich sesji znajduje się w
zmiennej HISTFILE.
7.1.5. Edycja wiersza polecenia
Za pomocą strzałek w lewo oraz w prawo, możemy przesuwać kursor w wierszu polecenia, jednak istnieją znacznie bardziej efektywne sposoby na edycje wpisanego polecenia.
- Ctrl+a - przenosi kursor na początek wiersza.
- Ctrl+e - przenosi kursor na koniec wiersza.
- Ctrl+f - przenosi kursor o jeden znak w prawo.
- Ctrl+b - przenosi kursor o jeden znak w lewo.
- Alt+f - przenosi kursor o jedno słowo w prawo.
- Alt+b - przenosi kursor o jedno słowo w lewo.
- Ctrl+u - usuwa wszystko z linii polecenia.
Te skróty pozwalają na sprawniejsze poruszenie się w wierszu polecenia.
7.1.6. Uzupełnianie poleceń
Chcąc przyspieszyć pisanie poleceń możemy wykorzystać uzupełnianie poleceń. W wierszu polecenia zapisujemy fragment polecenia lub ścieżki następnie naciskamy klawisz Tab. Powłoka uzupełni nasz zapis do wspólnej części z na przykład nazwami plików, katalogów czy poleceń. Po następnym naciśnięciu tego klawisza, powłoka zwróci możliwe warianty pasujące do tego co zapisaliśmy.
[user@server1 ~]$ deb #Pierwsze naciśnięcie klawisza Tab [user@server1 ~]$ debug #Drugie naciśnięcie klawisza Tab [user@server1 ~]$ debug debugfs debuginfod-find [user@server1 ~]$ debug
Kiedy dopiszemy kilka liter z jednego z wariantów, polecenie dopełni je pozostałymi lub zwróci zawężoną ilość możliwych do wyboru elementów.
7.1.7. Podstawienie tyldy
Tylda w powłoce oznacza jedno - katalog domowy użytkownika. Za jej pomocą możemy w prosty sposób odwoływać się do elementów w katalogu domowym użytkownika ale i nie tylko. Poniżej przedstawiłem trzy zastosowania podstawienia tyldy.
- ~/Dokumenty - odwołanie się do elementu znajdującego się w katalogu domowym użytkownika.
- ~+ - odwołanie się do obecnego katalogu roboczego (wyświetla ścieżkę bezwzględną obecnego katalogu roboczego), równoznaczne z podstawiemiem polecenia pwd.
- ~- - odwołanie się do poprzedniego katalogu roboczego, podstawienie również zwraca ścieżkę bezwzględną do katalogu, w którym się znajdowaliśmy przed przejściem do obecnego.
Podstawienie tyldy może zaoszczędzić nam czas oraz zmieniejszyć ilość pisania. Poniżej znajduje się kilka przykładów prezentujących powyższe podstawienia.
[user@server1 logs]$ echo ~+ /home/user/logs [user@server1 logs]$ echo ~ /home/user [user@server1 logs]$ cd /etc [user@server1 etc]$ echo ~- /home/user/logs
7.1.8. Aliasy
Alias to nazwa zastępcza, dzięki której możemy zastąpić długie polecenia za pomocą pojedynczego wyrazu. Aliasy definiowane są pomocą polecenia alias, jako argument przyjmuje on definicję aliasów, czyli nazwę zastępnczą, znak równości oraz polecenie w podwójnych apostrofach. Między tym elementami nie powinno być spacji. Poniżej znajduje się definicja aliasów, który szuka w katalogu domowym plików powyżej 1 GB a następnie zwraca ich atrybutu.
alias bigfiles="find ~ -size +1G -exec ls -lh {} \;" [user@server1 ~]$ bigfiles -rw-r--r--. 1 user user 1.5G Jul 1 12:55 /home/user/test.img
Ważną rzeczą związna z aliasami jest fakt iż kiedy powłoka otrzymuje polecenie do interpretacji to sprawdza na początku czy nie jest ono aliasem i jeśli tak jest to wykonuje to co znajduje się pod nim. Aliasy mogą mieć takie same nazwy jak programy czy inne polecenia w systemie, dlatego też mogą je przesłaniać. Tak jest w przypadku superużytkownika z poleceniami cp, mv czy rm. Poniższy przykład dobrze to obrazuje.
[user@server1 ~]$ alias rm="rm -i" [user@server1 ~]$ rm test.img rm: remove regular file 'test.img'? n
Aby powłoka nie brała nazwy polecenia przy poszukiwaniu aliasów, należy poprzedzić ją znakiem lewego ukośnika czy backslashu (\).
[user@server1 ~]$ rm logs rm: remove symbolic link 'logs'? n [user@server1 ~]$ \rm logs
Usuwaniu aliasów służy polecenie unalias.
[user@server1 ~]$ unalias bigfiles [user@server1 ~]$ bigfiles bash: bigfiles: command not found...
7.1.9. Metaznaki oraz nazwy wieloznaczne
Chcąc odwołać się do wielu elementów posiadających wspólne fragmenty nazw możemy użyć tzw. metaznaków lub nazw wieloznacznych, służą one podstawianiu znaków pod używane wraz z nim nazwy. Załóżmy że mamy dwa rodzaje archiwów w katalogu jedne rozpoczynają się od nazwy backup a drugie od nazwy d kazde archiwum zawiera w nazwie po podanej części myślnik oraz datę. Chcemy wyświetlić atrybuty archiwów z nazwą zaczynającą się od d w tym celu możemy użyć nazwy wieloznacznej. Podstawiając za nazwą gwiazdkę.
[js@fujitsu windows]$ ls -l D* -rwxr--r-- 1 windows windows 11718211581 05-01 21:09 D-2022-05-01.7z -rwxr--r-- 1 windows windows 11718211581 05-02 21:08 D-2022-05-02.7z -rwxr--r-- 1 windows windows 11718211581 05-03 21:08 D-2022-05-03.7z -rwxr--r-- 1 windows windows 11718269229 05-04 21:15 D-2022-05-04.7z -rwxr--r-- 1 windows windows 11718658739 05-05 21:14 D-2022-05-05.7z -rwxr--r-- 1 windows windows 11718634289 05-06 21:14 D-2022-05-06.7z -rwxr--r-- 1 windows windows 11718634289 05-07 21:08 D-2022-05-07.7z -rwxr--r-- 1 windows windows 11718634289 05-08 21:08 D-2022-05-08.7z -rwxr--r-- 1 windows windows 11718633900 05-09 21:15 D-2022-05-09.7z ...
Do stosowania nazw wieloznacznych, możemy stosować wiele znaków ich opis znajduje się na liście poniżej.
- * - gwiazdka, ten symbol podstawia dowolną ilość
dowolnych znaków. Mogą one w ogóle nie występować.
[user@server1 ~]$ ls -l D* -rw-r--r--. 1 user user 0 Jul 1 13:39 D
- ? - znak zapytania, pojedynczy dowolny znak.
[user@server1 ~]$ ls -l ??.* -rw-r--r--. 1 user user 2732 Jun 30 19:14 ls.out
- [] - nawias kwadratowy, zakresy lub lista znaków.
Lista znaków:
[user@server1 ~]$ ls -l /dev/*[ty] crw-------. 1 root root 10, 126 Jul 1 11:00 /dev/cpu_dma_latency crw-------. 1 root root 10, 228 Jul 1 11:00 /dev/hpet crw-r-----. 1 root kmem 1, 4 Jul 1 11:00 /dev/port crw-------. 1 root root 10, 231 Jul 1 11:00 /dev/snapshot lrwxrwxrwx. 1 root root 15 Jul 1 11:00 /dev/stdout -> /proc/self/fd/1 crw-rw-rw-. 1 root tty 5, 0 Jul 1 13:03 /dev/tty
Zakres:[user@server1 ~]$ sudo ls -ld /etc/systemd/system/[m-o]* drwxr-xr-x. 2 root root 4096 Jun 26 13:54 /etc/systemd/system/multi-user.target.wants drwxr-xr-x. 2 root root 48 Jun 26 13:50 /etc/systemd/system/network-online.target.wants
Zakresy oraz listy znaków mogą zostać zanegowane za pomocą wykrzyknika.[user@server1 ~]$ sudo ls -ld /etc/systemd/system/[!m-o]* [sudo] password for user: drwxr-xr-x. 2 root root 65 Jun 26 13:54 /etc/systemd/system/basic.target.wants drwxr-xr-x. 2 root root 31 Jun 26 13:50 /etc/systemd/system/bluetooth.target.wants ...
Powyższe przypasowane elementy nie zawierają liter od m-o na początku swoich nazw.
Stosując nazwy wieloznaczne możemy automatycznie wykonywać te same polecenia na elementach posiadających wspólne nazwy.
7.1.10. Potoki i polecenia potokowe
Omawiając przkierowania strumieni wspomniałem o potokach. Potok to przekierowanie wyjścia jednego polecenia na wyjście drugiego za pomocą znaku pionowej kreski (|).
[user@server1 ~]$ ls -l /etc | head total 1320 drwxr-xr-x. 3 root root 28 Jun 26 13:50 accountsservice -rw-r--r--. 1 root root 16 Jun 26 14:01 adjtime -rw-r--r--. 1 root root 1529 Jun 23 2020 aliases drwxr-xr-x. 3 root root 65 Jun 26 13:54 alsa drwxr-xr-x. 2 root root 4096 Jun 26 13:58 alternatives -rw-r--r--. 1 root root 541 Aug 9 2021 anacrontab -rw-r--r--. 1 root root 769 Aug 28 2021 appstream.conf -rw-r--r--. 1 root root 55 Feb 11 10:53 asound.conf -rw-r--r--. 1 root root 1 Aug 9 2021 at.deny
Za pomocą potoków możemy łączyć polecenia w długie łańcuchy przekazując strumień wyjściowy wychodzący z innych poleceń na wejście kolejnych. Polecenia tego typu nazwyane są poleceniami potokowymi. Poniżej znajduej się jedno z nich.
[user@server1 ~]$ ls -l /etc | sed -n '15p' | awk '{printf $1}'
Powyższe polecenie wyświetli pierwszą kolumnę atrybutów pliku z
15 lini zawartości katalogu /etc. Polecenia
sed
oraz
awk
znajdują się poza zakresem
merytorycznym tego materiału.
7.1.11. Cytowanie
Za tą enigmatyczną nazwą stoją mechanizmy, których możemy użyć, aby znaki specjalne w powłoce, by traktowane jako zwykłe znaki bez żadnego specjalnego znaczenia. Pierwszym z nich jest użycie lewego ukośnika (\). Jeśli na przykład stworzyślimy plik on nazwie *. To jeśli spróbujemy go usunąć bez żadnego cytowania usuniemy wszystko co znajduje się w katalogu.
[user@server1 ~]$ rm \* rm: remove regular empty file '*'? y [user@server1 ~]$ ls D err.out etc.tar file1 ls2.out ls.out test.img
Jak widać na załączonym przykładzie moim plikom nic się nie stało. Używanie lewego ukośnika może być uciążliwe jeśli do zacytowania mamy więcej niż jeden znak. Wówczas możemy się posłużyć pojedynczym apostrofem (''). Wszystko co zostanie umieszczone miedzy nimi, będzie traktowane dosłownie. Najprostszym przykładem użycia jest odwołanie się do zmiennej.
[user@server1 ~]$ zmienna='abc' [user@server1 ~]$ echo $zmienna abc [user@server1 ~]$ echo '$zmienna' $zmienna
Gdy odwołaliśmy się do zmiennej w pojedynczych cudzysłowach, znak
dolara został potraktowany dosłownie, więc polecenie
echo
wypisało ciąg znaków
$zmienna
. Ostatnim rodzajem cytowania
podobnym do pojedynczego apostrofu jest podwójny apostrof. Zauważalną
różnicą jest to, iż podwójny apostrof pozwala na użycie specjalnego
znaczenia takich znaków jak: lewy ukośnik (\),
znak dolara ($) oraz pojedynczy apostrof
(''), dzięki czemu wewnątrz literałów prezentowanych
za pomocą podwójnych apostrofów możemy uzyskać wartości zmiennych.
[user@server1 ~]$ echo "Pierwszym literami alfabetu są litery $zmienna" Pierwszym literami alfabetu są litery abc
7.1.12. Wyrażenia regularne
Wyrażenia regularne służą wyszukiwaniu wzorców w tekście. Wzorce składają się z ze znaków specjalnych oraz innych zwykłych znaków mających przybliżyć odnalezienie wzorca. Wyrażenia regularne w powłoce możemy obsługiwać za pomocą polecenia grep. W tym materiale również używaliśmy wyrażeń regularnych przy wyświetlaniu zawartości pliku /etc/login.defs
[user@server1 ~]$ grep -v -e '^#' -e '^$' /etc/login.defs MAIL_DIR /var/spool/mail UMASK 022 HOME_MODE 0700 PASS_MAX_DAYS 99999 PASS_MIN_DAYS 0 PASS_WARN_AGE 7 ...
Na powyższym przykładzie widzimy składnie polecenia, źródłem danych nie musi być wyłącznie plik, równie dobrze mogą one pochodzić z przekierowania. Na przykład z potoku. Najpierw jednak zajmiemy się czymś prostszym, a do tego poziomu dojdziemy pod koniec. Najprostszym wyrażeniem może być zwykły ciąg znaków.
[user@server1 ~]$ grep 'pass' /etc/login.defs # passwd command) should therefore be configured elsewhere. Refer to # PASS_MAX_DAYS Maximum number of days a password may be used. # PASS_MIN_DAYS Minimum number of days allowed between password changes. # PASS_MIN_LEN Minimum acceptable password length. # PASS_WARN_AGE Number of days warning given before a password expires.
Jak możemy zauważyć polecenie zwróciło wszystkie linie zawierające wyrażenie jakie podaliśmy przed ścieżką do pliku. Podane wyrażenie zapisaliśmy za pomocą małych liter i takie też zostało przypasowane jeśli chcemy, aby nie była rozrózniana wielkość liter należy użyć opcji -i.
[user@server1 ~]$ grep -i 'pass' /etc/login.defs # passwd command) should therefore be configured elsewhere. Refer to # Password aging controls: # PASS_MAX_DAYS Maximum number of days a password may be used. # PASS_MIN_DAYS Minimum number of days allowed between password changes. # PASS_MIN_LEN Minimum acceptable password length. # PASS_WARN_AGE Number of days warning given before a password expires. PASS_MAX_DAYS 99999 PASS_MIN_DAYS 0 PASS_WARN_AGE 7
Poniżej umieściłem listę znaków wykorzystywanych do tworzenie wyrażeń regularnych wraz z opisem.
- . - pojedynczy dowolny znak,
- * - przypasowanie wzorca min. 0 razy lub więcej razy.
- + - przypasowanie wzorca min. 1 raz lub więcej razy.
- ^ - metaznak oznaczający początek wiersza. Wzorzec rozpoczynający się od tego znaku znajduje się na początku wiersza.
- $ - metaznak oznaczający koniec wiersza. Wzorzec zakończony tym znakiem znajduje się na końcu wiersza.
- [] - metaznak ozanaczający zbiory oraz zakresu. Zakresy mogą być różne: litery [a-z], wielkie litery [A-Z] czy cyfry [0-9]. Zakresy nie muszą być pełne, mogą być np. od a do o - [a-o].
- [^...] - negacja zbioru, zamiast trzech kropek wstawiamy znaki. Przypasowanie następuje wówczas, kiedy we wzorcu nie znajdują się podane znaki.
Wiecęj znaków oraz informacji znajduje się na stronie podręcznika
polecenia grep man grep
oraz
na stronie podręcznika poświęconej wyrażeniom regularnym:
man 7 regex
. Teraz przedstawie kilka
dodatkowych opcji polecenia grep.
- -E - opcja umożliwia użycie rozszerzonych
wyrażeń regularnych, jedną z ciekawych opcji tego trybu jest użycie
alternatyw, czyli dodatkowych wzorców. Kiedy
nie będzie przypasowań do pierwszego wzorca grep sprawdzi
pozostałe. Alternatywy zapisuje się po znaku potoku, po
kresce pionowej |.
[user@server1 ~]$ cat colors blue yellow green orange white black [user@server1 ~]$ grep -E 'red|white' colors white
- -v - odwraca przypasowanie wzorca, polecenie wówczas wypisze wszystkie linie nie pasujące do wzorca.
- -o - zamiast całych wierszy, polecenie zwróci tylko pasujący do wzorca fragment danych.
Wiecej opcji znajduje się na stronie podręcznika polecenia grep. Myślę, że teraz bez problemu jesteśmy w stanie zrozumieć przykład z początku tego podrozdziału.
Odnośnie egzaminu:
Polecenie grep jest poręcznym narzędziem stosowany do
wyłuskiwania informacji z pliku lub wyjścia polecenia. Wybrane
informacje mogą zostać przekierowane do pliku, pozostawiając dane
wejściowe nienaruszone.
7.1.13. Zarządzanie zadaniami
Uruchamiając jakiś program w terminalu, możemy go odłączyć od niego i przekazać jego wykonanie do tła. Wówczas taki program staje się zadaniem. Program kontynuje swoje wykonanie w tle, ale jest kontrolowany przez terminal, w którym został uruchomiony. W podpowłoce uruchomiłem plik test, który jest mały skryptem, który tak naprawdę nic nie robi.
[user@server1 ~]$ bash test
Użyłem kombinacji klawiszy Ctrl+z, aby zatrzymać wykonanie.
[user@server1 ~]$ bash test ^Z [1]+ Stopped bash test
W ostatniej linii, na początku w nawiasie kwadratowym znajduje się numer zadania. Za pomocą tego numeru możemy odwoływać się do zadania. Teraz uruchomimy je w tle.
[user@server1 ~]$ bg %1 [1]+ bash test &
Do uruchomienia zadania w tle służy polecenie bg, Do odwołania się do niego służą numery zadań poprzedzone znakiem procentu (%). Możemy przywrócić działanie zadania na pierwszy plan przywołując je za pomocą polecenia fg, metoda odwołania się do zadania jest taka sama jak w przypadku polecenia bg. Zanim przełaczym zadanie na pierwszy plan, sprawdźmy jego status za pomocą polecenia jobs.
[user@server1 ~]$ jobs [1]+ Running bash test &
Teraz możemy przełączyć polecenie, aby finalnie je zamknąć za pomocą klawiszy Ctrl + c.
[user@server1 ~]$ fg %1 bash test ^C
W ten sposób zarządza się zadaniami za pomocą mechanizmów powłoki. Zadań przekazanych do tła systemu, może być wiele. Zadania nie zostaną zakończone w momencie wylogowania się z systemu. Dlatego jeśli wykonanie jakiego zadania, będzie wymagać czasu mozemy przenieść je do tła. Przy planach użycia tła systemu warto wziąć po uwagę to, aby przekierować wyjście programów/poleceń do jakiegoś pliku lub do urządzenia /dev/null, które ma jedno zadanie. Ignorować wszelkie napływające do niego dane.
Chcąc uruchomić jakieś zadanie w tle odrazu, możemy pominąć tą całą zabawę w jego zatrzymywanie i przekazywanie do tła. Możemy uruchomić je od razu kończąc polecenie znakiem ampersendu (&).
[user@server1 ~]$ bash test & [1] 14048 [user@server1 ~]$ jobs [1]+ Running bash test &
7.2. Pliki startowe powłoki
Plik startowe powłoki mają za zadanie wykonać kilka czynności konfiguracjynych, aby użytkownik po jej uruchomieniu nie musiał tracić czasu na ustawienie na przykład ścieżki wszukiwania poleceń, czyli zmiennej PATH. Pliki te definiują również aliasy, które jak do tej pory mogły się wydawać zwykłymi poleceniami. Pliki startowe powłoki możemy podzielić na pliki globalne (mające zastosowanie dla całego systemu) oraz pliki lokalne (mające zastosowanie tylko dla jednego użytkownika).
7.2.1. Globalne pliki startowe powłoki
Do globalnych plików startowych możemy zaliczyć takie pliki jak /etc/bashrc, /etc/profile oraz katalog /etc/profile.d. Zmiany w tych plikach wpływają na konfigurację powłoki wszystkich użytkowników w systemie. Poniżej znajduje się lista ze skróconym opisem co dane pliki zawierają.
- /etc/bashrc - plik zawiera ustawienia właściwości PROMPT_COMMAND, ustawienia historii, definicje znaku zachęty, maski użytkownika oraz definicje zmiennej środowiskowej SHELL.
- /etc/profile - plik zawiera definicje części zmiennych środowiskowych, dopisuje pewne katalogi do zmiennej PATH.
- /etc/profile.d - katalog zawiera skrypt rozszerzające konfiguracje zawarte w powyższych plikach, te skrypt są uruchamiane przez oba z nich.
Jeśli musimy umieścić dodatkowe konfiguracje w tych plikach najlepiej umieścić je w skrypcie w katalogu /etc/profile.d.
7.2.2. Pliki startowe powłoki użytkownika
Każdy użytkownik posiada swoje pliki startowe powłoki ~/.bash_profile - odpowiadający globalnemu /etc/profile oraz ~/.bashrc - odpowiadający globalnemu /etc/bashrc. Te pliki kopiowane są z katalogu szkieletowego - /etc/skel podczas tworzenia katalogu domowego przy zakładaniu nowego użytkownika. Jeśli zajrzymy do zawartości tych katalogów, to dowiemy się że:
- W pliku ~/.bash_profile umieszczamy dodatkowe zmienne środowiskowe oraz dodatkowe programy lub skrypty startowe.
- W pliku ~/.bashrc umieszczamy dodatkowe aliasy oraz funkcje powłoki (funkcje powłoki wykraczają poza ten materiał).
Pliki startowe powłoki są uruchamione określonej kolejności. W ramach eksperymentu umieściłem, krótką informacje na końcu każdego z nich a następnie wylogowałem się i zalogowałem ponownie. W poniższym bloku kodu, znajduje się wynik tego eksperymentu:
xf0r3m@inspiron-3542:~$ ssh user@rhel9-vm1 user@rhel9-vm1's password: Register this system with Red Hat Insights: insights-client --register Create an account or view all your systems at https://red.ht/insights-dashboard Last login: Sat Jul 2 15:29:33 2022 from 192.168.122.1 Globalny /etc/bashrc Globalny /etc/profile Lokalny ~/.bashrc Lokalny ~/.bash_profile
Jak mogliśmy się domyślić na początku uruchiamiane są pliki globalne a następnie lokalne.
Dodatkowym plikiem użytkownika o nieco innym znaczeniu jest ~/.bash_logout. Czynności zapisane w tym pliku są wykonywane podczas wylogowywania użytkownika.
Odnośnie egzaminu:
Jeśli jedno z zadań będzie dotyczyć dodania aliasu lub zmiennej
środowiskowej, to należy wiedzieć w jakich plikach je umieścić.
Ćwiczenie 1: Zmiana symbolu zachęty
Jako zwykły użytkownik na maszynie server1 dostosuj znak zachęty aby wyglądał jak ten ujęty w podwójne apostrofy "<user@server1 in /etc >:". /etc w tym przypadku jest ścieżką do obecnego katalogu roboczego. Zapisz nową definicję znaku zachęty do odpowiedniego pliku, wyloguje się i zaloguj ponownie następnie usuń tę definicję.
Ćwiczenie 2: Przkierowanie strumieni
Jako zwykły użytkownik na maszynie server1 wyświetl zawartość katalogów /etc, /dvd oraz /var przekieruj standardowe wyjście oraz strumień błędów do pliku /tmp/ioerror Sprawdź zawartość pliku.
Podsumowanie
W tym rodziale zapoznaliśmy się z powłoką BASH. Nauczyliśmy się korzystać z jej mechanizów, poznaliśmy również podstawy wyrażeń regularnych. Na koniec dowiedzieliśmy się jak używać plików startowych powłoki, aby dostosować ją do własnych potrzeb. W następnym rodziale zajmiemy się procesami.
8. Zarządzanie procesami oraz harmonogram zadań
Zarządzanie procesami oraz obsługa harmonogramu zadań jest kolejnym z zadań, które będziemy wykonywać jako administrator systemu Linuks.
8.1. Zarządzanie procesami
Procesy są to odniesienia w pamięci do uruchomionych w systemie programów. Procesy są sposobem organizacji przydzielania zasobów komputera. Struktura procesów w systemie ma charakter hierarchiczny, każdy proces może mieć swoje podprocesy, tzw. procesy potomne. Każdy z procesów posiada swój unikalny identyfikator PID, identyfikator służy jądru do komunikacji z procesami. W systemie istnieje masa procesów, wśród nich możemy wyróżnić takie jak demony, które świadczą usługi użytkownikom oraz innym procesom. Zwykle działają one w tle, oraz pozostają w stanie bezczynności oczekując na żądania od użytkownika lub od innego procesu.
Procesy podczas wykonywania swoich czynności mogą znajdować się w 5 różnych stanach. Stan procesu zależy od tego co robi w danym momencie. Procesy mogą przyjmować następujące stany:
- Running - (pol. uruchomiony), proces jest obecnie wykonywany przez CPU.
- Sleeping - (pol. spanie), proces oczekuje na dane.
- Waiting - (pol. czekanie), proces czeka na swoją kolej do wykonania przez procesor.
- Stopped - (pol. zatrzymany), proces otrzymał sygnał zatrzymania wykonania i nie wznowii go do momentu otrzymiania odpowiedniego sygnału.
- Zombie - (pol. zombie), proces jest martwy, nie posiada już żadnych zasobów. Widnieje wśród innych procesów gdyż czeka na zakończenie przez inny proces.
Procesy podczas swoje cyklu życia w systemie, zmieniają te stany w zależności od tego jaką czynność wykonują. Najczęściej będzie to lawirowanie między trzema pierwszymi. Teraz kiedy znamy charakterystykę procesów możemy przejść do praktyki, a na początku zajmiemy się wyświetlaniem informacji o procesach.
8.1.1. Polecenie ps
Polecenie ps, służy do wyświetlania procesesów w tabeli. Domyślnie to polecenie bez żadnych opcji wyświetli procesy uruchomione w tym oknie terminala.
[user@server1 ~]$ ps PID TTY TIME CMD 1452 pts/1 00:00:00 bash 1891 pts/1 00:00:00 ps
Wynik polecenia podzielony jest na 4 kolumny. Kolumna
PID
zwraca identyfikator procesu,
następnie kolumna TTY
wyświetla
powiązaną z procesem nazwę terminala, na którym został uruchomiony,
później w kolumnie TIME
znajduje się
łączny czas procesora w wyrażony w sekundach poświęcony na wykonanie
tego procesu. Na końcu w kolumnie CMD, znajduje się polecenie
odpowiedzialne za ten proces. To polecenie nie zwraca zbyt wielu
informacji, które mogły by nam pomóc w zarządzaniu procesami. Warto
dodać do tego polecenia kilka opcji.
Jedną z nich może być opcja -e, która zwraca każdy występujący w systemie proces, następną jak warto dodać jest opcja -f, zwracająca wiecej szczegółów nt. procesu, jednak ta opcja nie jest dla nas wystarczająca, ponieważ do zarządzania procesami potrzebujemy jeszcze kilku informacji, które jest w stanie zwrócić nam opcja -l. Te wymienione trzy opcje, tworzą najbardziej powszechne użycie polecenia ps.
[user@server1 ~]$ ps -efl F S UID PID PPID C PRI NI ADDR SZ WCHAN STIME TTY TIME CMD ... 4 S root 1443 849 0 80 0 - 4884 - 10:34 ? 00:00:00 sshd: user [priv] 5 S user 1448 1443 0 80 0 - 4884 - 10:34 ? 00:00:00 sshd: user@pts/1 0 S user 1452 1448 0 80 0 - 56082 do_wai 10:34 pts/1 00:00:00 -bash 1 I root 1828 2 0 80 0 - 0 - 13:15 ? 00:00:00 [kworker/u2:2-events_unbound] 1 I root 1838 2 0 80 0 - 0 - 13:58 ? 00:00:00 [kworker/0:1-events] 1 I root 1851 2 0 80 0 - 0 - 14:02 ? 00:00:00 [kworker/u2:1-events_unbound] 1 I root 1910 2 0 80 0 - 0 - 15:28 ? 00:00:00 [kworker/0:0-kdmflush/253:0] 1 I root 1931 2 0 80 0 - 0 - 15:37 ? 00:00:00 [kworker/0:2-kdmflush/253:0] 0 R user 1932 1452 0 80 0 - 56375 - 15:38 pts/1 00:00:00 ps -efl
Polecenie to zwraca bardzo dużo informacji o procesach. Najważniejsze
dla nas są kolumny: S
,
UID
, PID
,
PPID
, PRI
,
NI
oraz CMD
,
w których znajdują się takie informacje jak:
S
- Stan procesu.UID
- Identyfikator użytkownika, w tym przypadku jest to nazwa użytkownika.PID
- Identyfikator procesu.PPID
- Identyfikator procesu nadrzędnego (procesu, który uruchomiło ten proces).PRI
- Priorytet procesu.NI
- Wartość nice.CMD
- Polecenie, które uruchomiło proces.
Jako ciekawostkę podam, iż procesy, które w kolumnie
TTY
posiadają znak zapytania
(?) pochodzą prawdopodbnie od któregoś z demonów.
Polecenie ps daje możliwość wyświetlenia tylko tych informacji, które potrzebujemy dzięki opcji -o. Możemy użyć polecenia poniżej:
[user@server1 ~]$ ps -eo user,s,pid,command USER S PID COMMAND root S 1 /usr/lib/systemd/systemd rhgb --switched-root --system --deserialize 31 root S 2 [kthreadd] root I 3 [rcu_gp] root I 4 [rcu_par_gp] root I 6 [kworker/0:0H-events_highpri] root I 9 [mm_percpu_wq] root S 10 [rcu_tasks_kthre] root S 11 [rcu_tasks_rude_] root S 12 [rcu_tasks_trace] root S 13 [ksoftirqd/0] root I 14 [rcu_preempt]
Za pomocą ps, możemy wyszukać proces na podstawie polecenia. Do tego wykorzystamy opcje -C.
[user@server1 ~]$ ps -o user,s,pid,command -C sshd USER S PID COMMAND root S 849 sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups root S 1974 sshd: user [priv] user S 1979 sshd: user@pts/0 root S 2098 sshd: user [priv] user S 2103 sshd: user@pts/1
Polecenie ps zawiera ogromną ilość opcji. Ich opisy znajdują się na stronie podręcznika polecenia.
8.1.2. Polecenie top
Polecenie z poprzednie podrozdziału służyło do wyświetlania procesów. Za pomocą tego przedstawionego tutaj możemy je monitorować w czasie rzeczywistym. Polecenie top, może posłużyć do sprawdzenia czy system nie jest przeciążony.
[user@server1 ~]$ top top - 16:31:38 up 6:00, 1 user, load average: 0.00, 0.00, 0.00 Tasks: 174 total, 1 running, 173 sleeping, 0 stopped, 0 zombie %Cpu(s): 0.0 us, 0.3 sy, 0.0 ni, 99.7 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st MiB Mem : 960.5 total, 123.2 free, 464.1 used, 373.2 buff/cache MiB Swap: 2048.0 total, 2048.0 free, 0.0 used. 335.9 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 1 root 20 0 106212 15976 10328 S 0.0 1.6 0:01.96 systemd 2 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kthreadd 3 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 rcu_gp 4 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 rcu_par_gp 6 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 kworker/0:0H-events_highpri 9 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 mm_percpu_wq 10 root 20 0 0 0 0 S 0.0 0.0 0:00.00 rcu_tasks_kthre 11 root 20 0 0 0 0 S 0.0 0.0 0:00.00 rcu_tasks_rude_ 12 root 20 0 0 0 0 S 0.0 0.0 0:00.00 rcu_tasks_trace 13 root 20 0 0 0 0 S 0.0 0.0 0:00.36 ksoftirqd/0 14 root 20 0 0 0 0 I 0.0 0.0 0:00.26 rcu_preempt 15 root rt 0 0 0 0 S 0.0 0.0 0:00.05 migration/0 16 root 20 0 0 0 0 S 0.0 0.0 0:00.00 cpuhp/0 18 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kdevtmpfs 19 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 netns 20 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 inet_frag_wq
Informacje zwracane przez to polecenie możemy podzielić na dwie części jedną z nich jest część, w której znajduje się podsumowanie. W pierszej linii znajduje się linia identyczna z informacją zwracaną przez polecenie uptime, następne linie to: ilość liczbowa procesów w systemie, informacje o zużyciu procentowym procesora, zużyciu pamięci operacyjnej oraz przestrzeni wymiany. Ostatnia kolumna z ostatniego rzędu zwraca rzeczywistą ilość dostępnej pamięci operacyjnej bez wliczania przestrzeni wymiany.
Drugą częścią jest tabelaryczne przedstawienie listy procesów dostępnych w systemie. W tym przypadku procesy, które zużywają najwięcej zasobów komputera wyświetlane są w pierwszych wierszach tabeli. Przez co można stwierdzić, że tabela jest posortowana względem wartości procentowej zużycia procesora. Polecenie top jest bardzo elastyczne, posiadamy możliwość dostosowania kolumn wyświetlanych w tabeli oraz części z podsumowaniem, informacje na ten temat znajdują się na stronie podręcznika.
8.1.3. Priorytet procesu
Podczas wykonywania procesów, każdy z procesów dostaje dostęp do procesora na ułamek sekundy, wówczas proces zmienia swój stan na Running, po upływie tego czasu proces w zależności od czynności przechodzi albo w Waiting albo w Sleeping. Kiedy proces przebywa w tych stanach wykonywane są inne procesy, później proces znów zostaje wznowiony i tak w kółko. Tego typu działanie nazywane jest wielozadaniowością (a przynajmniej się takie wydaje). Każdy z procesów otrzymuje określoną ilość czasu, jednak są procesy, które mogą otrzymać go więcej lub mniej. Czasami zmiana tych wartość jest to niezbędna do funkcjonowania systemu. Czynnikiem który wpływa na tę decyzje jest priorytet - kolumna PRI przy poleceniu ps. Priorytety są już z góry określone podczas uruchamiania procesu. Najwyszym priorytetem (proces otrzyma najwięcej czasu procesora) jest 0, a najniższym (proces otrzyma najmniej czasu procesora) jest 39. Administratorzy mają wpływ na priorytet procesu za pomocą wartości nice. Kiedy administrator chce zmienić wartość priorytetu, ustala wartość nice dla procesu a ona jest do niego dodawana. Wartość nice, może być w zakresie od -20 do 19. Jeśli chcemy aby proces posiadał w momencie uruchomienia inny priorytet uruchamiamy go za pomocą polecenia nice.
[user@server1 ~]$ ps -efl | grep $(pidof top) 0 S user 2152 1980 0 80 0 - 56480 do_sel 17:24 pts/0 00:00:00 top [user@server1 ~]$ nice -n 19 top [user@server1 ~]$ ps -efl | grep $(pidof top) 0 S user 2137 1980 0 99 19 - 56480 do_sel 17:20 pts/0 00:00:00 top
Kolumna numer 7 zawiera wartość priorytetu, a 8 kolumna zawiera wartość nice. Zwróćmy uwagę na rozbierzności w wyświetlaniu priorytetów procesów między poleceniami top oraz ps. Nie mniej jednak wartość nice sprawiła zmianę priorytetu procesu top.
Jeśli proces jest już uruchomiony to również możemy zmienić jego priorytet, za pomocą polecenie renice, jednak najpierw poznamy dwa polecenia, które ułatwią nam pracę z poleceniem renice oraz każdym innym, które potrzebuje identyfikatora procesu. Tymi poleceniami są polecenia pidof oraz pgrep.
[user@server1 ~]$ pidof top 2170 [user@server1 ~]$ pgrep top 2170
Polecenia bez żadnych opcji zwracają to samo - identyfikator procesu i tymi poleceniami będziemy się wspomagać. Oczywiście więcej informacji na ich temat znajduje się na stronach podręcznika. Wracajac do wartości nice, zmienie teraz priorytet działającego procesu za pomocą polecenia renice.
[user@server1 ~]$ sudo renice -n -10 $(pidof top) [sudo] password for user: 2170 (process ID) old priority 0, new priority -10 [user@server1 ~]$ ps -efl | grep $(pidof top) 0 S user 2170 1980 0 70 -10 - 56480 do_sel 17:43 pts/0 00:00:00 top
Priorytet procesu zmienił się. Zwróćmy uwagę na to, iż polecenie renice wymaga uprawnień superużytkownika do działania.
8.1.4. Zarządzanie procesami za pomocą syganałów
Działanie procesów, może być kontrolowane za pomocą sygnałów, które są do nich wysyłane przez jądro systemu. Te sygnały mogą zatrzymać wykonanie procesu, przenieść proces na do tła, poprosić go o zakończenie działania lub gdy jest dość oporny na poprzedni sygnał poprostu unicestwić. Każdy z sygnałów posiada swoją nazwę oraz numer. My możemy używać dowolnej formy. Poniżej znajduje się lista najczęściej wykorzystywanych sygnałów wraz z numerami.
- SIGHUP - 1 - sygnał zawieszenia, powoduje odłącznieni się od terminala, którym proces wystartował. W przypadku demonów, ten sygnał spowoduje ponowne odczytanie konfiguracji bez restartu demona.
- SIGINT - 2 - sygnał przerwania, wysyłany jest do procesu w momencie naciśnięcia klawiszy Ctrl+c.
- SIGKILL - 9 - sygnał zabicia, powoduje unicestwienie procesu, a sprzątaniem po nim zajmuj się jądro.
- SIGTERM - 15 - sygnał zakończnia, prośba o zakończenie swojego działania. W przypadku tego sygnału proces ma możliwość posprzątania po sobie oraz polubownego zakończenia wszystkich czynności. Ten sygnał jest domyślnym sygnałem wysyłanym do procesów.
- SIGCONT - 18 - sygnał kontynuacji pracy w tle, równoznaczny z poleceniem bg.
- SIGSTOP - 19 - sygnał zatrzymania, równoznaczny z naciśnięciem kombinacji klawiszy Ctrl+z.
- SIGTSTP - 20 - sygnał kontynuacji pracy na pierwszym planie, równoznaczny z poleceniem fg.
Do wysyłania sygnałów do procesów służy polecenie kill lub pkill. Różnią się one tym, iż poleceniu kill podaje się PID, natomiast pkill nazwę procesu lub polecenie. Numery sygnałów podjemy po myślniku przed PID-em lub nazwą. Jeśli chcemy użyć nazw sygnałów należy podać je po opcji -s (w przypadku polecenia kill) lub --signal (w przypadku polecenia pkill). Listę dostępnych sygnałów możemy wyświetlić za pomocą poniższego polecenia:
[user@server1 ~]$ kill -l 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM 16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP 21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ 26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR 31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3 38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8 43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13 48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7 58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2 63) SIGRTMAX-1 64) SIGRTMAX
W ramach przykładu zakończymy działania procesu top.
[user@server1 ~]$ pkill top [user@server1 ~]$ kill $(pidof top)
Do kończenia pracy procesów możemy użyć również polecenia killall, które kończy pracę wszystkich procesów, które pasują do określonych kryteriów.
8.2. Harmonogram zadań
Harmonogram zadań służy do planowania wykonania poleceń czy uruchomienia programów w przyszłości. Na Linuksie możemy to zrobić na dwa sposóby, w zależności od potrzeby powtórzenia danego zadania. Na Linuksie zadania z harmonogramu moga być uruchomione raz w określonym czasie lub wykonywane cyklicznie co jakiś okres czasu. Narzędziami odpowiedzialnymi za obsługę funkcji harmonogramu zadań na Linuksie są at oraz cron. W RHEL możemy również spotkać się z mechanizmem kontroli dostępu do tych programów.
8.2.1. Kontrola dostępu do harmongramu
W RHEL stosowany jest mechanizm kontroli dostępu do harmonogramu zdań zarówno dla obu narzędzi. Ten mechanizm składa się z dwóch plików, jeden z rozszerzeniem *.allow oraz jeden z rozszerzeniem *.deny. W tych plikach umieszczamy wpis z nazwą użytkownika w zależności od tego czy użytkownik ma mieć lub nie mieć dostępu do tych narzędzi. Sama obecność tych plików w systemie ma wpływ na to czy użytkownicy będą mogli korzystać z harmonogramu zadań. Każdy program posiada swoją parę plików. W poniższej tabeli znajdują się rozpisane zależności, które obrazują w jaki sposób obecność tych plików wpływa na dostęp do narzędzi harmonogramu zadań.
Obecność pliku *.allow | Obecność pliku *.deny | Wpływ na dostęp do at oraz cron |
---|---|---|
Istnieje, posiada wpisy użytkowników. | Nie musi istnieć. | Wszyscy użytkownicy w pliku posiadają dostęp. |
Istnieje, ale jest pusty. | Nie musi istnieć. | Nikt nie ma dostępu. |
Nie istnieje. | Istnieje, posiada wpisy użytkowników. | Wszyscy użytkownicy, poza tymi zapisanym w pliku *.deny mają dostęp. |
Nie istnieje. | Istnieje, ale jest pusty. | Wszyscy użytkownicy posiadają dostęp. |
Nie istnieje. | Nie istnieje. | Nikt nie ma dostępu. |
Powyższe zasady nie obowiązują oczywiście superużytkownika, nawet mimo umieszczenia jego nazwy w plik *.deny. Domyślnie w RHEL plik *.allow nie istnieje, natomiast plik *.deny istnieje, ale jest pusty.
Odnośnie egzaminu:
Definiując wpisy w tych plikach, należy pamiętać o tym aby jedna linia
zwierała jednego użytkownika. To jedyna poprawna metoda.
Po wpisaniu nazwy użytkownika do pliku, jeśli będzie on chciał skorzystać z at lub cron zobaczy poniższe komunikaty.
[user@server1 ~]$ at You do not have permission to use at. [user@server1 ~]$ crontab -e You (user) are not allowed to use this program (crontab) See crontab(1) for more information
Oczywiście dla przykładu zablokowałem dostęp do obu narzędzi.
8.2.2. Wykonanie zadań w przyszłości - polecenie at
Polecenie at służy do planowania pojedynczego wykonania zadania w przyszłości. Podczas wydawania polecenia podajemy czas oraz ewentualnie datę kiedy zadanie ma zostać wykonane. Czas możemy podać na kilka różnych sposobów:
- at 1:15am - polecenie zostanie uruchomione o 01:15 następnego dnia,
- at noon - polecenie zostanie uruchomione w południe tego lub nastęnego dnia,
- at 23:45 - polecenie zostanie uruchomione o 23:45,
- at midnight - polecenie zostanie uruchomione o północy,
- at 17:05 tommorow - polecenie zostanie uruchomione w dniu jutrzejszym o 17:05,
- at now + 5 hours - polecenie zostanie uruchonione za 5 godzin,
- at 3:00 10/12/2022 - polecenie zostanie uruchomione o 3 w nocy 12 października 2022 roku (w amerykańskim zapisie daty na początku podaje się miesiąc następnie dzień miesiąca).
Po wydaniu polecenia z datą, polecenie uruchomi tryb interaktywyny, gdzie w każdej linii będziemy mogli zapisać polecenie, które wykona się o podanym czasie. Po zakończeniu zapisywania poleceń naciskamy kombinację Ctrl+d, aby zakończyć działanie programu i zapisać polecenia, wówczas po znaku zachęty pojawi się znak <EOT> oznaczający zakończenie wprowadzania poleceń.
[user@server1 ~]$ at midnight warning: commands will be executed using /bin/sh at> date at> pwd at> whoami at> who at> w at> <EOT> job 2 at Wed Jul 6 00:00:00 2022
Polecenia zapisywane są w odpowiednich pliku w katalogu /var/spool/at. Dostęp do katalogu wymaga uprawnień administratora.
[user@server1 ~]$ sudo ls -l /var/spool/at [sudo] password for user: total 4 -rwx------. 1 user user 3365 Jul 5 09:28 a0000201a56968
Programem odpowiedzialnym za wykonanie poleceń jest demon atd. Za pomocą opcji polecenia at możemy na przykład wyświetlić listę zdefiniowanych zadań (-l):
[user@server1 ~]$ at -l 2 Wed Jul 6 00:00:00 2022 a user
W pierwszej kolumnie znajduje się numer zadania. Jest on istotny jeśli chcemy na przykład wyświetlić jego plik za pomocą opcji -c.
[user@server1 ~]$ at -c 2 #!/bin/sh # atrun uid=1000 gid=1000 # mail user 0 umask 22 SHELL=/bin/bash; export SHELL HISTCONTROL=ignoredups; export HISTCONTROL HISTSIZE=1000; export HISTSIZE HOSTNAME=server1.example.com; export HOSTNAME PWD=/home/user; export PWD LOGNAME=user; export LOGNAME XDG_SESSION_TYPE=tty; export XDG_SESSION_TYPE MOTD_SHOWN=pam; export MOTD_SHOWN HOME=/home/user; export HOME LANG=en_US.UTF-8; export LANG ... ${SHELL:-/bin/sh} << 'marcinDELIMITER29478f5e' date pwd whoami who w marcinDELIMITER29478f5e
Zadanie możemy też usunąć za pomocą opcji -r lub -d, plik z katalogu /var/spool/at również zostanie usunięty.
[user@server1 ~]$ at -d 2 [user@server1 ~]$ at -l
Do usunięcia potrzebny jest numer zadania, który znajduje się
pierwszej kolumnie listy zadań wyświetlonej za pomocą polecenia
at -l
. Obie przestawione powyżej
opcje są aliasami do poleceń atq oraz atrm.
Działanie narzędzi harmonogramu zadań jest rejestrowane, a ich komunikaty diagnostyczne są zapisywane w /var/log/cron. Mimo iż nazwa pliku wskazuje iż dotyczy on głównie crond to komunikaty atd również są tam zapisywane. Aby wyświetlić jego zawartość potrzebne są uprawnienia administratora:
[user@server1 ~]$ sudo tail /var/log/cron [sudo] password for user: Jul 5 09:01:01 server1 anacron[1651]: Jobs will be executed sequentially Jul 5 09:01:01 server1 run-parts[1640]: (/etc/cron.hourly) finished 0anacron Jul 5 09:01:01 server1 CROND[1639]: (root) CMDEND (run-parts /etc/cron.hourly) Jul 5 09:21:01 server1 anacron[1651]: Job `cron.daily' started Jul 5 09:21:01 server1 anacron[1651]: Job `cron.daily' terminated Jul 5 09:21:01 server1 anacron[1651]: Normal exit (1 job run) Jul 5 10:01:01 server1 CROND[1941]: (root) CMD (run-parts /etc/cron.hourly) Jul 5 10:01:01 server1 run-parts[1941]: (/etc/cron.hourly) starting 0anacron Jul 5 10:01:01 server1 run-parts[1941]: (/etc/cron.hourly) finished 0anacron Jul 5 10:01:01 server1 CROND[1940]: (root) CMDEND (run-parts /etc/cron.hourly)
8.2.3. Definiowanie powtarzalnych zadań - program cron
Na Uniksach, bo nie tylko na Linuksie, istnieje program służący do definiowania powtarzalnych zadań uruchamianych co jakiś czas. Takim programem, a raczej demonem jest cron. Działanie tego programu opiera się o pliki zwane tablicami cron lub crontabami. Każdy użytkownik może korzystać z tego narzędzia, chyba, że występuje on w pliku /etc/cron.deny. Użytkownicy do kontroli harmonogramu zadań, używają polecenia crontab. Każdy z nich zapisuje zadania w swojej tablicy znajdującej się w katalogu /var/spool/cron. Zapis zadań w tablicy wymaga ściśle określonej składni. Wpis składa się z 5 pól czasu, ewentualnego pola zawierającego nazwę użytkownika (pole to występuje tylko w systemowej tablicy cron /etc/crontab), z którego uprawnieniami ma zostać wykonane to zadanie, oraz reszty linii zawierającej polecenie do wykonania. Poniżej znajduje się przykład wpis, który sobie przeanalizujemy.
15 13 4 7 * echo "Hello World" > /dev/pts/1
Każdy wpis zadania w tablicy cron rozpoczyna się od 5 pól określających kiedy owe zadanie ma zostać wykonane. Pola od lewej definiują kolejno:
15
- pole 1, minuta w godzinie. W tym polu określamy konkretną minutę godziny w której zadanie ma zostać uruchomione, jeśli jest to jedyne skonfigurowane pole wówczas zadanie bedzie uruchamiać się co godzinę. To pole przyjmuje wartości od 0 do 59.13
- pole 2, godzina w dniu. To pole wskazuje na godzinę, w której zadanie ma zostać uruchomione. Jeśli to jedyne skonfigurowane pole, wówczas zadanie będzie uruchamiać się o pełnej godzinie kazdego dnia. To pole może przyjmować wartości od 0 do 23.4
- pole 3, dzień miesiąca. Pole wskazuje dzień miesiąca w którym ma zostać uruchomione zadanie. Jeśli jest to jedyne zdefiniowane pole, to zadanie będzie się uruchamiać tego dnia każdego miesiąca. Pole to może przyjmować wartości od 1 do 31.7
- pole 4, miesiąc, pole wskazuje na miesiąc w roku. Pole może przyjmować zarówno wartości liczbowe jak alfabetyczne, nazwy miesięcy składają się trzech pierwszych małych liter angielskiej nazwy miesiąca.*
- pole 5, dzień tygodnia, pole wskazuje na dzień tygodnia podobnie jak miesiąc może zawierać wartości liczbowe oraz alfabetyczne zawierające trzy pierwsze małe litery angielskiej nazwy dnia. Wartość 0 oraz 7 oznaczają niedzielę.
Pola czasu przyjmują takie wartości jak listy (określajace konkretne godziny, dni itd. Na przykład 15,16), zakresy (określające, którego do którego polecenia ma zostać wykonane np. 10-20) oraz wartości skokowe, które definiują co ile minut, godzin lub dni wykonać to zadanie. Listy oraz zakresy można łączyć ze sobą zazwyczaj 10-15,21 może to oznacząć uruchomienie zadania od 10-15 oraz 21 dnia miesiąca. Więcej informacji na temat można znaleźć na stronie podręcznika pliku /etc/crontab.
Ostatnie pole, jest miejscem do umieszaczania poleceń. Jeśli polecenie zwraca istotne dane wyjściowe to najlepiej jest je przekierować.
Odnośnie egzamin:
Wykonując zadania administracyjne, powinniśmy mieć opanowaną składnie
wpisów zadań oraz rozumienie jej poszczególnych części.
Do edycji tablicy cron służy polecenie crontab z opcją -e. Polecenie to uruchomi edytor, w którym to zapiszemy wpisy harmonogramu, po zakończeniu edycji i zapisaniu zmian polecenie utworzy plik w /var/spool/cron o nazwie użytkownika. Ten plik staje się teraz jego tablicą cron. Po zapisaniu pliku tablica zostaje zainstalowana w pamięci demona. W ten sposób definiuje się wpisy harmonogramu zadań cron.
Za pomocą opcji -l możemy wyświetlić obecną tablicę cron.
[user@server1 log]$ crontab -l 15 13 4 7 * echo "Hello World" > /dev/pts/1
Za pomocą opcji -r możemy usunąć obecną tablicę cron:
[user@server1 log]$ crontab -r [user@server1 log]$ crontab -l no crontab for user
8.2.4. Wykonanie pominiętych zadań - program Anacron
Nie które komputery z zainstalownym Linuksem, nie są właczone 24/7. Za tem cześć zadań zdefiniowana w systemowym harmonogramie w plikach /etc/cron.* nie jest wykonywana. Pliki te dotyczą czynność systemowych zdefiniowanych co godzinę, dzień, tydzień czy miesiąc. Ta przypadłość najczęściej dotyczy komputerów osobistych. Dlatego też, aby uruchomić te zdania używa się demona anacron. Aby demon rozpoczął uruchmianie niewykonanych zadań muszą zostać w systemie spełnione trzy czynniki. Pliki tablicy anacron muszą istnieć w katalogu /var/spool/anacron, musi upłynąć odpowiednia ilość czasu (zdefiowana w pliku systemowej tablicy /etc/anacrontab) oraz komputer musi być podłączony do stałego źródła zasilania. Poniżej znajduje sie plik konfiguracyjny anacron.
SHELL=/bin/sh PATH=/sbin:/bin:/usr/sbin:/usr/bin MAILTO=root RANDOM_DELAY=45 START_HOURS_RANGE=3-22 1 5 cron.daily nice run-parts /etc/cron.daily 7 25 cron.weekly nice run-parts /etc/cron.weekly @monthly 45 cron.monthly nice run-parts /etc/cron.monthly
W pierwszej kolumnie znajduje się okres (w dniach) jaki musi upłynąć
od ostatniego uruchomienia tych zdań. W drugiej znajduje się opóźnienie
które musi minąć od uruchomienia systemu, to opóźnienie jest zazwyczaj
powiększone o wartość zdefiniowaną w zmiennej
RANDOM_DELAY
.
W następnej kolumnie znajduje się identyfikator zdania, a ostatnia
kolumna to już pole polecenia. Dość istotną rolę gra tutaj wartość
zmiennej START_HOURS_RANGE
. Określa
ona w jakich godzinach anacron może działać.
Działanie demona możemy wymusić poprzez wydanie polecenia anacron.
[user@server1 ~]$ sudo anacron [sudo] password for user: [user@server1 ~]$
Ćwiczenie 1: Wartość nice procesu
Na maszynie server1, uruchomy dwa termiale (mogą być to dwa połączenia SSH z tą maszyną) następnie w jednym z terminali uruchom program top, na drugim terminalu za pomocą polecenia ps lub pgrep ustal PID oraz wartość nice dla wcześniej uruchomionego polecenia top. Zakończ działanie programu top, następnie uruchom je ponownie z priorytetem zmniejszonym o 8 (+8). Potwierdź zmianę priorytet na drugim terminalu. Następnie zwiększ priorytet o 10 (-10) nie zamykając programu top i potwierdź to w drugim terminalu.
Ćwiczenie 2: Konfiguracja tablicy cron użytkownika
Na maszynie server1 jako superużytkownik zapewnij dostęp
do cron dla zwykłego użytkownika, na którego się logujesz.
Jako zwykły użytkownik sprawdź nazwę aktualnego terminala
(polecenie tty) oraz obecną datę i godzinę (polecenie
date). Za pomocą harmonogramu zadań cron ustaw
wykonanie polecenia
echo "Hello World" > nazwa_terminala
(za nazwa_terminala podstawiamy nazwę uzyskaną z polecenia
tty) za 3 minuty od bierzącego czasu. Zaczekaj na wykonanie
zadania.
Podsumowanie
W tym rodziale zapoznaliśmy się z procesami, wyświetaliśmy ich listę korzystaliśmy z polecenia top, zmienialiśmy ich priorytet oraz zarządzaliśmy nimi za pomocą sygnałów. W drugiej części zajęliśmy się narzędziami harmonogramu zadań. Nauczyliśmy się korzystać z takich programów jak at czy cron. Na koniec poznaliśmy specyficzny dla dystrybucji klasy enterprise demon Anacron. W następnym rozdziale zapoznamy się podstawami zarządzania pakietami oprogramowania na RHEL.
9. Podstawy zarządzania pakietami oprogramowania
Pakiety inaczej zwane paczkami czy ogólnie oprogramowanie dystrybucji, to archiwa przechowywujące zazwyczaj skompilowane oprogramowanie przeznaczone dla systemu, który używamy. Wewnątrz pakietów znajduje się cała strukturktura katalogowa z plikami pakietu, tak by podczas instalacji wystarczyło je tylko rozpakować. Wewnątrz znajdują się również metadane zawierające informacje o pakiecie.
Większość pakietów posiada długie nazwy, które nie są dokońca rozumiałe. Weźmy na przykład taką nazwę jak:
openssl-1.1.1-8.el8.x86_64.rpmZawiera ona takie elementy jak:
- Jednoznaczną nazwę oprogramowania pozwalającą, zidentyfikować
co to za program (
openssl
). - Numer wersji oprogramowania
(
1.1.1
). - Numer wydania (
8
). - Nazwę dystrybucji, rodziny dystrybucji itp. Ten element nie jest
obligatoryjny. Nie które dystrybucje włączają go do numeru wydania
(
el8
). - Nazwa architektury dla jakiej zostało skompilowane oprogramowanie
(
x86-64
). - Rozszerzenie (
.rpm
).
Kompilacja programów ze źródeł wymaga odpowiedniego środowiska (w ten sposób tworzy się binarne wersje programów udostępnionych w pakietach). Aby oprogramowanie z pakietu mogło działać tak samo, jak na w systemie, w którym zostało skompilowane wymaga identycznego środowiska. To środowisko jest przedstawiane za pomocą zależności pakietu, czyli wszystkich innych pakietów, wymaganych do działania tego programu, który chcemy zainstalować. Informacje o zależnościach znajdują się w metadanych pakietu.
Systemy, w których dystrybucja oprogramowania jest oparta o pakiety musi posiadać bazę danych pakietów. W przypadku RHEL znajduje się ona w katalogu /var/lib/rpm. Na podstawie danych umieszczonych w tym katalogu oprogramowanie do zarządzania pakietami pobiera informacje o zainstalowanych w systemie pakietach.
Aby móc zarządzać pakietami potrzebne są do tego odpowiednie programy. Red Hat posiada takie polecenie jak rpm (ang. Red Hat Packet Manager) i jest to podstawowe narzędzie do instalacji, aktualizacji, wyszukiwania informacji czy usuwania oprogramowania z systemu. Rpm jest bardzo prostym narzędziem jednak posiada jedną wadę, otóż nie rozwiązuje samodzielnie zależności. Dlatego też pojawił się taki program jak yum, który pełni takie same role jak rpm jednak nie posiada wspomnianej wady. Od wersji 8 RHEL, yum został zastąpiony przez dnf, który rozszerza funkcjonalność yum. W tym rodziale zajmiemy się wyłącznie rpm. W następnym zaś skupimy się na dnf.
9.1. Red Hat Packet Manager - RPM
9.1.1. Pobieranie danych z pakietu
Jedną z podstawowych czynności jakie możemy wykonać przy użyciu tego narzędzia jest pobieranie informacji o pakietach, za pomocą opcji -q podając jako argument nazwę programu możemy dowiedzić się czy takowy jest zainstalowany w systemie.
[user@server1 ~]$ rpm -q zsh package zsh is not installed [user@server1 ~]$ rpm -q bash bash-5.1.8-4.el9.x86_64
Pakiet zsh
nie jest zainstalowany
w moim systemie. Natomiast drugie wywołanie potwierdza, że systemie
zainstalowano powłokę BASH.
Z racji tego, iż rpm to nie tylko narzędzie ale i format danych za pomocą tego polecenia, możemy wyświetlić pliki konfiguracyjne programu (-qc), który zawiera pakiet czy pliki dokumentacji (-qd).
#Plik dokumentacji: [user@server1 ~]$ rpm -qd bash /usr/share/doc/bash/FAQ /usr/share/doc/bash/INTRO /usr/share/doc/bash/RBASH /usr/share/doc/bash/README /usr/share/doc/bash/bash.html /usr/share/doc/bash/bashref.html ... #Pliki konfiguracji: [user@server1 ~]$ rpm -qc bash /etc/skel/.bash_logout /etc/skel/.bash_profile /etc/skel/.bashrc
Wszystkie pliki pakietu możemy wyświetlić za pomocą opcji -ql. Generalnie opcja -q, jest modyfikatorem odpowiedzialnym za pobieranie danych z bazy lub z samego pliku pakietu.
[user@server1 ~]$ rpm -ql bash /etc/skel/.bash_logout /etc/skel/.bash_profile /etc/skel/.bashrc /usr/bin/alias /usr/bin/bash /usr/bin/bashbug /usr/bin/bashbug-64 /usr/bin/bg /usr/bin/cd ...
Za pomocą opcji -qf możemy wyszukać pakietu, z którego pochodzi podany plik.
[user@server1 ~]$ rpm -qf /etc/bashrc setup-2.13.7-6.el9.noarch
Polecenie zwróci nazwę pakietu. Zwróćmy uwagę na to, że nazwy zainstalowanych pakietów w RHEL różnią się od nazw plików tym, że nie posidają rozszerzenia. Jeśli nie wiemy czym jest ten pakiet przedstawiowny na poprzednim przykładzie za pomocą opcji -qi możemy sprawdzić do czego służy.
[user@server1 ~]$ rpm -qi setup-2.13.7-6.el9.noarch Name : setup Version : 2.13.7 Release : 6.el9 Architecture: noarch Install Date: Sun 26 Jun 2022 01:48:46 PM CEST Group : System Environment/Base Size : 726478 License : Public Domain Signature : RSA/SHA256, Sat 20 Nov 2021 04:26:39 PM CET, Key ID 199e2f91fd431d51 Source RPM : setup-2.13.7-6.el9.src.rpm Build Date : Tue 10 Aug 2021 06:16:15 PM CEST Build Host : ppc64le-03.build.eng.rdu2.redhat.com Packager : Red Hat, Inc. <http://bugzilla.redhat.com/bugzilla> Vendor : Red Hat, Inc. URL : https://pagure.io/setup/ Summary : A set of system configuration and setup files Description : The setup package contains a set of important system configuration and setup files, such as passwd, group, and profile.
Przed przejściem do kolejnego zaganienia musimy umieścić płytę instalacjyną z RHEL w napędzie maszyny. Z niej będziemy pobierać pakiety do dalszych ćwiczeń, gdyż nasze maszyny nie są podłączone do sieci Red Hat. Po włożeniu płyty do napędu dodajmy poniższy wpis do pliku /etc/fstab, aby płyta posiadała prosty i stały punkt montowania. Na płycie znajdują się dwa katalogi BaseOS/Packages oraz AppStream/Packages, gdzie znajdują się pakiety.
/dev/sr0 /mnt iso9660 ro 0 0
Po zapisaniu zmian w pliku wywołujemy polecenie
sudo mount -a
, aby zamontować płytę
w podkatalogu /mnt. Kiedy płyta jest już zamontowana w
systemie, możemy wyświetlić informacje z metadanych pliku pakietu za
pomocą opcji -qip.
[user@server1 ~]$ rpm -qip /mnt/BaseOS/Packages/bash-completion-2.11-4.el9.noarch.rpm Name : bash-completion Epoch : 1 Version : 2.11 Release : 4.el9 Architecture: noarch Install Date: (not installed) Group : Unspecified Size : 1057184 License : GPLv2+ Signature : RSA/SHA256, Sat 20 Nov 2021 11:52:53 AM CET, Key ID 199e2f91fd431d51 Source RPM : bash-completion-2.11-4.el9.src.rpm Build Date : Mon 09 Aug 2021 09:47:13 PM CEST Build Host : s390-070.build.eng.bos.redhat.com Packager : Red Hat, Inc. <http://bugzilla.redhat.com/bugzilla> Vendor : Red Hat, Inc. URL : https://github.com/scop/bash-completion Summary : Programmable completion for Bash Description : bash-completion is a collection of shell functions that take advantage of the programmable completion feature of bash.
Polecenie zwraca taką samą ilość informacji jak polecenie rpm wraz z opcją -qi.
9.1.2. Sprawdzanie pakietów
Za pomocą jednego z programów związanych z rpm oraz za pomocą samego polecenia rpm możemy sprawdzić poprawność oraz wiarygodność pakietów, które zamierzamy zainstalować, jak i sprawdzić co zostało zmienione przez nas w plikach programów, które są już zainstalowane w systemie względem oryginalnego pakietu.
Walidację pakietu, który mamy zainstalować możemy przeprowadzić względem dwóch kryteriów, jednym z nich jest poprawność plików znajdujących się w pakiecie. Ta metoda polega na sprawdzeniu sumy kontrolnej MD5.
[user@server1 ~]$ rpmkeys -K /mnt/BaseOS/Packages/zsh-5.8-9.el9.x86_64.rpm --nosignature /mnt/BaseOS/Packages/zsh-5.8-9.el9.x86_64.rpm: digests OK
Drugim kryterium jest wiarygodność. Każdy pakiet zawiera podpis twórcy/dostawcy, w naszym przypadku jest to dostawca którym jest firma Red Hat, ten podpis dokonywany jest za pomoca klucza kryptograficznego. Część tego klucza odpowiedzialna za szyfrowanie danych jest instalowana w naszym systemie i pozostaje do naszej dyspozycji. Poza omówią funkcją ta część klucza może również pomoć nam sprawdzić czy pakiet który pobraliśmy z internetu rzeczywiście został stworzony przez firmę Red Hat, za nim zaczniemy używać klucza musimy go na początku zaimportować, importu dokonujemy za pomocą polecenia poniżej, ścieżka do klucza również znajduje się na przykładzie.
[user@server1 ~]$ sudo rpmkeys --import /etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release
Import klucza, jak i sprawdzenie wiargodności pakietów wymaga uprawnień administratora.
[user@server1 ~]$ rpmkeys -K /mnt/BaseOS/Packages/zsh-5.8-9.el9.x86_64.rpm /mnt/BaseOS/Packages/zsh-5.8-9.el9.x86_64.rpm: digests signatures OK
Teraz polecenie sprawdziło nie tylko poprawność plików
(digests
), ale także ich wiarygodność
(signatures
).
Za pomocą polecenia rpm możemy sprawdzić zainstalowane już pakiety pod kątem zmian względem plików znajdujących w oryginalnym pakiecie. Służy temu opcja -V, jeśli nie ma żadnych zmian to polecenie nic nie zwróci. Możemy oczywiście zwiększyć ilość komunikatów generowanych podczas pracy programu z pomocą opcji -v, wówczas polecenie zwróci informacje na temat każdego sprawdzonego pliku pakietu.
[user@server1 ~]$ sudo rpm -V at [sudo] password for user: .......T. c /etc/at.deny
Informacja zwracana przez to polecenie składa się z trzech kolumn, w
pierwszej kolumnie znajdują się flagi, które mowią nam co uległo
zmianie, każda z 9-ciu kropek to jedna flaga, w drugiej kolumnie
znajdują się rodzaj pliku w tym przypadku
c
. Ostatnia kolumna zawiera ścieżkę
bezwzględną do pliku. Poniżej znajdują się listy z flagami oraz typami
plików. Kolejność na liście z flagami oznacza konkretną kropkę.
- S - różnica w wielkości pliku,
- M - różnica w uprawnieniach,
- 5 - różnica w sumie kontrolnej pliku,
- D - różnica w numerze głównym i pobocznym urządzenia, urządzenie zostało zmienione,
- L - zmieniona ścieżka dowiązania symbolicznego,
- U - zmieniony właściciel pliku,
- G - zmieniona grupa pliku,
- T - różnica w czasie modyfikacji,
- P - różnica w POSIX Capabilities
Kropka (.) oznacza brak zmian. Poniżej znajduje się lista zawierająca typy plików.
- c - %config - pliki konfiguracyjne,
- d - %docs - pliki dokumentacji,
- g - %ghost - pliki, których zawartość nie znajduje się wewnątrz pakietu,
- l - %license - pliki licencji,
- r - %readme - plik README.
9.1.3. Instalacja i reinstalacja
Aby jak najlepiej wykorzystać polecenie rpm do instalacji pakietów wykorzystuje się trzy opcje: -i - oznaczającą samą instalacje pakietu, -v - zwiększającą ilość generowanych przez polecenie komunikatów, -h - wyświetlająca pasek postępu w postaci serii krzyżyków (#), po zapisaniu tych opcji podajemy ścieżkę do pliku pakietu. Uwaga, tutaj pojawia się omawiana wcześniej wada: brak rozwiązywania zależność, jeśli spróbujemy zainstalować jakiś pakiet, które zależności nie są rozwiązane (spełnione), rpm nie podejmie w ogóle instalacji, zwraca błąd o niespełnionych zależnościach. Na przykładzie poniżej znajduje się instalacja powłoki zsh.
[user@server1 ~]$ sudo rpm -ivh /mnt/BaseOS/Packages/zsh-5.8-9.el9.x86_64.rpm [sudo] password for user: Verifying... ################################# [100%] Preparing... ################################# [100%] Updating / installing... 1:zsh-5.8-9.el9 ################################# [100%]
Teraz powłoka zsh jest zainstalowana w systemie. Pakiety możemy również reinstalować podając po -i długą opcję --reinstall.
[user@server1 ~]$ sudo rpm -i --reinstall -vh /mnt/BaseOS/Packages/zsh-5.8-9.el9.x86_64.rpm Verifying... ################################# [100%] Preparing... ################################# [100%] Updating / installing... 1:zsh-5.8-9.el9 ################################# [ 50%] Cleaning up / removing... 2:zsh-5.8-9.el9 ################################# [100%]
9.1.4. Aktualizacje pakietów
Aktualizacji pakietu możemy dokonać na dwa sposoby, pierwszym z nich jest aktualizacja przy użyciu opcji -U, jeśli podany pakiet nie istnieje w systemie to zostanie on automatycznie zainstalowany. Opcji -U używa się wraz innymi opcjami instalacji -v oraz -h. Spróbujemy zaktualizować naszą powłokę zsh.
[user@server1 ~]$ sudo rpm -Uvh /mnt/BaseOS/Packages/zsh-5.8-9.el9.x86_64.rpm [sudo] password for user: Verifying... ################################# [100%] Preparing... ################################# [100%] package zsh-5.8-9.el9.x86_64 is already installed
W tym przykładzie użyłem tej samego pakietu do aktualizacji, co wygerowało monit o tym, że taki pakiet jest już zainstalowany w systemie.
Inną opcją aktualizacji jest odświerzenie (ang. freshening), ta metoda wymaga aby pakiet w starszej wersji był już zainstalowany w systemie. Odświerzenie wymaga opcji -F i używa się jej wraz z pozostałymi opcjami wymienionymi podczas instalacji oraz aktualizacji.
[user@server1 ~]$ sudo rpm -Fvh /mnt/BaseOS/Packages/zsh-5.8-9.el9.x86_64.rpm [sudo] password for user:
Polecenie nie zrobiło nic poniważ podałem ten sam pakiet, które jest już zainstalowany.
9.1.5. Usuwanie pakietów
Do usuwania pakietów z systemu służy opcja -e, używa się jej wraz z opcją -v, aby polecenie zróciło chociaż jakiś komunikat, po usunięciu pakietu. Poniżej znajdują się polecenia pokazujące usunięcie pakietu z systemu.
[user@server1 ~]$ rpm -q zsh zsh-5.8-9.el9.x86_64 [user@server1 ~]$ sudo rpm -ev zsh Preparing packages... zsh-5.8-9.el9.x86_64 [user@server1 ~]$ rpm -q zsh package zsh is not installed
Na podstawie informacji zwracanej przez ostatnie polecenie możemy wywnioskować, iż pakiet został usunięty.
9.1.6. Pozostałe czynności wykonywane na pakietach.
Do pozostałych czynności jakie możemy wykonać zaliczamy nadpisanie pakietu. Jeśli podejrzewany, że mogły wystąpić błędy podczas instalacji możemy nadpisać pakiety dodając do opcji instalacji długą opcję --replacepkgs.
[user@server1 ~]$ sudo rpm -ivh --replacepkgs /mnt/BaseOS/Packages/zsh-5.8-9.el9.x86_64.rpm [sudo] password for user: Verifying... ################################# [100%] Preparing... ################################# [100%] Updating / installing... 1:zsh-5.8-9.el9 ################################# [100%]
Wynik działania nadpisania jest identyczny jak w przypadku instalacji.
Czasami może się zdarzyć taka potrzeba, aby wyodrębnić jeden z plików znajdujących wewnątrz pakietu, możemy wówczas taki pakiet rozpakować do katalogu, a następnie przekopiować interesujące nas pliki. Załóżmy że potrzebujemy pliku /etc/bashrc. Za pomocą opcji -qf możemy ustalić z jakiego pakietu pochodzi.
[user@server1 ~]$ rpm -qf /etc/bashrc setup-2.13.7-6.el9.noarch
Pobieramy plik z internetu lub możemy załadować go z płyty. Do polecenia rpm2cpio podajemy ścieżkę do pliku, następnie wyjście polecenia przekierowujemy za pomocą potoku do polecenia cpio z następującymi opcjami -i (wypakuj), -m (zachowaj oryginalny czas modyfikacji plików), -d (utwórz katalogi poprzedzające pliki). Takie wypakowanie nalepiej jest zrobić w odrębnym katalogu na przykład w /tmp.
[user@server1 ~]$ mkdir /tmp/setup.rpm [user@server1 ~]$ cd /tmp/setup.rpm/ [user@server1 setup.rpm]$ rpm2cpio /mnt/BaseOS/Packages/setup-2.13.7-6.el9.noarch.rpm | cpio -imd 1430 blocks [user@server1 setup.rpm]$ ls etc run usr [user@server1 setup.rpm]$ ls -l etc/bashrc -rw-r--r--. 1 user user 3019 Jun 23 2020 etc/bashrc
Teraz możemy przekopować potrzebny nam pliki.
Ćwiczenie 1: Instalacja pakietu zsh
Na maszynie server1, jak użytkownik z mozliwością podniesienia uprawnień zamontuj płytę/obraz płyty w systemie. Za pomocą polecenia rpm wyświetl informacje (podstawowe) o pakiecie zsh, sprawdź jego poprawność oraz wiarygodność, a następnie zainstaluj go w systemie. Na koniec sprawdź czy występują jakieś róznice między plikami zainstalowanymi, a plikami oryginalnymi występującymi w pakiecie.
Ćwiczenie 2: Pobieranie informacji oraz usunięcie pakietu
Na maszynie server1, jak użytkownik z mozliwością podniesienia uprawnień zamontuj płytę/obraz płyty w systemie. Za pomocą polecenia rpm sprawdzić czy zainstalowany jest pakiet setup i wyświetl jego pliki konfiguracyjne. Wyświetl informacje na temat pakietu zlib-devel znajdującego się na obrazie płyty. Zainstaluj ponownie pakiet zsh a następnie go usuń.
Podsumowanie
W tym rozdziale zapoznaliśmy się z pojęciem pakietu oprogramowania oraz z podstawowymi metodami na zarządzanie nim w RHEL w praktyce. Dowiedzieliśmy się jak instalować, usuwać oraz wydobywać informacje o i z pakietów. W następnym rodziale zajmiemy się bardziej zaawansowanym zarządzeniem pakietami przy użyciu polecenia dnf.
10. Zaawansowane zarządzanie pakietami.
W poprzednim rozdziale zapoznaliśmy się z podstawą zarządania pakietami jaka nie wątpliwie jest program rpm. Jego główną wadą jest to, iż nie rozwiązuje on zależności instalowanych pakietów. Z tego powodu potrzebne było lepsze narzędzie do obsługi oprogramowania w systemie, dlatego też twórcy RHEL wdrożyli program yum, który przez lata sprawdzał się postaci menedżera pakietów, a od wersji 8 Red Hat Enterprise Linux został on zastąpiony programem dnf, który ma nieco większe możliwości. Zanim przejdziemy do zarządzania pakietami, trochę teorii.
Dnf wprowadza do zarządzania pakietami takie pojęcia jak grupy pakietów - są tematyczne grupy aplikacji, którymi możemy wzbogacić nasz system. Powiedzmy, że potrzebujemy w systemie obsługi kart inteligentnych to zamiast szukać odpowiednich pakietów, możemy zainstalować wszystkie niezbędne programy podając poleceniu dnf nazwę grupy.
Wraz z dnf pojawiają się takie pojęcia jak moduł aplikacji oraz strumień aplikacji. Moduł aplikacji, to podobnie do grupy jest zbiór pakietów, ale odpowiedzialnych za jedną aplikację. W module zawarte są wszystkie pakiety odpowiedzialne za działanie aplikacji, poza zależnościami mogą znajdować się tam także biblioteki, generalnie całe środowisko. Moduły posiadają swoje strumienie, czyli konkretne wersje pakietów aplikacji, które dostarczają. W systemie może być zainstalowany tylko jeden strumień danej aplikacji. Między strumieniami można się przełączać. będziemy to omawiać pod koniec tego rozdziału. Moduły w strumieniach posiadają jeszcze profile. Profile są to zbiory pakietów, programów określanych przez moduł zbudowane z myślą o przeznaczeniu aplikacji. Na przykład systemy bazodanowe mogą posiadać pakiety przeznaczone dla serwera oraz dla klienta. Jeśli baza danych znajduje się na innym serwerze niż aplikacja, która z niej korzysta, to w systemie aplikacji nie ma sensu instalować wszystkich pakietów związanych z cała bazą wystarczą pakiety, które będą udostępniać tylko i wyłącznie możliwość połączenia się z bazą.
RHEL w wersji 8 dzieli również repozytorium (bazę pakietów) na dwie części. Piewsza część BaseOS, zawiera jak sama nazwa wskazuje pakiety bazowe, które zawierają większość pakietów niezbędnych do działania systemu operacyjnego. Druga część AppStream zawiera wszystkie dodatkowe aplikacje. Tego rodzaju podział został wprowadzony z względu na to, że w momencie przezprowadzania aktualizacji systemu, aktualizowane było również zainstalowane na nim oprogramowanie co mogło nie być porządane i wprowadzać nie potrzebne zamieszanie lub destabilizować cały systemu.
Kolejną rzeczą wartą wspomnienia są repozytoria. Nasze systemy, których używamy do wypróbowywania przykładów oraz do rozwiązywania ćwiczeń, nie są zarejestrowane na naszych kontach Red Hat. Rejestracja systemu daje możliwość aktualizacji pakietów zawartych na płytach oraz instalowania ich bezpośrednio z sieci. Oprócz repozytoriów firmy Red Hat mamy rownież inne repozytoria dostępne w sieci. Takie jak na przykład RPM Fusion. Bez tych repozytoriów korzystanie z RHEL 9 w codziennym użyciu na desktopie nie miało by sensu. Przynajmniej w moim wypadku ;). Konfigurację repozytoriów przeprowadza się zapisując je w pliku w katalogu /etc/yum.repos.d, w jednym pliku może znajdować się kilka repozytoriów, sposób organizacji zależy od nas.
Na koniec, kilka spraw organizacyjnych. W RHEL 9 poki co brakuje modułów. W tym odnośniku znajduje się dowód, że na moduły przyjdzie na poczekać do wersji 9.1. https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/9/html-single/managing_software_with_the_dnf_tool/index#con_modules_assembly_distribution-of-content-in-rhel-9 Tak więc wszystkie przykłady jakie będę wykonywać w tym rodziale będą realizowane za pomocą Red Hat Enterprise Linux w wersji 8.6. Po zarejestrowaniu się możemy pobrać RHEL aż do wersji 8.0. Także możemy stworzyć środowisko maszyny server1 na podstawie RHEL 8.
10.1. Konfiguracja repozytorium dnf
Jak już wspomniałem repozytorium konfigurujemy za pomocą plików złożonych w katalogu /etc/yum.repos.d. Na początku jednak musimy dodać płytę do pliku /etc/fstab. Opisywałem ten proces na początku 9 rozdziału o tutaj. Dlatego też w przykładach przyjmę iż płyta jest montowana w podkatalogu /mnt. Jak pamiętamy z poprzedniego rozdziału na płycie znajdują się dwa katalogi z pakietami: BaseOS/Packages oraz AppStream/Packages. W konfiguracji podajemy tylko te pierwsze człony tych ścieżek, ponieważ w niej wskazujemy katalog bazowy. Konfiguracja każdego z repozytorium wymaga minimum 4 wierszy. Poniższy przykład przedstawia zawartość pliku konfiguracjynego repozytoriów z płyty instalacjynej RHEL 8.
[BaseOS] name=BaseOS baseurl=file:///mnt/BaseOS gpgcheck=0 [AppStream] name=AppStream baseurl=file:///mnt/AppStream gpgcheck=0
W nawiasach kwadratowych znajdują się unikatowe identyfikatory
repozytoriów ([BaseOS]
), następnie
dyrektywa name
zawiera ich opisy
w przypadku środowisk testowych nie musimy się wysilać z opisami czy
sprawdzać autentyczności pakietów przy użyciu GPG
(gpgcheck=0
). Wyłączenie sprawdzania
pakietów usprawni proces ich instalacji, w przeciwym razie za
każdą czynnością opartą o repozytorium otrzymywalibyśmy monit. Istotną
funkcję pełni tym
przypadku dyrektywa baseurl
, która
wskazuje na miejsce przechowywania pakietów, tym przypadku jest katalog
zatem protokołem poprzedzającym ścieżkę będzie
file
, jak w każdym adresie URL
następuje ://
, a następnie
(w tym przypadku) bezwzględna ścieżka do katalogu.
Odnośnie egzaminu:
Umiejętnośc konfigurowania repozytoriów yum/dnf z
wykorzystaniem URL może być istotna do wykonania pewnych
zadań egzaminacyjnych. Konstruując URL możemy użyć takich
protokołów jak FTP, HTTP czy HTTPS (zapis w URL zawsze małymi
literami) po czym następuje dwukropek z dwoma slashami ://
a następnie adres repozytorium.
Po zdefiniowaniu repozytoriów zapisujemy zmiany w pliku. Aby zweryfikować poprawność konfiguracji wydajemy polecenie, które odświerza pamięć podręczną pakietów.
[user@rhel8-vm1 ~]$ sudo dnf makecache [sudo] password for user: Updating Subscription Management repositories. Unable to read consumer identity This system is not registered with an entitlement server. You can use subscription-manager to register. BaseOS 1.6 MB/s | 2.7 kB 00:00 AppStream 2.3 MB/s | 2.8 kB 00:00 Metadata cache created.
Metadane zostały załadowane do pamięci podręcznej. Za pomocą poniższego polecenia możemy wyświetlić informacje na temat zdefiniowanych w naszym systemie repozytoriów.
[user@rhel8-vm1 mnt]$ sudo dnf repoinfo -v ... DNF version: 4.7.0 cachedir: /var/cache/dnf Ostatnio sprawdzono ważność metadanych: 0:00:20 temu w dniu nie, 10 lip 2022, 22:51:36. Identyfikator repozytorium : AppStream Nazwa repozytorium : AppStream Wersja repozytorium : 1650471026 Aktualizacje repozytorium : śro, 20 kwi 2022, 18:10:27 Pakiety repozytorium : 6 609 Dostępne pakiety repozytorium : 5 345 Rozmiar repozytorium : 8.6 G Podstawowy adres URL repozytorium : file:///mnt/AppStream Wygaszenie repozytorium : 172 800 s (ostatnio: nie, 10 lip 2022, 22:51:36) Nazwa pliku repozytorium : /etc/yum.repos.d/local.repo Identyfikator repozytorium : BaseOS Nazwa repozytorium : BaseOS Wersja repozytorium : 1650471057 Aktualizacje repozytorium : śro, 20 kwi 2022, 18:10:59 Pakiety repozytorium : 1 714 Dostępne pakiety repozytorium : 1 712 Rozmiar repozytorium : 1.3 G Podstawowy adres URL repozytorium : file:///mnt/BaseOS Wygaszenie repozytorium : 172 800 s (ostatnio: nie, 10 lip 2022, 22:51:34) Nazwa pliku repozytorium : /etc/yum.repos.d/local.repo Razem pakietów: 8 323
Tak zdefiniowanych repozytoriów będziemy używać w przykładach oraz do rozwiązywania zadań w ćwiczeniach.
10.2. Zarządzanie pojedynczymi pakietami
Program dnf jest stanie wykonywać identyczne czynności jak polecenie rpm. Z racji tego, iż skonfigurowaliśmy wcześniej repozytorium nie musimy podawać żadnych ścieżek wystarczy nazwa pakietu, a ją możemy poznać wyświetlając listy pakietów.
10.2.1. Listy pakietów
Z pomocą poniższego polecenia możemy wyświetlić listę wszystkich pakietów. Domyślnie lista pakietów jest podzielona na dwie części: zainstalowane oraz dostępne pakiety.
[user@rhel8-vm1 ~]$ sudo dnf list Updating Subscription Management repositories. Unable to read consumer identity This system is not registered with an entitlement server. You can use subscription-manager to register. Ostatnio sprawdzono ważność metadanych: 9:22:00 temu w dniu nie, 10 lip 2022, 22:51:36. Zainstalowane pakiety GConf2.x86_64 3.2.6-22.el8 @AppStream ModemManager.x86_64 1.18.2-1.el8 @anaconda ModemManager-glib.x86_64 1.18.2-1.el8 @anaconda NetworkManager.x86_64 1:1.36.0-4.el8 @anaconda NetworkManager-adsl.x86_64 1:1.36.0-4.el8 @anaconda NetworkManager-bluetooth.x86_64 1:1.36.0-4.el8 @anaconda NetworkManager-config-server.noarch 1:1.36.0-4.el8 @anaconda NetworkManager-libnm.x86_64 1:1.36.0-4.el8 @anaconda NetworkManager-team.x86_64 1:1.36.0-4.el8 @anaconda NetworkManager-tui.x86_64 1:1.36.0-4.el8 @anaconda NetworkManager-wifi.x86_64 1:1.36.0-4.el8 @anaconda NetworkManager-wwan.x86_64 1:1.36.0-4.el8 @anaconda ... Dostępne pakiety CUnit.i686 2.1.3-17.el8 AppStream CUnit.x86_64 2.1.3-17.el8 AppStream GConf2.i686 3.2.6-22.el8 AppStream HdrHistogram.noarch 2.1.11-3.module+el8.5.0+12798+cbad756b AppStream HdrHistogram-javadoc.noarch 2.1.11-3.module+el8.5.0+12798+cbad756b AppStream HdrHistogram_c.i686 0.9.13-2.el8 AppStream HdrHistogram_c.x86_64 0.9.13-2.el8 AppStream Judy.x86_64 1.0.5-18.module+el8+2765+cfa4f87b AppStream LibRaw.i686 0.19.5-3.el8 AppStream LibRaw.x86_64 0.19.5-3.el8 AppStream ModemManager-glib.i686 1.18.2-1.el8 BaseOS NetworkManager-cloud-setup.x86_64 1:1.36.0-4.el8 AppStream NetworkManager-config-connectivity-redhat.noarch 1:1.36.0-4.el8 BaseOS NetworkManager-dispatcher-routing-rules.noarch
Ilość wyświetlonych pakietów możemy zmniejszyć za pomocą odpowiednich opcji, wyświetlając tylko listę pakietów zainstalowanych (--installed) lub listę pakietów dostępnych (--available).
[user@rhel8-vm1 ~]$ sudo dnf list --installed Updating Subscription Management repositories. Unable to read consumer identity This system is not registered with an entitlement server. You can use subscription-manager to register. Zainstalowane pakiety GConf2.x86_64 3.2.6-22.el8 @AppStream ModemManager.x86_64 1.18.2-1.el8 @anaconda ModemManager-glib.x86_64 1.18.2-1.el8 @anaconda NetworkManager.x86_64 1:1.36.0-4.el8 @anaconda NetworkManager-adsl.x86_64 1:1.36.0-4.el8 @anaconda NetworkManager-bluetooth.x86_64 1:1.36.0-4.el8 @anaconda NetworkManager-config-server.noarch 1:1.36.0-4.el8 @anaconda NetworkManager-libnm.x86_64 1:1.36.0-4.el8 @anaconda [user@rhel8-vm1 ~]$ sudo dnf list --available Updating Subscription Management repositories. Unable to read consumer identity This system is not registered with an entitlement server. You can use subscription-manager to register. Ostatnio sprawdzono ważność metadanych: 9:33:18 temu w dniu nie, 10 lip 2022, 22:51:36. Dostępne pakiety CUnit.i686 2.1.3-17.el8 AppStream CUnit.x86_64 2.1.3-17.el8 AppStream GConf2.i686 3.2.6-22.el8 AppStream HdrHistogram.noarch 2.1.11-3.module+el8.5.0+12798+cbad756b AppStream HdrHistogram-javadoc.noarch 2.1.11-3.module+el8.5.0+12798+cbad756b AppStream HdrHistogram_c.i686 0.9.13-2.el8 AppStream HdrHistogram_c.x86_64 0.9.13-2.el8 AppStream Judy.x86_64 1.0.5-18.module+el8+2765+cfa4f87b AppStream LibRaw.i686 0.19.5-3.el8 AppStream LibRaw.x86_64 0.19.5-3.el8 AppStream ModemManager-glib.i686 1.18.2-1.el8 BaseOS
Listy są podzielone na trzy kolumny w pierwsze z nich znajduje się
nazwa pakietu, w drugie wersja, a w trzeciej nazwa repozytorium, które
zawiera ten pakiet lub z które został on zainstalowany. W przypadku
wartości @anaconda
, są to pakiety
zainstalowane podczas instalacji systemu, w przypadku pakietów
instalowanych
za pomocą polecenia rpm w trzeciej kolumnie będzie widnieć
napis @System.
Przydatną opcją jeśli korzystamy z repozytoriów sieciowych może być updates wydawane po podpoleceniu list. W dnf opcje często posiadają formę podpoleceń, natomiast to co my możemy uważać za opcję jest modyfikatorem. Podpolecenie updates wyświetla pakiety możliwe do zaktualizowania.
10.2.2. Zapytania do repozytorium
Dnf w przeciwieństwie do rpm pozwala nam przeszukiwać repozytorium pod względem występowania na przykład pakietu lub możemy podać ścieżkę do pliku znajdującego się w systemie a program zwrócić nam informacje z jakiego pakietu pochodzi.
[user@rhel8-vm1 ~]$ sudo dnf repoquery zsh [sudo] hasło użytkownika user: Ostatnio sprawdzono ważność metadanych: 0:03:42 temu w dniu pon, 11 lip 2022, 08:36:18. zsh-0:5.5.1-9.el8.x86_64 [user@rhel8-vm1 ~]$ sudo dnf repoquery /etc/bashrc Ostatnio sprawdzono ważność metadanych: 0:04:02 temu w dniu pon, 11 lip 2022, 08:36:18. setup-0:2.12.2-6.el8.noarch
Podpolecenie repoquery pozwala na sprecyzowanie repozytorium, do którego będą kierowane zapytania, za pomocą opcji --repo.
[user@rhel8-vm1 ~]$ sudo dnf repoquery --repo BaseOS zsh Ostatnio sprawdzono ważność metadanych: 0:16:51 temu w dniu pon, 11 lip 2022, 08:36:18. zsh-0:5.5.1-9.el8.x86_64
Podpolecenie repoquery posiada całą masę modyfikatorów dzięki nim możemy na przykład sprawdzić zależności pakietów. Aby ujawnić listę modyfikatorów możemy użyć podpolecenia repoquery wraz z --help.
[user@rhel8-vm1 ~]$ sudo dnf repoquery --help Repoquery command-specific options: -a, --all Odpytuje wszystkie pakiety (skrót do „repoquery '*'” lub repoquery bez parametru) --show-duplicates Odpytuje wszystkie wersje pakietów (domyślnie) --arch [arch], --archlist [arch] wyświetla tylko wyniki dla tej ARCHITEKTURY -f FILE [FILE ...], --file FILE [FILE ...] wyświetla tylko wyniki posiadające PLIK ...
10.2.3. Pobieranie informacji o pakietach
Polecenie dnf pozwala uzyskać informacje na temat pakietu. Za pomocą podpolecenia info możemy pobrać informacje o na przykład wersji, numerze wydania, rozmiarze czy repozytorium w jakim jest przechowywane.
[user@rhel8-vm1 ~]$ sudo dnf info php Updating Subscription Management repositories. Unable to read consumer identity This system is not registered with an entitlement server. You can use subscription-manager to register. Ostatnio sprawdzono ważność metadanych: 0:40:02 temu w dniu pon, 11 lip 2022, 08:36:18. Dostępne pakiety Nazwa : php Wersja : 7.2.24 Wydanie : 1.module+el8.2.0+4601+7c76a223 Architektura : x86_64 Rozmiar : 1.5 M Źródło : php-7.2.24-1.module+el8.2.0+4601+7c76a223.src.rpm Repozytorium : AppStream Podsumowanie : PHP scripting language for creating dynamic web sites Adres URL : http://www.php.net/ Licencja : PHP and Zend and BSD and MIT and ASL 1.0 Opis : PHP is an HTML-embedded scripting language. PHP attempts to make : it easy for developers to write dynamically generated web pages. : PHP also offers built-in database integration for several : commercial and non-commercial database management systems, so : writing a database-enabled webpage with PHP is fairly simple. The : most common use of PHP coding is probably as a replacement for : CGI scripts. : : The php package contains the module (often referred to as : mod_php) which adds support for the PHP language to Apache HTTP : Server.
Teraz kiedy wiemy jak możemy uzyskać informacje na temat interesujących nas pakietów możemy przejść do podstawowych czynności z nimi związanych, czyli: instalacji, aktualizacji oraz usuwania.
10.2.4. Instalacja pakietów
Instalacja pakietów jest banalnie prosta w przypadku narzędzia dnf wymaga ona użycia podpolecenia install a następnie podania nazwy pakietu.
[user@rhel8-vm1 ~]$ sudo dnf install mc Updating Subscription Management repositories. Unable to read consumer identity This system is not registered with an entitlement server. You can use subscription-manager to register. Ostatnio sprawdzono ważność metadanych: 1:07:02 temu w dniu pon, 11 lip 2022, 08:36:18. Rozwiązano zależności. ================================================================================ Pakiet Architektura Wersja Repozytorium Rozm. ================================================================================ Instalowanie: mc x86_64 1:4.8.19-9.el8 AppStream 1.9 M Podsumowanie transakcji ================================================================================ Instalacja 1 pakiet Całkowity rozmiar: 1.9 M Rozmiar po zainstalowaniu: 6.8 M W porządku? [t/N]: ...
Program wyświetli w tabeli wszystkie instalowane pakiety, następnie całkowity rozmiar pobieranych pakietów oraz ilość miejsca na dysku zabranego na potrzeby instalacji. Po zapoznaniu się z tym możemy potwierdzić za pomocą t (w polskiej wersji językowej) lub y lub przerwać na przykład naciskając Enter, ponieważ opcja N (nie, no) jest domyślna. Po zatwierdzeniu pakietów rozpocznie się ich pobieranie oraz instalacja.
... Pobieranie pakietów: Wykonywanie sprawdzania transakcji Pomyślnie ukończono sprawdzanie transakcji. Wykonywanie testu transakcji Pomyślnie ukończono test transakcji. Wykonywanie transakcji Przygotowywanie : 1/1 Instalowanie : mc-1:4.8.19-9.el8.x86_64 1/1 Wykonywanie skryptu : mc-1:4.8.19-9.el8.x86_64 1/1 Sprawdzanie : mc-1:4.8.19-9.el8.x86_64 1/1 Installed products updated. Zainstalowano: mc-1:4.8.19-9.el8.x86_64 Ukończono.
[user@rhel8-vm1 ~]$ sudo dnf list --installed mc [sudo] hasło użytkownika user: Zainstalowane pakiety mc.x86_64 1:4.8.19-9.el8 @AppStream
Dnf daje nam możliwość przeprowadzanie lokalnej instalacji podając ścieżkę do pliku .rpm. Ta czynność wymaga użycia podpolecenia localinstall.
[user@rhel8-vm1 ~]$ sudo dnf localinstall /mnt/AppStream/Packages/dcraw-9.27.0-9.el8.x86_64.rpm [sudo] hasło użytkownika user: Updating Subscription Management repositories. Unable to read consumer identity This system is not registered with an entitlement server. You can use subscription-manager to register. Ostatnio sprawdzono ważność metadanych: 1:23:58 temu w dniu pon, 11 lip 2022, 08:36:18. Rozwiązano zależności. ================================================================================ Pakiet Architektura Wersja Repozytorium Rozm. ================================================================================ Instalowanie: dcraw x86_64 9.27.0-9.el8 @commandline 267 k Podsumowanie transakcji ================================================================================ Instalacja 1 pakiet Całkowity rozmiar: 267 k Rozmiar po zainstalowaniu: 548 k W porządku? [t/N]: t Pobieranie pakietów: Wykonywanie sprawdzania transakcji Pomyślnie ukończono sprawdzanie transakcji. Wykonywanie testu transakcji Pomyślnie ukończono test transakcji. Wykonywanie transakcji Przygotowywanie : 1/1 Instalowanie : dcraw-9.27.0-9.el8.x86_64 1/1 Wykonywanie skryptu : dcraw-9.27.0-9.el8.x86_64 1/1 Sprawdzanie : dcraw-9.27.0-9.el8.x86_64 1/1 Installed products updated. Zainstalowano: dcraw-9.27.0-9.el8.x86_64 Ukończono.
10.2.5. Aktualizacje pakietów
Aktualizacja pakietów za pomocą dnf wymaga użycia podpolecenia update. Aktualizacje pojedynczych pakietów przeprowadzamy podając ich nazwę po podpoleceniu. Ta funkcjonalność wymaga jednak aby pakiet był już zainstalowany w systemie. Jeśli wydamy to podpolecenie bez żadnego argumentu polecenie sprawdzi wszystkie zainstalowane pakiety w systemie, czy występują dla nich jakieś aktualizacje następnie spyta czy je zainstalować.
[user@rhel8-vm1 ~]$ sudo dnf update autofs [sudo] hasło użytkownika user: Updating Subscription Management repositories. Unable to read consumer identity This system is not registered with an entitlement server. You can use subscription-manager to register. Ostatnio sprawdzono ważność metadanych: 1:34:19 temu w dniu pon, 11 lip 2022, 08:36:18. Pakiet autofs jest dostępny, ale nie jest zainstalowany. Brak wyników dla parametru: autofs Błąd: Brak pakietów oznaczonych do aktualizacji. [user@rhel8-vm1 ~]$ sudo dnf update Updating Subscription Management repositories. Unable to read consumer identity This system is not registered with an entitlement server. You can use subscription-manager to register. Ostatnio sprawdzono ważność metadanych: 1:38:26 temu w dniu pon, 11 lip 2022, 08:36:18. Rozwiązano zależności. Nie ma nic do zrobienia. Ukończono.
10.2.6. Usuwanie pakietów
Usuwanie pakietów w przypadku dnf wymaga użycia podpolecenia remove. Polecenie usunie zainstalowany pakiet z systemu wraz ze wszystkimi jego plikami.
[user@rhel8-vm1 ~]$ sudo dnf remove mc [sudo] hasło użytkownika user: Updating Subscription Management repositories. Unable to read consumer identity This system is not registered with an entitlement server. You can use subscription-manager to register. Rozwiązano zależności. ================================================================================ Pakiet Architektura Wersja Repozytorium Rozm. ================================================================================ Usuwanie: mc x86_64 1:4.8.19-9.el8 @AppStream 6.8 M Podsumowanie transakcji ================================================================================ Usunięcie 1 pakiet Zwolnione miejsce: 6.8 M W porządku? [t/N]: t Wykonywanie sprawdzania transakcji Pomyślnie ukończono sprawdzanie transakcji. Wykonywanie testu transakcji Pomyślnie ukończono test transakcji. Wykonywanie transakcji Przygotowywanie : 1/1 Usuwanie : mc-1:4.8.19-9.el8.x86_64 1/1 Wykonywanie skryptu : mc-1:4.8.19-9.el8.x86_64 1/1 Sprawdzanie : mc-1:4.8.19-9.el8.x86_64 1/1 Installed products updated. Usunięto: mc-1:4.8.19-9.el8.x86_64 Ukończono.
W przypadku instalowania pakietu polecenie przekazywało nam informacje o użytym na potrzeby instalacji miejscu na dysku. Tak teraz informuje o jego zwolnieniu.
10.2.7. Więcej informacji na temat pakietów
Innym sposobem na uzyskanie informacji o tym jaki pakiet zawiera określony plik jest użycie podpolecenia provides. Sprawdza ono występowanie plików w pakietach zainstalowanych w systemie jak i tych możliwych do instalacji.
[user@rhel8-vm1 ~]$ sudo dnf provides /etc/passwd Updating Subscription Management repositories. Unable to read consumer identity This system is not registered with an entitlement server. You can use subscription-manager to register. Ostatnio sprawdzono ważność metadanych: 2:04:16 temu w dniu pon, 11 lip 2022, 08:36:18. setup-2.12.2-6.el8.noarch : A set of system configuration and setup files Repozytorium : @System Dopasowano z: Nazwa pliku : /etc/passwd setup-2.12.2-6.el8.noarch : A set of system configuration and setup files Repozytorium : BaseOS Dopasowano z: Nazwa pliku : /etc/passwd
Po za opisaną metodą na wyszukiwanie informacji o pakietach, do dyspozycji posiadamy jeszcze podpolecenie search, które wyszukuje słów kluczowych w podsumowaniu opisu pakietu oraz jego nazwie.
[user@rhel8-vm1 ~]$ sudo dnf search setup [sudo] hasło użytkownika user: Updating Subscription Management repositories. Unable to read consumer identity This system is not registered with an entitlement server. You can use subscription-manager to register. Ostatnio sprawdzono ważność metadanych: 2:20:48 temu w dniu pon, 11 lip 2022, 08:36:18. ==================== Dopasowano Nazwa i Podsumowanie: setup ==================== setup.noarch : A set of system configuration and setup files cryptsetup-libs.x86_64 : Cryptsetup shared library cryptsetup-libs.i686 : Cryptsetup shared library ibus-setup.noarch : IBus setup utility initial-setup-gui.x86_64 : Graphical user interface for the initial-setup : utility ... =========================== Dopasowano Nazwa: setup ============================ NetworkManager-cloud-setup.x86_64 : Automatically configure NetworkManager in : cloud cryptsetup.x86_64 : A utility for setting up encrypted disks cryptsetup-devel.i686 : Headers and libraries for using encrypted file systems cryptsetup-devel.x86_64 : Headers and libraries for using encrypted file systems cryptsetup-reencrypt.x86_64 : A utility for offline reencryption of LUKS : encrypted disks. ... ======================== Dopasowano Podsumowanie: setup ======================== rhsm-gtk.x86_64 : GTK+ widgets used by subscription-manager-gui and : initial_setup
Jak możemy zauważyć polecenie wyświetla znalezione informacje w trzech grupach.
10.3. Grupy pakietów
Pośród innych sposobów na zarządzanie pakietami możemy wymienić grupy pakietów. Są to zestawy pakietów odpowiedzialne za zapewnienie systemowi operacyjnemu pewnej funkcjonalności np. obsługi wirtualizacji i maszyn wirtualnych. Grupy pakietów obsługuje się identycznie jak pakiety indywidualne, możemy je wyświetlić, zainstalować, zaktualizować, wyświetlić informacje o nich oraz usunąć. Przjdziemy sobie przez te wszystkie zagadnienia.
10.3.1. Listy grup
Do obsługi grupy służy podpolecenie group, które posiada kolejne znane nam już z obsługi pojedynczych pakietów podpolecenia takie jak np list, którego zadaniem jest wyświetlenie grup pakietów.
[user@rhel8-vm1 ~]$ sudo dnf group list [sudo] hasło użytkownika user: Updating Subscription Management repositories. Unable to read consumer identity This system is not registered with an entitlement server. You can use subscription-manager to register. Ostatnio sprawdzono ważność metadanych: 2:39:54 temu w dniu pon, 11 lip 2022, 08:36:18. Dostępne grupy środowisk: Server Minimalna instalacja Workstation Custom Operating System Gospodarz wirtualizacji Zainstalowane grupy środowisk: Serwer z graficznym interfejsem użytkownika Zainstalowane grupy: Container Management Headless Management Dostępne grupy: Zgodność z przestarzałym systemem UNIX Narzędzia programistyczne .NET Core Development Graficzne narzędzia administracyjne Serwery sieciowe RPM Development Tools Obsługa aplikacji naukowych Narzędzia bezpieczeństwa Obsługa smart card Narzędzia systemowe
Jak możemy zawuważyć grupy dzielą się dwa rodzaje pierwszym z nich są
grupy środowisk
, drugim są
zwykłe grupy. Z grupami mogliśmy się już spotkać podczas instalacji
systemu, wybieraliśmy rodzaj instalacji Server with GUI.
Podczas wyboru oprogramowania mogliśmy wybrać dowolną z nich do
zainstalowania. Teraz za pomocą dnf możemy doinstalować
dodatkowe grupy lub usunąć nie potrzebne. Podpolecenie list
wyświetla również te obecnie zainstalowane oraz nie wyświetla
wszystkich dostępnych w systemie grup. Wszystkie grupy będą wyświetlone
jeśli uzupełnimy nasze polecenie o modyfikator --hidden.
W ten sposób możemy wybrać znacznie węższą grupę pakietów. Możemy
również używać modyfikatorów takich jak --installed lub
--available
Po za taką długą listą możemy wyświetlić podsumowanie, które zwróci informacje o ilości dostępnych oraz zainstalowanych grup.
[user@rhel8-vm1 ~]$ sudo dnf group summary Updating Subscription Management repositories. Unable to read consumer identity This system is not registered with an entitlement server. You can use subscription-manager to register. Ostatnio sprawdzono ważność metadanych: 3:08:10 temu w dniu pon, 11 lip 2022, 08:36:18. Zainstalowane grupy: 2 Dostępne grupy: 10
10.3.2. Informacje o grupie
Za wyświetlenie informacji o grupie odpowiedzialne jest podpolecenie info, zwraca ono listę pakietów obowiązkowych, które muszą być zainstalowane, aby system został rozszerzony o funkcjonalność przypisaną grupie oraz listę pakietów opcjonalnych.
[user@rhel8-vm1 ~]$ sudo dnf group info "Platforma wirtualizacji" [sudo] hasło użytkownika user: Updating Subscription Management repositories. Unable to read consumer identity This system is not registered with an entitlement server. You can use subscription-manager to register. Ostatnio sprawdzono ważność metadanych: 2:58:21 temu w dniu pon, 11 lip 2022, 08:36:18. Grupa: Platforma wirtualizacji Opis: Dostarcza interfejs do uzyskiwania dostępu i kontrolowania wirtualizowanych gości i kontenerów. Pakiety obowiązkowe: libvirt libvirt-client virt-who Pakiety opcjonalne: fence-virtd-libvirt fence-virtd-multicast fence-virtd-serial perl-Sys-Virt
10.3.3. Instalacja grup
Instalacja grup odbywa się na tej samej zasadzie, z drobnym wyjątkiem. Otóż jeśli w systemie będą występować jakieś składniki grupy, to jeśli będzie taka możliwość zostaną one zaktualizowane. Instalacja grupy odbywa się za pomocą podpolecenia install podpolecenia group. Jako argument podajemy nazwę grupy.
[user@rhel8-vm1 ~]$ sudo dnf group install "Obsługa smart card" Updating Subscription Management repositories. Unable to read consumer identity This system is not registered with an entitlement server. You can use subscription-manager to register. Ostatnio sprawdzono ważność metadanych: 3:37:36 temu w dniu pon, 11 lip 2022, 08:36:18. Rozwiązano zależności. ================================================================================ Pakiet Architektura Wersja Repozytorium Rozm. ================================================================================ Instalowanie pakietów grupy/modułu: esc x86_64 1.1.2-22.el8_4 AppStream 180 k pcsc-lite-ccid x86_64 1.4.29-5.1.el8_4 BaseOS 316 k Instalowanie zależności: opensc x86_64 0.20.0-4.el8 BaseOS 1.3 M pcsc-lite x86_64 1.9.5-1.el8 BaseOS 110 k pcsc-lite-libs x86_64 1.9.5-1.el8 BaseOS 43 k Instalowanie grup: Smart Card Support Podsumowanie transakcji ================================================================================ Instalacja 5 pakietów Całkowity rozmiar: 1.9 M Rozmiar po zainstalowaniu: 6.0 M W porządku? [t/N]: t Pobieranie pakietów: Wykonywanie sprawdzania transakcji Pomyślnie ukończono sprawdzanie transakcji. Wykonywanie testu transakcji Pomyślnie ukończono test transakcji. Wykonywanie transakcji Przygotowywanie : 1/1 Instalowanie : pcsc-lite-libs-1.9.5-1.el8.x86_64 1/5 Wykonywanie skryptu : pcsc-lite-libs-1.9.5-1.el8.x86_64 1/5 Instalowanie : pcsc-lite-ccid-1.4.29-5.1.el8_4.x86_64 2/5 Wykonywanie skryptu : pcsc-lite-ccid-1.4.29-5.1.el8_4.x86_64 2/5 Instalowanie : pcsc-lite-1.9.5-1.el8.x86_64 3/5 Wykonywanie skryptu : pcsc-lite-1.9.5-1.el8.x86_64 3/5 Instalowanie : opensc-0.20.0-4.el8.x86_64 4/5 Wykonywanie skryptu : opensc-0.20.0-4.el8.x86_64 4/5 Instalowanie : esc-1.1.2-22.el8_4.x86_64 5/5 Wykonywanie skryptu : esc-1.1.2-22.el8_4.x86_64 5/5 Sprawdzanie : opensc-0.20.0-4.el8.x86_64 1/5 Sprawdzanie : pcsc-lite-1.9.5-1.el8.x86_64 2/5 Sprawdzanie : pcsc-lite-ccid-1.4.29-5.1.el8_4.x86_64 3/5 Sprawdzanie : pcsc-lite-libs-1.9.5-1.el8.x86_64 4/5 Sprawdzanie : esc-1.1.2-22.el8_4.x86_64 5/5 Installed products updated. Zainstalowano: esc-1.1.2-22.el8_4.x86_64 opensc-0.20.0-4.el8.x86_64 pcsc-lite-1.9.5-1.el8.x86_64 pcsc-lite-ccid-1.4.29-5.1.el8_4.x86_64 pcsc-lite-libs-1.9.5-1.el8.x86_64 Ukończono.
Za pomocą dnf zainstalowałem w grupę pakietów odpowiedzialną za obsługę kart inteligentych.
10.3.4. Aktualizacja grupy
Aktualizacja grupy różni się podaniem innego podpolecenia. Zamiast install podajemy update.
[user@rhel8-vm1 ~]$ sudo dnf group update "Obsługa smart card" [sudo] hasło użytkownika user: Updating Subscription Management repositories. Unable to read consumer identity This system is not registered with an entitlement server. You can use subscription-manager to register. Ostatnio sprawdzono ważność metadanych: 3:47:16 temu w dniu pon, 11 lip 2022, 08:36:18. Rozwiązano zależności. ================================================================================ Pakiet Architektura Wersja Repozytorium Rozm. ================================================================================ Aktualizowanie grup: Smart Card Support Podsumowanie transakcji ================================================================================ W porządku? [t/N]: t Ukończono.
10.3.5. Usuwanie grupy
Tak samo jak w przypadku pojedynczych pakietów, możemy usunąć i grupy. Do usunięcia grupy potrzebne będzie podpolecenie remove oraz nazwa grupy.
[user@rhel8-vm1 ~]$ sudo dnf group remove "Obsługa smart card" Updating Subscription Management repositories. Unable to read consumer identity This system is not registered with an entitlement server. You can use subscription-manager to register. Rozwiązano zależności. ================================================================================ Pakiet Arch. Wersja Repozytorium Rozm. ================================================================================ Usuwanie: esc x86_64 1.1.2-22.el8_4 @AppStream 516 k pcsc-lite-ccid x86_64 1.4.29-5.1.el8_4 @BaseOS 1.4 M Usuwanie nieużywanych zależności: opensc x86_64 0.20.0-4.el8 @BaseOS 3.8 M pcsc-lite x86_64 1.9.5-1.el8 @BaseOS 218 k pcsc-lite-libs x86_64 1.9.5-1.el8 @BaseOS 50 k Usuwanie grup: Smart Card Support Podsumowanie transakcji ================================================================================ Usunięcie 5 pakietów Zwolnione miejsce: 6.0 M W porządku? [t/N]: t Wykonywanie sprawdzania transakcji Pomyślnie ukończono sprawdzanie transakcji. Wykonywanie testu transakcji Pomyślnie ukończono test transakcji. Wykonywanie transakcji Przygotowywanie : 1/1 Wykonywanie skryptu : esc-1.1.2-22.el8_4.x86_64 1/1 Usuwanie : esc-1.1.2-22.el8_4.x86_64 1/5 Usuwanie : opensc-0.20.0-4.el8.x86_64 2/5 Wykonywanie skryptu : opensc-0.20.0-4.el8.x86_64 2/5 Wykonywanie skryptu : pcsc-lite-1.9.5-1.el8.x86_64 3/5 Usuwanie : pcsc-lite-1.9.5-1.el8.x86_64 3/5 Wykonywanie skryptu : pcsc-lite-1.9.5-1.el8.x86_64 3/5 Usuwanie : pcsc-lite-ccid-1.4.29-5.1.el8_4.x86_64 4/5 Wykonywanie skryptu : pcsc-lite-ccid-1.4.29-5.1.el8_4.x86_64 4/5 Usuwanie : pcsc-lite-libs-1.9.5-1.el8.x86_64 5/5 Wykonywanie skryptu : pcsc-lite-libs-1.9.5-1.el8.x86_64 5/5 Sprawdzanie : esc-1.1.2-22.el8_4.x86_64 1/5 Sprawdzanie : opensc-0.20.0-4.el8.x86_64 2/5 Sprawdzanie : pcsc-lite-1.9.5-1.el8.x86_64 3/5 Sprawdzanie : pcsc-lite-ccid-1.4.29-5.1.el8_4.x86_64 4/5 Sprawdzanie : pcsc-lite-libs-1.9.5-1.el8.x86_64 5/5 Installed products updated. Usunięto: esc-1.1.2-22.el8_4.x86_64 opensc-0.20.0-4.el8.x86_64 pcsc-lite-1.9.5-1.el8.x86_64 pcsc-lite-ccid-1.4.29-5.1.el8_4.x86_64 pcsc-lite-libs-1.9.5-1.el8.x86_64 Ukończono.
Po wykonaniu tej czynności grupa została usunięta z systemu.
10.4. Zarządzanie modułami pakietów
Moduły to bardziej rozległe pakiety zawierające nie tylko samą aplikacje ale także jej całe środowisko do działania. Moduły posiadają strumienie, które są odrębnym zestawem pakietów przygotowanym z myslą o konkretnej wersji dostarczanego przez moduł programu. Każdy z modułów posiada jeszcze profil, który określa podzbiór pakietów przygotowany z myślą o przeznaczeniu aplikacji. Aby skorzystać z pewnej jej funkcji nie trzeba instalować gigabajtów pakietów. Do obsługi modułów wykorzystuje się podpolecenie module, a pracę z nimi rozpoczeniemy od wyświetlenia listy modułów.
10.4.1. Wyświetlanie modułów
Do wyświetlania list modułów służy podpolecenie list. Na poniższym przykładzie znajduje się fragment listy dostępnych w lokalnym repozytorium modułów.
[user@rhel8-vm1 ~]$ sudo dnf module list Updating Subscription Management repositories. Unable to read consumer identity This system is not registered with an entitlement server. You can use subscription-manager to register. Ostatnio sprawdzono ważność metadanych: 0:12:51 temu w dniu pon, 11 lip 2022, 12:31:38. AppStream Name Stream Profiles Summary 389-ds 1.4 389 Directory Server (base) ant 1.10 [d] common [d] Java build tool container-tools rhel8 [d][e] common [d] Most recent (rolling) versions of podman, bui ldah, skopeo, runc, conmon, runc, conmon, CRI U, Udica, etc as well as dependencies such as container-selinux built and tested together, and updated as frequently as every 12 weeks. ...
Modułów dostępnych w systemie jest kilkadziesiąt. Wyświetlenie listy nie posiada zbyt poręcznego formatu, aby zmieszczać pełny listing tego polecenia. Tak jak w przypadku pozostałych elementów, możemy podać podpoleceniu list argument w postaci ogólnej nazwy np. php.
[user@rhel8-vm1 ~]$ sudo dnf module list php Updating Subscription Management repositories. Unable to read consumer identity This system is not registered with an entitlement server. You can use subscription-manager to register. Ostatnio sprawdzono ważność metadanych: 0:17:20 temu w dniu pon, 11 lip 2022, 12:31:38. AppStream Name Stream Profiles Summary php 7.2 [d] common [d], devel, minimal PHP scripting language php 7.3 common [d], devel, minimal PHP scripting language php 7.4 common [d], devel, minimal PHP scripting language php 8.0 common [d], devel, minimal PHP scripting language Wskazówka: [d]omyślne, [e]włączone, [x]wyłączone, [i]zainstalowane
Jak możemy zauważyć na powyższym przykładzie do dyspozycji mamy kilka
strumieni. Domyślnym strumieniem jest
7.2
, a domyślnym profilem dla tych
strumieni jest common
. Domyślny
strumień oraz profil zostanie wybrany w momencie gdy nie sprecyzujemy
tego podczas instalacji. W ostatniej linii znajduje się legenda, litery
w nawiasach kwadartowych zdradzają stan modułu zainstalowanego w
systemie. Za pomocą modyfikatora --enabled możemy wyświetlić
wszystkie włączone strumienie modułów.
10.4.2. Informacje na temat modułu
Za pomocą podpolecenia info możemy wyświetlić na przykład jakie pakiety zawiera moduł. Podczas wyświetlania tego typu informacji warto podać interesujący nas strumień, aby zmniejszyć ilość generowanych danych. Strumień podajemy wraz z nazwą modułu oddzielając go dwukropkiem.
[user@rhel8-vm1 ~]$ sudo dnf module info php:7.2 [sudo] hasło użytkownika user: Updating Subscription Management repositories. Unable to read consumer identity This system is not registered with an entitlement server. You can use subscription-manager to register. Ostatnio sprawdzono ważność metadanych: 0:47:02 temu w dniu pon, 11 lip 2022, 12:31:38. Name : php Stream : 7.2 [d][a] Version : 8020020191108065827 Context : 2c7ca891 Architecture : x86_64 Profiles : common [d], devel, minimal Default profiles : common Repo : AppStream Summary : PHP scripting language Description : php 7.2 module Requires : httpd:[2.4] : nginx:[] : platform:[el8] Artifacts : apcu-panel-0:5.1.12-2.module+el8.1.0+3202+af5476b9.noarch : libzip-0:1.5.1-2.module+el8.1.0+3202+af5476b9.src : libzip-0:1.5.1-2.module+el8.1.0+3202+af5476b9.x86_64 : libzip-debuginfo-0:1.5.1-2.module+el8.1.0+3202+af5476b9.x86_64 : libzip-debugsource-0:1.5.1-2.module+el8.1.0+3202+af5476b9.x86_64 : libzip-devel-0:1.5.1-2.module+el8.1.0+3202+af5476b9.x86_64 : libzip-tools-0:1.5.1-2.module+el8.1.0+3202+af5476b9.x86_64 : libzip-tools-debuginfo-0:1.5.1-2.module+el8.1.0+3202+af5476b9.x86_64 : php-0:7.2.24-1.module+el8.2.0+4601+7c76a223.src : php-0:7.2.24-1.module+el8.2.0+4601+7c76a223.x86_64 : php-bcmath-0:7.2.24-1.module+el8.2.0+4601+7c76a223.x86_64 ...
Lista pakietów występuje w wierszu
Artifacts
.
10.4.3. Instalacja modułów
Instalacja modułów wygląda podobnie do instalacji takich elementów jak
grupy czy pojedyncze pakiety, używamy podpolecenia install
podpolecenia przeznaczonego do obsługi tego elementu. Podając moduł
możemy równocześnie wybrać zarówno strumień jak i profil korzystając
ze składni: moduł:strumień/profil
.
Dla przykładu zainstaluje moduł języka perl w domyślnym
strumieniu oraz domyślnym profilu. Nie będe zmieszczał tutaj
informacji zwracanej przez polecenie, ponieważ jest to moduł, który
zawiera ponad 100 pakietów.
[user@rhel8-vm1 ~]$ sudo dnf module install perl
Za pomocą podpolecenia list sprawdzimy jak wygląda na liście zainstalowany przed chwilą w systemie moduł.
[user@rhel8-vm1 ~]$ sudo dnf module list perl Updating Subscription Management repositories. Unable to read consumer identity This system is not registered with an entitlement server. You can use subscription-manager to register. Ostatnio sprawdzono ważność metadanych: 1:17:20 temu w dniu pon, 11 lip 2022, 12:31:38. AppStream Name Stream Profiles Summary perl 5.24 common [d], minimal Practical Extraction and Report Language perl 5.26 [d][e] common [d] [i], minimal Practical Extraction and Report Language perl 5.30 common [d], minimal Practical Extraction and Report Language perl 5.32 common [d], minimal Practical Extraction and Report Language Wskazówka: [d]omyślne, [e]włączone, [x]wyłączone, [i]zainstalowane
Na powyższym przykładzie możemy zobaczyć, że po zainstalowaniu
modułu perl z domyślnym strumieniem oraz domyślnym profilem.
Strumień 5.26
został włączony a
profil common
został zainstalowany.
Warto też dodać, że jeśli jakiś z komponentów był już zainstalowany to
podczas instalacji modułu zostanie sprawdzony czy nie wymaga
aktualizacji.
10.4.4. Aktualizacja modułu
Aktualizacji modułu, dokonuje tak samo jak aktualizacji grupy czy pojedynczego pakietu za pomocą podpolecenia update, tylko, że tym przypadku będzie to podpolecenie podpolecenia module.
[user@rhel8-vm1 ~]$ sudo dnf module update perl -y
W tym przypadku użyłem flagi -y
, która
automatycznie potwierdza wykonanie czynności. Dnf nie będzie
nas o nic pytać.
10.4.5. Usuwanie modułu
Usuwanie modułów wymaga już dwóch czynności piersza klasyczna wykonywana również na innych elementach. Drugą czynnością jest przywrócenie modułu wykonywane za pomocą podpolecenia reset. Usuniemy teraz moduł perl.
[user@rhel8-vm1 ~]$ sudo dnf module remove perl -y
Wydałem powyższe polecenie a następnie sprawdziłem jak wygląda lista stumieni modułu perl za pomocą poniższego polecenia.
[user@rhel8-vm1 ~]$ sudo dnf module list perl Updating Subscription Management repositories. Unable to read consumer identity This system is not registered with an entitlement server. You can use subscription-manager to register. Ostatnio sprawdzono ważność metadanych: 1:54:15 temu w dniu pon, 11 lip 2022, 12:31:38. AppStream Name Stream Profiles Summary perl 5.24 common [d], minimal Practical Extraction and Report Language perl 5.26 [d][e] common [d], minimal Practical Extraction and Report Language perl 5.30 common [d], minimal Practical Extraction and Report Language perl 5.32 common [d], minimal Practical Extraction and Report Language Wskazówka: [d]omyślne, [e]włączone, [x]wyłączone, [i]zainstalowane
Jak widzimy ten strumień jest nadal włączony mimo, iż domyślny profil został odinstalowany. Dlatego też musimy przywrócić moduł.
[user@rhel8-vm1 ~]$ sudo dnf module reset perl -y Updating Subscription Management repositories. Unable to read consumer identity This system is not registered with an entitlement server. You can use subscription-manager to register. Ostatnio sprawdzono ważność metadanych: 1:58:36 temu w dniu pon, 11 lip 2022, 12:31:38. Rozwiązano zależności. =========================================================================================== Pakiet Architektura Wersja Repozytorium Rozm. =========================================================================================== Przywracanie modułów: perl Podsumowanie transakcji =========================================================================================== Ukończono. [user@rhel8-vm1 ~]$ sudo dnf module list perl:5.26 Updating Subscription Management repositories. Unable to read consumer identity This system is not registered with an entitlement server. You can use subscription-manager to register. Ostatnio sprawdzono ważność metadanych: 1:59:21 temu w dniu pon, 11 lip 2022, 12:31:38. AppStream Name Stream Profiles Summary perl 5.26 [d] common [d], minimal Practical Extraction and Report Language Wskazówka: [d]omyślne, [e]włączone, [x]wyłączone, [i]zainstalowane
Na powyższym przykładzie przywróciłem moduł i sprawdziłem jak wygląda jego status w systemie. Teraz strumień nie jest włączony.
10.4.6. Przełączanie się miedzy strumieniami
Załóżmy taką sytuacje, że musimy zmień wersję php na serwerze z najnowszej (8.0) na niższą. Aby to zrobić musimy przełączyć się między strumieniami. Niestety nie ma lepszej metody niż ta opisana tutaj.
Na początku musimy przeprowadzić klasyczne usunięcie modułu, tak jak we wcześniejszym podrozdziale, ale na początku wyświetlimy sobie listę modułów php.
[user@rhel8-vm1 ~]$ sudo dnf module list php Updating Subscription Management repositories. Unable to read consumer identity This system is not registered with an entitlement server. You can use subscription-manager to register. Ostatnio sprawdzono ważność metadanych: 2:26:58 temu w dniu pon, 11 lip 2022, 12:31:38. AppStream Name Stream Profiles Summary php 7.2 [d] common [d], devel, minimal PHP scripting language php 7.3 common [d], devel, minimal PHP scripting language php 7.4 common [d], devel, minimal PHP scripting language php 8.0 [e] common [d] [i], devel, minimal PHP scripting language Wskazówka: [d]omyślne, [e]włączone, [x]wyłączone, [i]zainstalowane [user@rhel8-vm1 ~]$ sudo dnf module remove php:8.0 -y [user@rhel8-vm1 ~]$ sudo dnf module reset php:8.0
Następnie instalujemy nowy strumień modułu z dodatkową opcją pozwalającą na usunięcie pakietów, aby rozwiązać zależności.
[user@rhel8-vm1 ~]$ sudo dnf module install php:7.4 --allowerasing -y
Przełączenie gotowe. Teraz możemy to zweryfikować. Wyświetlając jeszcze raz listę modułów.
[user@rhel8-vm1 ~]$ sudo dnf module list php Updating Subscription Management repositories. Unable to read consumer identity This system is not registered with an entitlement server. You can use subscription-manager to register. Ostatnio sprawdzono ważność metadanych: 2:30:25 temu w dniu pon, 11 lip 2022, 12:31:38. AppStream Name Stream Profiles Summary php 7.2 [d] common [d], devel, minimal PHP scripting language php 7.3 common [d], devel, minimal PHP scripting language php 7.4 [e] common [d] [i], devel, minimal PHP scripting language php 8.0 common [d], devel, minimal PHP scripting language Wskazówka: [d]omyślne, [e]włączone, [x]wyłączone, [i]zainstalowane
Ćwiczenie 1: Konfiguracja dostępu do repozytorium
Na maszynie server1 z RHEL 9 skonfiguruj dostęp do lokalnego repozytorium wykorzystując do tego płyte/obraz płyty z RHEL 9. Plik nazwij local.repo. Uwaga, repozytorium musi być dostępne odrazu po ponownym uruchomioniu maszyny.
Ćwiczenie 2: Instalacja i zarządzanie pojedynczymi pakietami
Na maszynie z RHEL 8 wykorzystując użytkownika z możliwością podniesienia uprawnień, użyj polecenia dnf do wyświetlenia oddzielnie pakietów możliwych do instalacji oraz pakietów zainstalowanych. Wyświetl informacje na temat pakietu httpd, pokaż jego zależności, następnie zainstaluj go, potwierdź tę czynność wyświetlając plik dziennika /var/log/dnf.log. na koniec usuń pakiet.
Ćwiczenie 3: Instalacja i zarządzanie grupami pakietów
Na maszynie z RHEL 8 wykorzystując użytkownika z możliwością podniesienia uprawnień, użyj polecenia dnf do wyświetlenia zainstalowanych i możliwych do zainstalowania grup. Zainstaluj grupę "Security Tools" i "Scientific Support". Potwierdź to wyświetlając plik dziennika narzędzia. Pokaż pakiety zawarte w grupie "Scientific Support", a następnie usuń tę grupę.
Ćwiczenie 4: Instalacja i zarządzanie modułami
Na maszynie z RHEL 8 wykorzystując użytkownika z możliwością podniesienia uprawnień, użyj polecenia dnf do wyświetlenia listy modułów w systemie. Zainstaluj php w domyślnym strumieniu o profilu rozwojowym. Zweryfikuj instalacje, następnie usuń moduł.
Ćwiczenie 5: Przełączanie się miedzy strumieniami.
Na maszynie z RHEL 8 wykorzystując użytkownika z możliwością podniesienia uprawnień, użyj polecenia dnf do zainstalowania modułu postgresql, w domyslnym strumieniu i domyślnym profilu. Następnie dokonaj przełączenia między strumieniami na starszą wersję o profilu klienta.
Podsumowanie
Tym rodziałem zakończyliśmy zarządzanie pakietami. Ten rodział pokazał nam jak zarządzać pakietami za pomocą bardziej zaawansowanego narzędzia jakim jest dnf. Nauczyliśmy się zarządać pojednyczymi pakietami, grupami oraz modułami. W następnym rodziale zajmiemy się uruchamianiem systemu operacyjnego.
11. Proces ładowania systemu, GRUB oraz jądro
Proces ładowania systemu następuje w momencie gdy naciskamy przycisk zasilania komputera. Pierwsza faza - faza oprogramowania układowego jest niezależna od stosowanego systemu operacyjnego. Jej zadaniem jest przeprowadzenie tzw. POST-u, czyli sprawdzenia wszystkich komponentów sprzętowych przed uruchomieniem komputera po to aby nadawał się on do stablinej pracy. Faza pierwsza przeprowadzana jest przez oprogramowanie układowe, które może występować dwóch postaciach: BIOS oraz UEFI. UEFI jest oprogramowaniem występującym w wszystkich nowszych komputerach, posiada ono znacznie większe możliwości niż tradycyjny BIOS. Po teście następuję poszukiwanie urządzenia pamięci masowej przechowywującego system operacyjny. Teraz przechodzimy do drugiej fazy rozruchu - fazy programu ładującego. Program ładujący rezyduje w pierwszym sektorze dysku jest on odpowiedzialny za odnalezienie jądra na dysku, rozpakowanie go, załadowanie do pamięci i uruchomienie. Programy rozruchowe (a przynajmniej te wykorzystywane z dystrybucjami Linuks) pozwalają użytkownikowi komputera na wybór jądra oraz zmianę domyślnych parametrów uruchomieniowych. Kiedy jądro jest uruchamiane wówczas rozpoczyna się start systemu operacyjnego. Zadaniami jądra w odniesieniu do procesu ładowania jest zainicjowanie wszystkich urządzeń oraz uruchomienie programu typu init, tym samym przechodząc do czwartej ostatniej fazy - fazy inicjalizacji w niej program typu init uruchamia wszystkie usługi, uruchamiajac tym samym przestrzeń użytkownika, pod koniec tej fazy użytkownik ma przed sobą gotowy do działania system. Stan systemu operacyjnego pozwalający na zalogowanie się użytkownika do niego kończy cały proces uruchamiania.
11.1. Program rozruchowy GRUB
Dla dystrybucji Linuksa istnieje kilka programów rozruchowych. Tutaj jednak skupimy sie na jednym z nich, który jest stosowany w RHEL a jest nim GRUB. Jest on najczęsciej stosowany wśród wiodących dystrybucji. Styczność z nim mamy już na samym początku uruchomienia naszego systemu, po jego uruchomieniu wyświetla on menu zawierające wpisy uruchomieniowe naszego systemu. Poniżej znajduje się obrazek przedstawiający to menu.
Na obrazku możemy zobaczyć dwa wpisy i jeden jest zaznaczony na biało. Jest on domyślną opcją rozruchową. Jeśli nie dokonamy żadnych zmian po upływie czasu odmierzanego w ostatniej linii tekstu pod menu, zaznaczona opcja zostanie automatycznie zatwierdzona i rozpocznie się uruchamianie systemu. Po menu możemy poruszać się za pomocą strzałek w górę oraz w dół.
Opcje uruchomieniowe kryjące się za wpisami w menu możemy edytować zaznaczając wybrany wpis, a następnie naciskając klawisz e. GRUB daje nam możliwość debugowania rozruchu za pomocą wbudowanej powłoki. Powłokę możemy uruchomić naciskając klawisz c podczas wyświetlania menu. W powłoce kryje się około 100 poleceń do wykorzystania.
11.1.1. Konfiguracja programu GRUB
Za wyświetlanie menu odpowiedzialny jest plik konfiguracjyny grub.cfg znajdujący się w katalogu /boot/grub2. Jednak plik ten nie nadaje się do modyfikacji, gdyż aktualizacja jądra nadpisze wszystkie dokonane w nim zmiany, ponieważ jest generowany automatycznie przez specjalnie przygotowane do tego narzędzie.
Zmian w GRUB możemy dokonać edytując inny pliki, taki jak /etc/default/grub. Na poniższym przykładzie znajduje się jego zawartość:
[user@rhel8-vm1 ~]$ nl /etc/default/grub 1 GRUB_TIMEOUT=5 2 GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)" 3 GRUB_DEFAULT=saved 4 GRUB_DISABLE_SUBMENU=true 5 GRUB_TERMINAL_OUTPUT="console" 6 GRUB_CMDLINE_LINUX="crashkernel=auto resume=/dev/mapper/rhel-swap rd.lvm.lv=rhel/root rd.lvm.lv=rhel/swap rhgb quiet" 7 GRUB_DISABLE_RECOVERY="true" 8 GRUB_ENABLE_BLSCFG=true
Gdzie każda z tych linii oznacza m.in.:
GRUB_TIMEOUT=5
, określa czas odliczany do uruchomienia domyślnego wpisu.GRUB_DISTRIBUTOR
, określa nazwę dystrybucji.GRUB_DEFAULT
, przechowuje identyfikator domyślnego wpisu. Jeśli posiada wartośćsaved
, oznacza to, że identyfikator wpisu zostanie pozyskany za pomocą opcji GRUB_SAVEDEFAULT lub grub-set-default.GRUB_DISABLE_SUBMENU=true
, wyłącza stosowanie podmenu w menu główym.GRUB_TERMINAL_OUTPUT="console"
, ustawia wyście terminala programu, w tym przypadku jest to domyślna konsola.GRUB_CMDLINE_LINUX="crashkernel=auto resume=/dev/mapper/rhel-swap rd.lvm.lv=rhel/root rd.lvm.lv=rhel/swap rhgb quiet"
- opcja przechowuje argumenty przekazywane jądru Linuksa.GRUB_DISABLE_RECOVERY="true"
, jeśli ta opcja ustawiona jest na true, podczas generowania menu nie będą generowane automatyczne wpisy GRUB z opcjami pozwalającymi na uruchomienie systemu w trybie awaryjnym (Mimo to w RHEL pojawia się taki wpis, więc musi być to zrealizowane w inny sposób).GRUB_ENABLE_BLSCFG=true
, opcja pozwala na użycie plików blscfg zamiast klasycznych wpisów w /boot/grub/grub.cfg.
W tym pliku możemy dokonywać zmian, jednak najpierw warto zaponać się bliżej z GRUB, rozszerzając wiedzę z tego rodziału o np. dokumentację Red Hat, ostatni wpis jest dość specyficzyny i używany w nowszych dystrybucjach klasy enterprise. Jeśli już dokonamy w nim zmian, zmiany te trzeba zatwierdzić po przez wygenerowanie nowego pliku grub.cfg a służy do tego polecenie grub2-mkconfig po opcji -o należy podać ścieżkę docelową, gdzie polecenie ma zapisać nową konfigurację w przeciwnym wypadku zwróci ją na standardowe wyjście.
[user@rhel8-vm1 ~]$ sudo grub2-mkconfig -o /boot/grub2/grub.cfg [sudo] hasło użytkownika user: Generating grub configuration file ... done
Poza plikiem /etc/default/grub, wyżej przedstawione polecenie wykorzystuje również skrypty pomocnicze znajdujące się w katalogu /etc/grub.d. Poniżej znajduje się listing jego zawartości:
[user@rhel8-vm1 ~]$ sudo ls -l /etc/grub.d/ [sudo] hasło użytkownika user: razem 96 -rwxr-xr-x. 1 root root 8958 03-28 16:12 00_header -rwxr-xr-x. 1 root root 1043 02-09 12:13 00_tuned -rwxr-xr-x. 1 root root 232 03-28 16:12 01_users -rwxr-xr-x. 1 root root 832 03-28 16:12 08_fallback_counting -rwxr-xr-x. 1 root root 14088 03-28 16:12 10_linux -rwxr-xr-x. 1 root root 830 03-28 16:12 10_reset_boot_success -rwxr-xr-x. 1 root root 889 03-28 16:12 12_menu_auto_hide -rwxr-xr-x. 1 root root 11696 03-28 16:12 20_linux_xen -rwxr-xr-x. 1 root root 2559 03-28 16:12 20_ppc_terminfo -rwxr-xr-x. 1 root root 10670 03-28 16:12 30_os-prober -rwxr-xr-x. 1 root root 1412 03-28 16:12 30_uefi-firmware -rwxr-xr-x. 1 root root 700 04-01 11:49 35_fwupd -rwxr-xr-x. 1 root root 214 03-28 16:12 40_custom -rwxr-xr-x. 1 root root 216 03-28 16:12 41_custom -rw-r--r--. 1 root root 483 03-28 16:12 README
Plików w tym katalogu jest całkiem sporo. Istotną rzeczą w tych plikach są liczby na początku nazw. Te liczby prócz znaczeń opisanych w pliku README okreslają kolejność uruchamiania tych skryptów. Każdy pliki wykonuje jakąś czynność podczas generowania pliku konfiguracyjnego, np. 00_header ładuje plik /etc/default/grub; 10_linux odpowiada za generowanie wpisów uruchamiających dystrybucje, jednak jak wiemy w RHEL odpowiada za to inny mechanizm; 30_os-prober odpowiada za poszukiwanie zainstalowanych na dyskach komputera innych systemów operacyjnych, np. MS Windows; 40_custom oraz 41_custom pozwalają na zapisanie swojej konfiguracji.
11.1.2. Ładowanie systemu do określonego trybu
Edytując wpis ładujący system z poziomu menu GRUB możemy uruchomić system w trybie ratunkowym, odzyskiwania lub przerwać jego ładowanie w momencie gdy głównym system plików jest jeszcze intrd (mały obraz systemu plików ładowany do pamięci przez jądro aby zapewnić mu dostęp do sterowników dysków, żeby mógł zamontować właściwy system plików z katalogiem głównym). Za pomocą takiego uruchomienia systemu możemy zmienić zapomniane hasło superużytkownika. Aby zapoznać się z tym trybem przywrócimy utracone hasło root. Do tego ćwiczenia potrzebny będzie RHEL 8, gdyż w RHEL 9 nie ważne jaki tryb uruchominy, nadal wymagane będzie hasło aby przejść do powłoki. Zatem jedyną opcją na odzyskanie dostępu w RHEL 9 jest podmontowanie systemu plików w środowisku powłoki instalatora.
Po uruchomieniu maszyny, podczas wyświetlania menu GRUB naciskamy e, następnie w linii rozpoczynającej się od linux dopisujemy na końcu rd.break. Następnie naciskamy Ctrl+x, aby uruchomić tak zmodyfikowany wpis. Po uruchomieniu się systemu uzyskamy poniższy znak zachęty:
switch_root:/#
W tym momencie musimy zmienić katalog główny ramdysku na katalog główny znajdujący się na dysku. Kernel po odnalezieniu dysku z katalogiem głównym montuje go w katalogu /sysroot środowiska ramdysku. Do przełączenia katalogu głównego posłuży nam polecenie chroot:
switch_root:/# chroot /sysroot
Po przełączeniu się uzyskamy taki znak zachęty jak ten poniżej.
sh-4.4#
Z zamontowanym w tym momencie katalogiem głównym jest pewien problem, otóż na tym etapie uruchomienia systemu jest on zamontowany w trybie tylko do odczytu, a zmiana hasła wymaga zapisania informacji w pliku /etc/shadow, dlatego też musimy zamontować katalog główny tym razem w pełnym dostępie.
sh-4.4# mount -o remount,rw /
Teraz możemy wydawać polecenie passwd i ustalić nowe hasło dla superużytkownika. Następnie musimy stworzyć pusty plik w katalogu głównym o nazwie .autorelabel. Ponieważ SELinux musi wytworzyć nowe etykiety, jeśli tego nie zrobimy zmiany nie przyniosą skutku.
sh-4.4# passwd sh-4.4# touch .autorelabel
Po wykonaniu tych czynności możemy opuścić środowisko zmienionego katalogu a następnie zrestartować maszynę uruchamiając ją już normalnie.
sh-4.4# exit switch_root:/# reboot
Po uruchomieniu systemu nastąpi nadawanie nowych etykiet, po tym system może zostać ponownie uruchomiony, kiedy będzie gotowy do pracy możemy zalować się nowym hasłem na super użytkownika.
Odnośnie egzaminu:
Musimy wiedzieć jak załadować system do określonego trybu z poziomu
menu GRUB2, aby na przykład móc zmodyfikować plik /etc/fstab,
lub zresetować hasło superużytkownika.
11.2. Jądro systemu Linuks
Jądro to rdzeń każdej dystrybucji, odpowiada za wiele apektów działania
systemów oraz udostępnia masę funkcji, bez których dystrybucjom ciężko
było by być systemami operacyjnymi. Jedną z takich funkcji jest
zarządzanie urządzeniami. Do komunikacji z nimi jądro potrzebuje
sterowników. Sterownik w odniesieniu do jądra nazywane są modułami
część modułów wymaganych przez jądro może być już w nie wbudowana a
część jest ładowana w razie potrzeby (do tego też służy
initrd).
RHEL 8.6, którego używam również i w tym rozdziale jest
dostarczany
z jądrem 4.18.0-372.9.1.el8.x86_64, tę informację można uzyskać za
pomocą polecenia uname -r
. I to jądro
wystarcza dla potrzeb systemu operacyjnego.
Warto jednak pamiętać o tym, że rozwój technologiczny komputerów oraz całej dziedziny informatyki nie stoi w miejscu i jądro Linuks próbuje za nim nadąrzyć. W związku z tym funkcjonalność jądra również ulega zmianie, więc jeśli odbiorcy chcą skorzystać z tych zmian muszą przebudować jądra używane na ich komputerach. Najprostszą i za razem bezpieczną metodą jest instalacja jednego jądra obok drugiego. Oczywiście tylko jedno jądro może działać w tym samym czasie. Ta metoda w względu na przechowywanie dotychczas używanego jądra pozwala wrócić do niego, gdy nowe jądro okaże się nie odpowiednie dla naszego środowiska. Rozwój jądra Linuks to nie tylko dokładanie nowych funkcji ale również usuwanie już niewspieranych technologii, chociaż dystrybucje mogą działajać na różnym sprzęcie, który może mieć lata świetności dawno za sobą, stąd też modułowa budowa jądra. Rózwój jądra nie jest jedym powodem do jego przebudowania, nie które aplikacje lub systemy bazodanowe mogą wymagać nowszej jego wersji, aby zapewnić maksimum wydajności. Tym zajmiemy się w tym podrozdziale: przebudowa jądra. Omówimy sobie również gdzie znajduje się jądro w systemie.
11.2.1. Pliki jądra w systemie
Jądro to zwykły program, którego zadaniem jest wykonanie czynności i zapewnienie funkcji, które przez większość z nas uznałaby za "systemowe". Jednak to nadal program, więc musi gdzieś w systemie plików istnieć jego plik. Pliki jądra najczęściej znajdują się w katalogu /boot. Plik jądra zazwyczaj nazywa się vmlinuz-*, część po myślniku już zależy od dystrybucji. Obok pliku jądra w tym samym katalogu znajduje sie również plik ramdysku. W przypadku RHEL w katalogu /boot znajdują się podkatalogi: grub - zawierający konfigurację programu ładującego, loaders - zawierający pliki blscfg zawierajace wpisy menu programu ładującego oraz katalog efi przechowujący program ładujący dla komputerów uruchamianych w trybie UEFI. W tym katalogu znajdują się również pliki pomocnicze jądra takie jak config-* oraz System.map-*. Gwiazdki (*) w nazwach plików oznaczczają wersję jądra. Poniżej znajduje się listing zawartości tego katalogu.
[user@rhel8-vm1 ~]$ ls -l /boot razem 213492 -rw-r--r--. 1 root root 195982 04-16 04:33 config-4.18.0-372.9.1.el8.x86_64 drwxr-xr-x. 3 root root 17 07-10 17:27 efi drwx------. 4 root root 83 07-14 07:33 grub2 -rw-------. 1 root root 112548052 07-10 17:50 initramfs-0-rescue-1ad7389b6ff44aac9cfcab2485444bc8.img -rw-------. 1 root root 53300132 07-10 17:57 initramfs-4.18.0-372.9.1.el8.x86_64.img -rw-------. 1 root root 27283456 07-10 18:00 initramfs-4.18.0-372.9.1.el8.x86_64kdump.img drwxr-xr-x. 3 root root 21 07-10 17:42 loader lrwxrwxrwx. 1 root root 49 07-10 17:45 symvers-4.18.0-372.9.1.el8.x86_64.gz -> /lib/modules/4.18.0-372.9.1.el8.x86_64/symvers.gz -rw-------. 1 root root 4359450 04-16 04:33 System.map-4.18.0-372.9.1.el8.x86_64 -rwxr-xr-x. 1 root root 10460528 07-10 17:47 vmlinuz-0-rescue-1ad7389b6ff44aac9cfcab2485444bc8 -rwxr-xr-x. 1 root root 10460528 04-16 04:34 vmlinuz-4.18.0-372.9.1.el8.x86_64
Katalog /boot nie jest jedynym miejscem, w którym znajdują się pliki jądra. Dynamicznie ładowane modułu znajdują sie w katalogu /usr/lib/modules. Katalog zawiera cała strukturę katalogową, w której znajdują sie najróżniejsze moduły z podziałem na wersję jądra dostępne w systemie.
[user@rhel8-vm1 ~]$ ls -l /usr/lib/modules razem 4 drwxr-xr-x. 3 root root 19 07-10 17:31 4.18.0-372.2.1.el8.x86_64 drwxr-xr-x. 6 root root 4096 07-10 17:55 4.18.0-372.9.1.el8.x86_64
W wewnątrz tej struktury znajdują się moduły sterowników:
[user@rhel8-vm1 ~]$ ls -l /usr/lib/modules/4.18.0-372.9.1.el8.x86_64/kernel/drivers/ | head -25 razem 48 drwxr-xr-x. 5 root root 239 07-10 17:30 acpi drwxr-xr-x. 2 root root 169 07-10 17:30 ata drwxr-xr-x. 3 root root 20 07-10 17:30 base drwxr-xr-x. 2 root root 24 07-10 17:30 bcma drwxr-xr-x. 3 root root 180 07-10 17:30 block drwxr-xr-x. 2 root root 272 07-10 17:30 bluetooth drwxr-xr-x. 3 root root 17 07-10 17:30 bus drwxr-xr-x. 2 root root 25 07-10 17:30 cdrom drwxr-xr-x. 6 root root 192 07-10 17:30 char drwxr-xr-x. 2 root root 50 07-10 17:30 counter drwxr-xr-x. 2 root root 143 07-10 17:30 cpufreq drwxr-xr-x. 2 root root 36 07-10 17:30 cpuidle drwxr-xr-x. 6 root root 107 07-10 17:30 crypto drwxr-xr-x. 4 root root 54 07-10 17:30 dax drwxr-xr-x. 2 root root 23 07-10 17:30 dca drwxr-xr-x. 5 root root 60 07-10 17:30 dma drwxr-xr-x. 2 root root 4096 07-10 17:30 edac drwxr-xr-x. 2 root root 113 07-10 17:30 firewire drwxr-xr-x. 2 root root 69 07-10 17:30 firmware drwxr-xr-x. 2 root root 107 07-10 17:30 gpio drwxr-xr-x. 3 root root 17 07-10 17:30 gpu drwxr-xr-x. 5 root root 4096 07-10 17:30 hid drwxr-xr-x. 2 root root 74 07-10 17:30 hv drwxr-xr-x. 3 root root 4096 07-10 17:30 hwmon ...
Poza zwykłymi plikami jądra, w systemie istnieje interfejs przez nie udostępniany, a jest nim katalog /proc. Ten katalog zawiera masę podkatalogów odpowiadających uruchomionym w systemie procesom oraz kilkdziesiąt plików pomocniczych. Z tego katalogu korzystają takie narzędzia jak: ps, top, mem czy lscpu. Poniżej znajduje się listing podkatalogów procesów:
[user@rhel8-vm1 ~]$ ls -l /proc | head razem 0 dr-xr-xr-x. 9 root root 0 07-14 07:28 1 dr-xr-xr-x. 9 root root 0 07-14 07:28 10 dr-xr-xr-x. 9 root root 0 07-14 07:28 1000 dr-xr-xr-x. 9 root root 0 07-14 07:28 1010 dr-xr-xr-x. 9 root root 0 07-14 07:28 1011 dr-xr-xr-x. 9 root root 0 07-14 07:28 1015 dr-xr-xr-x. 9 root root 0 07-14 07:29 1017 dr-xr-xr-x. 9 root root 0 07-14 07:28 1020 dr-xr-xr-x. 9 root root 0 07-14 07:28 11
Informacje na temat procesora oraz pamięci możemy uzyskać bezpośrednio od jądra korzystając takich plików jak /proc/cpuinfo oraz /proc/meminfo.
Plik zawierający informacje o procesorze:
[user@rhel8-vm1 ~]$ cat /proc/cpuinfo processor : 0 vendor_id : GenuineIntel cpu family : 6 model : 60 model name : Intel Core Processor (Haswell, no TSX) stepping : 1 microcode : 0x1 cpu MHz : 1696.073 cache size : 16384 KB physical id : 0 siblings : 1 core id : 0 cpu cores : 1 apicid : 0 initial apicid : 0 fpu : yes fpu_exception : yes cpuid level : 13 ...
Plik zawierający informacje o pamięci:
[user@rhel8-vm1 ~]$ cat /proc/meminfo MemTotal: 824024 kB MemFree: 92668 kB MemAvailable: 285968 kB Buffers: 20 kB Cached: 284704 kB SwapCached: 1628 kB Active: 167040 kB Inactive: 396240 kB ...
11.2.2. Pakiety jądra
Jądro do dystrybucji dostarczane jest za pomocą zwykłych pakietów z oprogramowaniem, które mozemy zainstalować z repozytorium. Jądro rozbite jest na kilka pakietów, których lista oraz opis zawartości znajdują się poniżej.
- kernel - Nie zawiera plików, zapewnia jedynie poprawną instalację innych pakietów jądra.
- kernel-core - Zawiera pliki jądra wraz z niewielką ilością modułów zepewniającą podstawową funkcjonalność.
- kernel-devel - Zawiera pliki wspomagające kompilację modułów.
- kernel-modules - Zawiera moduły powszechnie znanych urządzeń.
- kernel-modules-extra - Zawiera moduły dodatkowych, różnych urządzeń (mniej spotykanych).
- kernel-headers - Zawiera pliki wspierające wymianę informacji pomiędzy jądrem, bibliotekami przestrzeni użytkownika oraz programami.
- kernel-tools - Zawiera narzędzia pozwalające na kontrolę jądra.
- kernel-tools-libs - Zawiera biblioteki wspomagające działanie narzędzi jądra.
Nie wszystkie z tych pakietów muszą występować w systemie, aby jądro normalnie funkcjonowało, oraz nie wszystkie one są potrzebne do jego przebudowania. Za pomoca polecenia poniżej możemy sprawdzić jakie pakiety jądra są zainstalowane w naszym systemie.
[user@rhel8-vm1 ~]$ rpm -qa | grep 'kernel' kernel-tools-libs-4.18.0-372.9.1.el8.x86_64 kernel-tools-4.18.0-372.9.1.el8.x86_64 kernel-4.18.0-372.9.1.el8.x86_64 kernel-core-4.18.0-372.9.1.el8.x86_64 kernel-modules-4.18.0-372.9.1.el8.x86_64
Te pakiety trzeba będzie pobrać, kiedy bedziemy chcieli przebudować jądro. Zanim jednak to nastąpi przeanalizujemy wersje jądra aby móc wybrać to najbardziej odpowiednie.
11.2.3. Wersja jądra
Wersje jądra możemy sprawdzić za pomocą polecenia
uname -r
. Dzieli się ona na kilka
części, które mogą pomóc nam w zidentyfikowaniu nowego jądra
odpowiedniego dla naszego systemu:
[user@rhel8-vm1 ~]$ uname -r 4.18.0-372.9.1.el8.x86_64
4
- Numer główny wersji. Numer rodziny wersji jądra. Ulega on zmianie gdy następuje wewnątrz jądra duża zmiana.18
- Numer rewizji. Zmiany zachodące w jądrze są za małe aby utworzyć na nową linię (zmienić główny numer), jednak są dość znaczące.0
- Numer łatki. Łatki poprawiają błędy oraz zabezpieczenia, mogą również wprowadzać drobne ulepszenia.-372.9.1.el8
- sygnatura budowania jądra przez dystrybucję. Każda główna dystrybucja zajmuje się samodzielnym budowaniem jądra. Więc w tej części znajduje się numer buildu przprowadzanego prze dystrybucje. Kiedy będziemy wybierać jądro dla naszej dystrybucji możemy kierować się tymi oznaczeniami.x86_64
- nazwa architektury.
W tym przypadku jest AMD64 lub kto woli EM64T.
Po za zapoznaniu się z wersją, możemy przejść do przebudowy jądra na naszych maszynych.
11.2.4. Przebudowa jądra
Przebudowę jądra rozpoczniemy od ustalenia jego obecnej wersji oraz wybrania odpowiedniej dla naszych rozwiązań. Z racji tego, iż jest to tylko przykład wybierzemy kolejny build dystrybucji.
[user@rhel8-vm1 ~]$ uname -r 4.18.0-372.9.1.el8.x86_64
W wiec w naszym przypadku najlepiej będzie zainstalować wersje np. 373 lub inną podobną. Teraz musimy ustalić źródło, skąd pobierzemy pakiety potrzebne do zainstalowania nowego jądra. Opcje mamy dwie: strona Red Hat (ponieważ nasze system nie są zarejestrowane w sieci Red Hat, musimy pobrać pakiety logując się na stronie a następnie wybrać z sekcji pobierania odpowiednie pakiety) lub strona rpmfind.net, która jest wyszukiwarką pakietów wśród wielu serwerów lustrzanych różnych dystrybucji klasy enterprise. Skutkiem użycia pakietów ze strony rpmfind jest to, iż poźniej nasze jądro może widnieć jako np. CentOS w menu GRUB, więc najlepszym rozwiazaniem jest skorzystanie z strony Red Hat. Pakiety możemy pobrać na maszynie za pomocą zainstalowanej przeglądarki lub na komputerze który ją hostuje i następnie przesłać zbiorcze archiwum za pomocą sftp (patrz: rozdział 19). Listę pakietów niezbędnych do zainstalowania nowego jądra możemy wyświetlić za pomocą polecenia:
[user@rhel8-vm1 ~]$ rpm -qa | grep 'kernel' kernel-tools-libs-4.18.0-372.9.1.el8.x86_64 kernel-tools-4.18.0-372.9.1.el8.x86_64 kernel-4.18.0-372.9.1.el8.x86_64 kernel-core-4.18.0-372.9.1.el8.x86_64 kernel-modules-4.18.0-372.9.1.el8.x86_64
Na komputerze na którym hostuje maszynę wirtualną pobrałem z strony Red Hat najnowsze pakiety jądra przeznaczone dla RHEL 8. Stworzyłem z nich archiwum nastepnie przesłałem do wcześniej utworzonego podkatalogu w katalogu /tmp na maszynie z RHEL 8. Poniżej znajduje się lista pobranych pakietów:
[user@rhel8-vm1 kernel]$ ls -l razem 97736 -rw-r--r--. 1 user user 8436304 07-14 10:22 kernel-4.18.0-372.16.1.el8_6.x86_64.rpm -rw-r--r--. 1 user user 41240076 07-14 10:22 kernel-core-4.18.0-372.16.1.el8_6.x86_64.rpm -rw-r--r--. 1 user user 33296868 07-14 10:22 kernel-modules-4.18.0-372.16.1.el8_6.x86_64.rpm -rw-r--r--. 1 user user 8654240 07-14 10:23 kernel-tools-4.18.0-372.16.1.el8_6.x86_64.rpm -rw-r--r--. 1 user user 8445172 07-14 10:23 kernel-tools-libs-4.18.0-372.16.1.el8_6.x86_64.rpm
Teraz instalacja jest już banalna, wystarczy użyć polecenia dnf, a ono wykona wszystkie czynności za nas.
[user@rhel8-vm1 kernel]$ sudo dnf install kernel-* Updating Subscription Management repositories. Unable to read consumer identity This system is not registered with an entitlement server. You can use subscription-manager to register. Rozwiązano zależności. ================================================================================ Pakiet Arch. Wersja Repozytorium Rozm. ================================================================================ Instalowanie: kernel x86_64 4.18.0-372.16.1.el8_6 @commandline 8.0 M Aktualizowanie: kernel-tools x86_64 4.18.0-372.16.1.el8_6 @commandline 8.3 M kernel-tools-libs x86_64 4.18.0-372.16.1.el8_6 @commandline 8.1 M Instalowanie zależności: kernel-core x86_64 4.18.0-372.16.1.el8_6 @commandline 39 M kernel-modules x86_64 4.18.0-372.16.1.el8_6 @commandline 32 M Podsumowanie transakcji ================================================================================ Instalacja 3 pakiety Aktualizacja 2 pakiety Całkowity rozmiar: 95 M W porządku? [t/N]:
Po zatwierdzeniu rozpocznie się instalacja. Po skończonej instalacji musimy uruchomić ponownie maszynę. W menu GRUB nowe jądro będzie na pierwszej domyślnej pozycji. Po załadowaniu systemu wersją jądra używana przez ten system to:
[user@rhel8-vm1 ~]$ uname -r 4.18.0-372.16.1.el8_6.x86_64
Jak możemy zauważyć to jądro różni się od porzedniego drobnymi zmianami wprowadzonymi przez dystrybucję, gdyż zmianie uległ numer rewizji w numerze buildu.
Odnośnie egzaminu:
Zawsze należy instalować nowe jądro, a nie aktualizować stare.
Aktualizacja usuwa każde istniejące jądro i zastępuje je nowym w
przypadku problemów po instalacji z nowym jądrem nie będzie możliwości
powrotu do poprzedniego działającego poprawnie jądra.
Ćwiczenie 1: Właczenie komunikatów podczas ładowania systemu
Jako użytkownik z możlwością podniesienia uprawnień na maszynie z RHEL 8, usuń wartość quiet, z opcji GRUB_CMDLINE_LINUX w pliku /etc/default/grub. Następnie uruchom polecenie grub2-mkconfig aby wygenerować nowy plik konfiguracyjny GRUB. Na koniec uruchom ponownie system, aby zobaczyć komunikaty generowane przez jądro.
Ćwiczenie 2: Przywrócenie hasła superużytkownika
Na maszynie z RHEL 8, przerwij ładowanie systemu i zmień hasło superużytkownika. Po ponownym uruchomieniu maszyny zaloguj się na jego konto i ustaw hasło takie jakie było do tej pory (chyba, że go nie pamiętasz).
Ćwiczenie 3: Instalacja nowego jądra
Na maszynie z RHEL 8, jako użytkownik z możliwością podniesienia uprawnień, sprawdź wersję jądra domyślnie używaną w w systemie, następnie ustal jakie pakiety jądra są zainstalowane. Pobierz nowszą wersję jądra z Red Hat Customer Portal lub rpmfind.net i przeprowadź instalacje nowego jądra. Po czym zrestartuj system i sprawdź obecną jego wersję.
Podsumowanie
W tym rodziale zapoznaliśmy się z procesem ładowania systemu. Poznaliśmy po krótce każdą z jego faz. Przyjrzeliśmy się bliżej z programowi ładującemu GRUB jego plikom konfiguracyjnymi oraz narzędziom z nim związanym. Nauczyliśmy się uruchamiać system w trybie awaryjnym aby przywrócić hasło superużytkownika lub poprawić wpisy w pliku /etc/fstab. Na koniec poruszyliśmy temat jądra, dowiedzieliśmy sie gdzie znajdują się pliki jądra, jakie pakiety odpowiadają za nie w systemie oraz nauczyliśmy się poprawnie interpretować jego wersje jądra aby móc zainstalować nową jego wersję. Następnym rodziale przyjrzymy się ostatniej fazie rozruchu.
12. Inicjalizacja systemu, pliki dziennika oraz dostarajanie systemu
W tym rozdziale zajmiemy się czwartą ostatnią fazą uruchamiania systemu czyli jego inicjalizacją. Dla dystrybucji Linuksa istnieje wiele programów typu init. Większość z wiodących dystrybucji używa Systemd (ang. System daemon), jednak wielu programistów uważa, że systemd jest sprzeczne z filozofią Uniksa, dlatego też wśród społeczności powstało wiele rozwidleń, będących odpowiednikami dystrybucji wiodących ale dających końcowemu użytkownikowi wybór z jakiego (poza systemd) z programów typu init chce korzystać. W niektórych przypadkach decyzje podejmujemy sciągając odpowiedni obraz płyty, a w niektórych wyboru dokonujemy go podczas instalacji. Nie mniej jednak RHEL korzysta z systemd i to nim się zajmiemy, dlatego też odniesienia jako programu lub procesu typu init będą odnośić się do systemd.
Jak zapewne zdajemy sobie sprawę wiele programów generuje komunikaty diagnostyczne. Nie które z nich są wyświetlane na naszych terminalach, inne te których nie widzimy, albo nie są generowane albo są zbierane przez jednego z demonów systemowych i zapisywane w jednym z systemowych katalogów. W jednym z nich znajdują się właśnie pliki dziennika.
Poza instalacją i konfiguracją oprogramowania, zarządzaniem plikami, katalogami czy użytkownikami być może będziemy musieli dostoswać nasz system, aby był bardziej wydajny co może spowodować większy pobór energii elektrycznej lub będziemy zmuszeni, aby nasz system był bardziej energooszczędny, to bedziemy mogli zrealizować za pomocą jednego z demonów, którego będzie trzeba zainstalować.
12.1. Inicjalizacja systemu - systemd
W większości wiodących dystrybucji, wybiera systemd jak program typu init dla swoich systemów. Mimo sprzeciwu części społeczności, to systemd nie jest programem, który jest pozbawiony zalet. Ma ich bardzo wiele i są one dość istotne. Systemd jest to program typu init, którego głównymi zadaniami jest przygotowanie systemu do pracy oraz zarządanie usługami. W fazie inicjalizacji uruchamiana jest większość usług, które do czasu wdrożenia systemd uruchamiane są jedna po drugiej co wydłużało proces uruchamiania systemu. Natomiast nowy program postawił na współbieżność uruchamiania - wszystkie usługi startują w tym samym czasie. Systemd może również opóźnić uruchomienie konkretej usługi kiedy będzie ona rzeczywiście wymaga zaoszczędzając przy tym zasoby systemu. Kolejną rzeczą, którą wprowadza systemd jest zarządzanie zasobami, którymi operuja usługi. Program za pomocą oczywiście odpowiedniej konfiguracji jest wstanie stworzyć zasób, który potrzebują inne usługi, następnie uruchomić demona, który taki zasób powinien udostępniać w momencie gdy demon z zasobem jeszcze się uruchamia, inne te które go wymagają widzą że jest on dostępny i wysyłają zapytania do tego demona o dostęp do zasobu. Te zapytania są buforowane do momentu jego pełnego uruchomienia, na koniec te zapytania wraz kontrolą nad zasobem są przekazywane do niego. Jest to kolejna cecha, która przyspiesza ładowanie systemu. Kolejną cechą systemd jest zmiana administracji usług. Teraz nie są wymgane już skrypty wystarczy krótki plik, kilka, kilkanaście linijek i usługa jest już zdefiniowana.
12.1.1. Jednostki
Jednostki są to pliki za pomocą których opisuje się różne komponenty systemu dla systemd. Pliki jednostek są to zwykłe pliki tekstowe, podzielone na dwie, trzy sekcje. Pierwsza sekcją służy do opisu jednostki, druga jest zależna od typu jednostki i zawiera specyficzne dla niego dyrektywy. Trzecia sekcja służy w zazwyczaj od określania włączania i wyłączania jednostki (Uwaga, tutaj włączanie i wyłączanie tyczy się angielskich słów enable oraz disable. Jednostki systemd się aktywuje lub uruchamia [ang. start]). Poniżej znajduje się plik jednostki demona ssh.
[user@server1 ~]$ cat /usr/lib/systemd/system/sshd.service [Unit] Description=OpenSSH server daemon Documentation=man:sshd(8) man:sshd_config(5) After=network.target sshd-keygen.target Wants=sshd-keygen.target [Service] Type=notify EnvironmentFile=-/etc/sysconfig/sshd ExecStart=/usr/sbin/sshd -D $OPTIONS ExecReload=/bin/kill -HUP $MAINPID KillMode=process Restart=on-failure RestartSec=42s [Install] WantedBy=multi-user.target
Ten plik przestawia jednostkę usługi. Omawianie dyrektyw wykracza
poza ramy tego materiału, dlatego nie będzie tutaj to realizowane.
Więcej wiedzy znajduje się na stronie podręcznika
man systemd.unit
. Poniżej znajduje
się lista typów jednostek oraz krótki opis za co odpowiadają w
systemie.
- .socket - Jednostki gniazd zazwyczaj są powiązane z jednostkami usług, służą do przedstawiania gniazd, które są wykorzystywane w komunikacji miedzyprocesowej lub sieciowej.
- .device - Jednostka urządzenia, wystąpienie urządzenia w ujęciu systemd. Takie jednostki są wykorzystywane do aktywacji innych jednostek w momencie pojawienia się urządzenia w systemie.
- .mount - Jednostka montowania, określa gdzie i jak zamontować lub odmontować określony system plików.
- .automount - Jednostka automontowania wspomaga montowanie systemów plików na żądanie.
- .swap - Jednostka przestrzeni wymiany, określa przestrzeń wymiany w odniesieniu do systemd.
- .target - Cel. Jednostka logiczna, zestaw plików jednostek.
- .path - Jednostka ścieżki. Wykorzystywana do aktywacji innej jednostki w momencie próby uzyskania dostępu do określonego pliku lub katalogu.
- .timer - Jednostka służy do aktywacji innej jednostki na podstawie czasu w niej zdefiniowanego.
- .slice - Jednostka wycinka, służy do przydzielania i zarządania zasobami grupie procesów.
- .service - Jednostka usługi. Wystąpienie demona w systemd.
12.1.2. Jednostki celu
Cel w ujęciu systemd jest logiczna grupą jednostek różnego rozdzaju, które mogą na przykład składać się na jeden z komponentów systemu operacyjnego, na przykład środowisko graficzne. Często cele mogą odpowiadać klasycznym poziomom uruchomienia systemu. W systemie jest zdefiniowanych kilka celów, o to one:
- halt - Zamyka i zatrzymuje system. Wyłączenie komputera wymaga naciśnięcia przycisku zasilania.
- poweroff - Zamyka i wyłącza system.
- shutdown - Zamyka system.
- rescue - Tryb jednego użytkownika dla funkcji administracyjnych oraz przywracania systemu. Lokalne systemy plików zostają zamontowane, nie które podstawowe usługi są uruchamiane ale sieć pozostaje odłączona od systemu.
- emergency - Uruchomiana zostaje powłoka ratunkowa, a główny system plików zostaje zamontowany w trybie tylko do odczytu. Sieć oraz pozostałe usługi są wyłączone.
- multi-user - Normalne działanie systemu, ale bez trybu graficznego.
- graphical - Normalne działanie systemu z trybem graficznym.
- reboot - Zamyka system, a następnie uruchamia komputer ponownie.
- default - Dowiązanie symboliczne najczęściej do celu graphical lub multi-user.
- hibernate - Przenosi system w stan hibernacji.
Cele wykorzystywane są do uruchamiania wielu jednostek zapisanych w ich zależnościach.
12.1.3. Polecenie systemctl
Polecenie służącym do zarządzania systemd jest systemctl, za jego pomocą możemy wykonywać proste czyności administracyjne związane z jednostkami oraz celami. Polecenie to zawiera duża ilość różnego rodzaju podpoleceń oraz modyfikatorów, są one opisane na stronie podręcznika tego polecenia. My za poznamy się z nim w praktyce.
Wydając polecenie systemctl bez żadnej opcji polecenie wyświetli table przedstawiącą wszystkie aktywne jednostki wraz z ich stanem oraz krótkim opisem. Poniżej znajduje się jej fragment
UNIT LOAD ACTIVE SUB DESCRIPTION ... rhsmcertd.service loaded active running Enable periodic update of ... rsyslog.service loaded active running System Logging Service rtkit-daemon.service loaded active running RealtimeKit Scheduling Policy ... spice-vdagentd.service loaded active running Agent daemon for Spice guests sshd.service loaded active running OpenSSH server daemon switcheroo-control.service loaded active running Switcheroo Control Proxy service systemd-journal-flush.service loaded active exited Flush Journal to Persistent ... ...
Tego nie widać na przykładzie ale jeśli wywołamy w terminalu polecenie, możemy zobaczyć, że poszczególne typy jednostek są oddzielone od siebie za pomocą poziomej linii. W drugiej kolumnie znajduje się stan jednostki. Ta kolumna podzielona jest na trzy mniejsze kolumny. Pierwsza określa czy jednostka jest załadowana, druga określa tzw. stan wyższego poziomu aktywacji. Jest to ogólny stan aktywacji i może przybierać on różne wartości takim najważniejszymi są active, failed, inactive. Trzecia zaś określa niższy poziom aktywacji, może on zawierać informacje specyficzne dla typu jednostki lub demona.
Powyższy przykład zawiera tylko załadowane jednostki, ale jeśli chcielibyśmy zobaczyć wszystkie jednostki dostępne w systemie musimy dodać do polecenia modyfikator --all. Innym przydatnym modyfikatorem jest -t pozwalający podać typ jednostki.
UNIT LOAD ACTIVE SUB DESCRIPTION accounts-daemon.service loaded active running Accounts Service alsa-restore.service loaded inactive dead Save/Restore Sound Card State alsa-state.service loaded active running Manage Sound Card State (restore and store) atd.service loaded active running Deferred execution scheduler auditd.service loaded active running Security Auditing Service ● auto-cpufreq.service not-found inactive dead auto-cpufreq.service ● autofs.service not-found inactive dead autofs.service avahi-daemon.service loaded active running Avahi mDNS/DNS-SD Stack blk-availability.service loaded inactive dead Availability of block devices chronyd.service loaded active running NTP client/server colord.service loaded active running Manage, Install and Generate Color Profiles cpupower.service loaded inactive dead Configure CPU power related settings crond.service loaded active running Command Scheduler cups.service loaded active running CUPS Scheduler dbus-broker.service loaded active running D-Bus System Message Bus dm-event.service loaded inactive dead Device-mapper event daemon
Kolejnym dość istonym modyfikatorem, który pozwoli man namierzyć jednostki, których aktywacja zakończyła się niepowodzeniem. Jest --failed.
[user@server1 ~]$ systemctl --failed UNIT LOAD ACTIVE SUB DESCRIPTION ● kdump.service loaded failed failed Crash recovery kernel arming LOAD = Reflects whether the unit definition was properly loaded. ACTIVE = The high-level unit activation state, i.e. generalization of SUB. SUB = The low-level unit activation state, values depend on unit type. 1 loaded units listed.
Pod tabelą znajduje się również krótki opis kolumn ze stanem.
Za pomocą podpolecenia list-dependencies możemy wyświetlić zależności jednostki.
[user@server1 ~]$ systemctl list-dependencies tuned.service tuned.service ● ├─dbus-broker.service ● ├─dbus.socket ● ├─polkit.service ● ├─system.slice ● └─sysinit.target ● ├─dev-hugepages.mount ● ├─dev-mqueue.mount ● ├─dracut-shutdown.service ○ ├─iscsi-onboot.service ● ├─kmod-static-nodes.service ○ ├─ldconfig.service ● ├─lvm2-lvmpolld.socket ● ├─lvm2-monitor.service ○ ├─multipathd.service ...
Koła oznaczają aktywną jednostkę, a okręgi nieaktywną jednostkę.
12.1.4. Zarządzanie jednostkami
Poza podpolecaniami służacymi wyświetlaniu informacji o jednostkach, systemctl posiada dużą ilość podpoleceń związanych z zarządzaniem jednostkami. Jednostki możemy aktywować, dezaktywować, włączać, wyłączać, wyświetlić podsumowanie na ich temat czy zablokwać zmianę stanu. Pierwszą rzeczą jak zrobimy z będzie wyświetlenie informacji o jednostce, a służy do tego podpolecenie status.
[user@server1 ~]$ sudo systemctl status atd.service [sudo] password for user: ● atd.service - Deferred execution scheduler Loaded: loaded (/usr/lib/systemd/system/atd.service; enabled; vendor preset: enabled) Active: active (running) since Sun 2022-07-17 07:40:58 CEST; 1h 34min ago Docs: man:atd(8) Main PID: 934 (atd) Tasks: 1 (limit: 5760) Memory: 300.0K CPU: 5ms CGroup: /system.slice/atd.service └─934 /usr/sbin/atd -f Jul 17 07:40:58 server1.example.com systemd[1]: Started Deferred execution scheduler.
Na podstawie tych informacji możemy wywnioskować, że jednostka jest załadowana, jest aktywna a jej demon nadal działa. Znamy także stronę podręcznika opisującą tego demona oraz jego PID. Ważną rzeczą podczas wyświetlania status jednostki jest wykonanie tego z uprawnieniami administratora, wówczas na samym dole zostaną nam wyświetlone komunikaty diagnostyczne, pobrane z plików dziennika systemd, te komunikaty pomagają zlokalizować usterki, które mogą być odpowiedzialne za problem z aktywacją jednostki.
Jednostkę możemy zatrzymać oraz uruchomić za pomocą podpoleceń stop oraz start.
[user@server1 ~]$ sudo systemctl stop atd.service [sudo] password for user: [user@server1 ~]$ sudo systemctl status atd.service ○ atd.service - Deferred execution scheduler Loaded: loaded (/usr/lib/systemd/system/atd.service; enabled; vendor preset: enabled) Active: inactive (dead) since Sun 2022-07-17 09:23:11 CEST; 2s ago Docs: man:atd(8) Process: 934 ExecStart=/usr/sbin/atd -f $OPTS (code=exited, status=0/SUCCESS) Main PID: 934 (code=exited, status=0/SUCCESS) CPU: 5ms Jul 17 07:40:58 server1.example.com systemd[1]: Started Deferred execution scheduler. Jul 17 09:23:11 server1.example.com systemd[1]: Stopping Deferred execution scheduler... Jul 17 09:23:11 server1.example.com systemd[1]: atd.service: Deactivated successfully. Jul 17 09:23:11 server1.example.com systemd[1]: Stopped Deferred execution scheduler. [user@server1 ~]$ sudo systemctl start atd.service [user@server1 ~]$ sudo systemctl status atd.service ● atd.service - Deferred execution scheduler Loaded: loaded (/usr/lib/systemd/system/atd.service; enabled; vendor preset: enabled) Active: active (running) since Sun 2022-07-17 09:23:44 CEST; 2s ago Docs: man:atd(8) Main PID: 1576 (atd) Tasks: 1 (limit: 5760) Memory: 260.0K CPU: 4ms CGroup: /system.slice/atd.service └─1576 /usr/sbin/atd -f Jul 17 09:23:44 server1.example.com systemd[1]: Started Deferred execution scheduler.
Do ponownego uruchomienia jednostki służy inne podpolecenie niż stop, start, a jest nim restart.
[user@server1 ~]$ sudo systemctl restart atd.service [sudo] password for user: [user@server1 ~]$ sudo systemctl status atd.service ● atd.service - Deferred execution scheduler Loaded: loaded (/usr/lib/systemd/system/atd.service; enabled; vendor preset: enabled) Active: active (running) since Sun 2022-07-17 09:41:38 CEST; 3s ago Docs: man:atd(8) Main PID: 1595 (atd) Tasks: 1 (limit: 5760) Memory: 264.0K CPU: 3ms CGroup: /system.slice/atd.service └─1595 /usr/sbin/atd -f Jul 17 09:41:38 server1.example.com systemd[1]: Started Deferred execution scheduler.
Do włączanie i wyłączania jednostek służą podpolecenia takie jak enable oraz disable.
[user@server1 ~]$ sudo systemctl disable atd.service [sudo] password for user: Removed /etc/systemd/system/multi-user.target.wants/atd.service. [user@server1 ~]$ sudo systemctl status atd.service ● atd.service - Deferred execution scheduler Loaded: loaded (/usr/lib/systemd/system/atd.service; disabled; vendor preset: enabled) Active: active (running) since Sun 2022-07-17 09:41:38 CEST; 6min ago Docs: man:atd(8) Main PID: 1595 (atd) Tasks: 1 (limit: 5760) Memory: 264.0K CPU: 3ms CGroup: /system.slice/atd.service └─1595 /usr/sbin/atd -f Jul 17 09:41:38 server1.example.com systemd[1]: Started Deferred execution scheduler.
W linii Loaded:
za ścieżką do pliku
jednostki, status zmienił się z enabled na
disabled
. Jeśli użyjemy podpolecenia
enable, status wróci do poprzedniej wartości.
[user@server1 ~]$ sudo systemctl enable atd.service Created symlink /etc/systemd/system/multi-user.target.wants/atd.service → /usr/lib/systemd/system/atd.service. [user@server1 ~]$ sudo systemctl status atd.service ● atd.service - Deferred execution scheduler Loaded: loaded (/usr/lib/systemd/system/atd.service; enabled; vendor preset: enabled) Active: active (running) since Sun 2022-07-17 09:41:38 CEST; 9min ago Docs: man:atd(8) Main PID: 1595 (atd) Tasks: 1 (limit: 5760) Memory: 264.0K CPU: 3ms CGroup: /system.slice/atd.service └─1595 /usr/sbin/atd -f Jul 17 09:41:38 server1.example.com systemd[1]: Started Deferred execution scheduler.
Włączenie jednostki powoduje utworzenie dowiązania symbolicznego w katalogu zależności celu, natomiast wyłączenie usuwa to dowiązanie.
Za pomocą podpoleceń mask oraz unmask możemy zablokować włączenie oraz aktywację jednostki. Użycie podpolecenia mask tworzy dowiązanie do pliku /dev/null i zaznacza w systemd, że jednostka jest zablokowana. Podpolecenie umask odwraca działania podpolecenia mask. Usuwa stworzone dowiązanie oraz zmienia status jednostki w systemd.
[user@server1 ~]$ sudo systemctl mask atd.service [sudo] password for user: Created symlink /etc/systemd/system/atd.service → /dev/null. [user@server1 ~]$ sudo systemctl status atd.service ● atd.service Loaded: masked (Reason: Unit atd.service is masked.) Active: active (running) since Sun 2022-07-17 09:41:38 CEST; 28min ago Main PID: 1595 (atd) CPU: 3ms CGroup: /system.slice/atd.service └─1595 /usr/sbin/atd -f Jul 17 09:41:38 server1.example.com systemd[1]: Started Deferred execution scheduler. Jul 17 10:09:58 server1.example.com systemd[1]: atd.service: Current command vanished from the unit file, execution of the command list ... [user@server1 ~]$ sudo systemctl unmask atd.service Removed /etc/systemd/system/atd.service. [user@server1 ~]$ sudo systemctl status atd.service ● atd.service - Deferred execution scheduler Loaded: loaded (/usr/lib/systemd/system/atd.service; enabled; vendor preset: enabled) Active: active (running) since Sun 2022-07-17 09:41:38 CEST; 30min ago Docs: man:atd(8) Main PID: 1595 (atd) Tasks: 1 (limit: 5760) Memory: 264.0K CPU: 3ms CGroup: /system.slice/atd.service └─1595 /usr/sbin/atd -f Jul 17 09:41:38 server1.example.com systemd[1]: Started Deferred execution scheduler. Jul 17 10:09:58 server1.example.com systemd[1]: atd.service: Current command vanished from the unit file, execution of the command list ...
12.1.5. Zarządzanie jednostkami celów
Zarządzaniem jednostkami celów, różni się od zarządzania jednostkami usług czy innych typów. Jednostki celów przedstawiają różne stany uruchomienia systemu operacyjnego, więc aby miało to jakiś sens zarządzanie nim sprowadza się głównie do dwóch czynności, jedną z nich jest określenie oraz ustawienie domyślnego stanu, w którym to system operacyjny jest zdatny do użycia. W tym przypadku określa to jednostka celu - default. Za pomocą podpoleceń możemy sprawdzić która z dostarczonych z systemem jednostek jest wskazywana przez to dowiązanie. Możemy to określić za pomocą podpolecenia get-default.
[user@server1 ~]$ sudo systemctl get-default [sudo] password for user: graphical.target
Tę wartość możemy zmienić, wpływając również na sposób ładowania
systemu. Jeśli zmienię domyślny cel z
graphical.target
na
multi-user.target, wówczas system zatrzyma ładowanie systemu
przed uruchomieniem środowiska graficznego. Zmianie domyślnego celu
służy podpolecenie set-default.
[user@server1 ~]$ sudo systemctl set-default multi-user.target [sudo] password for user: Removed /etc/systemd/system/default.target. Created symlink /etc/systemd/system/default.target → /usr/lib/systemd/system/multi-user.target. [user@server1 ~]$ sudo systemctl get-default multi-user.target
Jeśli zrestartujemy teraz maszynę, uruchomi się ona bez środowiska graficznego.
Odnośnie egzaminu:
Może być tak, że na egzaminie będzie trzeba zmienić domyślny cel
ładowanie systemu.
Pomiędzy celami możemy się przełączać w trakcie działania systemu. Służy do tego podpolecenie isolate.
[user@server1 ~]$ sudo systemctl isolate multi-user.target
Po wydaniu tego polecenia, jeśli otworzymy okno maszyny zobaczymy, że środowisko graficzne zostało wyłączone. Aby włączyć je z powrotem użyjemy tego samego polecenia, jednak wskazując inny cel.
[user@server1 ~]$ sudo systemctl isolate graphical.target [sudo] password for user:
Tym że akcentem zakończyliśmy omawianie systemd. Oczywiście to zagadnienia jest tak obszerne, że można by napisać około 200, 300 stronicową książke na ten temat bazując na samej dokumentacji programu.
12.2. Prowadzenie plików dzienników systemowych
Zbieranie informacji o tym co się dzieje w systemie to bardzo ważna czynność wykonywana przez systemy operacyjne. Nie które z komponentów instalowanych w nich zwracają bardzo ubogie w informacje komunikaty o błędach lub ostrzeżenia z których nic nie wynika. Najczęściej ma to na celu poprawienie wyglądu oraz doświadczeń użytkownika (UI/UX Design), przez co wielu użytkowników zostaje na lodzie chcąc samodzielnie rozwiązać problemy. Ta cecha nie tyczy się tylko systemów MS Windows. Wiodące środowiska graficzne w dystrybucjach również mają z tym problem. Ale w Uniksach mamy dobrze zorganizowane pliki dzienników, dzieki którym w możemy znaleźć przyczynę, nie których problemów.
12.2.1. Rejestrator systemowy - rsyslog
Rsyslog jest odpowiedzialny za zbieranie komunikatów diagnostycznych i umieszczenie ich w przeznaczonych dla nich miejscach. Nie które komunikaty mogą trafiać do plików inne mogą być wyświetlane w terminalach pracujących na serwerze użytkowników. Te reguły są zapisane w pliku konfiguracyjnym demona /etc/rsyslog.conf. Program wspiera dostoswane pliki konfiguracyjne użytkowników przechowywane w /etc/rsyslog.d. Plik konfiguracyjny rsyslog wygląda następująco:
[user@server1 ~]$ grep -v -e '^#' -e '^$' /etc/rsyslog.conf global(workDirectory="/var/lib/rsyslog") module(load="builtin:omfile" Template="RSYSLOG_TraditionalFileFormat") include(file="/etc/rsyslog.d/*.conf" mode="optional") module(load="imuxsock" # provides support for local system logging (e.g. via logger command) SysSock.Use="off") # Turn off message reception via local log socket; # local messages are retrieved through imjournal now. module(load="imjournal" # provides access to the systemd journal StateFile="imjournal.state") # File to store the position in the journal *.info;mail.none;authpriv.none;cron.none /var/log/messages authpriv.* /var/log/secure mail.* -/var/log/maillog cron.* /var/log/cron *.emerg :omusrmsg:* uucp,news.crit /var/log/spooler local7.* /var/log/boot.log
Ostatnie linie na końcu zawierają zasady,
które określaja jakie komunikaty należy zbierać i co z nimi
zrobić. Zasady dzielą się na dwie części na selektor,
określający komunikaty diagostyczne oraz akcje
definiującą dla nich miejsce docelowe. Poza tym selektor również możemy
rozłożyć na funkcje - wskazującą na demona lub
komponent od którego
należy przechwycić komunikaty oraz priorytet
określający ważność komunikatu. Funkcję od priorytetu oddziela się
kropką. Spis funkcji oraz priorytetów znajduje się na stronie
podręcznika pliku /etc/rsyslog.conf. Gwiazdka to symbol
wieloznaczny wskazujący zarówno wszystkie priorytety jak i wszystkie
funkcje w zależności gdzie został użyty. Priorytet
none
wskazuje aby nie przechwytywać
komunikatów z tej funkcji. Jak możemy zobaczyć w pierwszej zasadzie
na jedną akcje może przypadać wiele selektorów. Selektory oddziela się
średnikiem (;). W polu akcji zazwyczaj znajdują się
ścieżki do plików wskazujących gdzie należy zapisać komunikaty
diagnostyczne, jedyny wyjątkiem są komunikaty o najwyższym priorytecie
za pomocą wewnętrzengo modułu są one wyświetlane w terminalach jako
wiadomości do użytkowników.
Jak możemy zauważyć większość plików dzienników znajduje się w katalogu /var/log. A prawie wszystkie komunikaty diagostyczne trafiają do jednego pliku /var/log/messages. Ten plik jest głównym plikiem dziennika w systemie. Każda linia reprezentuje jeden z komunikatów. Taki plik najlepiej wyświetlać za pomocą polecenia less lub more.
Odnośnie egzaminu:
Używanie polecenie tail wraz z opcją -f może okazać
się przydatne podczas śledzenia komunikatów diagnostycznych w trakcie
uruchamiania usług lub testowania, aby wychwycić wszysktie problemy.
Jeśli będziemy chcieli coś zmienić w konfiguracji rsyslog,
warto przed
uruchomieniem ponowym usługi sprawdzić poprawność konfiguracji za
pomocą polecenia rsyslog -N 1
. Gdzie
1
oznacza ilość wyświetlanych
przez polecenie komunikatów.
12.2.2. Obrót plików dziennika
Pliki dziennika to zwykłe pliki tekstowe, które potrafią bardzo szybko przyrastać w zależności od tego co się dzieje w systemie. Taki nie kontrolowany przyrost plików może szybko wypełnić dostępne miejsce dysku. Zastosowano więc mechanizm rotacji plików dziennika. Stare pliki są usuwane robiąc miejsce nowym. Tym zadaniem zajmuje się wywoływany w codziennym katalogu cron (/etc/cron.daily) skrypt logrotate. Skrypt ten posiada swój plik konfiguracyjny /etc/logrotate.conf.
[user@server1 ~]$ grep -v -e '^$' /etc/logrotate.conf # see "man logrotate" for details # global options do not affect preceding include directives # rotate log files weekly weekly # keep 4 weeks worth of backlogs rotate 4 # create new (empty) log files after rotating old ones create # use date as a suffix of the rotated file dateext # uncomment this if you want your log files compressed #compress # packages drop log rotation information into this directory include /etc/logrotate.d # system-specific logs may be also be configured here.
Na podstawie tego pliku możemy dowiedzieć się, że rotacja jest dokonywana co tydzień, pozostawione mają zostać pliki dziennika na cztery tygodnie wstecz oraz po usunięciu starych, następnie zmianie nazw obecnym skrypt utworzy nowe puste pliki dla nowych komunikatów zapisywanych w plikach dzienika. Definicje zachowania dla rotacji plików dziennika dostarczane wraz z programami znajdują się w katalogu /etc/logrotate.d. Oto zawartość tego katalogu.
[user@server1 ~]$ ls -l /etc/logrotate.d/ total 56 -rw-r--r--. 1 root root 91 Mar 31 2021 bootlog -rw-r--r--. 1 root root 130 Oct 14 2019 btmp -rw-r--r--. 1 root root 160 May 12 2021 chrony -rw-r--r--. 1 root root 88 Oct 21 2021 dnf -rw-r--r--. 1 root root 93 Nov 23 2021 firewalld -rw-r--r--. 1 root root 172 Jul 29 2021 iscsiuiolog -rw-r--r--. 1 root root 162 Apr 14 19:04 kvm_stat -rw-r--r--. 1 root root 312 Nov 1 2021 psacct -rw-r--r--. 1 root root 226 Jan 19 16:31 rsyslog -rw-r--r--. 1 root root 155 Mar 18 10:32 samba -rw-r--r--. 1 root root 237 Jan 17 20:46 sssd -rw-r--r--. 1 root root 88 Apr 13 17:00 subscription-manager -rw-r--r--. 1 root root 100 Feb 4 15:58 wpa_supplicant -rw-r--r--. 1 root root 145 Oct 14 2019 wtmp
Zawartość takiego pliku może zdradzać, w jaki sposób logrotate zachowa się wobec takiego pliku, nadpisując tym samym konfigurację z pliku, z wcześniejszego przykładu (globalnego pliku konfiguracji).
12.2.3. Plik dziennika rozruchu
W katalogu /var/log znajduje się plik boot.log przedstawiający uruchamianie ostatniej fazy rozruchu. W tym pliku możemy podejrzeć czy wszystkie usługi wystartowały czy też nie. Uwaga, plik nie nadaje się do przeglądania za pomocą polecenie less.
[user@server1 ~]$ sudo head /var/log/boot.log [ OK ] Started User Login Management. [ OK ] Started Daemon for power management. [ OK ] Started Authorization Manager. Starting Modem Manager... Starting firewalld - dynamic firewall daemon... [ OK ] Finished Rotate log files. [ OK ] Started Accounts Service. [ OK ] Started Power Profiles daemon. [ OK ] Started Modem Manager. [ OK ] Started Disk Manager. ... [FAILED] Failed to start Crash recovery kernel arming. See 'systemctl status kdump.service' for details.
W nawiasach kwadratowych wyświetla on OK
lub FAILED
.
12.2.4. Własne komunikaty diagnostyczne
Czasami możemy chcieć uzupełnić systemowy plik dziennika /var/log/messages o kilka komunikatów, które będą wyznaczać początek i koniec testowanego oprogramowania lub dodwać kilka notatek wyjaśniających takie a nie inne komunikaty. Dzięki rsyslog za pomocą jednego z jego wewnętrznych modułów możemy dokonać wpisów do tego pliku dziennika. Realizować to będziemy za pomocą polecenia logger. Na przykład:
[user@server1 ~]$ logger "Hello, World! It's $LOGNAME" [user@server1 ~]$ sudo tail -1 /var/log/messages [sudo] password for user: Jul 17 13:03:42 server1 user[2706]: Hello, World! It's user
Te komunikaty są rozpoznawane przez rsyslog jako user.notice, jednak za pomocą opcji -p możemy podać swój selektor. Polecenie logger możemy być przydatne do testowania zmian w konfiguracji rsyslog.
12.3. Dzienniki systemd
Systemd poza funkcjami omówionymi na początku tego rozdziału dostarcza wielu narzędzi, które czasami bywają irytujące, ale nie które z nich jak np. demon systemd-journald są całkiem przydatne, ponieważ to za jego zasługą dowiadujemy się dlaczego nasza usługa nie chce się uruchomić. Ten demon przechwytuje komunikaty z bardzo wielu źródeł od jądra przez ramdysk do różnorakich usług. Swoje komunikaty przechowuje w pliku /run/log/journal, zatem w pliku, który nie jest trwały i zostanie zniszczony w momencie zamknięcia systemu. Konfiguracja tego demona przechowywana jest w pliku /etc/systemd/journald.conf, w którym w razie potrzeby możemy zmienić.
12.3.1. Wyświetlanie dziennika systemd
Do wyświetlenia informacji zebranych przez demona systemd-journald mamy do dyspozycji takie polecenie jak journalctl. Jesli wydamy to polecenie bez żadnych opcji to polecenie zwróci ono treść podobną do zawartości /var/log/messages.
[user@server1 ~]$ sudo journalctl [sudo] password for user: Jul 16 12:48:20 server1.example.com kernel: Linux version 5.14.0-70.13.1.el9_0.x86_64 (mockbuild@x86-vm-08.build.eng.bos.redhat.com) (gcc (GCC) 11.2.> Jul 16 12:48:20 server1.example.com kernel: Linux version 5.14.0-70.13.1.el9_0.x86_64 (mockbuild@x86-vm-08.build.eng.bos.redhat.com) (gcc (GCC) 11.2.> Jul 16 12:48:20 server1.example.com kernel: The list of certified hardware and cloud instances for Red Hat Enterprise Linux 9 can be viewed at the Re> Jul 16 12:48:20 server1.example.com kernel: Linux version 5.14.0-70.13.1.el9_0.x86_64 (mockbuild@x86-vm-08.build.eng.bos.redhat.com) (gcc (GCC) 11.2.> Jul 16 12:48:20 server1.example.com kernel: Linux version 5.14.0-70.13.1.el9_0.x86_64 (mockbuild@x86-vm-08.build.eng.bos.redhat.com) (gcc (GCC) 11.2.> Jul 16 12:48:20 server1.example.com kernel: The list of certified hardware and cloud instances for Red Hat Enterprise Linux 9 can be viewed at the Re> Jul 16 12:48:20 server1.example.com kernel: Command line: BOOT_IMAGE=(hd0,msdos1)/vmlinuz-5.14.0-70.13.1.el9_0.x86_64 root=/dev/mapper/rhel-root ro c> Jul 16 12:48:20 server1.example.com kernel: x86/fpu: Supporting XSAVE feature 0x001: 'x87 floating point registers' Jul 16 12:48:20 server1.example.com kernel: x86/fpu: Supporting XSAVE feature 0x002: 'SSE registers' Jul 16 12:48:20 server1.example.com kernel: x86/fpu: Supporting XSAVE feature 0x004: 'AVX registers' ...
Przy użyciu opcji -o wraz z wartością verbose, narzędzie zwróci bardzo szczegółowy opis każdego z komunikatów.
Sat 2022-07-16 12:48:20.235840 CEST [s=5135ad3430d34e718c820bc5b157f883;i=1;b=9ca0ad75315f4891b4807b449a2ce046;m=233ae8;t=5e3e9df815e40;x=7786ef23901> _SOURCE_MONOTONIC_TIMESTAMP=0 _TRANSPORT=kernel PRIORITY=5 SYSLOG_FACILITY=0 SYSLOG_IDENTIFIER=kernel MESSAGE=Linux version 5.14.0-70.13.1.el9_0.x86_64 (mockbuild@x86-vm-08.build.eng.bos.redhat.com) (gcc (GCC) 11.2.1 20220127 (Red Hat 11.2.1-9), G> _BOOT_ID=9ca0ad75315f4891b4807b449a2ce046 _MACHINE_ID=4015aef220c344e1875a3fbbd1453b45 _HOSTNAME=server1.example.com
Polecenie ma masę opcji nie ma sensu ich tutaj wszystkich przytaczać.
Znajdziemy je na stronie podręcznika
man journalctl
.
Komunikaty dla poszczególnych usług znajdziemy na końcu informacji zwracanych przez systemctl status. Dlatego ważne jest, aby używać tego polecenia z uprawnieniami administratora.
12.3.2. Konfiguracja miejsca do przechwywania dzienników systemd
Jak wiemy dziennik systemd nie jest przechowywany na stałe w systemie. To możemy zmienić. W bardzo prosty sposób. Otóz, dyrektywa Storage w konfiguracji demona może mieć cztery wartości:
- volatile - Przechowuje informacje tylko w pamięci
- persistent - Przechowuje informacje w katalogu /var/log/journal, jeśli katalog nie istnieje zostanie utworzony, chyba że jest z tym jakiś problem to demon wraca do przechowywania komunikatów wyłącznie w pamięci.
- auto - Podobnie do presistent, jednak nie tworzy ona katalogu.
- none - wyłącza przechowywanie komunikatów diagnostycznych gdzie kolwiek.
Domyślną jej wartością jest auto, więc aby włączyć przechowywanie dzienników na stałe, wystarczy utworzyć katalog journal w katalogu /var/log. Tutaj pragnę zaznaczyć, że w RHEL 8 wystarczyło zrestartować usługę, ale w przypadku RHEL 9 należy zrestartować cały system. Kiedy system będzie gotowy wewnątrz katalogu zostanie utworzony podkatalogu o nazwany wartością /etc/machine-id.
[user@server1 ~]$ ls -l /var/log/journal/ total 4 drwxr-sr-x+ 2 root systemd-journal 4096 Jul 16 20:17 4015aef220c344e1875a3fbbd1453b45 [user@server1 ~]$ cat /etc/machine-id 4015aef220c344e1875a3fbbd1453b45
Teraz komunikaty dziennika systemd bedą przechowywane w tym katalogu.
12.4. Dostosowywanie systemu
W RHEL jak i inych systemach klasy enterprise możemy spotkać się z narzędziem, które na podstawie monitorowania zasobów komputera może zmienić ich ustawienia aby podnieść ich wydajność lub gdy przestanie być to konieczne ją obniżyć aby zaoszczędzić wykorzystywaną energię elektryczną. Tym zajmuje się demon tuned. Nie występuję on domyślnie w systemie i trzeba go zainstalować.
Tuned może dynamicznie na podstawie danych uzyskanych z różnych monitorów zasobów dostosowywać wydajność sprzętu do potrzeb. Może on również zostać przez nas statycznie skonfigurowany za pomocą predefiniowanych profili. Wydajność systemu wówczas nie zmieni się dopóki my nie załadujemy innego profilu. Konfiguracja statyczna jest jego domyślną konfiguracją.
12.4.1. Polecenie tuned-adm
Demon tuned dostarczany jest w postaci pakietów i znajduje się na płycie instalacyjnej z RHEL. Instalacji dokonuje za pomocą poniższego polecenia:
[user@server1 ~]$ sudo dnf install tuned -y Updating Subscription Management repositories. Unable to read consumer identity This system is not registered with an entitlement server. You can use subscription-manager to register. Last metadata expiration check: 2:38:24 ago on Sun 17 Jul 2022 11:44:30 AM CEST. Package tuned-2.18.0-1.el9.noarch is already installed. Dependencies resolved. Nothing to do. Complete!
Uwaga, w RHEL 9 demon może wymagać ręcznej aktywacji jednostki za pomocą polecenia systemctl. Wraz z demonem zostanie nam dostarczone polecenie tuned-adm za pomocą, którego będziemy mogli administrować wydajnością systemu dostosowywaną przez te profile. Za pomocą podpolecenia list możemy wyświetlić listę dostępnych profili.
[user@server1 ~]$ sudo tuned-adm list Available profiles: - accelerator-performance - Throughput performance based tuning with disabled higher latency STOP states - balanced - General non-specialized tuned profile - desktop - Optimize for the desktop use-case - hpc-compute - Optimize for HPC compute workloads - intel-sst - Configure for Intel Speed Select Base Frequency - latency-performance - Optimize for deterministic performance at the cost of increased power consumption - network-latency - Optimize for deterministic performance at the cost of increased power consumption, focused on low latency network performance - network-throughput - Optimize for streaming network throughput, generally only necessary on older CPUs or 40G+ networks - optimize-serial-console - Optimize for serial console use. - powersave - Optimize for low power consumption - throughput-performance - Broadly applicable tuning that provides excellent performance across a variety of common server workloads - virtual-guest - Optimize for running inside a virtual guest - virtual-host - Optimize for running KVM guests Current active profile: virtual-guest
Poza listą podpolecenie zwraca również aktywny profil. Identyczne działanie możemy otrzymać poprzez wydanie polecenia tuned-adm wraz z podpoleceniem active.
[user@server1 ~]$ sudo tuned-adm active [sudo] password for user: Current active profile: virtual-guest
Zmiany profilu dokonujemy za pomocą podpolecenia profile a następnie podajemy nazwę profilu.
[user@server1 ~]$ sudo tuned-adm profile balanced [user@server1 ~]$ sudo tuned-adm active Current active profile: balanced
Demon sam jest wstanie na podstawie naszej konfiguracji sprzętowej dobrać odpowiedni profil. Aby uzyskać od niego taką informację wydajemy polecenie z podpoleceniem recommend.
[user@server1 ~]$ sudo tuned-adm recommend virtual-guest
Profil rekomendowany możemy ustawić przez podanie jego nazwy jako argumentu podpolecenia profile lub tak jak przedstawiłem to na poniższym przykładzie.
[user@server1 ~]$ sudo tuned-adm profile $(sudo tuned-adm recommend)
Jeśli dostosowanie wydajności nie jest już nam potrzebne możemy je wyłączyć za pomocą podpolecenia off.
[user@server1 ~]$ sudo tuned-adm off [user@server1 ~]$ sudo tuned-adm active No current active profile.
Ćwiczenie 1: Zmiana domyślnego celu ładowania systemu
Jako użytkownik z możliwością podniesienia uprawnień na maszynie oznaczonej jako server1 zmień domyślny cel ładowania systemu na multi-user.target. Uruchom ponownie maszynę i za pomocą polecenia systemctl oraz who sprawdź zmiany. Następnie wróć do standardowego celu i ponownie zweryfikuj zmiany.
Ćwiczenie 2: Zapis własnego komunikatu diagnostycznego
Jako użytkownik z możliwością podniesienia uprawnień na maszynie oznaczonej jako server1 zapis swój komunikat diagnostyczny. Następnie wyświetl go w terminalu lub konsoli.
Ćwiczenie 3: Zastosowanie profili wydajności
Jako użytkownik z możliwością podniesienia uprawnień na maszynie oznaczonej jako server1 za pomocą polecenia tuned-adm Wyświetl listę profil, następnie ustaw profil balanced i potwierdź to za pomocą odpowiednie podpolecenia. Ustaw profil rekomendowany, następnie wyłacz profil. Pamiętaj! Może być konieczna ręczna aktywacja jednostki tuned.service.
Podsumowanie
W tym rodziale dowiedzieliśmy się w jaki sposób realizowany jest ostatni etap rozruchu systemu. Poznaliśmy odpowiedzialne za nie narzędzie oraz część jego możliwości. Dowiedzieliśmy się za co odpowiada rsyslogd oraz gdzie możemy szukać zapisanych w systemie komunikatów diagnostycznych. Na koniec poznaliśmy narzędzie które możemy dostoswać wydajność naszego komputera do określonych potrzeb. W następnym rodziale zajmiemy się podstawami obsługi dysków.
13. Podstawy zarządzania pamięcią masową
Dane na których operują użytkownicy, wyniki ich pracy czy programy przez nich używane muszą być gdzieś składowane, aby co ponowne uruchomienie komputera nie trzeba było konfigurować naszego środowiska na nowo. Odziwo istnieją użytkownicy, który korzystają z dystrybucji Linuksa w trybie LiveCD (systemu załadowanego z płyty do pamięci komputera). Aby móc wykorzystać komputer do składowania danych potrzebujemy specjalnych urządzeń - dysków, i to zarządzaniem dyskami zajmiemy się w tym rozdziale.
W tym rozdziale powinna znaleźć się także obsługą dysków za pomocą technologii VDO, jednak z RHEL 9 została ona wciągnieta do LVM, które będą omawaiane w następnym rozdziale. Także omówimy sobie VDO zaraz po nauczeniu się podstaw LVM.
Do wykonania ćwiczeń oraz przykładów będzie nam potrzebna maszyna oznaczona jak server2 (patrz: rodział 1).
13.1. Podstawowe pojęcia związane z zarządzaniem dyskami
Dyski w systemach uniksowych są urządzeniami blokowymi służącymi do przechowywania danych. Dyski mogą być podzielone na logiczne części nazwane partycjami. Partycje w ujęciu systemów operacyjnych są podstawową jednoską związaną z zarządzaniem dyskami, więc aby uzyskać dostęp do przestrzenii znajdującej się na dysku, musimy utworzyć na nim partycję. Na tym polega zarządzanie dyskami, na tworzeniu, zmienianiu i usuwaniu partycji. Informacja o partycjach zwana tablicą partycji znajdujących się na dysku znajduje się w pierwszym jego sektorze obok programu rozruchowego. Partycjami możemy zarządzać za pomocą dwóch schematów MBR oraz GPT.
13.1.1 Schemat partycjonowania MBR (Master Boot Record)
MBR jest jednym z pierwszych schematów partycjonowania, został on ustanowiony dawno temu, więc posiada pewne ograniczenia względem dysków stosowanych w obecnych komputerach. Schemat ten jest domyślnym schematem wykorzystywanym przez komputery obsługiwane z pomocą BIOS-u. Pozwala on podzielenie dysku na maksymalnie 4 partycje podstawowe (służące do przechowywania danych). Jeśli wymagana jest większa ilość, to wówczas należy poświęcić jedną z partycji podstawowych na partycję rozszerzoną (kontener na partycje logiczne), a następnie realizować dalsze partycjonowanie za pomocą partycji logicznych (te partycje również służą do przechowywania danych jednak różnią się one nieco do partycji podstawowych). Partycji logicznych na dysku może być maksymalnie 11, co daje nam maksymalną ilość partycji na dysku wynoszącą 14. W praktycje może oznaczać, że to więcej niż kto kolwiek, kiedy kolwiek potrzebował. Schemat ten ma jeszcze jedno ograniczenie otóż, nie może zaadresować przestrzenii większej niż 2TB ze względu na to iż jest to 32-bitowy schemat partycjonowania, jak wiemy obecne dostępne dyski dysponują przestrzenią powyżej 10TB.
13.1.2. Schemat patycjonowania GPT (GUID Partition Table)
Wraz rozwojem komputerów, wprowadzeniem nowego oprogramowania układowego jakim jest UEFI, zaczął być wdrażany kompatybilny z nim schemat GPT. Schemat ten nie posiada podziałów na partycje podstawowe, rozszerzone, logiczne itd. Wszystkie są podstawowe i może być ich aż do 128. Maksymalna pojemność dysków, które GPT może zaadresować jest nadal daleko po za zasięgiem ludzkości. Umożliwia on także nadawanie etykiet partycjom co nie było możliwe w przypadku MBR. Poza tym GPT, tworzy kopie obszaru na którym zajduje się informacja o partycjach zaraz przed końcem dysku, co również nie było realizowane w schemacie MBR.
13.1.3. Partycje dyskowe w systemie
Podczas partycjowania należy uważać aby nie nadpisać obecnie istniejących partycji, albo nie zostawiać między nimi przerw marnując tym samym przestrzeń dysku. Partycje w systemie są uprządkowane za pomocą numeracji. W przypadku partycjonowania ze schematem MBR, partycje podstawowe otrzymują numery od 1 do 4, natomiast numeracja dysków logicznych rozpocznyna sie od 5. W przypadku schematu GPT numeracja rozpoczynia się od 1. Za pomocą polecenia lsblk możemy wświetlić dostępne w systemie urządzenia blokowe:
[user@server2 ~]$ lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS sr0 11:0 1 8G 0 rom /mnt vda 252:0 0 10G 0 disk ├─vda1 252:1 0 1G 0 part /boot └─vda2 252:2 0 9G 0 part ├─rhel-root 253:0 0 8G 0 lvm / └─rhel-swap 253:1 0 1G 0 lvm [SWAP] vdb 252:16 0 256M 0 disk vdc 252:32 0 256M 0 disk vdd 252:48 0 256M 0 disk vde 252:64 0 256M 0 disk vdf 252:80 0 4G 0 disk vdg 252:96 0 1G 0 disk vdh 252:112 0 1G 0 disk
W moim przypadku dyski noszą nazwy vdX
,
gdzie X to litera porządkowa dysku zatem pierwszy dysk to
vda, drugi vdb i tak dalej. Przy niektóych nazwach
widnieją cyfry, te nazwy to nazwy partycji. W Twoim przypadku
oznaczenia dysku mogą być nieco inne, ponieważ ja zamiast
VirtualBox
używam wirtualizacji KVM wraz ze innym sterownikiem
odpowiedzialnym za obsługę pamięci masowych. Nie miej jednak polecenie
z przykładu zwraca nazwę urządzenia, przedstawiając dysk w postaci
drzewa, zwraca rozmiar zarówno dysków jak i partycji, typ urządzenia
oraz punkt montowania partycji w systemie.
Typ lvm
oznacza logiczne woluminy
LVM (będzie o tym w następny rozdziale).
13.1.4. Narzędzia do zarządzania pamięcią masową
W RHEL dostępnych jest wiele narzędzi odpowiedzialnych za zarządzanie dyskami. Każda technologia wdrożona do systemu posiada swoje oprogramowanie. W tym rozdziale skupimy się wyłączenia na dwóch z nich. Na programie parted pozwalającym na obsługę schematu MBR oraz gdisk obsługującym schemat GPT. Ze względu na to iż będzie pracować z urządzeniami komputera, do wykonywania czynności przy użyciu tych narzędzi będą potrzebne uprawnienia administratora.
13.1.5. Technologia thin provisioning
Omawiając podstawy zarządzania dyskami należałoby wspomnieć o technologii thin provisioning jest technika polegająca na przedstawianiu logiczynych zasobów dyskowy znacznie większych niż są one w rzeczywistości. Przez utworzone w ten sposób woluminy posiadają one znaczenie wiekszą pojemność niż utrzymujące je fizyczne urządzenia, kiedy dochodzi się do poziomu wyczerpywania fizycznego miejsca, rozszerza się wolumin o kolejne fizyczne dyski. Dzięki tej technologii można logicznie założyć duży zasób dyskowy do wykorzystania i jeśli rzeczywiście będzie potrzeba użycia takie ilości przestrzeni będzie się dodwać stopniowo kolejne dyski nie wydając pieniędzy na przestrzeń, której nigdy nie wykorzystamy.
13.2. Zarządzenie partycjami ze schematem MBR
W tym podrozdziale nauczymy się zarządzać partycjami ze schematem MBR przy użyciu narzędzia parted. Tego polecenia możemy używać albo w trybie interaktywnym albo bezpośrednio z wiersza polecenia. Poniższe czynności będą opierać się wyłącznie na obsłudze z poziomu wiersza polecenia. Na początek wyświetlimy sobie zawartość dysku.
[user@server2 ~]$ sudo parted /dev/vdb print Error: /dev/vdb: unrecognised disk label Model: Virtio Block Device (virtblk) Disk /dev/vdb: 268MB Sector size (logical/physical): 512B/512B Partition Table: unknown Disk Flags:
Za pomocą podpolecenia print
możemy
wyświetlić informacje na temat dysku oraz znajdujące się na nim
partycje. Zwróćmy uwagę na pierwszą linię, mówi ona o tym, że nie
znaleziony etykiety dysku, w tym przypadku chodzi o schemat
partycjonowania (tablicę partycji). Zapamiętajmy też składnie tego
polecenia, gdyż pierwszym
argumentem zawsze jest nazwa urządzenia następnie podpolecenie
wykonujące określoną czynność. Poniższe polecenie nada etykietę
msdos ustawiając tym samym schemat na MBR.
[user@server2 ~]$ sudo parted /dev/vdb mklabel msdos [sudo] password for user: Information: You may need to update /etc/fstab. [user@server2 ~]$ sudo parted /dev/vdb print Model: Virtio Block Device (virtblk) Disk /dev/vdb: 268MB Sector size (logical/physical): 512B/512B Partition Table: msdos Disk Flags: Number Start End Size Type File system Flags
Teraz kiedy zdecydowaliśmy o schemacie partycjonowania, możemy utworzyć partycję. Przy tworzeniu partycji jest pewien haczyk. Otóż podczas tworzenia partycji w parted należy podać początek oraz koniec. Zatem chcąc stworzyć partycję o wielkości 100 MB podajemy początek 1 (co jest równe 1M, jest również pierwsza partycja więc rozpoczyna się od pierwszego megabajta dysku) 101M stosując również skróty jednostek odnoszące się wyłacznie do wielkorotności jak M - megabajt, G - gigabajt itd. Następną partycję moglibyśmy zacząć od 101M i ustawiając jej koniec, na koniec pozostałej wolnej części dysku za pomocą takiego wyrażenia jak: 100%Free.
[user@server2 ~]$ sudo parted /dev/vdb mkpart primary 1 101M [sudo] password for user: Information: You may need to update /etc/fstab. [user@server2 ~]$ sudo parted /dev/vdb print Model: Virtio Block Device (virtblk) Disk /dev/vdb: 268MB Sector size (logical/physical): 512B/512B Partition Table: msdos Disk Flags: Number Start End Size Type File system Flags 1 1049kB 101MB 99.6MB primary
Po podpoleceniu podajemy rodzaj partycji w tym przypadku jest to
primary
, następnie podajemy jej
początek 1
oraz koniec
101M
. Tak utworzą partycję możemy
teraz usunąć za pomocą podpolecenia rm, które przyjmuje
numer jako argument.
[user@server2 ~]$ sudo parted /dev/vdb rm 1 [sudo] password for user: Information: You may need to update /etc/fstab. [user@server2 ~]$ sudo parted /dev/vdb print Model: Virtio Block Device (virtblk) Disk /dev/vdb: 268MB Sector size (logical/physical): 512B/512B Partition Table: msdos Disk Flags: Number Start End Size Type File system Flags
13.3. Zarządzanie partycjami ze schematem GPT
Zarządzanie partycjami ze schematem GPT różni się od tego ze schematem MBR. Nie tylko tym, że wykorzystuje się do tego inne narzędzia. Te narzędzia mają również inną zasadę działania. Do zarządzania partycjami GPT wykorzystuje się narzędzie gdisk, które jest narzędziem interaktywnym, jego różnica polega na tym, że nie zapisze ono zmian na dysku do póki nie użyjemy odpowiednie polecenia. Polecenia w tym narzędziu przyjmują postać pojedynczych liter, a ich listę możemy uzyskać w momencie wydania polecenia znaku zapytania (?). Polecenie uruchamia się podając nazwę urządzenia jako argument.
[user@server2 ~]$ sudo gdisk /dev/vdd GPT fdisk (gdisk) version 1.0.7 Partition table scan: MBR: not present BSD: not present APM: not present GPT: not present Creating new GPT entries in memory. Command (? for help): ? b back up GPT data to a file c change a partition's name d delete a partition i show detailed information on a partition l list known partition types n add a new partition o create a new empty GUID partition table (GPT) p print the partition table q quit without saving changes r recovery and transformation options (experts only) s sort partitions t change a partition's type code v verify disk w write table to disk and exit x extra functionality (experts only) ? print this menu Command (? for help):
Polecenie na początku zwróci listę używanych na dysku schematów tablicy partycji. Następnie wydałem odpowiednie polecenie aby wyświetić listę dostępnych polecenień. Jak widać na dysku nie ma żadnej tablicy za pomocą polecenia o zostanie stworzona nowa tablica partycji (miejsce z informacjami o partycjach dysku) w schemacie GPT.
Command (? for help): o This option deletes all partitions and creates a new protective MBR. Proceed? (Y/N): Y Command (? for help): w Final checks complete. About to write GPT data. THIS WILL OVERWRITE EXISTING PARTITIONS!! Do you want to proceed? (Y/N): y OK; writing new GUID partition table (GPT) to /dev/vdd. The operation has completed successfully.
Poza utworzeniem nowej tablicy partycji ze schematem GPT, program zabezpieczy MBR dla wstecznej zgodności z komputerami obsługiwanymi przez BIOS. Na koniec wyszedłem, aby zapisać zmiany i uruchomiłem program ponownie.
[user@server2 ~]$ sudo gdisk /dev/vdd GPT fdisk (gdisk) version 1.0.7 Partition table scan: MBR: protective BSD: not present APM: not present GPT: present Found valid GPT with protective MBR; using GPT. Command (? for help):
Teraz program przedstawia, że odnalazł prawidłową tablicę ze schematem GPT oraz zabezpieczony MBR. Teraz aby utworzyć partycję użyje opcji n następnie pozostawie część domyślnych informacji. Podam tylko jej wielkość w linii oznaczonej jako ostatnii sektor. Wiecej szczegółów znajduje się na przykładzie poniżej:
Command (? for help): n Partition number (1-128, default 1): First sector (34-524254, default = 2048) or {+-}size{KMGTP}: Last sector (2048-524254, default = 524254) or {+-}size{KMGTP}: +100M Current type is 8300 (Linux filesystem) Hex code or GUID (L to show codes, Enter = 8300): Changed type of partition to 'Linux filesystem' Command (? for help): p Disk /dev/vdd: 524288 sectors, 256.0 MiB Sector size (logical/physical): 512/512 bytes Disk identifier (GUID): F5BE61A0-220E-409E-AB2F-18AFDD56D410 Partition table holds up to 128 entries Main partition table begins at sector 2 and ends at sector 33 First usable sector is 34, last usable sector is 524254 Partitions will be aligned on 2048-sector boundaries Total free space is 319421 sectors (156.0 MiB) Number Start (sector) End (sector) Size Code Name 1 2048 206847 100.0 MiB 8300 Linux filesystem
Warto zwrócić uwagę na to w jaki sposób została podana wielkość
partycji (+100M
). Za pomocą opcji
p możemy wyświetlić zmiany jakie zaszły póki co w pamięci.
Więc żeby zmiany, które zostały utworzone zapisać podajemy polecnie
w, nastepnie potwierdzamy zapisanie zmian.
Command (? for help): w Final checks complete. About to write GPT data. THIS WILL OVERWRITE EXISTING PARTITIONS!! Do you want to proceed? (Y/N): y OK; writing new GUID partition table (GPT) to /dev/vdd. The operation has completed successfully.
Aby usunąc partycję podajemy opcję d, która następnie poprosi o podanie numery partycji o ile jest więcej niż jedna. Jeśli jest tylko jedna automatycznie ją usunie.
[user@server2 ~]$ sudo gdisk /dev/vdd [sudo] password for user: GPT fdisk (gdisk) version 1.0.7 Partition table scan: MBR: protective BSD: not present APM: not present GPT: present Found valid GPT with protective MBR; using GPT. Command (? for help): d Using 1 Command (? for help): p Disk /dev/vdd: 524288 sectors, 256.0 MiB Sector size (logical/physical): 512/512 bytes Disk identifier (GUID): F5BE61A0-220E-409E-AB2F-18AFDD56D410 Partition table holds up to 128 entries Main partition table begins at sector 2 and ends at sector 33 First usable sector is 34, last usable sector is 524254 Partitions will be aligned on 2048-sector boundaries Total free space is 524221 sectors (256.0 MiB) Number Start (sector) End (sector) Size Code Name
Oczywiście jeśli przypadkowo coś usuneliśmy lub zmieniliśmy możemy użyć opcji q, aby zakończyć działanie programu bez zapisywania zmian na dysku.
Odnośnie egzaminu:
Znajomość zarówno parted oraz gdisk jest
wystarczająca, aby zrealizować proste zadania związane z zarządzaniem
dyskami na egzaminie.
Ćwiczenie 1: Zarządzanie partycjami za pomocą parted
Jako użytkownik z możliwością podniesienia uprawnień, na maszynie oznaczonej jako server2 utwórz jedną 100 MB partycję na jednym z dysków o pojemności 250 MB. Użyj do tego tablicy o schemacie MBR. Do utworzenia partycji użyj narzędzia parted z poziomu wiersza polecenia. Nastepnie utworz taką samą partycję ale w trybie interaktywnym tego polecenia. Wyświetl informacje na temat dysku. Na koniec usuń obie partycje używając wiersza polecenia.
Ćwiczenie 2: Zarządzanie partycjami za pomocą gdisk
Jako użytkownik z możliwością podniesienia uprawnień, na maszynie oznaczonej jako server2 utwórz przy tablicy w schemacie GPT dwie partycje po 80MB każda. Wyświetl informacje na temat dysku. Jeśli chcesz usuń te partycje.
Podsumowanie
W tym rozdziale poznaliśmy podstawy teoretyczne oraz praktyczne zarządzania dyskami. Nauczyliśmy się tworzenia oraz usuwania partycji przy różnych schematach tablic. W następnym rozdziale przejdziemy do bardziej zaawansowanych czynności związanych z zarządzaniem pamięcią masową w RHEL.
14. Zaawansowane zarządzanie pamięcią masową
W tym rodziale zajmiemy się bardziej zawansowanymi zagadnieniami związanymi zarządzaniem pamiecią masową. W tym rozdziale poruszymy również pominięty z względu na zmiany w RHEL podrozdział związany z bardziej efektywnym wykorzystaniem przestrzeni na dysku dzięki VDO. Kolejnym zagadnienieniem będzie LVM, który pozwala spojrzeć nieco inaczej na urządzenia służące do przechowywania danych. Ostatnim tematem będzie Stratis, który łączy ze sobą kilka komponentów systemu pozwalających na stworzenie stablinego i wydajnego systemu plików (o systemach plików będzie w następnym rozdziale).
14.1. Zarządzanie pamięcią masową przy użyciu LVM
LVM, czyli Logical Volume Manager pozwala inaczej spojrzeć na dostępne w naszych komputerach dyski. Za pomocą tego narzędzia możemy zebrać wszystkie dostępne w systemie dyski zainicjować je, aby były gotowe do pracy z LVM, wówczas dyski stają się woluminami fizycznymi. Woluminy fizyczne łączy się w grupę woluminów, która staje się pulą to tworzenie nowych urządzeń dyskowych bazujących na miejscu dostępnym w grupie. Takie urządzenia noszą nazwę woluminów logicznych. W ujęciu LVM najmiejszą logiczną jednostką alokacji przestrzeni dyskowej są ekstenty. Ekstenty dzielą się na logiczne będące cząstkami woluminów logicznych oraz na fizyczne będące elementami woluminów fizycznych. Ekstenty podczas tworzenia grupy woluminów mają domyślną wielkość wynoszącą około 4 MB. Oczywiście można to zmienić. A wielkości ekstentów (logicznych i fizycznych) nie muszą być sobie równe. Pojęcie ekstenów będzie potrzebne nam przy VDO.
Elementy logiczne LVM są bardzo eleastyczne, może je dodawać usuwać, rozszerzać, zmniejszać i zmieniać wcześniej nadane nazwy. Tym się właśnie zajmiemy w tym rodziale. Oczywiście będziemy pracować z urządzeniami więc niezbędne będą uprawnienia administratora.
14.1.1. Tworzenie woluminów fizycznych
Aby rozpocząć pracę z LVM musimy przekształcić dysk lub partycję aby nadawała się do pracy z tym rozwiązaniem. Na tych urządzeniach blokowych zostaną utworzone specjalne struktury, dzięki czemu będzie można później włączyć je do grupy.
Chcąc użyć partycji jako woluminu fizycznego tworzmy partycje, bez znaczenia czy jest schemat tablicy partycji GPT czy MBR, następnie partycji ustawiamy flagę lvm. Tak przygotowana partycja jest gotowa by użyć jej jako woluminu fizycznego. Poniżej znajduje się przykład przedstawiający jak to zrealizować.
[user@rhel90 ~]$ sudo gdisk /dev/vdb GPT fdisk (gdisk) version 1.0.7 Partition table scan: MBR: not present BSD: not present APM: not present GPT: not present Creating new GPT entries in memory. Command (? for help): o This option deletes all partitions and creates a new protective MBR. Proceed? (Y/N): Y Command (? for help): p Disk /dev/vdb: 524288 sectors, 256.0 MiB Sector size (logical/physical): 512/512 bytes Disk identifier (GUID): 66CCB514-9659-461D-834B-1661E9D112F4 Partition table holds up to 128 entries Main partition table begins at sector 2 and ends at sector 33 First usable sector is 34, last usable sector is 524254 Partitions will be aligned on 2048-sector boundaries Total free space is 524221 sectors (256.0 MiB) Number Start (sector) End (sector) Size Code Name Command (? for help): n Partition number (1-128, default 1): First sector (34-524254, default = 2048) or {+-}size{KMGTP}: Last sector (2048-524254, default = 524254) or {+-}size{KMGTP}: +128M Current type is 8300 (Linux filesystem) Hex code or GUID (L to show codes, Enter = 8300): 8e00 Changed type of partition to 'Linux LVM' Command (? for help): w Final checks complete. About to write GPT data. THIS WILL OVERWRITE EXISTING PARTITIONS!! Do you want to proceed? (Y/N): y OK; writing new GUID partition table (GPT) to /dev/vdb. The operation has completed successfully.
Tak utworzoną partycje możemy zainicjować jako wolumin fizyczny za pomocą polecenia pvcreate.
[user@rhel90 ~]$ sudo pvcreate /dev/vdb1 Devices file /dev/vdb is excluded by filter: device is partitioned. Physical volume "/dev/vdb1" successfully created.
Teraz wolumin nadaje się do podłączenia do grupy.
Inicjowanie całych dysków jest o wiele prostsze. Wystarczy użyć polecenie pvcreate i podać nazwę urządzenia jako argument.
[user@rhel90 ~]$ sudo pvcreate /dev/vdc Devices file /dev/vdb is excluded by filter: device is partitioned. Physical volume "/dev/vdc" successfully created.
Listę dostępnych w systemie woluminów fizycznych możemy wyświetlić za pomocą polecenia pvs.
[user@rhel90 ~]$ sudo pvs [sudo] hasło użytkownika user: Devices file PVID none last seen on /dev/vdd1 not found. Devices file PVID none last seen on /dev/vdd2 not found. Devices file PVID none last seen on /dev/vdc1 not found. Devices file /dev/vdb is excluded by filter: device is partitioned. PV VG Fmt Attr PSize PFree /dev/vda2 rhel lvm2 a-- <11,00g 0 /dev/vdb1 lvm2 --- 128,00m 128,00m /dev/vdc lvm2 --- 256,00m 256,00m
Kolumny oznaczają kolejno: fizyczny wolumin
(PV
), grupę do której należy fizyczny
wolumin (VG
), format
(Fmt
), atrybuty
(Attr
, wartości poszczególnych bitów
są rozpisane w na stronie podręcznika), rozmiar fizyczny
(PSize
) oraz fizyczną ilość wolnego
miejsca (PFree
).
14.1.2. Tworzenie grup woluminów
Posiadając już odpowiednie zasoby w postaci woluminów fizycznych, możemy utworzyć grupę woluminów, aby móc zarządzać zaawansowanymi właściwościami LVM. Grupy tworzone są za pomocą polecenia vgcreate. Utworzę teraz grupę z wcześniej stworzonych woluminów.
[user@rhel90 ~]$ sudo vgcreate vg_course /dev/vdb1 /dev/vdc Devices file /dev/vdb is excluded by filter: device is partitioned. Volume group "vg_course" successfully created
Polecenie przyjmuje jako pierwszy argument nazwę grupy a następnie wchodzące w jej skład fizyczne woluminy. Listę utworzonych w systemie grup możemy wyświetlić za pomocą polecenia vgs. Natomiast bardziej szczegółowe informacje na temat grupy możemy uzyskać więcej informacji za pomocą polecenia vgdisplay.
[user@rhel90 ~]$ sudo vgs [sudo] hasło użytkownika user: Devices file PVID none last seen on /dev/vdd1 not found. Devices file PVID none last seen on /dev/vdd2 not found. Devices file PVID none last seen on /dev/vdc1 not found. Devices file /dev/vdb is excluded by filter: device is partitioned. VG #PV #LV #SN Attr VSize VFree rhel 1 2 0 wz--n- <11,00g 0 vg_course 2 0 0 wz--n- 376,00m 376,00m
Polecenie to zwraca informacje podobne do poprzedniego polecenia
pvs. Dodatkowe kolumny zwracają informacje na temat
ilość woluminów fizycznych w grupie
(#PV
), ilość woluminów logicznych
(#LV
) oraz ilość snapshotów w
grupie woluminów. Reszta kolumn jest podobna do tych informacji
zwracanych przez pvs. Innym narzędziem zwracającym więcej
informacji na temat grupy woluminów jest vgdisplay,
jako argument przyjmuje ona nazwę grupy, jeśli zostanie pominięta
polecenie zwróci informacje na temat wszystkich grup w systemie.
[user@rhel90 ~]$ sudo vgdisplay vg_course [sudo] hasło użytkownika user: Devices file PVID none last seen on /dev/vdd1 not found. Devices file PVID none last seen on /dev/vdd2 not found. Devices file PVID none last seen on /dev/vdc1 not found. --- Volume group --- VG Name vg_course System ID Format lvm2 Metadata Areas 2 Metadata Sequence No 1 VG Access read/write VG Status resizable MAX LV 0 Cur LV 0 Open LV 0 Max PV 0 Cur PV 2 Act PV 2 VG Size 376,00 MiB PE Size 4,00 MiB Total PE 94 Alloc PE / Size 0 / 0 Free PE / Size 94 / 376,00 MiB VG UUID g4X6FW-P1fu-jS0t-UaGg-8mIK-Kv0J-2bLWSD
Polecenie to zwraca rozmiar fizycznych ekstentów, który w tym przypadku posiada wartość domyślną. Rozmiar ten możemy zmienić podając opcje -s oraz wielkość fizycznych ekstentów jako argument opcji podczas tworzenia grupy. Chcąc wydobyć konkretne informacje z tego polecenia możemy posłużyć się poleceniem grep.
[user@rhel90 ~]$ sudo vgdisplay vg_course | grep 'PE Size' [sudo] hasło użytkownika user: Devices file PVID none last seen on /dev/vdd1 not found. Devices file PVID none last seen on /dev/vdd2 not found. Devices file PVID none last seen on /dev/vdc1 not found. PE Size 4,00 MiB
14.1.3. Tworzenie woluminów logicznych LVM
Do tworzenia woluminów logicznych służy polecenie lvcreate. Wydając to polecenie wraz z opcją --help, zostaną nam zwrócone wszystkie możliwe rodzaje segmentów woluminów logicznych. W tym materiale będą nas interesować tylko dwa linear (liniowy, zwykły) oraz VDO. O VDO będzie w następnym podrozdziale. Zatem do stworzenia liniowego woluminu logicznego potrzebujemy wielkości (opcja -L) oraz nazwy grupy w której ma zostać stworzony. Inną dość przydatną opcją, niezależną od rodzaju woluminu jest opcja -n, która pozwala na nadanie nazwy woluminowi. Teraz utworzę wolumin logiczny w grupie, którą wcześniej utworzyłem.
[user@rhel90 ~]$ sudo lvcreate -L 100MB -n lvol0 vg_course Logical volume "lvol0" created.
Czasami podana wielkość woluminu może zostać zaokrąglona, ze względu na potrzebę użycia okrągłej liczby ekstentów. W przypadku tego woluminu zostały użyte 25 ekstenty (25 x 4MB = 100MB), co możemy podejrzeć wydając polecenie vgdisplay z opcją -v Przez co zwróci ona bardziej szczegółowe informacje na temat grupy, w tym informacje na temat woluminów logicznych w niej zawartych.
[user@rhel90 ~]$ sudo vgdisplay -v vg_course ... --- Logical volume --- LV Path /dev/vg_course/lvol0 LV Name lvol0 VG Name vg_course LV UUID Z2cH37-sWGu-NEIR-JoKN-AT5M-o5EI-d8QmKU LV Write Access read/write LV Creation host, time rhel90, 2022-07-22 11:35:47 +0200 LV Status available # open 0 LV Size 100,00 MiB Current LE 25 Segments 1 Allocation inherit Read ahead sectors auto - currently set to 256 Block device 253:2 ...
Innm narzędziem, które zwraca informacje na temat woluminów logicznych jest lvs. Zwraca ono podobne informacje do vgs na przykład:
[user@rhel90 ~]$ sudo lvs Devices file PVID none last seen on /dev/vdd1 not found. Devices file PVID none last seen on /dev/vdd2 not found. Devices file PVID none last seen on /dev/vdc1 not found. LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert root rhel -wi-ao---- 9,79g swap rhel -wi-ao---- 1,20g
Informacje zawierają nazwę woluminu
(LV
),
grupę woluminów (VG
), atrybuty
(Attr
) oraz wielkości
(LSize
).
Poza klasyczną wielkością podawną w wielkrotnościach bajtów, wielkość woluminu możemy podawać ilości ekstentów, służy do tego opcją -l.
Tak utworzone woluminy są pełno prawnymi urządzeniami blokowymi przypominającymi partycję. Możemy zainstalować na nich odpowiedni system plików (będzie o tym w następnym rozdziale), zamontować je w systemie i wykorzystać do przechowywania danych.
14.1.4. Zmiana nazwy elementów LVM
Nazwę możemy zmienić takim elementom jak wolumin logiczny - polecenie lvrename oraz grupa woluminów - polecenie vgrename. Polecenie lvrename wymaga podania scieżki do woluminu (znajdziemy go za pomocą polecenia vgdisplay -v) oraz nowej nazwy. Możemy ominąć potrzebę podawania ścieżki do woluminu, poprzedzając jego nazwę, nazwą grupy. Ze zmianą nazwy grupy jest o wiele prościej wystarczy podać poleceniu vgrename starą nazwę grupy oraz nową.
Zmiana nazwy woluminu za pomoca ścieżki woluminu:
[user@rhel90 ~]$ sudo lvrename /dev/vg_course/lvol0 rhelvol0 Renamed "lvol0" to "rhelvol0" in volume group "vg_course"
Zmiana nazwy woluminu za pomocą nazwy grupy:
[user@rhel90 ~]$ sudo lvrename vg_course rhelvol0 rhel9vol0 Renamed "rhelvol0" to "rhel9vol0" in volume group "vg_course"
Zmiana nazwy grupy:
[user@rhel90 ~]$ sudo vgrename vg_course rhcsa9 Devices file /dev/vdb is excluded by filter: device is partitioned. Volume group "vg_course" successfully renamed to "rhcsa9"
14.1.5. Rozszerzanie elementów LVM
Za pomocą poleceń vgextend możemy rozszerzyć grupę woluminów o dodatkowe woluminy fizyczne. Natomiast za pomocą polecenia lvextend możemy rozszerzyć wolumin logiczny o dodatkowe miejsce, przy czym wolumin należy podać w postaci ścieżki.
Rozszerzenie grupy woluminów o kolejny wolumin fizyczny:
[user@rhel90 ~]$ sudo vgextend rhcsa9 /dev/vdd Devices file /dev/vdb is excluded by filter: device is partitioned. Volume group "rhcsa9" successfully extended
Rozszerzenie woluminów logicznych o dodatkową przestrzeń:
[user@rhel90 ~]$ sudo lvextend -L +100M /dev/rhcsa9/rhel9vol0 Size of logical volume rhcsa9/rhel9vol0 changed from 100,00 MiB (25 extents) to 200,00 MiB (50 extents). Logical volume rhcsa9/rhel9vol0 successfully resized.
Zwróćmy uwagę w jaki sposób podajemy wielkość o którą chcemy rozszerzyć podany wolumin.
14.1.6. Zmniejszanie elementów LVM
Za pomocą kolejnej pary poleceń lvreduce, oraz vgreduce możemy zmniejszyć ilość miejsca w przypadku woluminów logicznych oraz usunąć z grupy okreslone woluminy fizyczne. Przyczym warto dodać, o ile rozszerzenie miejsca nie było działaniem destrukcyjnym (gdy np. na woluminach logicznych znajdują sie systemy plików oraz dane) to zmieniejszanie z całą pewnością jest takim działaniem.
Zmniejszenie woluminu logicznego o 50 MB, przy czym wielkość możemy podać odejmując podaną wartość lub podając nową wielkość dla woluminu. Obie formy są poprawne.
[user@rhel90 ~]$ sudo lvreduce -L -50M /dev/rhcsa9/rhel9vol0 [sudo] hasło użytkownika user: Rounding size to boundary between physical extents: 48,00 MiB. WARNING: Reducing active logical volume to 152,00 MiB. THIS MAY DESTROY YOUR DATA (filesystem etc.) Do you really want to reduce rhcsa9/rhel9vol0? [y/n]: y Size of logical volume rhcsa9/rhel9vol0 changed from 200,00 MiB (50 extents) to 152,00 MiB (38 extents). Logical volume rhcsa9/rhel9vol0 successfully resized. [user@rhel90 ~]$ sudo lvreduce -L 100M /dev/rhcsa9/rhel9vol0 WARNING: Reducing active logical volume to 100,00 MiB. THIS MAY DESTROY YOUR DATA (filesystem etc.) Do you really want to reduce rhcsa9/rhel9vol0? [y/n]: y Size of logical volume rhcsa9/rhel9vol0 changed from 152,00 MiB (38 extents) to 100,00 MiB (25 extents). Logical volume rhcsa9/rhel9vol0 successfully resized.
Usunięcie z grupy jednego z woluminów fizycznych.
[user@rhel90 ~]$ sudo vgreduce rhcsa9 /dev/vdd [sudo] hasło użytkownika user: Devices file /dev/vdb is excluded by filter: device is partitioned. Removed "/dev/vdd" from volume group "rhcsa9"
14.1.7. Wycofywanie zmian LVM na dyskach
Wycofywanie zmian rozpoczniemy od usunięcia woluminów logicznych a służy temu polecenie lvremove, aby usunąć wolumin podaje się nazwę grupy oraz nazwę woluminu:
[user@rhel90 ~]$ sudo lvremove rhcsa9 rhel9vol0 Devices file /dev/vdb is excluded by filter: device is partitioned. Do you really want to remove active logical volume rhcsa9/rhel9vol0? [y/n]: y Logical volume "rhel9vol0" successfully removed. Volume group "rhel9vol0" not found Cannot process volume group rhel9vol0
Kombinację tych dwóch wartości możemy zastąpić ścieżką do woluminu, a potwierdzenie możemy wymusić za pomocą opcji -f.
Po usunięciu woluminów przyszedł czas na usunięcie grupy woluminów, do tego należy wykorzystać polecenie vgremove. Polecenie to przyjmuje nazwę grupy jako argument.
[user@rhel90 ~]$ sudo vgremove rhcsa9 [sudo] hasło użytkownika user: Devices file /dev/vdb is excluded by filter: device is partitioned. Volume group "rhcsa9" successfully removed
Po usunięciu grupy pozostaje tylko wyczyszcznie dysków ze wszelkich struktur stworzonych na potrzeby LVM. Polecenie, które wykona tę czynność to pvremove.
[user@rhel90 ~]$ sudo pvremove /dev/vdb1 /dev/vdc Devices file /dev/vdb is excluded by filter: device is partitioned. Labels on physical volume "/dev/vdb1" successfully wiped. Labels on physical volume "/dev/vdc" successfully wiped.
14.2. Wykorzystanie VDO do zarządzania pamięciami masowymi
VDO, czyli Virtual Disk Optimizer jest technologia zarządzania pamięciami masowymi pozwalająca na zaoszczędzenie wykorzystywanej przestrzeni, zwiększenie wydajności przesyłanych danych oraz zaoszczędzenie pieniędzy przeznaczonych na zakup dysków. VDO wykorzystuje takie techniki jak kompresja, technologia thin provisioning oraz unikanie tworzenia duplikatów plików. Kiedyś VDO było odrębną techniką tak jak LVM czy Stratis. Obecnie od RHEL 8.5 zostało zunifikowane wraz z LVM jako jeden z rodzajów logicznych woluminów. Tym zajmiemy się tym podrodziale otóż utworzymy logiczny volumin VDO.
Aby użyć wolumin typu VDO musimy dysponować co najmniej 5GB przestrzenii w grupie woluminów. Ja poniżej stworzyłem grupę składającą się z jednego 10GB fizycznego voluminu.
[user@rhel90 ~]$ sudo pvcreate /dev/vdf [sudo] hasło użytkownika user: Devices file /dev/vdb is excluded by filter: device is partitioned. Physical volume "/dev/vdf" successfully created. [user@rhel90 ~]$ sudo vgcreate vg-vdo /dev/vdf Devices file /dev/vdb is excluded by filter: device is partitioned. Volume group "vg-vdo" successfully created [user@rhel90 ~]$ sudo vgs Devices file PVID none last seen on /dev/vdd1 not found. Devices file PVID none last seen on /dev/vdd2 not found. Devices file PVID none last seen on /dev/vdc1 not found. Devices file /dev/vdb is excluded by filter: device is partitioned. VG #PV #LV #SN Attr VSize VFree rhel 1 2 0 wz--n- <11,00g 0 vg-vdo 1 0 0 wz--n- <10,00g <10,00g
Przed utworzeniem woluminu, musimy poznać ilość ekstentów dostępnych w grupie. Za pomocą poniższego polecenia możemy ustalić te liczbę. Jest ona istotna, ponieważ jeśli jej nie podamy nie będziemy mogi skorzystać z thin provisioning.
[user@rhel90 ~]$ sudo vgdisplay -v vg-vdo | grep 'Free PE' [sudo] hasło użytkownika user: Devices file PVID none last seen on /dev/vdd1 not found. Devices file PVID none last seen on /dev/vdd2 not found. Devices file PVID none last seen on /dev/vdc1 not found. Total PE / Free PE 2559 / 2559
Teraz możemy za pomocą polecenia lvcreate utworzyć wolumin logiczny w stylu VDO:
[user@rhel90 ~]$ sudo lvcreate --type vdo -n vdo-vol0 -l 2559 -V 1TB vg-vdo The VDO volume can address 6 GB in 3 data slabs, each 2 GB. It can grow to address at most 16 TB of physical storage in 8192 slabs. If a larger maximum size might be needed, use bigger slabs. Logical volume "vdo-vol0" created.
W ten sposób stworzyłem wolumin w stylu VDO, za pomocą opcji -V podaje wirtualną wielkość tego urządzenia. Polecenie poza utworzeniem podanego woluminu utworzy dodatkowy wolumin puli. Tak utworzony wolumin VDO może nam posłużyć do przechowywania danych na serwerze. Poniżej znajduje się wynik działania poleceń lvs oraz vgdisplay.
[user@rhel90 ~]$ sudo lvs -a vg-vdo Devices file PVID none last seen on /dev/vdd1 not found. Devices file PVID none last seen on /dev/vdd2 not found. Devices file PVID none last seen on /dev/vdc1 not found. LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert vdo-vol0 vg-vdo vwi-a-v--- 1,00t vpool0 0,00 vpool0 vg-vdo dwi------- <10,00g 40,02 [vpool0_vdata] vg-vdo Dwi-ao---- <10,00g
Zwróćmy uwagę, że samo utrzymanie takiego woluminu, kosztuje nas 4GB miejsca na dysku i nie jest to zależne od jego rozmiaru. Poniżej znajdują się informacje uzyskane z polecenia vgdisplay:
[user@rhel90 ~]$ sudo vgdisplay -v vg-vdo Devices file PVID none last seen on /dev/vdd1 not found. Devices file PVID none last seen on /dev/vdd2 not found. Devices file PVID none last seen on /dev/vdc1 not found. --- Volume group --- VG Name vg-vdo System ID Format lvm2 Metadata Areas 1 Metadata Sequence No 16 VG Access read/write VG Status resizable MAX LV 0 Cur LV 2 Open LV 0 Max PV 0 Cur PV 1 Act PV 1 VG Size <10,00 GiB PE Size 4,00 MiB Total PE 2559 Alloc PE / Size 2559 / <10,00 GiB Free PE / Size 0 / 0 VG UUID qPdY4n-YQUG-x5tu-szTe-B3bT-idC8-vseZXH --- Logical volume --- LV Path /dev/vg-vdo/vpool0 LV Name vpool0 VG Name vg-vdo LV UUID H9mloX-8x8N-4OHz-HHvz-qWhZ-dnJE-Sq1sCX LV Write Access read/write LV Creation host, time rhel90, 2022-07-22 15:17:50 +0200 LV VDO Pool data vpool0_vdata LV VDO Pool usage 40,02% LV VDO Pool saving 100,00% LV VDO Operating mode normal LV VDO Index state online LV VDO Compression st online LV VDO Used size 4,00 GiB LV Status NOT available LV Size <10,00 GiB Current LE 2559 Segments 1 Allocation inherit Read ahead sectors auto --- Logical volume --- LV Path /dev/vg-vdo/vdo-vol0 LV Name vdo-vol0 VG Name vg-vdo LV UUID sc5RL6-LfF6-jzCT-6TNK-c4Q3-J2sf-m1ZufS LV Write Access read/write LV Creation host, time rhel90, 2022-07-22 15:17:53 +0200 LV VDO Pool name vpool0 LV Status available # open 0 LV Size 1,00 TiB Current LE 262144 Segments 1 Allocation inherit Read ahead sectors auto - currently set to 256 Block device 253:4 --- Physical volumes --- PV Name /dev/vdf PV UUID kAxqd2-v4Xo-nmB8-311H-nM2d-DtHn-WutyCf PV Status allocatable Total PE / Free PE 2559 / 0
W RHEL pozostało jeszcze jedno polecenie, które pozwala zwrócić statystykę na temat obecnego w systemie woluminu puli VDO, takim poleceniem jest vdostats. Poniżej znajduje się przykład jego użycia.
[user@rhel90 ~]$ sudo vdostats --si Device Size Used Available Use% Space saving% vg--vdo-vpool0-vpool 10.7G 4.3G 6.4G 40% 0%
Na powyższym przykładzie użyłem opcji
--si
, aby przeskalować jednostki do
poziomu czytelnego dla człowieka.
Usuwanie takiego woluminu wygląda jak usuwanie każdego innego woluminu, jednak w tym przypadku program zapyta czy usunąć także zależny wolumin puli.
14.4. Zarządzanie pamięcią masową za pomocą Stratis
Stratis jest to technologia łącząca ze sobą trzy kompnenty systemowe, pozwalając na łączenie dysków w pule oraz tworzenie już gotowych do montowania systemów plików typu XFS. Stratis jest praktycznie rzecz biorąc bardzo podobny do LVM jednak nie tworzymy logicznych woluminów, a gotowe systemy plików, grupa do której należą dyski nazwane w tym przypadku blockdev nazywana jest pulą.
Stratis nie jest natywnie dostępny w systemie i trzeba go zainstalować. Pakiety znajdują się w repozytorium na płycie instalacyjnej z RHEL 9. Aby zainstalować w Stratis za systemie wydajemy poniższe polecenie:
[user@rhel90 ~]$ sudo dnf install stratisd stratis-cli -y [sudo] hasło użytkownika user: Updating Subscription Management repositories. Unable to read consumer identity This system is not registered with an entitlement server. You can use subscription-manager to register. Ostatnio sprawdzono ważność metadanych: 0:36:10 temu w dniu pią, 22 lip 2022, 15:23:29. Pakiet stratisd-2.4.2-3.el9.x86_64 jest już zainstalowany. Pakiet stratis-cli-2.4.3-2.el9.noarch jest już zainstalowany. Rozwiązano zależności. Nie ma nic do zrobienia. Ukończono.
Stratis występuje w systemie w postaci demona, dlatego też należy włączyć i uruchomić jego jednostkę.
[user@rhel90 ~]$ sudo systemctl enable stratisd.service [user@rhel90 ~]$ sudo systemctl start stratisd.serivce [user@rhel90 ~]$ sudo systemctl status stratisd ● stratisd.service - Stratis daemon Loaded: loaded (/usr/lib/systemd/system/stratisd.service; enabled; vendor preset: enabled) Active: active (running) since Fri 2022-07-22 08:16:57 CEST; 7h ago Docs: man:stratisd(8) Main PID: 758 (stratisd) Tasks: 6 (limit: 7746) Memory: 4.1M CPU: 8.731s CGroup: /system.slice/stratisd.service └─758 /usr/libexec/stratisd --log-level debug lip 22 08:16:56 rhel90 stratisd[758]: [2022-07-22T06:16:56Z INFO libstratis::stratis::run] stratis daemon version 2.4.2 started lip 22 08:16:56 rhel90 stratisd[758]: [2022-07-22T06:16:56Z INFO libstratis::stratis::run] Using StratEngine lip 22 08:16:56 rhel90 stratisd[758]: [2022-07-22T06:16:56Z INFO libstratis::engine::strat_engine::liminal::identify] Beginning initial ... lip 22 08:16:56 rhel90 stratisd[758]: [2022-07-22T06:16:56Z DEBUG libstratis::stratis::run] 2: thread started lip 22 08:16:56 rhel90 stratisd[758]: [2022-07-22T06:16:56Z DEBUG libstratis::stratis::run] 3: thread started lip 22 08:16:57 rhel90 stratisd[758]: [2022-07-22T06:16:57Z INFO libstratis::stratis::ipc_support::dbus_support] D-Bus API is available ...
14.3.1. Tworzenie puli Stratis
Teraz kiedy Stratis jest uruchomiony. Możemy przejść do utworzenia puli. Do utworzenia puli użyjemy podpolecenia pool polecenia stratis oraz podpolecenia create podpolecenia pool. Jako argumenty podajemy nazwę puli oraz listę dysków.
[user@rhel90 ~]$ sudo stratis pool create rhcsa /dev/vdg [sudo] hasło użytkownika user:
Informacje na temat puli możemy uzyskać za pomocą podpolecenia list podpolecenia pool.
[user@rhel90 ~]$ sudo stratis pool list Name Total Physical Properties UUID rhcsa 1 GiB / 37.63 MiB / 986.37 MiB ~Ca,~Cr 5091bc53-7693-4a92-a434-fe8e682d0f58
Z informacji zwracanych z tego polecenie nas na tym etapie powinno interesować kolumna zawierająca informacje o wielkości puli. Teraz możemy utworzyć system plików.
14.3.2. Tworzenie systemu plików Stratis
Tworzenie systemu plików odbywa się za pomocą podpolecenia create, podpolecenia filesystem. To podpolecenie wymaga jako argumenty nazwę puli oraz nazwę systemu plików.
[user@rhel90 ~]$ sudo stratis filesystem create rhcsa rhcsafs0 [user@rhel90 ~]$ sudo stratis filesystem Pool Name Name Used Created Device UUID rhcsa rhcsafs0 546 MiB Jul 22 2022 16:34 /dev/stratis/rhcsa/rhcsafs0 5ca8e5b1-f32a-42e0-ac90-29777b3fc8ed
Zwróćmy uwagę na to, iż Stratis sam dobiera na podstawie
wielkości puli wielkość systemu plików. Tak utworzony system jest
dostępny pod ścieżką w kolumnie
Device
i gotowy do montowania.
14.3.3. Rozszerzenie puli oraz zmiana nazwy puli i systemu plików Stratis
Do rozszerzenia puli Stratis służy podpolecenie add-data podpolecenia pool. To podpolecenie oczekuje podania nazwy urządzenia dyskowego.
[user@rhel90 ~]$ sudo stratis pool add-data rhcsa /dev/vdh [user@rhel90 ~]$ sudo stratis blockdev Pool Name Device Node Physical Size Tier rhcsa /dev/vdg 1 GiB Data rhcsa /dev/vdh 1 GiB Data
Za pomoca podpolecenia blockdev
, mamy
możliwość podejrzenia przypisanych do puli dysków. Jak widzimy teraz
w puli znajdują się dwa dyski, zatem będziemy mogli utworzyć kolejny
system plików, ponieważ samych systemów plików nie możemy zmienić.
Teraz zmienimy nazwę puli oraz nazwę systemu plików.
Do zmiany nazw służy podpolecenie rename kolejno podpolecenia pool oraz filesystem. Na poniższym przykładzie znajduje się zastosowanie tego podpolecenia:
[user@rhel90 ~]$ sudo stratis pool rename rhcsa rhcsa9 [user@rhel90 ~]$ sudo stratis filesystem rename rhcsa9 rhcsafs0 rhcsa9fs0
14.3.4. Usuwanie elementów Stratis
Za pomocą podpolecenia destroy możemy usunąć zarówno system plików jak i pulę Stratis. Poniżej znajduje się przykład użycia, tego podpolecenia w innych ujęciach.
Usunięcie systemu plików:
[user@rhel90 ~]$ sudo stratis filesystem destroy rhcsa9 rhcsa9fs0
Usunięcie puli Stratis:
[user@rhel90 ~]$ sudo stratis pool destroy rhcsa9
Żadna pula już w systemie nie istnieje.
[user@rhel90 ~]$ sudo stratis pool Name Total Physical Properties UUID
Odnośnie egzaminu:
Nie musimy uczyć się na pamięć podpoleceń czy składni. Wiekszość
informacji możemy uzyskać wydając polecenie z opcją --help lub
wydać samo podpolecenie bez argumentów. Jedyne o czym należy pamiętać
to które polecenie lub podpolecenie jest od czego.
Ćwiczenie 1: Tworzenie grup woluminów oraz logicznych woluminów
Jako użytkownik z możliwością podniesienia uprawnień na serwerze oznaczonym jako server2. Stwórz z jedego z 250MB dysków wolumin fizyczny następnie utwórz grupę vg100 ustawiając wielkość fizycznych ekstentów na 16MB, wykorzystując utworzony fizyczny wolumin. Utwórz dwa woluminy logiczne o nazwach kolejno lvol0 oraz swapvol o wielkości 100 oraz 120MB. Zweryfikuj wykonane wcześniej czynności za pomocą poleceń: pvs, lvs, vgs oraz vgdisplay.
Ćwiczenie 2: Rozszerzenie grupy woluminów oraz logicznego woluminu
Jako użytkownik z możliwością podniesienia uprawnień na serwerze oznaczonym jako server2. Użyj kolejnego dysku o wielkości 250MB jako woluminu fizycznego LVM. Dodaj nowy wolumin do grupy z poprzedniego ćwiczenia. Rozszerz pojemność woluminu logicznego lvol0 do 300MB. Sprawdź wykonane czynności za pomocą poleceń: pvs, lvs, vgs oraz vgdisplay.
Ćwiczenie 3: Redukcja oraz usunięcie woluminów logicznych
Jako użytkownik z możliwością podniesienia uprawnień na serwerze oznaczonym jako server2. Zmniejsz rozmiar woluminu logicznego lvol0 do 80MB. Usuń oba woluminy logiczne. Sprawdź wykonane czynności za pomocą poleceń: pvs, lvs, vgs oraz vgdisplay.
Ćwiczenie 4: Wycofywanie zmian LVM na dyskach
Jako użytkownik z możliwością podniesienia uprawnień na serwerze oznaczonym jako server2. Usuń grupę woluminów logicznych vg100. Wyczyść konfiguracje LVM z dysków. Sprawdź wykonane czynności za pomocą polecenia lsblk.
Ćwiczenie 5: Logiczne woluminy VDO
Jako użytkownik z możliwością podniesienia uprawnień na serwerze oznaczonym jako server2. Utwórz konfigurację LVM na podstawie jedno z 10GB dysków (jeśli nie masz takiego dysku, dodaj go). W utworzonej grupie utwórz wolumin VDO o wielkości wirtualnej 50GB. Zweryfikuj wykonanie czynności za pomocą poleceń vgdisplay oraz vdostats. Wycofaj wszystkie dokonane zmiany.
Ćwiczenie 6: Tworzenie puli Stratis
Jako użytkownik z możliwością podniesienia uprawnień na serwerze oznaczonym jako server2. Sprawdź za pomocą lsblk dostępność jednego dysków o pojemności 1GB. Nastepnie utwórz z jego użyciem nową pulę Stratis o nazwie strpool. Potwierdź wykonanie czynności wyświetlając informacje o puli oraz o urządzeniach blokowych za pomocą podpoleceń polecenia Stratis oraz polecenia lsblk.
Ćwiczenie 7: Rozszerzenie i usunięcie puli Stratis
Jako użytkownik z możliwością podniesienia uprawnień na serwerze oznaczonym jako server2. Za pomocą drugiego dysku o pojemności 1GB rozszerz rozmiar puli Stratis strpool. Zweryfikuj wykonaną czynność. Na koniec usuń pulę Stratis, zweryfikuj to za pomocą polecenia lsblk.
Podsumowanie
W tym rozdziale poznaliśmy zaawansowane sposoby na zarządzanie dyskami naszych komputerów. Poznaliśmy wiele poleceń, których składni nie trzeb się uczyć na pamięć. Trzeba się jednak orientować jakie polecenie jest do czego. Poznaliśmy zaległą technologię VDO oraz trochę uprzedzającą fakty zebrane w następnym rodziale technologię Stratis. W następnym rozdziale poznamy systemy plików oraz sposoby na formatowanie tworzonych w tym oraz w poprzednim rozdziale urządzeń blokowych, aby w końcu można było ich użyć do przechowywania danych.
15. Systemy plików oraz przestrzeń wymiany
W ostatnich dwóch rozdziałach poruszaliśmy temat zarządzania przestrzenią dyskową. Oczywiście opisywane tam metody znajdą również zastosowanie w przypadku innych pamięci masowych niż dyski. Czynności wykonywane tam kończyły się wraz z utworzeniem docelowego urządzenia przeznaczonego do przechowywania danych. To jednak nie koniec, aby takie urządzenie mogło przechowywać dane muszą zostać na nim zainstalowane specjalne struktury, które będą zajmować się organizacją oraz sposobem dostepu do danych zebranych na urządzeniu. Tym właśnie jest system plików.
Komputery, ktorych używamy do pracy zawsze mają określną liczbę zasobów. Jednym z nich jest pamięć operacyjna, która przechowuję zarówno kod uruchomionych programów jak i dane, na których one pracują. W zależności od konfiguracji sprzętowej może się ona szybko wyczerpać, więc wymyślono coś takiego jak przestrzeń wymiany. Jest specjalny rodzaj alokacji przestrzeni na dysku, przechowywujący w niej nieużywane w danym momencie obszary pamięci operacyjnej. Jeśli te dane będą potrzebne znów wrócą one do pamięci, a inne zostaną przeniesione właśnie do przestrzeni wymiany. Przestrzeń wymiany inaczej nosi nazwę swapu (czyt. słapu).
15.1 Systemy plików na RHEL 9
Red Hat Enterprise Linux w wersji 9 natywnie obsługuje cztery systemy plików są nim między innymi:
- Systemy plików EXT - jest domyślny system plików dla każdej dystrybucji. Jest on dostępny w 4 wersjach przy czym EXT w wersji 1 jest przestarzy i nie jest już wspierany. Korzystając z EXT nalepiej jest korzystać z wersji 4, zawiera ona najwięcej udogodnień oraz funkcji.
- Systemy plików XFS - jest to system plików stosowany w systemach klasy enterprise, choć obecnie powoli staje się standarem jako podstawowy system plików dla wielu dystrybucji Linuksa. Może on obsłużyć większe pliki niż EXT4 oraz zaalokować przestrzenie dyskowe. Póki co nie ma narzędzia które pozwalało by na zmniejszenie systemu plików tego typu.
- System plików VFAT - system plików utrzymywany w dystrybucjach, aby można było zapewnić zgodność w przesyłaniu plików między Linuksem a systemami MS Windows. Najczęściej jest on stosowany na pamięciach USB.
- System plików ISO 9660 - system plików stosowany na płytach CD/DVD, na których przechowywane są dane. Obrazy płyty z systemami operacyjnymi (dystrybucje) również zawierą struktury tego systemu plików.
Zarządzanie systemami plików obejmuje ich tworzenie, rozszerzanie, zmniejszanie, montowanie oraz odmontowywanie. Tworzenie systemu plików nazwywane jest jego instalacją lub formatowaniem. Obsługa danego systemu plików dostarcza kilku narzędzi, które będziemy poznawać w trakcie wykonywania przykładów, poza nimi system posiada jeszcze kilka poleceń dotyczących ogólnie systemów plików.
15.2. Montowanie oraz odłączanie systemów plików
Chcąc skorzystać z przestrzeni dyskowej zawartej na partycji, musi ona zostać sformatowana pod określny system plików. Załóżmy, że zostało już to zrobione. Musi ona również zostać podłączona do katalogu głównego, tym właśnie zajmuje się montowanie. Do montowania służy polecenie mount. Wydanie go bez podania żadnego argumentu spowoduje wyświetlenie wszystkich zamontowanych w systemie systemów plików.
/dev/mapper/rhel-root on / type xfs (rw,relatime,seclabel,attr2,inode64,logbufs=8,logbsize=32k,noquota) selinuxfs on /sys/fs/selinux type selinuxfs (rw,nosuid,noexec,relatime) systemd-1 on /proc/sys/fs/binfmt_misc type autofs (rw,relatime,fd=31,pgrp=1,timeout=0,minproto=5,maxproto=5,direct,pipe_ino=12986) mqueue on /dev/mqueue type mqueue (rw,nosuid,nodev,noexec,relatime,seclabel) hugetlbfs on /dev/hugepages type hugetlbfs (rw,relatime,seclabel,pagesize=2M) debugfs on /sys/kernel/debug type debugfs (rw,nosuid,nodev,noexec,relatime,seclabel) tracefs on /sys/kernel/tracing type tracefs (rw,nosuid,nodev,noexec,relatime,seclabel) fusectl on /sys/fs/fuse/connections type fusectl (rw,nosuid,nodev,noexec,relatime) configfs on /sys/kernel/config type configfs (rw,nosuid,nodev,noexec,relatime) /dev/vda1 on /boot type xfs (rw,relatime,seclabel,attr2,inode64,logbufs=8,logbsize=32k,noquota) /dev/sr0 on /mnt type iso9660 (ro,relatime,nojoliet,check=s,map=n,blocksize=2048)
System do działania potrzebuje wielu systemów plików i to nie tylko tych dyskowych ale także tych wirtualnych dla tego wynik działania tego polecenia nie jest zbyt czytelny. Możemy go jednak bardzej uściślić podając w za pomocą opcji -t interesującyu nas system plików.
[user@rhel90 ~]$ mount -t xfs /dev/mapper/rhel-root on / type xfs (rw,relatime,seclabel,attr2,inode64,logbufs=8,logbsize=32k,noquota) /dev/vda1 on /boot type xfs (rw,relatime,seclabel,attr2,inode64,logbufs=8,logbsize=32k,noquota)
Aby zamontować system plików należy podać po poleceniu mount, nazwę urządzenia, punkt montowania oraz ewentualnie opcje. Punkten montowania może być dowolny katalog znajdujący się w systemie. Najlepiej jakby był pusty, ponieważ pliki z zamontowanego katalogu przesłonią jego rzeczywistą zawartość.
Innym argumentem są opcje montowania. Polecenie posiada kilka opcji ogólnych, natomiast montowanie określnego systemu plików pozwala także na użycie specyficznych dla niego opcji. Poniżej znajduje się kilka ogólnych opcji, opcje specyficzne znajdują się na stronie podręcznika poświęconej systemowi plików.
- acl (noacl) - włącza lub wyłacza możliwość stosowania list kontroli dostępu.
- auto (noauto) - włącza lub wyłącza możliwość automatycznego montowania systemu plików podczas uruchamiania systemu (będzie o tym w tym rozdziale).
- defaults - zestaw domyślnych opcji pozwalających na pełne wykorzystanie zamontowanego systemu plików.
- _netdev - opcja używana dla systemów plików wymagających sieci, co powoduje zestawienie połączenia sieciowego za nim nastąpi monotowanie systemu plików. Przydatne w gdy montujemy udział NFS.
- x-systemd.requiers= - opcja pozwala na wskazanie jednostki, której aktywacja jest wymagana do zamontowania systemu plików.
- remount - opcja pozwala na montowanie zamontowanego już systemu plików w innym katalogu.
- ro (rw) - montuje system plików tylko do odczytu lub w pełnym dostępie.
Poleceniem służącym do odłączania systemu plików jest umount. Najczęściej podaje się mu punkt montowania. Po odmontowaniu system plików staje się niedostępny dla użytkowników oraz programów.
15.3. Pozyskiwanie identyfikatora UUID systemu plików
Podczas montowania jednym z podawanych argumentów jest nazwa urządzenia. Sprawdza się to podczas szybkiego montowania w trakcie działania systemu. Nazwa urządzenia nie jest jedyną wartością jaką możemy podać poleceniu mount podczas montowania jako wartość wskazującą na urządzenie. Do montowania możemy użyć etykiety, którą ustawiamy podczas formatowania partycji lub specjalnego identyfikatora UUID nadawanego po zainstalowaniu systemu plików na partycji.
Identyfikator w przypadku systemów plików takich jak EXT oraz XFS ma długość 128 bitów natomiast w przypadku VFAT są to tylko 32 bity, 8 heksadecymalnych znaków. UUID możemy uzyskać za przy użyciu specyficznego narzędzia dostarczanego wraz system plików lub dwóch programów ogólnych blkid lub znanego już wcześniej lsblk wraz z opcją -f.
[user@rhel90 ~]$ blkid /dev/mapper/rhel-root: UUID="c09cb7eb-2f8e-459e-bb64-21dde92cd7c0" BLOCK_SIZE="512" TYPE="xfs" /dev/vda2: UUID="AHWsb0-0mbi-MxDK-0bpS-Q6ib-cz4l-rHQWAr" TYPE="LVM2_member" PARTUUID="45658df6-02" [user@rhel90 ~]$ lsblk -f /dev/vda NAME FSTYPE FSVER LABEL UUID FSAVAIL FSUSE% MOUNTPOINTS vda ├─vda1 xfs bootfs fb4c6cf9-8041-42ce-9e75-82026a4a0164 753,1M 26% /boot └─vda2 LVM2_memb LVM2 001 AHWsb0-0mbi-MxDK-0bpS-Q6ib-cz4l-rHQWAr ├─rhel-root xfs c09cb7eb-2f8e-459e-bb64-21dde92cd7c0 5,9G 39% / └─rhel-swap swap 1 be58cfe2-c3a6-4731-9b0b-f58604074bd8 [SWAP]
Odnośnie egzaminu:
Alternatywne nazwenictwo jest istotne gdy chcemy utworzyć wpisy
automatycznego montowania podczas uruchamiania systemu. Klasyczne
nazwy, którymi posługujemy się w systemie przy następnym uruchomieniu
mogą już być zupełnie inne dla tych samych urządzeń, a UUID
czy etykieta jest przypisana na stałe do systemu plików, zostanie
zmieniona dopiero przez ponowne sformatowanie partycji.
15.4. Nadawanie etykiet systemom plików
Etykiety są jedną z metod alternatywnego nazewnictwa urządzeń przechowywujących systemy plików. Możemy je nadwać za pomocą narzędzi dostarczanych wraz z systemem plików. Dla systemów EXT jest narzędzie e2label, natomiast dla XFS jest polecenie xfs_admin wraz z opcją -L. Przy czym etykiety mają swoje ograniczenia w ilość znaków. Dla XFS ten limit wynosi 12 znaków, a w przypadku EXT4 jest to 16 znaków. Teraz odmontuje system plików zamontowany w /boot a następnie nadam mu etykietę i zamontuje ponownie. Na początku jednak sprawdzam nazwę urzędzenia partycji oraz zainstalowany na niej system plików.
[user@rhel90 ~]$ lsblk -f NAME FSTYPE FSVER LABEL UUID FSAVAIL FSUSE% MOUNTPOINTS sr0 iso966 Jolie RHEL-9-0-0-BaseOS-x86_64 2022-04-19-20-42-48-00 0 100% /mnt vda ├─vda1 │ xfs fb4c6cf9-8041-42ce-9e75-82026a4a0164 753,1M 26% /boot └─vda2 LVM2_m LVM2 AHWsb0-0mbi-MxDK-0bpS-Q6ib-cz4l-rHQWAr ├─rhel-root │ xfs c09cb7eb-2f8e-459e-bb64-21dde92cd7c0 5,9G 39% / └─rhel-swap swap 1 be58cfe2-c3a6-4731-9b0b-f58604074bd8 [SWAP] [user@rhel90 ~]$ sudo umount /boot [sudo] hasło użytkownika user: [user@rhel90 ~]$ sudo xfs_admin -L "bootfs" /dev/vda1 zapisywanie wszystkich superbloków nowa etykieta = "bootfs" [user@rhel90 ~]$ sudo mount /boot [user@rhel90 ~]$ lsblk -f NAME FSTYPE FSVER LABEL UUID FSAVAIL FSUSE% MOUNTPOINTS sr0 iso966 Jolie RHEL-9-0-0-BaseOS-x86_64 2022-04-19-20-42-48-00 0 100% /mnt vda ├─vda1 │ xfs bootfs fb4c6cf9-8041-42ce-9e75-82026a4a0164 753,1M 26% /boot └─vda2 LVM2_m LVM2 AHWsb0-0mbi-MxDK-0bpS-Q6ib-cz4l-rHQWAr ├─rhel-root │ xfs c09cb7eb-2f8e-459e-bb64-21dde92cd7c0 5,9G 39% / └─rhel-swap swap 1 be58cfe2-c3a6-4731-9b0b-f58604074bd8 [SWAP]
Jak możemy zauważyć różnice pomiędzy pierwszym wywołaniem lsblk
a drugim. Przy drugim wywowałaniu przy partycji zamontowanej
w katalogu /boot
w kolumnie
LABEL
widnieje teraz napis
bootfs
. Tak utworzoną etykietę
możemy wykorzystać podczas ustawiania automatycznego montowania.
15.5. Automatyczne monotowanie systemów plików - /etc/fstab
Katalog główny możemy być rozbity na kilka różnych systemów plików. Plik zawarte w poszczególnych katalogach są potrzebne do rozruchu systemu, dlatego też w katalogu /etc znajduje się plik tekstowy fstab, w którym to przechowywane są wpisy systemów plików montowanych podczas uruchamiania systemu. Wpisy poza automatycznym montowaniem, skracają też potrzebę podawania wszystkich argumentów poleceniu mount. Jeśli taki system plików nie jest montowany automatycznie to, żeby go zamontować wystarczy podać albo punkt montowania albo nazwę urządzenia. Raczej będzie to punkt montowania. Poniżej znajduję się kilka wpisów, które posłużą nam do analizy.
[user@rhel90 ~]$ sudo grep -v -e '^#' -e '^$' /etc/fstab /dev/mapper/rhel-root / xfs defaults 0 0 UUID=fb4c6cf9-8041-42ce-9e75-82026a4a0164 /boot xfs defaults 0 0 /dev/mapper/rhel-swap none swap defaults 0 0 /dev/sr0 /mnt iso9660 ro 0 0
Aby nieco ułatwić czytelność pozbyłem się komentarzy oraz pustych wierszy. Każdy z wpisów składa się z 6 kolumn, kolumny te kolejno przedstawiają:
- Kolumna 1: nazwa urządzenia. Zazwyczaj znajdują się tutaj identyfikatory UUID lub etykiety, jednak możliwe jest kilka wyjątków, otóż: nazwy woluminów logicznych LVM są unikatowymi identyfikatorami i będą wskazywać to samo urządzenie za każdym razem. Tak samo jest z systemami plików tworzonymi przez usługę Stratis. Na końcu przykładu znajduje się montowanie płyty. Urządzenie /dev/sr0, zazwyczaj oznacza pierwszy napęd optyczny w systemie. Zatem jeśli w komputerze mamy tylko jeden napęd również możemy tak zapisać automatyczne montowanie
- Kolumna 2: punkt montowania. Ta kolumna wskazuje nazwy katalogów do których należy podłączyć montowane systemy plików. Wyjątkiem jest tutaj przestrzeń wymiany, ponieważ w miejscu montowania wstawia się wartość none lub swap.
- Kolumna 3: typ systemu plików
- Kolumna 4: opcje montowania
- Kolunma 5: Ustawienia programu dump, ta kolumna ma zastosowanie tylko w przypadku systemów plików EXT. Dla innych jej wartość zawsze wynosi 0. Program dump tworzy kopie bezpieczeństwa systemu plików.
- Kolumna 6: kolejność partycji do sprawdzenia, ta opcja również tyczy się systemów plików EXT, jej zadaniem jest wskazanie kolejności sprawdzania systemów plików przez program e2fsck, który skanuje system plików pod kątem błędów i je naprawia. Zazwyczaj definiowane kolejności to 0 - wyłączające sprawdzanie, 1 - przeznaczone dla głównego systemu plików (zawierającego katalog główny) oraz 2 - każdy pozostały system plików jeśli zbierze się więcej niż jeden system plików z tą kolejnością to są one sprawdzane jeden po drugim.
Kolumny 5 oraz 6 nie mają zastosowania dla innych systemów plików niż EXT, dlatego też przy wpisach innych systemów plików wpisuje się 0 (zero).
Za pomocą polecenia mount wraz z opcją -a możemy zamontować wszystkie systemy plików, których wpisy znajdują się w tym pliku. Często będziemy korzystać z tego polecenia zatwierdzając zamiany w tym pliku.
Odnośnie egzaminu:
Zgubiony lub niepoprawny wpis w pliku /etc/fstab może
unieruchomić system. Aby to naprawić należy poprawić wpisy w trybie
ratunkowy. Ze względu na to należy zwrócić szczególną uwagę na
poprawność umieszczanych w tym pliku wpisów.
15.6. Monitorowanie zużycia miejsca w systemie plików
Jednym z zadań administracyjnych na serwerach jest monitorowanie zużycia miejsca w systemie plików. Jednym z dostępnych narzędzi jest polecenie df, które domyślnie wyświetla urządzenie jego rozmiar, ilość zużytego miejsca, ilość dostępnego miejsca, procentowe zużycie miejsca na dysku oraz punkt montowania. Poniżej znajduje się przykład.
[user@rhel90 ~]$ df -h System plików rozm. użyte dost. %uż. zamont. na devtmpfs 606M 0 606M 0% /dev tmpfs 636M 0 636M 0% /dev/shm tmpfs 255M 7,4M 247M 3% /run /dev/mapper/rhel-root 9,8G 3,9G 6,0G 40% / /dev/sr0 8,0G 8,0G 0 100% /mnt tmpfs 1,0M 0 1,0M 0% /run/stratisd/keyfiles tmpfs 128M 52K 128M 1% /run/user/42 tmpfs 128M 36K 128M 1% /run/user/1000 /dev/vda1 1014M 261M 754M 26% /boot
Użyłem w przykładzie polecenia wraz z opcją -h, która powoduje skalowanie jednostek. Domyślnie polecenia przedstawia wartości w postaci KB (kilobajtów). Wraz z tą opcją używa się jeszcze kilku innych takich jak:
- -T - dodaje kolumnę z rodzajem systemu plików.
- -x - wyłącza wyświetlanie określonego systemu plików.
- -t - wyświetla wyłącznie urządzenia sformatowane na określony typ plików.
- -i - wyświeta zużycie systemu plików w wezłąch i-node.
15.7. Określenie użycia systemu plików
Za pomocą polecenia df mogliśmy ustalić ogólne wartości na temat zużycia systemu plików. Za pomocą polecenia du możemy ustalić i ile miejsca zajmują określone pliki oraz foldery. To polecenie również domyślnie zwraca informacje w KB. Najczęściej wykorzystywanymi opcjami są -s wyświetające podsumowanie oraz -h skalujące jednostki to poziomu czytelnego przez człowieka.
[user@rhel90 ~]$ sudo du -sh /usr [sudo] hasło użytkownika user: 3,6G /usr
15.8. Zarządzanie systemami plików
Zarządzanie systemami plików wygląda podobnie w wszystkich poznanych tutaj przypadkach (metodach zarządzania pamięcią masową). W tym podrozdziale skupimy się na najbardziej zaawansowanych przypadkach.
15.8.1. Tworzenie systemów plików
Tworzenie systemów plików, czy też formatowanie partycji wygląda identycznie czy jest to wolumin logiczny czy partycja na dysku. Na poniższym przykładzie zaprezentowałem tworzenie partycji na trzech partycjach podstawowych na każdej z nich zainstalowałem inny system plików:
[user@rhel90 ~]$ sudo mkfs -t vfat /dev/vdb1 mkfs.fat 4.2 (2021-01-31) [user@rhel90 ~]$ sudo mkfs -t ext4 /dev/vdb2 mke2fs 1.46.5 (30-Dec-2021) Tworzenie systemu plików o 78848 blokach 1k oraz 19680 i-węzłach UUID systemu plików: d97751fb-dce0-4406-b03b-925dfa64a183 Kopie zapasowe superbloku zapisane w blokach: 8193, 24577, 40961, 57345, 73729 Przydzielanie tablicy grup: zakończono Zapis tablicy i-węzłów: zakończono Tworzenie kroniki (4096 bloków): wykonano Zapis superbloków i podsumowania systemu plików: wykonano [user@rhel90 ~]$ sudo mkfs -t xfs /dev/vdb3 meta-data=/dev/vdb3 isize=512 agcount=4, agsize=4883 blks = sectsz=512 attr=2, projid32bit=1 = crc=1 finobt=1, sparse=1, rmapbt=0 = reflink=1 bigtime=1 inobtcount=1 data = bsize=4096 blocks=19531, imaxpct=25 = sunit=0 swidth=0 blks naming =version 2 bsize=4096 ascii-ci=0, ftype=1 log =log wewnętrzny bsize=4096 blocks=1368, version=2 = sectsz=512 sunit=0 blks, lazy-count=1 realtime =brak extsz=4096 blocks=0, rtextents=0
W przykładzie użyłem polecenia mkfs i za pomocą opcji -t podałem typ żądanego systemu plików. Równie dobrze możemy podać nazwę polecenia a następnie po kropce typ systemu plików (np. mkfs.ext4). Następnie podaje się urządzenie blokowe, które ma zostać sformatowane.
Tworzenie systemu plików dla woluminu VDO najlepiej jest przeprowadzić z użyciem opcji -E nodiscard dla EXT4 lub opcją -K dla XFS obie wykonują tę samą czynność i pozwalają zainstalować je szybciej na tego typu pamięciach masowych.
15.8.2. Montowanie oraz odłączanie systemu plików
Za pomocą polecenia mount możemy podłączyć systemy plików z poprzedniego podrozdziału do naszego systemu. Polecenie mount nie wymaga podania rodzaju systemu plików, potrafi ono samo to określić.
[user@rhel90 ~]$ sudo mount /dev/vdb3 /media/ [sudo] hasło użytkownika user: [user@rhel90 ~]$ sudo mount -t xfs /dev/mapper/rhel-root on / type xfs (rw,relatime,seclabel,attr2,inode64,logbufs=8,logbsize=32k,noquota) /dev/vda1 on /boot type xfs (rw,relatime,seclabel,attr2,inode64,logbufs=8,logbsize=32k,noquota) /dev/vdb3 on /media type xfs (rw,relatime,seclabel,attr2,inode64,logbufs=8,logbsize=32k,noquota)
Ostatni wiersz dotyczy montowania ze wcześniejszego polecenia.
Aby odmontować ten system plików należy wydać poniższe polecenie:
[user@rhel90 ~]$ sudo umount /media [user@rhel90 ~]$ sudo mount -t xfs /dev/mapper/rhel-root on / type xfs (rw,relatime,seclabel,attr2,inode64,logbufs=8,logbsize=32k,noquota) /dev/vda1 on /boot type xfs (rw,relatime,seclabel,attr2,inode64,logbufs=8,logbsize=32k,noquota)
Wiersz dotyczący katalogu /media nie wystąpił po odmontowaniu, tak wiec system plików został odłączony od systemu.
15.8.3. Montowanie automatyczne z użyciem pliku /etc/fstab
Tak jak już wcześniej wspomiałem, za pomocą pliku /etc/fstab możemy zdefiniować wpisy z systemami plików, które będą automatycznie montowane podczas uruchamiania systemu lub będzie możliwość ich szybszego montowania, za pomocą polecenia mount. Definiując nowy wpis musimy wypełnić, każdą z kolumn. Należy również dodać, że tworząc wpisy /etc/fstab, należy pisać bardzo uważnie, ponieważ jeden błąd może unieruchomić cały system.
Dodanie wpisów do /etc/fstab można dokonać na wiele sposobów. Ja na przykład przełączyłem się na superużytkownika i za pomocą echo dodawałem kolejne wpisy, co zobrazowałem na poniższym przykładzie.
[user@rhel90 ~]$ mkdir /{vfat,ext4,xfs}fs1 [user@rhel90 ~]$ lsblk -f /dev/vdb NAME FSTYPE FSVER LABEL UUID FSAVAIL FSUSE% MOUNTPOINTS vdb ├─vdb1 vfat FAT16 BA6B-6E4E ├─vdb2 ext4 1.0 d97751fb-dce0-4406-b03b-925dfa64a183 └─vdb3 xfs 37f34709-79da-4adb-aff4-8de1cfafe9c6 [root@rhel90 user]# echo "UUID=BA6B-6E4E /vfatfs1 vfat defaults 0 0" >> /etc/fstab [root@rhel90 user]# echo "UUID=d97751fb-dce0-4406-b03b-925dfa64a183 /ext4fs1 ext4 defaults 0 0" >> /etc/fstab [root@rhel90 user]# echo "UUID=37f34709-79da-4adb-aff4-8de1cfafe9c6 /xfsfs1 xfs defaults 0 0" >> /etc/fstab [user@rhel90 ~]$ grep -v -e '^#' -e '^$' /etc/fstab /dev/mapper/rhel-root / xfs defaults 0 0 UUID=fb4c6cf9-8041-42ce-9e75-82026a4a0164 /boot xfs defaults 0 0 /dev/mapper/rhel-swap none swap defaults 0 0 /dev/sr0 /mnt iso9660 ro 0 0 UUID=BA6B-6E4E /vfatfs1 vfat defaults 0 0 UUID=d97751fb-dce0-4406-b03b-925dfa64a183 /ext4fs1 ext4 defaults 0 0 UUID=37f34709-79da-4adb-aff4-8de1cfafe9c6 /xfsfs1 xfs defaults 0 0 [user@rhel90 ~]$ sudo mount -a [user@rhel90 ~]$ df -h System plików rozm. użyte dost. %uż. zamont. na ... /dev/vdb1 75M 0 75M 0% /vfatfs1 /dev/vdb2 67M 14K 62M 1% /ext4fs1 /dev/vdb3 71M 4,6M 67M 7% /xfsfs1
Na początku stworzyłem punkty montowania, trzy podkatalogi w katalogu głównym. Następnie odszukałem w systemie identyfikatory UUID, ponieważ są to zwykłe partycje musiałem ich użyć. Za pomocą przekierowania wyjścia polecenia echo zapisałem wpisy odpowiednie dla tych partycji, aby to potwierdzić użyłem polecenia mount wraz z opcją -a, żeby zamontować wszystkie wpisy w pliku. Polecenie oczywiście te zamontowane pomija, więc spokojnie każdą zmianę w tym pliku możemy potwierdzać za pomocą tego polecenia. Na koniec wyświetliłem sprawdzenie stanu zużycia systemów plików, aby lepiej zaprezentować fakt, iż systemy wcześniej zapisane do pliku /etc/fstab zostały poprawnie podłączone.
Wpis do pliku dotyczący LVM, różniłby się tylko tym, że
zamiast
UUID mogłaby być ścieżka do woluminu logicznego LVM.
Jeśli chodzi o systemy plików tworzone przez Stratis można
użyć UUID lub ścieżki urządzenia wyświetlanej na liście
systemów plików, jednak Stratis wymaga uruchomienia usługi
aby systemy plików były w ogóle widoczne, zatem przed opcją
defaults
należało by użyć opcji
x-systemd.requires=stratisd.service.
15.8.4. Rozszerzanie systemu plików na woluminie logicznym LVM
W systemie posiadam już zamontowane dwa woluminy logiczne z LVM. Chcę rozszerzyć ich wielkość o 100MB. Wszystkie czynności takiej jak związane z LVM zostały już wykonane poza samym rozszerzeniem woluminów. Polecenie lvextend jak i lvresize posiadają opcję -r, która pozwala na uruchomienie programu odpowiedzialnego za zmianę rozmiaru systemu plików. W przypadku EXT4 uruchamiany jest program resize2fs a w przypadku XFS xfs_growfs. Opcję -r możemy pominąć lub o niej zapomnieć, wówczas należy uruchomić te programy z poziomu wiersza polecenia. Poniżej znajdują się przykłady jak można rozszerzyć zamontowane już woluminy logiczne.
[user@rhel90 ~]$ sudo lvextend -L +100M -r /dev/vg-lvm/ext4vol Devices file /dev/vdb is excluded by filter: device is partitioned. Size of logical volume vg-lvm/ext4vol changed from 252,00 MiB (63 extents) to 352,00 MiB (88 extents). Logical volume vg-lvm/ext4vol successfully resized. resize2fs 1.46.5 (30-Dec-2021) System plików /dev/mapper/vg--lvm-ext4vol jest zamontowany pod /ext4fs2; wymagana zmiana rozmiaru w locie old_desc_blocks = 2, new_desc_blocks = 3 System plików na /dev/mapper/vg--lvm-ext4vol ma teraz 360448 (1k) bloków. [user@rhel90 ~]$ sudo lvextend -L +100M /dev/vg-lvm/xfsvol Size of logical volume vg-lvm/xfsvol changed from 252,00 MiB (63 extents) to 352,00 MiB (88 extents). Logical volume vg-lvm/xfsvol successfully resized. [user@rhel90 ~]$ sudo xfs_growfs /dev/vg-lvm/xfsvol meta-data=/dev/mapper/vg--lvm-xfsvol isize=512 agcount=4, agsize=16128 blks = sectsz=512 attr=2, projid32bit=1 = crc=1 finobt=1, sparse=1, rmapbt=0 = reflink=1 bigtime=1 inobtcount=1 data = bsize=4096 blocks=64512, imaxpct=25 = sunit=0 swidth=0 blks naming =version 2 bsize=4096 ascii-ci=0, ftype=1 log =log wewnętrzny bsize=4096 blocks=1368, version=2 = sectsz=512 sunit=0 blks, lazy-count=1 realtime =brak extsz=4096 blocks=0, rtextents=0 bloki danych zmienione z 64512 na 90112
15.9. Zarządzanie przestrzenią wymiany
Na wstępie tego rozdziału omówiliśmy sobie czym jest przestrzeń wymiany. Teraz przejdziemy do jej zarządzania. Poza użyciem specyficznego programu do formatowania partycji jako przestrzeni wymiany ten podrozdział nie będzie różnić się niczym od pozostałych. Nie ma różnicy czy stworzymy naszą przestrzeń wymiany na partycji czy woluminie logicznym. W systemie może być również wiecej niż jedna przestrzeń wymiany, są one wówczas priorytetyzowane.
15.9.1. Tworzenie przestrzeni wymiany
Do stworzenia przestrzeni wymiany wykorzystamy polecenie mkswap. Polecenie to może nadać etykietę partycji, poprzez użycie opcji -L. Do użycia mamy maksymalnie 16 znaków. Poniżej znajduje się przykład, w którym utworzyłem przestrzeń wymiany, zdefiniowałem także dla niej etykietę.
[user@rhel90 ~]$ sudo mkswap -L swapvol /dev/vg-lvm/swapvol Tworzenie obszaru wymiany w wersji 1, rozmiar = 52 MiB (bajtów: 54521856) LABEL=swapvol, UUID=3c99f75a-4559-4f6b-970b-f78cc4333e9b
15.9.2. Włączanie i wyłączanie swapu
Utworzony wcześniej swap jeszcze nie działa. Wymagane jest jego włączenie za pomocą polecenia swapon. To polecenie potrafi również wyświetlić wszystkie dostępne w systemie przestrzeni wymiany. Ręczne włączenie wymaga podania nazwy urządzenia. Poniżej znajduje się przykład:
[user@rhel90 ~]$ sudo swapon /dev/vg-lvm/swapvol [sudo] hasło użytkownika user: [user@rhel90 ~]$ sudo swapon NAME TYPE SIZE USED PRIO /dev/dm-1 partition 1,2G 7M -2 /dev/dm-7 partition 52M 0B -3
Po włączeniu przestrzeni wymiany uruchomiłem jeszcze raz polecenie swapon bez żadnych argumentów aby wyświetlić wszystkie swapy dostępne w systemie. W dystrybucjach Linuksa może być ich 32. Dezaktywacji swapu dokonujemy za pomocą polecenia swapoff podając jako argument nazwę urządzenia.
[user@rhel90 ~]$ sudo swapoff /dev/vg-lvm/swapvol [sudo] hasło użytkownika user: [user@rhel90 ~]$ sudo swapon NAME TYPE SIZE USED PRIO /dev/dm-1 partition 1,2G 6,8M -2
Po wyłączeniu swapu widzimy, że nie jest on już dostępny w systemie.
15.9.3. Automatyczne włączanie przetrzeni wymiany - /etc/fstab
Przestrzeń wymiany tak jak inne systemy plików może być włączana automatycznie podczas uruchamiania systemu operacyjnego. Poniżej znajduje się przykład, który obrazuje dodawanie przestrzeni wymiany do pliku /etc/fstab oraz jej automatyczne włączanie nie tylko poprzez ponowne uruchomienie systemu.
[root@rhel90 user]# echo "LABEL=swapvol none swap defaults 0 0" >> /etc/fstab [user@rhel90 ~]$ sudo swapon -a [user@rhel90 ~]$ swapon NAME TYPE SIZE USED PRIO /dev/dm-1 partition 1,2G 6,8M -2 /dev/dm-7 partition 52M 0B -3
Tym razem zamiast nazwy urządzenia użyłem etykiety. Polecenie swapon wraz z opcją -a, ma takie samo działanie dla przestrzeni wymiany jak mount -a dla zwykłych systemów plików.
15.9.4. Monitorowanie zużycia przestrzeni wymiany
Do kontrolowania z użycia przestrzeni wymiany możemy wykorzystać proste polecenie, które zwraca nam informacje o ilości wykorzystywanej w systemie pamięci operacyjnej. Do tego służy polecenie free. Pod czas korzystania z tego narzędzia najlepiej od razu przeskalować jednostki za pomocą polecenia -h.
[user@rhel90 ~]$ free -h total used free shared buff/cache available Mem: 1,2Gi 930Mi 104Mi 8,0Mi 236Mi 179Mi Swap: 1,3Gi 6,0Mi 1,2Gi
Druga linia zawiera informacje na temat przestrzeni wymiany. Prócz tego polecenia możemy wykorzystać dowolne polecenie monitorujące zasoby komputera, np. top.
Ćwiczenie 1: Tworzenie systemów plików oraz dodawanie wpisów do /etc/fstab
Jako użytkownik z możliwością podniesienia uprawnień, na maszynie oznaczonej jako server2. Na jednym z 250MB dysków utwórz tablicę partycji w schemacie MBR. Utwórz 3 partycje po 70MB na każdej z nich utwórz inny system plików. Utworz adekwatne dla nich punkty montowania. Zamontuj je ręcznie. Określ ich UUID a następnie dodaj wpisy montowania do pliku /etc/fstab. Ręcznie odłącz zamontowane wcześniej partycje, następnie zamontuj je automatycznie i potwierdź to za pomocą polecenia df -h.
Ćwiczenie 2: Wolumin VDO z XFS
Jako użytkownik z możliwością podniesienia uprawnień, na maszynie oznaczonej jako server2. Utwórz wolumin logiczny VDO o rozmiarze wirtualnym 50GB, sformatuj go pod XFS, dodaj do /etc/fstab, następnie zamontuj automatycznie potwierdź to przy użyciu polecenia df -h.
Ćwiczenie 3: Zarządzanie systemami plików z LVM
Jako użytkownik z możliwością podniesienia uprawnień, na maszynie oznaczonej jako server2. Utwórz dwa woluminy logiczne jeden o wielkości 100MB a drugi 120MB, utworz na nich systemy plików EXT4 na pierwszym, a drugim XFS. Zamontuj je w systemie. Dodaj drugi dysk do grupy, następnie rozszerz woluminy logiczne o 100MB przyczym użyj opcji -r podczas rozszerzenia woluminiu z XFS, a przy rozszerzaniu woluminu z EXT4 pomiń tę opcję i ręczenie rozszerz system plików. Zweryfikuj wykonane czynności.
Ćwiczenie 4: Montowanie automatyczne woluminu Stratis
Jako użytkownik z możliwością podniesienia uprawnień, na maszynie oznaczonej jako server2. Użyj jednego z 1GB dysków do stworzenia systemu plików Stratis. Dodaj wpis z systemem do pliku /etc/fstab. Uruchom system ponownie. Sprawdź czy system plików został zamontowany za pomocą polecenia df -h. Co mozemy zaobserować z wyników działania tego polecenia? Jaką pojemność ma zamontowany system plików Stratis?
Ćwiczenie 5: Przestrzeń wymiany
Jako użytkownik z możliwością podniesienia uprawnień, na maszynie oznaczonej jako server2. Na pozostałych z trzeciego ćwiczenia ekstentach, utwórz kolejny wolumin o nazwie swap. Stwórz z niego przestrzeń wymiany. Dodaj wpis tej przestrzeni do pliku /etc/fstab. Aktywują ją automatycznie, następnie wyświetl wszystkie dostępne przestrzenie wymiany w systemie oraz wyświetl łaczną pojemność swapu w systemie.
Podsumowanie
Tym rozdziałem zakończyliśmy naukę zarządzania pamięciami masowymi w RHEL. Poznaliśmy systemy plików oraz mechanizmy z nimi związane. Nauczyliśmy się instalować systemy plików na partycjach oraz woluminach logicznych. Dowiedzieliśmy się w jaki sposób montowane są automatycznie dostępne w systemie operacyjnym systemy plików oraz w jaki sposób poprawnie utworzyć wpis do pliku /etc/fstab. Na koniec poznaliśmy w jaki sposób zarządzać przestrzenią wymiany w RHEL. W następnym rozdziale zajmiemy się już podstawowymi pojęciami związanymi z siecią.
16. Podstawy sieci w RHEL 9
Potrzeba współdzielenia danych oraz zasobów między komputerami spowodowała, że zaczęto je łączyć w sieci. Na sieć komputerową składają się minimum dwa komputery, połączone ze sobą albo bezpośrednio albo za pomocą urządzenie pośredniczącego np. przełącznika. Aby komunikacja między nimi mogła być możliwa wbudowane w nie urządzenia sieciowe (karty/adaptery sieciowe) muszą zostać odpowiednio skonfigurowane z użyciem podstawowej wiedzy na temat sieci IP. Poznaną tutaj wiedzę na temat sieci IP, wykorzystamy do tworzenia oraz konfigurowania nowych połączeń sieciowych w systemach klasy enterprise.
16.1. Podstawowe pojęcia o sieciach komputerowych
Aby poprawnie skonfigurować interfejs sieciowy komputera musimy poznać podstawowe pojęcia związane z sieciami.
16.1.1. Adres IPv4
Adres protokołu internetowego w wersji 4, bo tak możemy rozszyfować nazwę tego podrozdziału jest podstawowym identyfikatorem służący to komunikacji w sieci. Każdy z komputerów podłączonych do sieci posiada ten adres przydzielony automatycznie z serwera DHCP lub przypisany ręcznie. Adres IPv4 występuje w postaci 4 oddzielonych kropką oktetów, każdy z oktetów może przyjąć wartości od 0 do 255. Adres IPv4 możemy sprawdzić za pomocą polecenia ip z podpoleceniem addr
[user@server10 ~]$ ip addr 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: enp1s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000 link/ether 52:54:00:55:b7:60 brd ff:ff:ff:ff:ff:ff inet 192.168.122.6/24 brd 192.168.122.255 scope global noprefixroute enp1s0 valid_lft forever preferred_lft forever inet6 fe80::5054:ff:fe55:b760/64 scope link noprefixroute valid_lft forever preferred_lft forever
Polecenie to wyświetla informacje na temat dostępnych w systemie
połączeń sieciowych (interfejsów). Jednym
z nich jest połączenie o nazwie enp1s0
posiadające adres 192.168.122.6. Drugie połączenie
sieciowe, to specjalny interfejs systemowy tzw.
pętla zwrotna, pozwala ona na komunikację z usługami
sieciowym w tym systemie. Adresem pętli zwrotnej jest zawsze
127.0.0.1.
Komputery podłączone do tej samej sieci posiadają identyczne, niektóre z częsci adresu IPv4. Część wspólna nazywana jest częścią sieciową, pozostała część (część hosta) jest ustatalna indywidualnie dla każdego hosta i tylko jemu przypisywana. Które części adresu są częścią hosta, a które są częscią sieci jest ustatalne w trakcie jej konfiguracji na podstawie klas adresowych. Klasy adresowe możemy podzielić na trzy klasy:
- Klasę A - W klasie A, część sieciowa obejmuje tylko jeden oktet przez co możemy utworzyć do 126 sieci po 16 777 214 hostów w każdej z nich. W klasie A pierwszy oktet przyjmuje wartości od 0 do 126, z wyłączeniem 10.
- Klasę B - W klasie B za część sieciową odpowiadają dwa oktety co daje większą ilość mniejszych sieci to i taki liczby potrafią zaskakiwać, ponieważ w tej klasie można utworzyć 16384 sieci po 65534 hosty. Klasa B w pierwszym oktecie stosuje wartości od 128 do 191.
- Klasę C - W klasie C za część sieciową odpowiadają aż trzy oktety, dzięki czemu możemy stworzyć dużą ilość małych sieci, a konkretnie 2 097 152 sieci po 254 hosty każda. Klasa C w pierwszym oktecie stosuje wartości od 192 do 223.
Poza tymi klasami w specyfikacji wyróżnia się takie klasy jak D oraz E, jednak mają one specjalne przeznaczenie.
Tak duże klasy adresów są dzielone na mniejsze części, aby łatwiej zarządzać takimi sieciami, zwiększyć ich wydajność oraz zapewnić oporność na na awarie czy odsepraować je od siebie. Po podziale każda z takich sieci posiada logicznie wytyczone granice. Te granice są wskazywane przez maskę podsieci, której zadaniem jest zaznaczenie części sieciowej adresu IPv4 oraz części przeznaczonej dla komputerów w sieci. Oktety maski podsieci mogą posiadać wartości takie jak 255, 0 oraz inne przy czym wartości większe od 0 nie mogą znajdować się przed oktetami zawierającymi 255 lub wartości inne niż 0. Z czego to wynika? Otóż z podstaw adresacji IPv4. Każdy adres składa się z 4 oktetów. Co to tak naprawdę oznacza? Każdy adres IPv4 możemy rozpisać za pomocą systemu binarnego (0 i 1), oktet o poprostu 8 bitów (bit - najmniejsza ilość informacji, przestawia pojedyńczy stan 0 lub 1), 8 zer lub jedynek. Na masce podsieci jedynki określają bity, które są częścią sieciową adresów, a zera tą część która pozostaje do adresowania hostów, dlatego też zera nie mogą występować między jedynkami. Poniżej znajduje się przykład. Mój serwer ma adres 192.168.122.7 oraz maskę podsieci: 255.255.255.0. Poniżej znajduje się zapis tych parametrów w postaci binarnej:
11000000.10101000.01111010.00000111 = 192.168.122.7 11111111.11111111.11111111.00000000 = 255.255.255.0 ==================================================== 11000000.10101000.01111010. | 00000111 192.168.122. 7 Część sieciowa adresu Część hosta
Maskę możemy zapisać w innej postaci niż dziesiętna (255.255.255.0). Jest to zapis w którym do określenia maski używa się ilości jedynek. Zatem maska z poprzedniego przykładu 255.255.255.0 wynosiła by 24. Kombinację adresu IPv4 hosta wraz z maską w takim zapisie oddzieloną ukośnikiem (/) nazywa się notacją CIDR i jest to obecnie najpopularnieszy sposób nadawania adresów IPv4 interfejsom sieciowym.
Maska podsieci może mieć maksymalną wartość 32 bitów, pozwalając na istnienie jednego adresu w sieci (najczęciej jest wskazanie na konkretny adres) lub minimalną wartość jaką jest 0, alokując tym samym wszystkie możliwe adresy, ok. 4,3 miliarda.
16.1.2. Adresy prywatne
Upowszechnienie się łącz szerokopasmowych dało możliwość budowania w sieci lokalnych, w których systemy są konfigurowane przez centralny serwer (router lub bramę). Tego typu sieci posługują się wenętrzną adresacją zawaną także prywatnymi klasami adresów. Tak jak w klasach publicznych, ogólno dostępne są trzy klasy:
- Klasa A: 10.0.0.0 - 10.255.255.255; maska 8 bitów (255.0.0.0) = 16 777 214 hostów.
- Klasa B: 172.16.0.0 - 172.31.255.255; maska 12 bitów (255.240.0.0) = 983010 hostów.
- Klasa C: 192.168.0.0 - 192.168.255.255; maska 16 bitów (255.255.0.0) = 65534 hostów.
Te klasy są ustalane w standardzie dotyczącym klas prywatnych, jednak administratorzy wolą używać mniejszych klas. Dlatego też klasa A pozostaje bez zmian, ale w klasie B używa się maski 16 bitowej, a w klasie C maski 24 bitowej.
16.1.3. Protokoły
Protokoły definiują standardy komunikacyjne, które umożliwiają wymianę informacji przez sieć. Protokoły działają na niższych warstwach niż usługi. Do protokołów możemy zaliczyć np. protokół IP, którego adresacji poświęciliśmy cały poprzedni podrozdział. W RHEL oraz w innych dystrybucjach w katalogu /etc w pliku protocols znajduje się zestawienie protokółów. Poniżej znajduje się fragment tego pliku.
[user@server10 ~]$ cat /etc/protocols ... ip 0 IP # internet protocol, pseudo protocol number hopopt 0 HOPOPT # hop-by-hop options for ipv6 icmp 1 ICMP # internet control message protocol igmp 2 IGMP # internet group management protocol ggp 3 GGP # gateway-gateway protocol ipv4 4 IPv4 # IPv4 encapsulation st 5 ST # ST datagram mode tcp 6 TCP # transmission control protocol ...
16.1.4. Protokoły TCP i UDP
Z pośród wcześniejszego zestawienia protokołów, za transmisję danych w sieciach opartych na protokole IP odpowiedzialne są dwa protokoły TCP oraz UDP.
Protokół TCP stosowany w przypadku usług, w których liczy się jakość danych. Ten protokół zestawia połączenie w swojej wartstwie między klient oraz serwerem. Wówczas następuje sekwencjonowana transmisja danych, strony potwierdzają otrzymanie pakietu danych przez to w przypadku zaginięcia pakietu jest on przesyłany ponownie. Większość usług w internecie opiera się o ten protokół, gdyż pozwala on na rzetelną wymianę informacji.
Innym również często wykorzysywanym protokołem jest UDP. Protokół ten nie zestawia połączenia i poprostu pusza swoje pakiety prawdopodbnie licząc na niezawodność protokołów warstwy niższej jak IP. Nie dokonują on retransmisji gdy pakiety zostaną zgubione. Jednak jest on znacznie szybszy niż TCP dlatego też jest on wykorzystywany do przesyłania danych w czasie rzeczywistym.
Protokoły TCP oraz UDP w wprowadzają pojecie portu czyli numeru połączenia, wykorzystywanego do komunikacji. Dane są przesyłane z portu prywatnego (portu klienta, port wysoki > 10000) do portu publicznego usługi. Do portów publicznych możemy zaliczyć: HTTP - 80/TCP, HTTPS - 443/TCP czy SSH - 22/TCP. Rodzaj transmisji został podany po ukośniku. Więcej portów publicznych znajduje się w pliku /etc/services, fragment zawartości tego pliku znajduje się poniżej:
[user@server10 ~]$ head -100 /etc/services ... ftp 21/tcp ftp 21/udp fsp fspd ssh 22/tcp # The Secure Shell (SSH) Protocol ssh 22/udp # The Secure Shell (SSH) Protocol telnet 23/tcp telnet 23/udp # 24 - private mail system lmtp 24/tcp # LMTP Mail Delivery lmtp 24/udp # LMTP Mail Delivery smtp 25/tcp mail smtp 25/udp mail time 37/tcp timserver ...
16.1.5. Protokół ICMP
Protokół ICMP jest protokołem diagnostycznym, a jego zadaniem jest sprawdzenie możliwości połaczenia z podanym komputerem. Narzędziem korzystającym z tego protokołu jest ping. Zadaniem tego narzędzia jest wysłanie do komputera pakietu i otrzymanie odpowiedzi. Na podstawie otrzymanych (lub nie) danych polecenie rejestruje każdą odpowiedź lub jej brak oraz pod koniec działania wyświetla statystkę.
[user@server10 ~]$ ping -c4 192.168.122.7 PING 192.168.122.7 (192.168.122.7) 56(84) bytes of data. 64 bytes from 192.168.122.7: icmp_seq=1 ttl=64 time=0.354 ms 64 bytes from 192.168.122.7: icmp_seq=2 ttl=64 time=0.344 ms 64 bytes from 192.168.122.7: icmp_seq=3 ttl=64 time=0.517 ms 64 bytes from 192.168.122.7: icmp_seq=4 ttl=64 time=0.573 ms --- 192.168.122.7 ping statistics --- 4 packets transmitted, 4 received, 0% packet loss, time 3086ms rtt min/avg/max/mdev = 0.344/0.447/0.573/0.100 ms
Przy dużej i w pełni działającej sieci odpowiedzi powinny nie przekraczać 2, 3 ms (milisekund). Czasy tutaj są poniżej 1 ms, ponieważ to sieć wirtualna w wewnątrz tego samego komputera.
16.1.6. Adres fizyczny
Każdy z interfejsów posiada swój adres fizyczny. Jest on wykorzystywany do transmisji danych w najniżej warstwie logicznej. Każdy z pakietów, które opuściły komputer źródłówy są opatrzone właśnie tym adresami. Aby poznać adres naszej karty sieciowej należy wydać poniższe polecenie:
[user@server10 ~]$ ip addr | grep 'ether' link/ether 52:54:00:55:b7:60 brd ff:ff:ff:ff:ff:ff
Adres mojej karty to: 52:54:00:55:b7:60
.
Protokół IP ściśle współpracuje z adresem fizycznym. Istnieje
nawet protokół ARP, który umożliwia zamianę adresów
IP na adresy fizyczne.
16.1.7. Adres IPv6
Ze względu na dość szybką ekspansję internetu, okazało sie że pula adresów IPv4 jest na wyczerpaniu. Czego się dziwić, jeśli mamy 8 miliardów ludzi na świecie, a tylko 4,3 miliarda adresów. Nie pomogła również adresacja prywatna. Zatem była potrzeba nowego rozwiązania. I w ten sposób narodził się Protokół internetowy w wersji 6. Jest on dostępny w RHEL od wersji 8. Zamiast 32-bitowego adresu wprowadza on 128-bitowy adres, który pozwoli zaadresować praktycznie nieosiągalną liczbę hostów (bo aż 340 i 36 zer). Adres ten składa się z 8 oddzielonych dwu kropkiem grupy, w której znajdują po cztery liczby heksadecymalne (0 - F).
Protokół IPv6, korzysta z protokołu NDP (ang. Neighbor Discover Protocol), do przeszukiwania sieci i odnajwydwania innych urządzeń sieciowych skonfigurowanych za pomocą tego protokołu. Rozszerza on również funkcjonalność IPv4 o diagnostykę problemów związanych z połączniem, powtarzalność adresów oraz routing. Za pomocą poniższego polecenia wyświetliłem adres IPv6 interfejsu na swoim komputerze.
[user@server10 ~]$ ip addr | grep 'inet6' inet6 fe80::5054:ff:fe55:b760/64 scope link noprefixroute
16.1.8. Nazwa hosta
Każdy system operacyjny ma swoją nazwę, aby ułatwić jego identyfikację w sieci. Nazwa hosta występuje w przypadku dystrybucji Linuksa w symbolu zachęty chociaż możemy ją poznać na kilka róznych sposób. Na przykład:
[user@server10 ~]$ hostname server10.example.com [user@server10 ~]$ hostnamectl --static server10.example.com [user@server10 ~]$ uname -n server10.example.com [user@server10 ~]$ nmcli general hostname server10.example.com [user@server10 ~]$ cat /etc/hostname server10.example.com
Natomiast najlepszym i najszybszym sposóbem aby zmienić taką nazwę jest zmiana jej w pliku użytym w ostatnim poleceniu przykładu: /etc/hostname. Po zmianie pliku musimy jeszcze zrestartować usługę systemd-hostnamed.service.
16.2. Urządzenia sieciowe i połączenia
Teraz kiedy mamy solidną porcę wiedzy teoretycznej możemy przejść do konfiguracji połączeń sieciowych w RHEL 9.
16.2.1. Nazewnictwo urządzeń sieciowych w systemie
Do pewnego czasu nazwy urządzeń sieciowych, tj. interfejsów sieciowych były łatwe do zapamiętania, przez co upraszczały zadania administracyjne z nimi związane. Wywodziły się one od takich słów jak Ethernet czy wireless lan i były numerowane od 0 kolejno w takiej samej kolejności w jakiej zostały odnalezione w momencie uruchomienia systemu. Jednak jak to bywa z takimi rozwiązaniami, w przypadku dużej ilość interfejsów po ponownym uruchomieniu systemu ich nazwy mogły być już zupełnie inne. Co prowadziło do problemów konfiguracji. Podobnie jest z dyskami.
Obecnie nazwy interfejsów są ustalane za pomocą zasad demona udevd, przez co wprowadza się do systemu spójne oraz przewidywalne nazwenictwo bez wcześniej wspomnianego problemu.
Teraz zamiast eth0 interfejs może widnieć po nazwą np. enp7s0 lub ens160.
16.2.2. Profile połączeń sieciowych
Do RHEL 9 każe połączenie sieciowe miało swój profil (plik konfiguracyjny) w katalogu /etc/sysconfig/network-scripts Obecnie zrezygnowano z tej metody na rzecz tworzenia plików key-file dla podsystemu sieciowego NetworkManager. Sens profili został w nowych plikach zachowany ponieważ koniec, końców chodzi o konfigurację sieciową interfejsu. Jako jedno z zalet plików key-file jest to iż są prostsze i łatwiejsze do utworzenia. Poniżej znajduje się pliki key-file głównego połączenia sieciowego na mojej maszynie.
[connection] id=enp1s0 uuid=eb849d6a-d642-32e9-9219-9496570c1d45 type=ethernet autoconnect-priority=-999 interface-name=enp1s0 timestamp=1658937868 [ethernet] [ipv4] address1=192.168.122.6/24,192.168.122.1 dns=192.168.122.1; method=manual [ipv6] addr-gen-mode=eui64 method=auto [proxy]
Posługiwanie się plikami key-file jest najlepszym rozwiązaniem jeśli definiujemy dodatkowy interfejs w systemie. Wówczas do dyspozycji mamy już gotowy plik i na jego podstawie możemy zbudować nasz plik. Poniżej zamieściłem plik, który utworzyłem na potrzeby drugiego połączenia na mojej maszynie. Ten plik zawiera minimalną ilość informacji potrzebną do prawidłowego połączenia sieciowego. To połączenie nie posiada definicji adresu bramy domyślniej (tam kierowane są pakiety jeśli ich adres, jest poza naszą siecią lokalną - adres routera lub bramy) oraz adresów serwerów DNS (serwery DNS zmieniają nazwy domenowe na adresy IP).
[connection] id=enp7s0 uuid=13e3cf57-9a36-4cb3-a4e0-c1b2411bf984 type=ethernet interface-name=enp7s0 [ethernet] [ipv4] address1=192.168.100.6/24 method=manual [ipv6] addr-gen-mode=eui64 method=auto [proxy]
Usunąłem z sekcji [connection]
takie
dyrektywy jak
autoconnect-priority=-999
, oraz
timestamp
. Z tego względu iż moje
połączenie jest w sieci wewnętrznej, usunąłem drugi adres po
przecinku w dyrektywie address1
oraz
dyrektywę dns
, z sekcji
[ipv4]
. Ten plik od pliku bazowego
różni się również wartością w dyrektywie
uuid
, wartość UUID możemy uzyskać za
pomocą polecenia uuidgen, podając
jako argument nazwę interfejsu. Tak stworzony plik należy
przenieść do katalogu /etc/NetworkManager/system-connections
a następnie załadować za pomocą polecenia
nmcli connection load
podając
ścieżkę do pliku jako argument. Po załadowaniu go, możemy aktywować
połączenie za pomocą polecenia
nmcli connection up filename
i w tym
poleceniu również należy podać ścieżkę pliku profilu.
Po aktywowaniu tego pliku w systemie pojawi się nowe połączenie:
[user@server10 ~]$ ip addr 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: enp1s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000 link/ether 52:54:00:55:b7:60 brd ff:ff:ff:ff:ff:ff inet 192.168.122.6/24 brd 192.168.122.255 scope global noprefixroute enp1s0 valid_lft forever preferred_lft forever inet6 fe80::5054:ff:fe55:b760/64 scope link noprefixroute valid_lft forever preferred_lft forever 3: enp7s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000 link/ether 52:54:00:ef:9f:e0 brd ff:ff:ff:ff:ff:ff inet 192.168.100.6/24 brd 192.168.100.255 scope global noprefixroute enp7s0 valid_lft forever preferred_lft forever inet6 fe80::5054:ff:feef:9fe0/64 scope link noprefixroute valid_lft forever preferred_lft forever
Odnośnie egzaminu:
Jak będziemy mogli zauważyć większość konfiguracji sieciowej obecnie
w RHEL kręci się wokół podsystemu NetworkManager.
Wystarczy, że będziemy znać jeden ze sposób na konfigurację połączenia
sieciowego w systemie.
16.2.3. Zarządzanie połączeniami sieciowym za pomocą podsystemu NetworkManager
Podsystem NetworkManager, to potężne narzędzie, które potrafi ułatwić zarządzanie połączeniami sieciowymi. Za pomocą polecenia nmtui, może zarządzać połączeniami za pomocą prostego interfejsu okien w trybie tekstowym (pakiety dialog, whiptail). Innym narzędziem jest polecenie nmcli, którego działanie opiera się na kategoriach objektów. W tym materiale skupimy się wyłącznie na połączeniach - connection oraz urządzeniach - device. Dostęp do czynności możliwych do wykonania otrzymamy gdy podamy po poleceniu nazwę kategorii obiektu i naciśniemy klawisz Tab. Na przykład:
[user@server10 ~]$ nmcli connection add delete edit help load monitor show clone down export import modify reload up
Jeśli wydamy polecenie nmcli connection
bez żadnej akcji wówczas polecenie zwróci nam listę dostępnych
w systemie połączeń.
[user@server10 ~]$ nmcli connection NAME UUID TYPE DEVICE enp1s0 eb849d6a-d642-32e9-9219-9496570c1d45 ethernet enp1s0 enp7s0 13e3cf57-9a36-4cb3-a4e0-c1b2411bf984 ethernet enp7s0
Poniżej znajduje się lista czynności związana z połączeniami:
- show - Wyświetla listę dostępnych połaczeń.
- up / down - Aktywuje/dezaktywuje połączenie.
- add - Dodaje połączenie.
- edit - Zmienia obecnie istniejące połączenie lub dodaje nowe.
- modify - Modyfikuje jedno z parametrów połączenia.
- delete - Usuwa połączenie.
- reload - Nakazuje NetworkManager aby ponownie załadował wszystkie profile połączeń.
- load - Nakazuje NetworkManager aby załadował profil połączenia.
Lista czynności związana z urządzeniami.
- status - Pokazuje status urządzenia.
- show - Wyświetla informacje na temat wszystkich lub określonych interfejsów sieciowych.
Nazwy kategorii obiektów oraz niektórych czynności możemy zapisać za pomocą jedno literowych skrótów. Na przykład chcąc wyświetlić dostępne w systemie połączenia możemy wydać następujące polecenie:
[user@server10 ~]$ sudo nmcli c s [sudo] hasło użytkownika user: NAME UUID TYPE DEVICE enp1s0 eb849d6a-d642-32e9-9219-9496570c1d45 ethernet enp1s0 enp7s0 13e3cf57-9a36-4cb3-a4e0-c1b2411bf984 ethernet enp7s0
W powyższym przykładzie użyłem skrótu
c
od kategorii connection
oraz skrótu s
od czynności
show. Więcej skrótów znajdziemy na stronie podręcznika.
16.2.4. Tworzenie nowych połączeń sieciowych za pomocą nmcli
Jak moglismy wynioskować na podstawie czynność z poprzedniego podrozdziału, możemy wykorzystać polecenie nmcli do tworzenia nowych połączeń. Dodawanie połączenia rozpoczniemy od sprawdzenia dostępnych w systemie interfejsów sieciowych.
[user@server10 ~]$ sudo nmcli d s [sudo] hasło użytkownika user: DEVICE TYPE STATE CONNECTION enp1s0 ethernet połączono enp1s0 enp7s0 ethernet połączono enp7s0 enp8s0 ethernet rozłączono -- lo loopback niezarządzane --
Jeden z interfejsów znajduje się w stanie
rozłączono
. Ten interfejs posłuży nam
do stworzenia nowego połączenia. Za pomocą czynności add
tworzmy nowe połączenie sieciowe.
[user@server10 ~]$ sudo nmcli c add type Ethernet ifname enp8s0 con-name enp8s0 ip4 192.168.100.8/24 gw4 192.168.100.1 [sudo] hasło użytkownika user: Pomyślnie dodano połączenie „enp8s0” (ff0d4164-b179-4d03-804d-ff08f8f4da31).
Na powyższym przykładzie dodałem nowe połączenie
(c add
) typu Ethernet
(type Ethernet
), użyłem do tego
interfejsu enp8s0
(ifname enp8s0
). Nadałem nazwę
połączeniu od nazwy interfejsu - enp8s0
(con-name enp8s0
), na końcu ustawiłem
adres IPv4 z 24 bitową maską
(ip4 192.168.100.8/24
) oraz adres
bramy domyślnej (gw4 192.168.100.1
).
Tak utworzone połączenie nie wymaga już żadnej czynności, od razu jest ono gotowe do pracy, o czym może świadczyć lista połączeń na poniższym przykładzie.
Połączenia zarządzane za pomocą NetworkManager możemy wyłączać oraz włączać.
[user@server10 ~]$ sudo nmcli c s [sudo] hasło użytkownika user: NAME UUID TYPE DEVICE enp1s0 eb849d6a-d642-32e9-9219-9496570c1d45 ethernet enp1s0 enp7s0 13e3cf57-9a36-4cb3-a4e0-c1b2411bf984 ethernet enp7s0 enp8s0 ff0d4164-b179-4d03-804d-ff08f8f4da31 ethernet enp8s0
Połączenia zarządzane za pomocą NetworkManager możemy wyłączać oraz włączać.
[user@server10 ~]$ sudo nmcli c down enp8s0 Pomyślnie dezaktywowano połączenie „enp8s0” (ścieżka aktywacji D-Bus: /org/freedesktop/NetworkManager/ActiveConnection/3) [user@server10 ~]$ sudo nmcli c s NAME UUID TYPE DEVICE enp1s0 eb849d6a-d642-32e9-9219-9496570c1d45 ethernet enp1s0 enp7s0 13e3cf57-9a36-4cb3-a4e0-c1b2411bf984 ethernet enp7s0 enp8s0 ff0d4164-b179-4d03-804d-ff08f8f4da31 ethernet -- [user@server10 ~]$ sudo nmcli c up enp8s0 Pomyślnie aktywowano połączenie (ścieżka aktywacji D-Bus: /org/freedesktop/NetworkManager/ActiveConnection/4) [user@server10 ~]$ sudo nmcli c s NAME UUID TYPE DEVICE enp1s0 eb849d6a-d642-32e9-9219-9496570c1d45 ethernet enp1s0 enp7s0 13e3cf57-9a36-4cb3-a4e0-c1b2411bf984 ethernet enp7s0 enp8s0 ff0d4164-b179-4d03-804d-ff08f8f4da31 ethernet enp8s0
16.2.5. Plik /etc/hosts
Za pomocą pliku /etc/hosts możemy zbudować wewnątrz systemu mapowanie nazw domenowych na adresy IP, dzięki czemu będziemy mogli posługiwać się prostymi nazwami zamiast adresami IP. Każdy z wpisów w pliku składa się z trzech kolumn: adresu IP, nazwy domenowej oraz aliasu (krótkiej dodatkowej nazwy, której możemy używać zamiast nazwy domenowej, jeśli ta okaże się dość długa). Najczęściej w aliasie zapisywana jest nazwa hosta bez sufiksu domenowego. Na poniższym przykładzie znajduje się zawartość pliku /etc/hosts z mojego serwera.
[user@server10 ~]$ cat /etc/hosts 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 192.168.122.6 server10.example.com server10 192.168.122.7 server20.example.com server20 192.168.100.6 server10s7.example.com server10s7 192.168.100.7 server20s7.example.com server20s7
Pierwsze dwa wpisy dotyczą tego aby odwołanie się do
localhost
zwracało adres pętli
zwrotnej. Wpisy poniżej to mapowania adresów na nazwy maszyn
wykorzystywanych do ćwiczeń w tym materiale. Zwróćmy uwagę na to, iż
w pierwszych wierszach zdefiniowano więcej niż jeden alias.
16.2.6. Testowanie łączności
A przetestować możliwość połączenia między klietem a serwera lub między serwerami możemy skorzystać z jednego z narzędzi potokołu ICMP, a mianowicie narzędzia ping.
[user@server10 ~]$ ping -c4 server20s7.example.com PING server20s7.example.com (192.168.100.7) 56(84) bytes of data. 64 bytes from server20s7.example.com (192.168.100.7): icmp_seq=1 ttl=64 time=0.497 ms 64 bytes from server20s7.example.com (192.168.100.7): icmp_seq=2 ttl=64 time=0.335 ms 64 bytes from server20s7.example.com (192.168.100.7): icmp_seq=3 ttl=64 time=0.483 ms 64 bytes from server20s7.example.com (192.168.100.7): icmp_seq=4 ttl=64 time=0.302 ms --- server20s7.example.com ping statistics --- 4 packets transmitted, 4 received, 0% packet loss, time 3096ms rtt min/avg/max/mdev = 0.302/0.404/0.497/0.086 ms
Za pomocą poniższego polecenia wysłałem cztery pakiety diagnostyczne
(-c4
) przy użyciu sieci wewnętrznej
do drugiej maszyny w laboratorium.
Ćwiczenie 1: Zmiana nazwy hosta
Jako użytkownik z możliwością podniesienia uprawnień, na maszynie oznaczonej server1 oraz server2 zmień nazwę hosta z server1 na server10 oraz z server2 na Przy użyciu wykorzystywanego przez ciebie sposóbu wirtualizacji, stwórz sieć wewnętrzną. Następnie dodaj do każdej z maszyn dodatkowy interfejs sieciowy. Jak użytkownik z możliwością podniesienia uprawnień za pomocą dowolnej metody dodaj i skonfiguruj połączenia sieciowe na obu maszynach. Następnie dodaj wpisy wskazujące na maszyny do pliku /etc/hosts na każdej znich. Wykonanie tych czynności potwierdź sprawdzeniem połączenia.
Podsumowanie
W tym rozdziale zapoznaliśmy się z fundamentalnymi pojęciami związanymi z siecią. Poznalimśmy adresy IPv4, klasy adresów, adresy IPv6 oraz kilka protokołów. Dowiedzieliśmy się jak zarządzać połączeniami sieciowym w RHEL 9. Poznaliśmy prosty system, który umożliwi nam pisanie nazw hostów zamiast adresów IP oraz sposób na testowanie łączności. W następnym rozdziale zajmiemy się sieciowym systemem plików.
17. Network File System
Niektóre z mechanizmów współdzielenia dostępnych na Red Hat Enterprise Linux pozwalają na korzystanie z udostępnionych plików, tak jakby były by one lokalnie dostępne. Jednym z takich mechanizmów jest NFS, jego obsługa na docelowym systemie sprowadza się do wydania pojedynczego polecenia mount, a z dodatkowym demonem AutoFS tak na prawdę wystarczy próba dostępu do katalogu w którym powinny znajdować się dane aby były one dostępne na naszym komputerze.
NFS czyli (ang. Network File System) sieciowy system plików jest usługą sieciową pozwalającą na współdzielenie zasobów plikowych. NFS działa w architekturze klient-serwer. Co oznacza, że jeden z komputerów udostępnia pliki, na których drugi komputer po podłączeniu jest w stanie pracować. NFS udostępnia foldery, a każdy taki folder nazwany jest udziałem. Natomiast sam proces udostępniania folderu (udziału) nazywany jest eksportem. Przyczym eksport może być dokonany w kierunku okreslonego/określonych klienta/klientów. Klient chcąc skorzystać z udziału NFS dokonuje jego montowania tak jakby podłączał dodatkowy system plików do swojego systemu, podając oczywiście odpowiednie parametry.
Za stosowaniem NFS płynie wiele korzyści o takich jak wieloplatformowość, wieloużytkowość, redukcja kosztów administracyjnych oraz związanych z zakupem kolejnych dysków. Po zastosowaniu mechanizmów AutoFS będziemy w stanie zapewnić użytkownikom zdalne katalogi domowe.
Dostępnych jest wiele wersji NFS. W RHEL od wersji 8 domyślną wersją NFS jest wersja 4.2, która daje możliwość wykorzystania wyłącznie protokołu TCP zapisu asynchronicznego oraz obsługuje pliki powyżej 2GB. Po za tym pozwala ona na połączenia przez firewall oraz internet. Wersja ta usprawnia kilka zabezpieczeń, wspiera szyfrowanie transmisji oraz możliwość użycia ACL.
17.1. Konfiguracja serwera oraz klienta NFS
Na początku zadań praktycznych skonfigurujemy sobie prosty udział, aby mniej więcej wiedzieć jak skonfigurować serwer NFS.
17.1.1. Konfiguracja serwera NFS
Konfigurację zaczynamy od serwera i tam na początku instalujemy niezbędne oprogramowanie.
[user@server20 ~]$ sudo dnf install nfs-utils [sudo] hasło użytkownika user: Updating Subscription Management repositories. Unable to read consumer identity This system is not registered with an entitlement server. You can use subscription-manager to register. Ostatnio sprawdzono ważność metadanych: 1:05:53 temu w dniu pią, 29 lip 2022, 15:59:59. Pakiet nfs-utils-1:2.5.4-10.el9.x86_64 jest już zainstalowany. Rozwiązano zależności. Nie ma nic do zrobienia. Ukończono.
Następnie tworzymy katalog który będzie udziałem. Nadajemy mu odpowiednie uprawnienia, aby każdy klient mógł zapisywać w nim swoje pliki.
[user@server20 ~]$ sudo mkdir /nfstest [sudo] hasło użytkownika user: [user@server20 ~]$ sudo chmod 777 /nfstest
Następnie w pliku /etc/exports, definiuje eksport udziału do klienta. Eksport pozwala również na zdefiniowanie dodatkowych opcji dotyczących udziału, w naszym przypadku będzie przypisanie klientowi możliwości zapisu oraz odczytu.
/nfstest server10(rw)
Po zdefiniowaniu eksportu możemy przejść do uruchomienia demona NFS. Następnie otworzymy port na zaporze sieciowej pozwalający na swobodną komunikację klienta z serwerem.
[user@server20 ~]$ sudo systemctl enable --now nfs-server.service Created symlink /etc/systemd/system/multi-user.target.wants/nfs-server.service → /usr/lib/systemd/system/nfs-server.service. [user@server20 ~]$ sudo firewall-cmd --permanent --add-service nfs success [user@server20 ~]$ sudo firewall-cmd --reload success
Teraz wystarczy tylko zmusić demona NFS, aby dokonał eksportu. A możemy to zrobić za pomocą poniższego polecenia.
[user@server20 ~]$ sudo exportfs -av exporting server10.example.com:/nfstest
Opcja -a
nakazuje eksport wszystkich
udziałów zapisanych w pliku /etc/exports, natomiast opcją
-v
włącza bardziej szczegółowe
wyświetlanie komunikatów diagnostycznych. Bez tej opcji polecenie nie
zwróci nic. Konfigurację serwera możemy uznać za zakończoną. Teraz
przejdziemy do konfiguracji klienta.
17.1.2. Konfiguracja klienta NFS
Konfigurację klienta tak jak serwera musimy rozpocząć od zainstalowania niezbędnego oprogramowania, ponieważ obsługa NFS nie jest natywnie wbudowana.
[user@server10 ~]$ sudo dnf install nfs-utils Updating Subscription Management repositories. Unable to read consumer identity This system is not registered with an entitlement server. You can use subscription-manager to register. Ostatnio sprawdzono ważność metadanych: 0:24:05 temu w dniu pią, 29 lip 2022, 17:16:50. Pakiet nfs-utils-1:2.5.4-10.el9.x86_64 jest już zainstalowany. Rozwiązano zależności. Nie ma nic do zrobienia. Ukończono.
Podłączanie się do serwera NFS wygląda jak zwykłe montowanie systemu plików w systemie.
[user@server10 ~]$ sudo mount server20:/nfstest /media
Nie musimy podawać nawet typu systemu plików. Aby nie musieć podłączać się za każdym razem możemy dopisać poniższy wiersz do pliku /etc/fstab.
server20:/nfstest /local nfs _netdev 0 0
Na powyższym przykładzie użyłem opcji
_netdev
, ponieważ do realizacji tego
montowania potrzebna jest działająca na systemie sieć.
17.2. Konfiguracja udziału NFS za pomocą AutoFS
Dla konfiguracji klienta jest o wiele lepsze rozwiązanie niż ręczne montowanie NFS lub wpis w /etc/fstab. W RHEL jest dostępny demon, który pozwala na zamontowanie udziału NFS w momecie gdy jest on potrzebny. Na przykład gdy chcemy wyświetlić zawartość katalogu, w którym powinny znajdować się udostępnione przez niego pliki. Tym zajmuje się właśnie AutoFS. Ten demon, nie tylko montuje na żądanie ale także odłącza go gdy nie ma prób uzyskania dostępu do niego przez okres 5 minut. Główny plik konfiguracyjny znajduje się w katalogu /etc pod nazwą autofs.conf. Poniżej znajduje się jego zawartość:
[ autofs ] timeout = 300 browse_mode = no mount_nfs_default_protocol = 4 [ amd ] dismount_interval = 300
W tym pliku są ustawiane globalne opcje takie jak czas oczekiwania
na udział (timeout=300
) czy czas po
którym udział zostanie odłączony
(dismount_interval=300
). Jednak ten
plik nie służy do definicji automatycznego montowania.
Wszelkiego rozdzaju montowanie bo nie tylko udziałów definiowane jest w pliku /etc/auto.master. Poniżej znajduje się jego zawartość bez komentarzy oraz pustych linii.
[user@server10 ~]$ grep -v -e '^#' -e '^$' /etc/auto.master /misc /etc/auto.misc /net -hosts +dir:/etc/auto.master.d +auto.master
Montowania za pomocą AutoFS nazwane jest mapowaniem. Mapowania możemy dokonać na trzy sposoby: główny, bezpośredni oraz pośredni. Przyczym główny sposób mapowania służy jedynie do określenia czy mapowanie będzie bezpośrednie lub pośrednie. Samych mapowań dokonuje się w plikach użytkowników składowanych w katalogu /etc/auto.master.d. W jednym z takich plików może znajdować się wiele punktów montowania. W pliku /etc/auto.master najczęściej definiuje się zbiorczy punkt montowania oraz rodzaj mapowania. Natomiast konkretne udziały z wyszczególnionymi punktami montowania zapisuje się właśnie w plikach użytkowników. Jedno z mapowań jest już zapisane w pierwszej linii powyższego przykładu.
17.2.1. Mapowanie bezpośrednie
W przypadku mapowania bezpośredniego montowana jest dowolna ilość niepowiązanych ze sobą punktów montowania. Przyczym o to kilka punktów o których trzeba wiedzieć używając tego rodzaju mapowania.
- Każdy udział montowany bezpośrednio jest widoczny dla użytkowników.
- Montowanie lokalne oraz bezpośrednio montowane udziały mogą istnieć w tym samym katalogu nadrzędnym.
- Uzyskanie dostępu do katalogu zawierającego wiele montowanych bezpośrednio udziałów podłączy do systemu je wszystkie.
Każdy udział montowany bezpośrenio będzie mieć osobny wpis w wyniku działania polecenia mount wydanego bez argumentów. Na poniższych przykładach pokazałem jak możemym wykorzystać AutoFS do bezpośredniego montowania udziału NFS z poprzedniego podrozdziału.
W pliku /etc/auto.master zapisuje poniższą linię:
/- /etc/auto.master.d/auto.direct
Oznacza ona mapowanie bezpośrednie. /-
onznacza, że punkty montowania w pliku mapowania użytkownika
/etc/auto.master.d/auto.direct
będą
przestawiowe w postaci ścieżek bezwzględnych. W pliku mapowania
zapisujemy poniższą linię.
/nfstest server20:/nfstest
Po włączeniu usługi za pomocą polecenia
sudo systemctl enable --now autofs.service
wystarczy, że wyświetlimy zawartość głównego katalogu i zauważym nowy
folder /nfstest z zamontowanym udziałem.
[user@server10 ~]$ ls -l / razem 26 dr-xr-xr-x. 2 root root 6 2021-08-10 afs drwxr-xr-x. 2 root root 6 07-29 13:11 autodir lrwxrwxrwx. 1 root root 7 2021-08-10 bin -> usr/bin dr-xr-xr-x. 5 root root 4096 07-16 21:23 boot drwxr-xr-x. 21 root root 3280 07-29 12:36 dev drwxr-xr-x. 108 root root 8192 07-29 21:46 etc drwxr-xr-x. 3 root root 18 07-16 21:25 home lrwxrwxrwx. 1 root root 7 2021-08-10 lib -> usr/lib lrwxrwxrwx. 1 root root 9 2021-08-10 lib64 -> usr/lib64 drwxr-xr-x. 2 root root 6 07-29 12:39 local drwxr-xr-x. 2 root root 6 2021-08-10 media drwxr-xr-x. 2 root root 0 07-29 21:46 misc dr-xr-xr-x. 1 root root 2048 04-19 22:42 mnt drwxr-xr-x. 2 root root 0 07-29 21:46 net drwxr-xr-x. 2 root root 6 07-29 15:14 nfshome drwxrwxrwx. 2 root root 6 07-29 17:17 nfstest drwxr-xr-x. 2 root root 6 2021-08-10 opt dr-xr-xr-x. 199 root root 0 07-29 12:36 proc dr-xr-x---. 2 root root 167 07-29 21:46 root drwxr-xr-x. 37 root root 1220 07-29 21:46 run lrwxrwxrwx. 1 root root 8 2021-08-10 sbin -> usr/sbin drwxrwxrwx. 2 root root 6 07-29 15:34 sharenfs drwxr-xr-x. 2 root root 6 2021-08-10 srv dr-xr-xr-x. 13 root root 0 07-29 12:36 sys drwxrwxrwt. 9 root root 4096 07-29 21:46 tmp drwxr-xr-x. 12 root root 144 07-16 21:11 usr drwxr-xr-x. 20 root root 4096 07-16 21:29 var
Poniżej zamieszczam wynik działania polecenia mount bez argumentów:
[user@server10 ~]$ mount ... /etc/auto.master.d/auto.direct on /nfstest type autofs (rw,relatime,fd=17,pgrp=1313,timeout=300, minproto=5,maxproto=5,direct,pipe_ino=26905) server20:/nfstest on /nfstest type nfs4 (rw,relatime,vers=4.2,rsize=262144,wsize=262144, namlen=255,hard,proto=tcp,timeo=600,retrans=2,sec=sys,clientaddr=192.168.122.6,local_lock=none, addr=192.168.122.7)
17.2.2. Mapowanie pośrednie
Mapowanie pośrednie jest wykorzystywane gdy chcemy zamontować wszystkie udziały w jednym wspólnym katalogu nadrzędnym. Oto kilka punktów jakie trzeba znać podczas mapowania pośredniego.
- Udziały zamontowane pośrednio są widoczne w momencie uzyskania do nich dostępu.
- Montowania lokalne oraz montowania pośrednie nie mogą istnieć w tym samym katalogu nadrzędnym.
- Każde montowanie pośrednie generuje jeden wpis w pliku /etc/mtab - systemowa tablica montowania (stąd informacje pobiera polecenie mount wydane bez żadnego argumentu).
- Próba uzyskania dostępu katalogu zawierającego punkty montowania pośredniego pokaże tylko udziały które zostały już zamontowane.
Poniżej przedstawiam w jaki sposób można zamontować udział NFS z poprzedniego podrozdziału za pomocą mapowania pośredniego AutoFS.
Na początęk wyświetlimy zawartość głównego pliku mapowania czyli /etc/auto.master
[user@server10 ~]$ grep -v -e '^#' -e '^$' /etc/auto.master /misc /etc/auto.misc /net -hosts +dir:/etc/auto.master.d +auto.master
W pierszej linii znajduje się definicja katalogu nadrzędnego
przygotowana przez AutoFS. W tej linii znajduje się także
ścieżka do pliku, w którym należy zapisać definicje udziałów do
mapowania pośredniego. Zapisujemy więc poniższą linię do pliku
/etc/auto.misc
.
nfstest server20:/nfstest
Po zapisaniu zmian w pliku restartujemy usługę. Teraz możemy spróbować uzyskać dostęp do udziału. Udział będzie dostępny jak podkatalog katalogu /misc
[user@server10 ~]$ sudo systemctl restart autofs.service [user@server10 ~]$ ls -l /misc/nfstest razem 0
Poniżej znajdują się wpisy z systemowego rejestru montowania:
/etc/auto.misc on /misc type autofs (rw,relatime,fd=5,pgrp=1042,timeout=300,minproto=5,maxproto=5, indirect,pipe_ino=24514) server20:/nfstest on /misc/nfstest type nfs4 (rw,relatime,vers=4.2,rsize=262144,wsize=262144, namlen=255,hard,proto=tcp,timeo=600,retrans=2,sec=sys,clientaddr=192.168.122.6,local_lock=none, addr=192.168.122.7)
Zwróćmy uwagę na to, iż występuje tylko jeden wpisy dotyczący katalogu /misc typu autofs. Gdzie w przypadku montowania bezpośredniego, każdy punkt montowania posiadał własny wpis typu autofs.
Jeśli należałoby wybrać między mapowaniem bezpośrednim oraz pośrednim. To tak naprawdę, nie ma lepszych czy gorszych. Każde z rodzajów mapowań ma swoje cechy kluczowe, które sobie omówiliśmy w listach przed każdym z przykładów. Na podstawie tych cech oraz potrzeb jakie ma spełniać udział należy wybrać odpowiednią dla siebie metodę.
17.2.3. Automatyczne montowanie zdalnych katalogów domowych
Przy użyciu AutoFS oraz montowania pośredniego możemy zamontować katalog domowy użytkownika z innego serwera o ile są one udostępnione za pomocą NFS. Aby to zrealizować potrzebne są dwa czynniki:
- Katalog /home na serwerze powinien zostać wyeksportowany.
- Udwzorowanie użytkowników na obu systemach powinno być takie same, tj. najlepiej aby użytkownicy mieli te same UID-y aby uniknąć problemów z prawem własności plików złożonych katalogch domowych.
Aby przetestować AutoFS w praktyce wykonamy kilka czynności, aby odzworowany użytkownik z jednego serwera na drugim serwerze miał dostęp do swoich danych.
Na początku na serwerze, który udostępnia katalogi domowe tworzymy użytkownika. Ja utworzyłem użytkownika user40 z UID wynoszącym 4040 oraz nadałem mu hasło.
[user@server20 ~]$ sudo useradd -u 4040 user40 [sudo] hasło użytkownika user: [user@server20 ~]$ sudo passwd user40 Zmienianie hasła użytkownika user40. Nowe hasło: BŁĘDNE HASŁO: Hasło jest krótsze niż 8 znaków Proszę ponownie wpisać nowe hasło:
Następnie dokonujemy eksportu katalogu /home oraz wymuszamy zmianę udziałów NFS.
[user@server20 ~]$ cat /etc/exports /home server10(rw) [user@server20 ~]$ sudo exportfs -avr exporting server10.example.com:/home
Tak naprawdę na tym konfiguracja serwera kończy się. Przejdziemy teraz do konfiguracji klienta. W pliku /etc/auto.master utworzymy nową deklaracje katalogu nadrzędnego dla punktów montowania pośredniego.
[user@server10 ~]$ grep -v -e '^#' -e '^$' /etc/auto.master /misc /etc/auto.misc /nfshome /etc/auto.master.d/auto.home /net -hosts +dir:/etc/auto.master.d +auto.master
W drugiej linii znajduje się katalog nadrzędny, w którym będą przechowywane katalogi domowe. Musimy go utworzyć.
[user@server10 ~]$ sudo mkdir /nfshome
Następnie w pliku w którym powinny znajować się definicję punktów montowania zapisujemy poniższą linię:
* -rw server20:/home/&
W tym zapisie gwiazdka odnosi się dowolnej nazwy punktu montowania, ponieważ użytkowników może być bardzo dużo i nie sensu ich tu wszystkich wypisywać. Ampersand (&) może być odwołaniem do wielu serwerów lub wielu udziałów NFS. W tym przypadku został użyty do wskazania wielu katalogów w udziale. Po zapisaniu zmian w pliku należy zrestartować usługę.
[user@server10 ~]$ sudo systemctl restart autofs
Teraz wystarczy odwzrować użytkownika i się na niego przełączyć.
[user@server10 ~]$ sudo useradd -u 4040 -b /nfshome -M user40 [user@server10 ~]$ su - user40 Hasło: [user40@server10 ~]$
Podczas odwzorowywania użytkownika nadałem mu UID 4040, taki
sam jak na serwerze (-u 4040
),
wskazałem mu inny niż /home katalog bazowy dla katalogów
domowych (-b /nfshome
) w tym przypadku
jest katalog nadrzędny dla punktów montowania pośredniego
AutoFS. Użyłem również opcji
-M
, aby podczas tworzenia nowego
użytkownika nie został utworzony katalog domowy. Po utworzeniu
użytkownika przełączyłem się na niego. Poniżej znajdują się wpisy
z systemowego rejestru montowania, świadczące o tym iż katalog
domowy użytkownika user40
jest
katalogiem zdalnym podłączonym z pomocą NFS.
[user40@server10 ~]$ pwd /nfshome/user40 [user40@server10 ~]$ mount ... /etc/auto.master.d/auto.home on /nfshome type autofs (rw,relatime,fd=11,pgrp=1756,timeout=300, minproto=5,maxproto=5,indirect,pipe_ino=28415) server20:/home/user40 on /nfshome/user40 type nfs4 (rw,relatime,vers=4.2,rsize=262144,wsize=262144 ,namlen=255,hard,proto=tcp,timeo=600,retrans=2,sec=sys,clientaddr=192.168.122.6,local_lock=none, addr=192.168.122.7)
W ten sposób mogę utrzymać jeden katalog domowy na zdalnym serwerze i korzystać z niego na wielu komputerach.
Odnośnie egzaminu:
Jednym z zdań egzaminacyjnych może być automatyczne montowanie zdalnych
katalogów domowych z wykorzystaniem NFS oraz AutoFS.
Ćwiczenie 1: Tworzenie udziału NFS oraz mapowanie bezpośrednie
Jako użytkownik z możliwością podniesienia uprawnień na maszynie oznaczonej jako server10 utwórz udział NFS z katalogu /sharenfs i udostępnij go. Na maszynie server20 zainstaluj usługę AutoFS, następnie skonfiguruj automatyczne montowanie wcześniej utworzonego udziału w sposób bezpośredni. Spróbuj uzyskać dostęp do udziału, aby go zamontować. Potwierdź to za pomocą polecenia df -h.
Ćwiczenie 2: Pośrednie mapowanie udziału NFS
Wykorzystując udział z poprzedniego ćwiczenia zmień konfigurację AutoFS aby udział montowany był w sposób pośredni w katalogu nadrzędnym /autoindir. Spróbuj uzyskać dostęp do udostępnionego w ten sposób udziału. Potwierdź to za pomocą polecenia df -h
Podsumowanie
W tym rodziale poznaliśmy pierwszą usługę sieciową, która służy do udostępniania plików a jest nią NFS. Nauczyliśmy się konfigurować udziały na serwerze oraz montować je na systemach klienckich. Poznaliśmy usługę AutoFS, która pozwala na za montowanie udziału NFS, kiedy będzie on potrzebny. Poznaliśmy też jej konfiguracje w kilku ciekawych przypadkach. Następny rozdział będzie poświęcony synchronizacji czasu systemowego oraz rozwiązywaniu nazw domenowych.
18. Synchronizacja czasu oraz rozwiązywanie nazw w RHEL 9
Wiele komponentów systemowych opiera swoje czynności o poprawność daty i czasu. Jednym z nich, który każdemu przychodzi do głowy jest cron - systemowy harmonogram zadań. Bez ustawień czasu harmonogram był by najzwyczajniej w świecie bezużyteczny. Nad poprawnością czasu w systemach Uniksowych czuwa protokół NTP wraz z jego najnowszą implementacją w postaci programu chrony.
Aby osoba korzystająca z komputera nie musiała zapamiętać liczb adresu IP chcąc zapmiętać adres strony, wprowadzono prostsze do zapamiętania nazwy domenowe. Mimo tego adres IP dalej jest potrzebny do realizacji połączenia, zatem wraz z nazwami domenowymi pojawiła się usługa DNS, której zadaniem jest zamiana nazw domenowych na adresy IP i vice versa o ile jest to możliwe.
18.1. Network Time Protocol - synchronizacja czasu
Synchronizacja czasu za pomocą NTP polega na jak najdokładnieszym ustawieniu czasu rzeczywistego na zegarze systemowym za pomocą sieci. Czas na serwerach NTP nie bierze się z nikąd najpopularniejszym sposób na uzyskanie dokładnego czasu są zegary atomowe rozlokowane w wielu instytucjach naukowych na całym świecie. Zegary te są podłączone do serwerów, których adresy są dostępne na oficjalnej stronie protokołu: ntp.org, gdzie znajdziemy zbiory serwerów nazywane pulami. Pule mogą mieć wiele różnych podziałów, na przykład na poszczególne kraje, a nawet konkretne dystrybucje Linuksa. W przypadku RHEL adres puli NTP to: rhel.pool.ntp.org. W tych pulach, może znajdować się wiele serwerów, które mają określone role. Wśród nich możemy wyróżnić takie jak:
- Serwer podstawowy - ten rodzaj serwera otrzymuje czas bezpośrednio z jego źródła czyli zegara atomowego. Serwery tego typu mogą przekazywać czas do serwerów podrzędnych jaki synchronizować czas klientów.
- Serwer podrzędny - serwery tego typu otrzymują czas od serwera podstawowego, głównie zajmują się synchonizacją czasu klientów, aby zmniejszyć obciążenie serwerów podstawowych.
- Peer - jest rodzaj serwera który przekazuje czas innym serwerom na tym samym poziomie. Peer-y mogą występować wśród serwerów podstawowych jak podrzędnych.
- Klient - klient nie jest rolą serwera, a raczej hostów, które korzystają z NTP. Klient pobiera czas z jednego z serwerów z puli a następnie ustawia swój zegar na podstawie uzyskanych z serwera różnic.
Sieć NTP ma hierachiczną budowę i opiera się ona o poziomy nazywane Stratum. Poziomy zaczynają się od poziomu 0 na tym poziomie znajdują się głownie zegary atomowe lub inne wzorce czasu. Klient NTP nie może uzyskać informacji z tego poziomu. Nie jest on podłączony do sieci. Drugim poziom - poziom 1 - jest miejscem w hierarchii, który znajdują się głównie serwery podstawowe oraz peer-y. Na kolejnych poziomach znajdują się serwery podrzędne oraz peer-y tych poziomów. Czas uzyskany z najwyższych poziomów można uznać za najbardziej dokładny i rzetelny. Wszystkich poziomów w hierarchi jest 15.
Klient wybiera serwer na podstawie czasu oczekiwania na odpowiedź, im krótszym tym czas będzie bardziej dokładny.
18.1.1. Konfiguracja demona Chrony
Chrony jest najnowszą implementacją demona synchronizacji czasu. Działa on na porcie 123 protokołu UDP. Jego plik konfiguracjny znajduje się bezpośrednio w katalogu /etc pod nazwą chrony.conf. Poniżej znajduje się jego zawartość.
pool 2.rhel.pool.ntp.org iburst sourcedir /run/chrony-dhcp driftfile /var/lib/chrony/drift makestep 1.0 3 rtcsync keyfile /etc/chrony.keys ntsdumpdir /var/lib/chrony leapsectz right/UTC logdir /var/log/chrony
Z tych przedstawionych na przykładzie na bardziej szczegółowe omówienie
zasługuje dyrektywa pool
wskazująca na
adres puli, dodatkowo atrybut iburst
powoduje przyspieszenie uzyskania czasu z serwera NTP. Ma to
swój cel głównie podczas uruchamiania systemu. W pliku wskazywanym
przez dyrektywę driftfile
przechowywany jest wskaźnik rozbierzności czasu zegara systemowego,
informacje przechowywane w tym pliku pomagają w utrzymaniu precyzji
zegara. Jeśli mielibyśmy wskazać konkretny serwer czasu, to wówczas
należało by użyć dyrektywy server. Dyrektywa
logdir
przechowuje plik dziennika
/var/log/chrony
.
Demon chrony dostarczany jest wraz z poleceniem chronyc za pomocą którego możemy sprawdzić wydajność demona oraz kontrolować jego działanie. Informacje o NTP z demona możemy uzyskać za pomocą podpoleceń takich jak sources oraz tracking.
Aby skonfigurować chrony nic nie trzeba robić. Wystarczy instalacja oraz włączenie jednostki. Domyślna konfiguracja świetnie sprawdza się w podstawowych zastosowaniach. Konfigurację zaczniemy zatem od sprawdzenia czy demon jest zainstalowany czy nie.
[user@server10 ~]$ sudo dnf install chrony Updating Subscription Management repositories. Unable to read consumer identity This system is not registered with an entitlement server. You can use subscription-manager to register. Ostatnio sprawdzono ważność metadanych: 0:31:37 temu w dniu pon, 1 sie 2022, 14:03:11. Pakiet chrony-4.1-3.el9.x86_64 jest już zainstalowany. Rozwiązano zależności. Nie ma nic do zrobienia. Ukończono.
W przypadku Red Hat Enterprise Linux 9 jest on domyślnie zainstalowany. To pozostaje tylko go włączyć.
[user@server10 ~]$ sudo systemctl enable --now chronyd.service Created symlink /etc/systemd/system/multi-user.target.wants/chronyd.service → /usr/lib/systemd/system/chronyd.service. [user@server10 ~]$ sudo systemctl status chronyd.service --no-pager ● chronyd.service - NTP client/server Loaded: loaded (/usr/lib/systemd/system/chronyd.service; enabled; vendor preset: enabled) Active: active (running) since Mon 2022-08-01 14:37:11 CEST; 23s ago Docs: man:chronyd(8) man:chrony.conf(5) Process: 1968 ExecStart=/usr/sbin/chronyd $OPTIONS (code=exited, status=0/SUCCESS) Main PID: 1970 (chronyd) Tasks: 1 (limit: 5891) Memory: 824.0K CPU: 18ms CGroup: /system.slice/chronyd.service └─1970 /usr/sbin/chronyd -F 2 sie 01 14:37:11 server10.example.com systemd[1]: Starting NTP client/server... sie 01 14:37:11 server10.example.com chronyd[1970]: chronyd version 4.1 starting (+CMDMON +NTP +RE…EBUG) sie 01 14:37:11 server10.example.com chronyd[1970]: Frequency -6.706 +/- 0.264 ppm read from /var/…drift sie 01 14:37:11 server10.example.com chronyd[1970]: Using right/UTC timezone to obtain leap second data sie 01 14:37:11 server10.example.com chronyd[1970]: Loaded seccomp filter (level 2) sie 01 14:37:11 server10.example.com systemd[1]: Started NTP client/server. sie 01 14:37:16 server10.example.com chronyd[1970]: Selected source 178.215.228.24 (2.rhel.pool.ntp.org) sie 01 14:37:16 server10.example.com chronyd[1970]: System clock TAI offset set to 37 seconds Hint: Some lines were ellipsized, use -l to show in full.
Za pomocą polecenia chronyc wraz z podpoleceniem sources możemy podejrzeć z jakim serwerem czasu połączył się nasz klient oraz na jakim poziomie hierarchi się one znajdują.
[user@server10 ~]$ chronyc sources MS Name/IP address Stratum Poll Reach LastRx Last sample =============================================================================== ^+ pingless.com 2 6 377 2 -3517us[-2773us] +/- 27ms ^+ s.complex.net.pl 2 6 377 1 -2877us[-2877us] +/- 44ms ^* ntp.ifj.edu.pl 2 6 377 1 +10ms[ +11ms] +/- 33ms ^+ any.time.nl 2 6 377 66 -2061us[-1153us] +/- 62ms
Gwiazdka w pierwszej kolumnie wiersza oznacza, że to właśnie z tego serwera został pobrany czas. Możemy się upewnić za pomocą drugiego podpolecenia tracking. Aby poznać więcej informacji na temat kolumn wyszukajmy sekcji sources na stronie podręcznika polecenia chronyc. Wynik działania podpolecenia tracking znajduje się poniżej:
[user@server10 ~]$ chronyc tracking Reference ID : C0560E43 (ntp.ifj.edu.pl) Stratum : 3 Ref time (UTC) : Mon Aug 01 12:48:05 2022 System time : 0.001653226 seconds slow of NTP time Last offset : -0.001851230 seconds RMS offset : 0.001920320 seconds Frequency : 7.629 ppm slow Residual freq : -0.463 ppm Skew : 4.887 ppm Root delay : 0.042983003 seconds Root dispersion : 0.008079479 seconds Update interval : 64.8 seconds Leap status : Normal
Zwróćmy uwagę na rozbierzność na temat poziomów serwera. W przypadku
mojego serwera czas systemowy spóźnia się o wartość zapisaną w wierszu
System time
.
Odnośnie egzaminu:
Podczas egzaminu maszyny egzaminacyjne nie będą mieć dostępu do
internetu, więc podczas konfiguracji klienta NTP będzie trzeba
wskazać na serwer w sieci egzaminacyjnej. Ujmujemy w komentarz
dyrektywę pool oraz server jeśli występuje,
następnie dopisujemy kolejną dyrektywę server z adresem
serwera NTP w sieci egzaminacyjnej.
18.1.2. Ustawienia daty i czasu
Podczas omawiania synchronizacji czasu nie może zabraknąć ręcznych ustawień. W przypadku RHEL można to zrealizować na dwa sposóby. Pierwszym z nich jest jest polecenie timedatectl oraz date. Tak prezentują się informacje zwracane przez oba narzędzia uruchomione bez żadnych argumentów:
[user@server10 ~]$ timedatectl Local time: pon 2022-08-01 15:34:51 CEST Universal time: pon 2022-08-01 13:34:51 UTC RTC time: pon 2022-08-01 13:34:51 Time zone: Europe/Warsaw (CEST, +0200) System clock synchronized: yes NTP service: active RTC in local TZ: no [user@server10 ~]$ date pon, 1 sie 2022, 15:34:55 CEST
Aby móc ustawić ręcznie datę oraz czas trzeba wyłączyć możliwość ustawienia daty oraz czasu z protokołu NTP. Możemy to zrobić za pomocą poniższego polecenia:
[user@server10 ~]$ sudo timedatectl set-ntp false [user@server10 ~]$ timedatectl Local time: pon 2022-08-01 15:35:58 CEST Universal time: pon 2022-08-01 13:35:58 UTC RTC time: pon 2022-08-01 13:35:58 Time zone: Europe/Warsaw (CEST, +0200) System clock synchronized: yes NTP service: inactive RTC in local TZ: no
Ustawienie daty oraz czasu następuje w przypadku timedatectl, dokonujemy za pomocą podpolecenia set-time następnie podajemy datę oraz godzinę.
[user@server10 ~]$ sudo timedatectl set-time "1970-01-01 12:01" [user@server10 ~]$ timedatectl Local time: czw 1970-01-01 12:01:12 CET Universal time: czw 1970-01-01 11:01:12 UTC RTC time: czw 1970-01-01 11:01:13 Time zone: Europe/Warsaw (CET, +0100) System clock synchronized: no NTP service: inactive RTC in local TZ: no
Natomiast w przypadku polecenia date używa się opcji --set.
[user@server10 ~]$ sudo date --set "1970-01-05 23:59" pon, 5 sty 1970, 23:59:00 CET [user@server10 ~]$ date pon, 5 sty 1970, 23:59:02 CET
Aby wszystko wróciło do normy, wystarczy że włączymy obsługę NTP.
[user@server10 ~]$ sudo timedatectl set-ntp true [sudo] hasło użytkownika user: [user@server10 ~]$ chronyc tracking Reference ID : D4539E53 (dedibox.demongeot.biz) Stratum : 3 Ref time (UTC) : Mon Aug 01 13:56:32 2022 System time : 0.000497948 seconds slow of NTP time Last offset : -0.000775014 seconds RMS offset : 0.000775014 seconds Frequency : 6.770 ppm slow Residual freq : -57.944 ppm Skew : 0.724 ppm Root delay : 0.065063119 seconds Root dispersion : 0.003521844 seconds Update interval : 1.5 seconds Leap status : Normal [user@server10 ~]$ timedatectl Local time: pon 2022-08-01 15:57:19 CEST Universal time: pon 2022-08-01 13:57:19 UTC RTC time: pon 2022-08-01 13:57:19 Time zone: Europe/Warsaw (CEST, +0200) System clock synchronized: yes NTP service: active RTC in local TZ: no
18.2. Rozwiązywanie nazw domenowych
Za rozwiązywanie nazw domenowych odpowiedzialna jest usługa DNS. W tym podrozdziale przyjrzymy się tylko konfiguracji klienta oraz poznamy narzędzia dzięki którym będziemy mogli odpytać serwer w poszukiwaniu adresu IP lub nazwy hosta. Na początek jednak trochę teorii.
Przestrzeń nazw domenowych posiada hierahiczną strukturę odwróconego drzewa. Podobnie do katalogu głównego. Podbnie tutaj występuję wezeł główny oznaczonony kropką (.). Kropka funkcjonuje również jako separator w nazwach. Po głównym weźle, ktory jest domyślny i nie trzeba do podawać występuje TLD czyli domena najwyższego rzędu. Domenami najwyszego rzędu są między innymi .com, .net, .org itd. Domeny geograficzne na przykład .pl również są domenami najwyższego rzędu. Po nich wystepują poddomeny niższego rzędu. Mogą być to domeny takie jak .com itd. o ile w hierarchi poprzedza je na przykład domena geograficzna. W poddomenach niższego rzędu występują już nazwy własne, które się wydzierżawia od dostawcy usług domenowych. Taką nazwą własną mozę być redhat lub github. Po nazwie własnej, występuje nazwa hosta. Ma to miejsce w 80% przypadków, reszta to sieci korporacyjne gdzie między nazwą hosta, a nazwą własną domeny możemy występować jeszcze duża ilość poddomen. Weźmy dla przykładu nazwe domenową tej strony. Jeśli zapiszemy ją zgodnie z hierarchią to będzie wyglądać jak na przykładzie ponizej.
.-↓ io.↓ github.↓ morketsmerke .io.github.morketsmerke
W taki sposób są rozwiązywane nazwy domenowe na adresy IP
przyczym najczęsiej w początkowej fazie, kroka oznaczająca główny
węzeł zostaje pominięta, następnie szuka się serwera nazwy
obsługującego github.io
. Następnie
otrzymuje się adres, który z hostów w sieci github to
morketsmerke (oczywiście w dużym skrócie). Ludzie za to
wpisują adresy do aplikacji w
sposób odwrotny do hierarchi: morketsmerke.github.io. I w
momencie gdy takie zapytanie trafi do serwera system DNS
zacznie
wysłać zapytania do innych serwerów odpowiedzialnych za utrzymanie
poszczególnych części nazwy.
Serwery DNS zajmują się utrzymaniem bazy mapowań adresów domenowych na adresy IP, odpowiadaniem na zapytania klientów oraz synchronizacją tych baz z innymi serwerami. Wpis bazie danych DNS nazywany jest rekordem. Serwery DNS dzieli się na serwery główne oraz podrzędne. Serwery podrzędne wykorzystuje się głównie do równoważenia obciążenia oraz nadmiarowości, ponieważ bazy są przesyłane na serwery podrzędne za każdą aktulizacją wprowadzą w konfiguracji domeny.
18.2.1. Plik /etc/resolv.conf
Za pomocą pliku /etc/resolv.conf, narzędzia odpowiedzialne za rozwiązywanie nazw wiedzą w jaki sposób mają tworzyć zapytania oraz gdzie przesyłać je dalej (na przykład, gdy korzystamy z aliasu zapisanego w pliku /etc/hosts). Plik można edytować jak każdy inny plik tekstowy. Zazwyczaj zawiera on do trzech dyrektyw. Zawartość pliku z jednej z moich maszyny prezentuje się na poniższym przykładzie.
[user@server10 ~]$ cat /etc/resolv.conf # Generated by NetworkManager search example.com nameserver 192.168.122.1
Dyrektywa search
zawiera sufiks z
nazwą domeny, jest on dodawany do każdej zapisanej nazwy hosta
pod czas tworzenia zapytania DNS. W tej dyrektywie może być
ich maksymalnie 6, przyczym warto pamiętać o tym aby na początku
zawsze znajdowała się domena lokalna. Kolejną dyrektywą jest
nameserver
zawierająca adresy
IP odpytywanych po kolei serwerów DNS. W tej
dyrektywie mogą znaleźć się maksymalnie 3 adresy, będą one odpytywane
w takiej samej kolejności jak zostały zapisane. Ostatnia dyrektywą
jest dyrektywa domain, jednak nie jest ona stosowana jeśli
w pliku jest zapisana dyrektywa search
.
18.2.2. Plik /etc/nsswitch.conf
Inny plikiem wpływającym na działanie rozwiązywania nazw systemach Uniksowych jest /etc/nsswitch.conf. Jego zadaniem jest wybranie odpowiedniego źródła dla żądanych informacji i w tym przypadku nie chodzi tylko o nazwy domenowe. Każdy wpis składa się ze wskazania bazy danych. W przypadku nazw domenowych jest hosts. Następnie wskazywane są źródła. Poniżej znajduje się przykładowy wpis:
hosts: files dns myhostname
Gdzie files
jest w tym przypadku
plikiem /etc/hosts; dns
jest
odpytaniem serwerów zapisanych w /etc/resolv.conf.
Jeśli program podczas rozwiązywania nazwy nie znajdzie jej w pliku, przechodzi do kolejego źródła. Plik /etc/nsswitch.conf za pomocą słów kluczowych pozwala na określenie akcji jeśli uzyskano dane lub nie z zapisanych źródeł. Poniżej znajduje się lista słów kluczowych.
- success - Informacje znalezione w źródle. Dostarczone do aplikacji, która ich żądała. Domyślna akcja: return (nie szukaj w innych źródłach).
- notfound - Nie znalaleziono informacji w źródle. Domyślna akcja: continue (szukaj w innym źródle)
- unavail - Źródło jest wyłączone, bądź nie odpowiada. Usługą może być wyłączona lub nie skonfigurowana. Domyślna akcja: continue (szukaj w innym źródle)
- tryagain - Źródło jest zajęte, spróbuj poźniej. Domyślna akcja: continue (szukaj w innym źródle)
Dzięki tym słowom kluczowym, jeśli np. nazwa hosta nie zostanie odnaleziona w pliku /etc/resolv.conf można przerwać dalsze poszukiwania.
hosts: files [notfound=return] dns myhostname
18.2.3. Narzędzia do rozwiązywania nazw domenowych
Czasem może zdarzyć się potrzeba przetestowania rozwiązywania nazw w systemie i do tego mogą posłużyć nam dostępne w systemie narzędzia. Jest ich kilka.
Pierwszym z nich jest dig. Bardzo elastyczne i użyteczne narzędzie. Możemy wykorzystać je do wielu czynności. Plusem tego narzędzia jest domyślna ilość zwracanych informacji. Poniżej znajduje się rozwiązanie nazwy redhat.com za pomocą tego narzędzia.
[user@server10 ~]$ dig redhat.com ; <<>> DiG 9.16.23-RH <<>> redhat.com ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 20452 ;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 512 ;; QUESTION SECTION: ;redhat.com. IN A ;; ANSWER SECTION: redhat.com. 312 IN A 52.200.142.250 redhat.com. 312 IN A 34.235.198.240 ;; Query time: 56 msec ;; SERVER: 192.168.122.1#53(192.168.122.1) ;; WHEN: Mon Aug 01 17:50:49 CEST 2022 ;; MSG SIZE rcvd: 71
Na samym dole mamy podsumowanie, w którym znajdują się informacje o tym jak długo trwało zapytanie, czy adres odpytywanego serwera. Polecenie to również możemy odpytać podając adres IP.
[user@server10 ~]$ dig -x 52.200.142.250 ; <<>> DiG 9.16.23-RH <<>> -x 52.200.142.250 ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 14382 ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 512 ;; QUESTION SECTION: ;250.142.200.52.in-addr.arpa. IN PTR ;; ANSWER SECTION: 250.142.200.52.in-addr.arpa. 300 IN PTR ec2-52-200-142-250.compute-1.amazonaws.com. ;; Query time: 88 msec ;; SERVER: 192.168.122.1#53(192.168.122.1) ;; WHEN: Mon Aug 01 17:55:58 CEST 2022 ;; MSG SIZE rcvd: 112
Użycie opcji -x
pozwala na podanie
adresu IP.
Kolejny narzędziem jest polecenie host. Jak argument przyjmuje nazwę domenową i zwraca adres IP serwera oraz pozostałe wpisy w bazie DNS powiązane z tą nazwą. Poniżej znajduje się przykład.
[user@server10 ~]$ host redhat.com redhat.com has address 34.235.198.240 redhat.com has address 52.200.142.250 redhat.com mail is handled by 10 us-smtp-inbound-2.mimecast.com. redhat.com mail is handled by 10 us-smtp-inbound-1.mimecast.com.
Za pomocą polecenia host możemy uzyskać podobne wyjście jak w przypadku polecenia dig. Służy do tego opcja -v.
[user@server10 ~]$ host -v redhat.com Trying "redhat.com" ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 5646 ;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0 ;; QUESTION SECTION: ;redhat.com. IN A ;; ANSWER SECTION: redhat.com. 247 IN A 52.200.142.250 redhat.com. 247 IN A 34.235.198.240 Received 60 bytes from 192.168.122.1#53 in 4 ms Trying "redhat.com" ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 13010 ;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 0 ;; QUESTION SECTION: ;redhat.com. IN AAAA ;; AUTHORITY SECTION: redhat.com. 1037 IN SOA a1-68.akam.net. noc.redhat.com. 2022080000 300 180 604800 14400 Received 82 bytes from 192.168.122.1#53 in 51 ms Trying "redhat.com" ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 56767 ;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0 ;; QUESTION SECTION: ;redhat.com. IN MX ;; ANSWER SECTION: redhat.com. 314 IN MX 10 us-smtp-inbound-1.mimecast.com. redhat.com. 314 IN MX 10 us-smtp-inbound-2.mimecast.com. Received 105 bytes from 192.168.122.1#53 in 50 ms
Kolejnym poleceniem jest nslookup. Polecenie to jest interaktywne. Pozwala ono na zmianę serwera w bardzo prosty sposób, ponieważ jego adres możemy podać jako argument polecenia lub już po jego uruchomieniu po poleceniu server.
[user@server10 ~]$ nslookup > server 8.8.8.8 Default server: 8.8.8.8 Address: 8.8.8.8#53 > redhat.com Server: 8.8.8.8 Address: 8.8.8.8#53 Non-authoritative answer: Name: redhat.com Address: 52.200.142.250 Name: redhat.com Address: 34.235.198.240 > exit
W wyniku polecenia pojawił się taki zapis jak
Non-authoritative answer
. Oznacza to,
że rozwiązanie nazwy otrzymano od serwera, który nie zarządza tą
domeną. Polecenie opuszczamy tylko za pomocą polecenia
exit
.
Ostatnim poleceniem jest getent. Polecenie to jest związane z plikiem /etc/nsswitch.conf, dlatego aby uzyskać za jego pomocą adres IP jednej z nazw należy podać jako pierwszy argument bazę danych z jakiej będziemy korzystać. Przypominam, że jest to hosts. Poniżej znajduje się przykład użycia tego polecenia.
[user@server10 ~]$ getent hosts redhat.com 34.235.198.240 redhat.com 52.200.142.250 redhat.com
Ćwiczenie 1: Zmiana daty i czasu
Jako użytkownik z możliwością podniesienia uprawnień, na maszynie oznaczonej jak server10, wyświetl obecną datę i godzine za pomocą obu poznanych narzędzi. Za pomocą polecenia timedatectl zmień datę i godzine na dowolną w przyszłość. Za pomocą polecenia date zwiększ godzinę o jedną naprzód. Ponownie wyświetl datę i godzinę za pomocą obu narzędzi. Przyróć datę i godzinę do rzeczywistych wartości.
Ćwiczenie 2: Konfiguracja Chrony
Jako użytkownik z możliwością podniesienia uprawnień, na maszynie oznaczonej jak server10. Jeśli jest taka potrzeba zainstaluj Chrony. W pliku konfiguracyjny wyłącz wszystkie dyrektywy (ujmij w komentarz) pool oraz server. Dodaj nową dyrektywę na server z adresem 127.127.1.0. Włącz/zrestartuj usługę. Potwierdź wykonanie zadania za pomocą wyświetlania źródeł Chrony - polecenie chronyc sources.
Podsumowanie
W tym rozdziale poznaliśmy sposóby na efektywną i automatyczną synchronizację czasu zegara systemowego. Za poznaliśmy się z najnowszą implementacją protokołu NTP jaką definitywnie jest Chrony poznaliśmy jego konfigurację oraz polecenia służące zarządzania nim. Poza tym poznaliśmy w jaki sposób uzyskiwane są adresy IP w systemie, czym jest DNS, pliki /etc/resolv.conf czy /etc/nsswitch.conf. Poznaliśmy również kilka narzędzi, dzięki którym możemy przeprowadzić diagnostykę rozwiązywania nazw na naszych systemach. W następnym rozdziale zajmiemy się obsługą bezpiecznego zdalnego logowania do powłoki - usługą SSH.
19. Usługa bezpiecznej powłoki
Usługa bezpiecznej powłoki, jest w obecnych czasach jedną z podstawowych rzeczy bez których nie wyobrażamy sobie pracy z jakimi kolwiek odległymi maszynami. SSH pozwala na bezpieczne zarządzania maszynami oraz przesyłanie informacji między nimi przez niezabezpieczone sieci takie jak internet. SSH pozwala na uwierzytelnienie użytkownika na zdalnym serwerze. Dba ona również o intergralność danych przesyłanych jej kanałami. Ta usługa dostarcza do systemów Uniksowych wielu narzędzi, które wyparły odpowiedniki korzystające ze zwykłych nieszyfrowanych kanałów.
19.1. Podstawy teoretyczne na temat SSH
W wielu Uniksach (w tym i dystrybucjach Linuksa) stosowana jest darmowa oraz wolna implementacja protokołu SSH - OpenSSH, jest ona odpowiednikiem własnościowej wersji. Obecnie najczęściej stoswany jest protokół SSH w wersji 2.
19.1.1. Kryptografia SSH
OpenSSH do zabezpiecznia transmisji danych wykorzystuje metody kryptograficzne zwane algorytmami. Są to serie rownań matematycznych mających za zadanie jak najbardziej zamaskować jawne dane aby nie mogły być one odczytane przez osoby nie znające klucza, czyli hasła bądź pliku, który za pomocą tych samych algorytmów pozwoli na odczytanie danych przeznaczonych dla ich odbiorców. Wśród metod szyfrowania możemy wymienić:
- Algorytmy symetryczne - w których do szyfrowania i odszyfrowyania danych używa się tego samego klucza ustalanego podczas pierwszego połączenia między stronami transmisji.
- Algorytmów asymetrycznych - metody te są nazwane również algorytmami klucza publicznego. Każdy z hostów generuje klucz prywatny. Następnie na podstawie tego klucza generowany jest klucz publiczny, który może być jawnie przesyłany przez internet, ponieważ służy on do identyfikacji użytkownika oraz szyfrowania danych. Hosty przesyłają sobie klucze publiczne i rozpoczyna się wymiana danych znanych tylko im. Dane w przypadku tego typu algorytmów mogą być odczytane tylko za pomocą klucza prywatnego. Algorytmy asymetryczne są wykorzystywane do zabezpieczania transmisji oraz uwierzytelniania użytkowników.
OpenSSH wykorzystuje głównie algorytm RSA, ponieważ może za jego pomocą szyfrować dane oraz uwierzytelniać użytkownika. Do uwierzytleniania możemy wykorzystać takie algorytmy jak DSA oraz ECDSA jednak służą one tylko temu celowi.
19.1.2. Metody uwierzytelniania OpenSSH
Aby użytkownik mógł pracować na zdalnym serwerze za pomocą SSH musi się uwierzytelnić. Uwierzytelnienia możemy dokonać na kilka różnych sposobów, a wsród nich możemy wyróżnić oparte na:
- GSSAPI
- Hoście
- Kluczu publicznym
- Haśle
- metodzie Challenge-response
W tym materiale jednak skupimy się wyłącznie na domyślnej metodzie jaką jest hasło oraz klucz publiczny.
19.1.3. Oprogramowanie OpenSSH
W RHEL usługa SSH w implementacji OpenSSH jest podzielona na trzy pakiety: openssh - dostarczający niezbędne biblioteki oraz polecenie ssh-keygen; openssh-client - dostarczający takie polecenia jak: ssh, scp czy sftp. Ostatnim pakietem jest openssh-server dostarczający demona sshd.
Polecenie ssh zastępuje stare polecenia telnet czy rlogin. Z poleceniem telnet możemy się jeszcze kiedyś spotkać. Polecenia scp i sftp zastępują kolejno rcp oraz ftp. Mimo to ftp jest dalej stosowany, aby umożliwić publiczny dostęp na przykład do repozytoriów oprogramowania.
19.2. Serwer OpenSSH - sshd
Serwerem OpenSSH jest program sshd. Jego konfiguracja znajduje się w pliku /etc/ssh/sshd_config. Poniżej znajduje się jej fragment:
#Port 22 #AddressFamily any #ListenAddress 0.0.0.0 #ListenAddress :: #HostKey /etc/ssh/ssh_host_rsa_key #HostKey /etc/ssh/ssh_host_ecdsa_key #HostKey /etc/ssh/ssh_host_ed25519_key # Ciphers and keying #RekeyLimit default none # Logging #SyslogFacility AUTH #LogLevel INFO # Authentication: #LoginGraceTime 2m #PermitRootLogin prohibit-password #StrictModes yes #MaxAuthTries 6 #MaxSessions 10 #PubkeyAuthentication yes # The default is to check both .ssh/authorized_keys and .ssh/authorized_keys2 # but this is overridden so installations will only check .ssh/authorized_keys AuthorizedKeysFile .ssh/authorized_keys ...
Zwróćmy uwagę na to, że prawie wszystkie dyrektywy są ujęte w komentarz po za jedną, która wskazuje gdzie należy złożyć wszystkie otrzymane klucz publiczne w celach uwierzytelniania. Demon OpenSSH jest domyślnie dostoswany do największej ilości przypadków jego użycia, więc zmian w plikach konfiguracyjnych najczęściej dokonuje się w specyficznych przypadkach.
Nazwa jednostki w RHEL nosi nazwę sshd.service. Każdą zmianę w tym pliku należy potwierdzić restartując demona. Opisy tych dyrektyw znajdują się na stronie podręcznika.
19.3. Konfiguracja klienta - ssh
Na każdej maszynie, na której znajduje się polecenie ssh znajduje się także plik konfiguracyjny /etc/ssh/ssh_config, który reguluje jego zachowanie. Posiada on też kilka dyrektyw sugerujących pewne domyślne ustawienia. Poniżej znajduje się jego fragment pobrany z jednej z moich maszyn.
# Host * # ForwardAgent no # ForwardX11 no # PasswordAuthentication yes # HostbasedAuthentication no # GSSAPIAuthentication no # GSSAPIDelegateCredentials no # GSSAPIKeyExchange no # GSSAPITrustDNS no # BatchMode no # CheckHostIP yes # AddressFamily any # ConnectTimeout 0 # StrictHostKeyChecking ask # IdentityFile ~/.ssh/id_rsa # IdentityFile ~/.ssh/id_dsa # IdentityFile ~/.ssh/id_ecdsa # IdentityFile ~/.ssh/id_ed25519 # Port 22 ...
Konfiguracja klienta została ujęta w ten sam sposób jak w przypadku serwera. Konfiguracja klienta również jest przygotowana do użycia we większości przypadków, dlatego też zmiany w konfiguracją będą wymagane tylko w specyficznych przypadkach.
19.4. Obsługa połączeń zdalnych - programy OpenSSH
Na początku tego rozdziału wspomnieliśmy o ilości programów dostarczanych wraz z pakietem OpenSSH. Teraz sobie je przetestujemy. Ten podrozdział został również rozszerzony o jeden program, który korzysta z SSH do przesyłania danych.
19.4. Połączenie ze zdalnym serwerem z pomocą ssh
Połączenie ze zdalnym serwerem wymaga wydania pojedynczego polecenia, w którym podajemy adres serwera, wówczas polecenie spróbuje zalogować na użytkownika z tą samą nazwą z jakiej korzystamy w lokalnym systemie.
[user@server10 ~]$ ssh server20 The authenticity of host 'server20 (192.168.122.7)' can't be established. ED25519 key fingerprint is SHA256:ZWgY+ro8oMwFh7vq56bS/Zk9CGpUe2sCrmxaukixr8M. This key is not known by any other names Are you sure you want to continue connecting (yes/no/[fingerprint])? yes Warning: Permanently added 'server20' (ED25519) to the list of known hosts. user@server20's password: Activate the web console with: systemctl enable --now cockpit.socket Register this system with Red Hat Insights: insights-client --register Create an account or view all your systems at https://red.ht/insights-dashboard Last login: Wed Aug 3 10:59:57 2022 from 192.168.122.6 [user@server20 ~]$
Po wydaniu polecenia nastepuje połączenie. Klient nie może zweryfikować
autentyczności serwera przedstawiającego się podanym
odciskiem klucza. Tak dzieje się gdy łączymy się
z serwerem po raz pierwszy. Polecenie zapyta nas czy chcemy kontynuować
połączenie, wybierając Yes
odcisk
klucza wraz z adresem serwera zostanie złożony w pliku
~/.ssh/known_hosts. Następnie zostaniemy zapytani o hasło.
Po jego podaniu jesteśmy podłączeni do serwera.
Chcąc podać innego użytkownika podczas połączenia SSH możemy to zrobić na dwa sposób. Na przykład:
[user@server10 ~]$ ssh -l user server20 #lub: [user@server10 ~]$ ssh user@server20
19.4.2. Generowanie, dystrybucja oraz logowanie się za pomocą klucza publicznego
Inną metodą uwierzytelniania stosowaną obok haseł jest uwierzytelnianie za pomocą klucza publicznego. Ma ono klika zalet, otóż możemy logować się bez podawania hasła, wówczas musimy pamiętać aby zabezpieczyć w inny sposób plik klucza. Możemy również nadać jedno hasło - hasło klucza i używać jednego hasła do wielu serwerów. W tym materiale zajmiemy się wyłącznie kluczami bez haseł.
Na początek zajmiemy się wygenerowaniem klucza. Dokonujemy tego za pomocą polecenia ssh-keygen podając kolejno opcję -N, przyczym należy pamiętać, że aby nadać puste hasło należy podać puste podwójne apostrofy ("") jako wartość tej opcji. Do generowania kluczy użyjemy także opcji -q, która powoduje nie wyświetlanie komunikatów podczas generowania klucza.
[user@server10 ~]$ ssh-keygen -N "" -q Enter file in which to save the key (/home/user/.ssh/id_rsa):
Polecenie zapyta o ścieżkę oraz nazwę pliku klucza. Tę wartość pozostawiam domyślnie.
Następnym etapem będzie przesłanie oraz instalacja klucza na zdalnym serwerze. Wykonamy tę czynność przy użyciu polecenia ssh-copy-id, przyjmuje ono takie same argumenty jak polecenie ssh, zatem aby zainstalować klucz na serwerze należy wydać poniższe polecenie. Polecenie to w ramach potwierdzenia naszej tożsamości zażąda hasła do połączenia się ze zdalnym użytkownikiem na serwerze.
[user@server10 ~]$ ssh-copy-id user@server20 /usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/user/.ssh/id_rsa.pub" /usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed /usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys user@server20's password: Number of key(s) added: 1 Now try logging into the machine, with: "ssh 'user@server20'" and check to make sure that only the key(s) you wanted were added.
Teraz kiedy klucz jest zainstalowany możemy bez przeszkód logować się na serwer.
[user@server10 ~]$ ssh user@server20 Activate the web console with: systemctl enable --now cockpit.socket Register this system with Red Hat Insights: insights-client --register Create an account or view all your systems at https://red.ht/insights-dashboard Last login: Wed Aug 3 11:39:18 2022 from 192.168.122.6 [user@server20 ~]$
19.4.3. Wykonywanie pojedyńczych poleceń na zdalnym serwerze
Za pomocą SSH możemy również wykonywać zdalnie pojedyncze polecenia, jeśli nie potrzebujemy dla jednej informacji zestawiać interaktywnej powłoki. Polecenie do wykonania na zdalnym serwerze podajemy po adresie serwera.
[user@server10 ~]$ ssh user@server20 "whoami; hostname; pwd" user server20.example.com /home/user
Najlepiej, jeśli ujmiemy polecenie w podwójne apostrofy. Wówczas mamy pewność, że zostanie ono w pełni przekazane do zdalnego systemu.
19.4.4. Bezpieczne kopiowanie plików
Za pomocą polecenia scp, możemy kopiować pliki z wykorzystaniem protokołu SSH w obu kierunkach. Tutaj dodatkową rolę odgrywa zainstalowanie klucza bez hasła. Jeśli to zrobimy wówczas będziemy mogli rozwiajać scieżki ze zdalnego systemu za pomocą klawisza Tab. Na poniższym przykładzie skopiuje plik /etc/chrony.conf do katalogu /tmp.
[user@server10 ~]$ scp server20:/etc/chrony.conf /tmp chrony.conf 100% 1369 1.5MB/s 00:00 [user@server10 ~]$ ls -l /tmp/chrony.conf -rw-r--r--. 1 user user 1369 08-03 11:58 /tmp/chrony.conf
Za pomocą opcji -r jesteśmy w stanie skopiować do całe katalogi.
[user@server10 ~]$ scp -r /home/user server20:/tmp/test/ .bash_logout 100% 18 40.4KB/s 00:00 .bash_profile 100% 141 386.3KB/s 00:00 .bashrc 100% 492 1.2MB/s 00:00 .bash_history 100% 9742 17.0MB/s 00:00 .lesshst 100% 93 182.5KB/s 00:00 known_hosts 100% 822 1.6MB/s 00:00 known_hosts.old 100% 90 154.6KB/s 00:00 id_rsa 100% 2610 6.2MB/s 00:00 id_rsa.pub 100% 579 1.4MB/s 00:00 gzip 100% 94KB 37.9MB/s 00:00 .viminfo 100% 10KB 13.7MB/s 00:00 [user@server10 ~]$ ssh user@server20 "ls -al /tmp/test/user" razem 136 drwx------. 3 user user 139 08-03 12:00 . drwxrwxr-x. 3 user user 18 08-03 12:00 .. -rw-------. 1 user user 9742 08-03 12:00 .bash_history -rw-r--r--. 1 user user 18 08-03 12:00 .bash_logout -rw-r--r--. 1 user user 141 08-03 12:00 .bash_profile -rw-r--r--. 1 user user 492 08-03 12:00 .bashrc -rwxr-xr-x. 1 user user 95872 08-03 12:00 gzip -rw-------. 1 user user 93 08-03 12:00 .lesshst drwx------. 2 user user 80 08-03 12:00 .ssh -rw-------. 1 user user 10036 08-03 12:00 .viminfo
19.4.5. Przesyłanie plików za pomocą polecenia sftp
Polecenie sftp działa na takiej samej zasadzie co polecenie ftp, jednak wykorzystuje do tego protokół SSH przy tym rozszerzając oraz usprawniając działanie przesyłania plików.
Polecenie to przyjmuje takie same argumenty jak ssh. Przy czym jest ono interaktywne, jak klasyczne ftp za pomocą znaku zapytania (?) możemy wyświetlić listę dostępnych poleceń.
[user@server10 ~]$ sftp user@server20 Connected to server20. sftp> ? Available commands: bye Quit sftp cd path Change remote directory to 'path' chgrp [-h] grp path Change group of file 'path' to 'grp' chmod [-h] mode path Change permissions of file 'path' to 'mode' chown [-h] own path Change owner of file 'path' to 'own' df [-hi] [path] Display statistics for current directory or filesystem containing 'path' exit Quit sftp get [-afpR] remote [local] Download file help Display this help text lcd path Change local directory to 'path' lls [ls-options [path]] Display local directory listing lmkdir path Create local directory ln [-s] oldpath newpath Link remote file (-s for symlink) lpwd Print local working directory ls [-1afhlnrSt] [path] Display remote directory listing lumask umask Set local umask to 'umask' mkdir path Create remote directory progress Toggle display of progress meter put [-afpR] local [remote] Upload file pwd Display remote working directory quit Quit sftp reget [-fpR] remote [local] Resume download file rename oldpath newpath Rename remote file reput [-fpR] local [remote] Resume upload file rm path Delete remote file rmdir path Remove remote directory symlink oldpath newpath Symlink remote file version Show SFTP version !command Execute 'command' in local shell ! Escape to local shell ? Synonym for help
Zwróćmy uwagę to, iż wiele poleceń występuję podwójnie, i są one poprzedzonych literą l. Aby lepiej zarządzać transferem plików posiadmy polecenia, które odwołują się czynności wykonywanych na lokalnym hoście, dzięki czemu nie musimy się rozłączać aby na przykład stworzyć katalog specjalnie na dane pobrane z serwera. Pobierzemy teraz plik /etc/fstab do katalogu /tmp.
sftp> lcd /tmp sftp> get /etc/fstab Fetching /etc/fstab to fstab fstab 100% 608 709.3KB/s 00:00
Za pomocą opcji -r takich poleceń get lub put możemy pobierać oraz przesyłać całe sturktury katalogów:
sftp> cd /tmp/dir_user/ sftp> put -r /tmp/user/.??* Uploading /tmp/user/.bash_history to /tmp/dir_user/.bash_history .bash_history 100% 9742 13.7MB/s 00:00 Uploading /tmp/user/.bash_logout to /tmp/dir_user/.bash_logout .bash_logout 100% 18 54.6KB/s 00:00 Uploading /tmp/user/.bash_profile to /tmp/dir_user/.bash_profile .bash_profile 100% 141 443.4KB/s 00:00 Uploading /tmp/user/.bashrc to /tmp/dir_user/.bashrc .bashrc 100% 492 1.7MB/s 00:00 Uploading /tmp/user/.lesshst to /tmp/dir_user/.lesshst .lesshst 100% 93 325.6KB/s 00:00 Uploading /tmp/user/.ssh/ to /tmp/dir_user/.ssh Entering /tmp/user/.ssh/ known_hosts 100% 822 3.3MB/s 00:00 known_hosts.old 100% 90 351.5KB/s 00:00 id_rsa 100% 2610 8.2MB/s 00:00 id_rsa.pub 100% 579 1.9MB/s 00:00 Uploading /tmp/user/.viminfo to /tmp/dir_user/.viminfo .viminfo 100% 10KB 23.3MB/s 00:00
Jak możemy zauważyć na powyższym przykładzie w sftp możemy używać nazw wieloznacznych.
19.4.6. Synchronizacja danych ze zdalnym serwerem
Jednym z programów wykorzystujących protokół SSH jest rsync, służy on do synchronizacji plików. Taka synchronizacja polega na skopiowaniu wszelkich danych znajdujących się na zdalnym serwerze do lokalnego katalogu lub odwrotnie i przy następnych synchronizacjach będą kopiowane tylko te pliki, które uległy zmianie. Na przykład skopiuje katalog domowy jednego z użytkowników na zdalnym serwerze.
[user@server10 ~]$ rsync -avrPz server20:/home/user/.??* /tmp/user_server20/ receiving incremental file list .bash_history 3,763 100% 3.59MB/s 0:00:00 (xfr#1, to-chk=7/8) .bash_logout 18 100% 17.58kB/s 0:00:00 (xfr#2, to-chk=6/8) .bash_profile 141 100% 137.70kB/s 0:00:00 (xfr#3, to-chk=5/8) .bashrc 492 100% 480.47kB/s 0:00:00 (xfr#4, to-chk=4/8) .lesshst 20 100% 9.77kB/s 0:00:00 (xfr#5, to-chk=3/8) .viminfo 2,263 100% 1.08MB/s 0:00:00 (xfr#6, to-chk=2/8) .ssh/ .ssh/authorized_keys 579 100% 188.48kB/s 0:00:00 (xfr#7, to-chk=0/8) sent 165 bytes received 3,064 bytes 2,152.67 bytes/sec total size is 7,276 speedup is 2.25
Aby taka synchronizacja miała sens potrzebne jest kilka opcji
takich jak -a
, powodująca włączenie
trybu archiwalnego, przez co pliki zostaną skopiowane wraz ze
wszystkimi atrybutami; -v
włączająca
wyświetlanie komunikatów diagnostycznych;
-r
włączająca rekurencje, zostaną
skopiowane katalogi wraz z podkatalogami;
-P
włączająca zwrócenie statystyk
postępu dla każdego przesyłanego pliku;
-z
włączająca kompresje.
Jeśli jeszcze raz spróbujemy pobrać te plik. Nic tak nie zostanie przesłane, ponieważ pliki nie uległy zmianie.
[user@server10 ~]$ rsync -avrPz server20:/home/user/.??* /tmp/user_server20/ receiving incremental file list sent 21 bytes received 228 bytes 498.00 bytes/sec total size is 7,276 speedup is 29.22
Ćwiczenie 1: Logowanie przez SSH z użyciem klucza
Jako użytkownik z możliwością podniesienia uprawnień na maszynach oznaczonych jako server10 oraz server20 utworz nowego użytkownika user20 oraz przypisz mu hasło. Następnie na server10, przełącz się na tego użytkownika oraz wygeneruj klucze SSH bez hasła. Zainstaluj klucz na server20 na koncie użytkowika user20 i spróbuj się na niego zalogować.
Ćwiczenie 2: Działanie dyrektywy PermitRootLogin
Jako użytkownika z możliwością podniesienia uprawnień na maszynie oznaczonej jako server20. Ustaw wartość dyrektywy PermitRootLogin serwera OpenSSH na no. Następnie z poziomu server10 spróbuj się zalogować przez SSH jako root. Następnie zmień wartość tej dyrektywy na yes i spróbuj ponownie.
Podsumowanie
W tym rodziale poruszyliśmy temat bezpieczengo zdalnego dostępu do odległych maszyn. Jest on realizowany za pomocą protokołu SSH, z którego teoretycznymi podstawami zapoznaliśmy się na początku tego rozdziału. Poruszyliśmy także temat plików konfiguracyjnych serwera jak i klienta SSH. Na koniec dowiedzieliśmy się jak korzystać z poleceń dostarczanych wraz z pakietem OpenSSH. W następnym rozdziale poznamy zaporę sieciową w systemie RHEL 9.
20. Zapora sieciowa w RHEL 9
Sieci komputerowe pozwalają na swobodną komunikację między komputerami, co w pewnych przypadkach jest niewskazane, ponieważ nie zawsze pożądane jest aby dowolny użytkownik internetu mógł połączyć się z naszym komputerem i wysyłać lub pobierać z niego dane. Swobodę ruchu kontrolują zapory sieciowe, które mogą być albo fizycznymi urządzeniam wpiętymi w wyższe segmenty sieci lub oprogramowaniem zainstalowanym na naszym komputerze czuwającym nad ruchem sieciowym skierowanym do niego.
Zapora sieciowa ma za zadanie monitorować oraz kontrolować ruch sieciowy. Jest to realizowane przez przeglądanie nagłówków pakietów przesyłanych przez sieć oraz analiza źródłowych adresów IP, używanych protokołów czy portów. W tym materiale skupimy się tylko i wyłącznie na oprogramowaniu firewall-a dostarczonym do Red Hat Enterprise Linux 9.
20.1. Teoria firewalld
Pakiet zapory sieciowej dostarczony do RHEL to firewalld. Zapory dostępne w dystrybucjach Linuks opierają swoją zasadę działania o dwa składniki: moduł jądra netfilter oraz framework służący do klasyfikacji oraz filtrowania pakietów - nftables. Dzięki czemu poza zwykłymi zasadami (za pomocą zasad organizuje się ruch wychodzący oraz przychodzący w systemie) możemy realizować bardziej zaawansowane funkcje takie jak translacja adresów (NAT) umożliwiająca połączenie sieci lokalnej z internetem czy przekierowanie portów pozwalające na kontrolowaną komunikację między użytkownikami internetu a serwerem wewnątrz sieci lokalnej.
Firewalld pozwala na kontrolowanie ruchu sieciowego bez wpływu na nawiązane już połączenia oraz bez potrzeby restartu żadnych usług. Możemy dodawać, usuwać i modyfikować zasady za pomocą albo specjalnego polecenia, albo za pomocą panelu sterowania RHEL, dostępnym przez przeglądarkę, który jest możliwy włączenia za poprzez aktywacje jednostki cockpit.service.
Zasada działania firewalld opiera się na strefach co pozwala na łatwiejsze oraz transparentne utrzymanie ruchu. Strefa określa poziom zaufania połączeń sieciowych oraz adresów źródłowych. W konfiguracji strefy znajdują się przypisane do nich połączenia sieciowe, przy czym jedno połączenie może być przypisane tylko do jednej strefy w tym samym czasie, ale jedna strefa może mieć wiele połączeń oraz zasady pozwalające na połączenia z wybraną usługą czy portem. Strefy definiują także domyślne zachowanie zapory. Kiedy pakiet trafia do zapory, sprawdza ona jego adres źródłowy czy nie występuje w którejś ze stref, jeśli nie ma przypasowania, ten sam pakiet konfrontowany jest podstawie innych kryteriów z regułami zapisanymi w strefie przypisanej do interfejsu sieciowego z którego ten pakiet przybył, jeśli dalej nie ma przypasowania, wówczas jest ono szukane w domyślnej strefie. Brak przypasowania na ostatnim etapie najczęściej oznacza, że pakiet zostanie zablokowany przez zaporę. W systemie możemy spotkać się z kilkoma predefiniowanym strefami, wypisanymi na poniższej liście:
- trusted - zezwól na wszystkie połączenia
- internal - Ruch przychodzący jest odrzucany, poza jawnie wskazanym. Ta strefa stosowana jest w sieciach wewnętrznych.
- home - Ruch przychodzący jest odrzucany, poza jawnie wskazanym. Ta strefa stosowana jest w sieciach domowych.
- work - Ruch przychodzący jest odrzucany, poza jawnie wskazanym. Ta strefa jest stoswana w miejscu pracy.
- dmz - Ruch przychodzący jest odrzucany, poza jawnie wskazanym. Ta strefa jest stosowana w strefie zdemilitaryzowanej (nie ma ograniczeń w połączeniach miedzy hostami w DMZ. Hosty są osiągalne z poziomu internetu, ale nie mogą nawiązywać połączeń z innymi komputerami w sieci lokalnej poza strefą).
- external - Ruch przychodzą jest odrzucany, poza jawnie wskazanym. W ruchu wychodzącym tej strefy dokonywana jest translacja adresów IP (NAT).
- public - Ruch przychodzący jest odrzucany, poza jawnie wskazanym. Ta strefa jest stosowana w miejscah publicznych. Każdy nowy interfejs jest przypisywany do tej strefy.
- block - Ruch przychodzący jest odrzucany ze specjalną wiadmością zwrotną protokołu ICMP.
- drop - Ruch przychodzacy jest odrzucany bez żadnej wiadomości zwrotnej.
Strefy na powyższej liście zostały uszeregowane od najbardzej zaufanej do najmniej. Domyślną strefą stosowaną w RHEL jest public. Ostatnie strefy są skierowane do środowisk o podwyższonym poziomie zabezpieczeń. Nie ma ograniczeń w ruchu wychodzącym w każdej ze stref.
Strefy z poziomu systemu operacyjnego, to zwykłe pliki tekstowe przechowywane w dwóch lokalizacjach. Pierwszą z nich jest katalog /usr/lib/firewalld/zones, w którym to są przechowywane systemowe pliki stref. Drugim katalogiem jest /etc/firewalld/zones gdzie przchowywane są pliki stref użytkowników. Jeśli zechcemy zmienić jeden z plików strefy np. za pomocą polecenia, to automatycznie zostanie otworzona jego kopia w katalogu /etc/firewalld/zones i to na niej zostaną zatwierdzone nasze zmiany. Każda ze stref może zostać przez nas zmieniona. Poniżej znajduje się lista dostępnych stref systemowych:
[user@server10 ~]$ ls -l /usr/lib/firewalld/zones razem 40 -rw-r--r--. 1 root root 312 2021-11-23 block.xml -rw-r--r--. 1 root root 306 2021-11-23 dmz.xml -rw-r--r--. 1 root root 304 2021-11-23 drop.xml -rw-r--r--. 1 root root 317 2021-11-23 external.xml -rw-r--r--. 1 root root 410 2021-11-23 home.xml -rw-r--r--. 1 root root 425 2021-11-23 internal.xml -rw-r--r--. 1 root root 729 2022-01-14 nm-shared.xml -rw-r--r--. 1 root root 356 2021-11-23 public.xml -rw-r--r--. 1 root root 175 2021-11-23 trusted.xml -rw-r--r--. 1 root root 352 2021-11-23 work.xml
Zawartość takiego pliku strefy prezentuje się w następujący sposób:
[user@server10 ~]$ cat /usr/lib/firewalld/zones/public.xml <?xml version="1.0" encoding="utf-8"?> <zone> <short>Public</short> <description>For use in public areas. You do not trust the other computers on networks to not harm your computer. Only selected incoming connections are accepted.</description> <service name="ssh"/> <service name="dhcpv6-client"/> <service name="cockpit"/> <forward/> </zone>
Każde z plików zawiera krótką nazwę, opis oraz deklaracje wskazujące
otwarcie ruchu dla wskazanych w dyrektywach
services
usług. Usługi też w
firewalld mają swoje pliki, w których deklarowane są używane
przez nie porty oraz protokoły. Lista plików usług znajduje się w
katalogu /usr/lib/firewalld/services. Poniżej znajduje się
jej fragment. W przypadku usług panuje taka sama zasada jak w przypadku
stref.
[user@server10 ~]$ ls -l /usr/lib/firewalld/services/ razem 728 -rw-r--r--. 1 root root 399 2021-11-23 amanda-client.xml -rw-r--r--. 1 root root 427 2021-11-23 amanda-k5-client.xml -rw-r--r--. 1 root root 283 2021-11-23 amqps.xml -rw-r--r--. 1 root root 273 2021-11-23 amqp.xml -rw-r--r--. 1 root root 285 2021-11-23 apcupsd.xml -rw-r--r--. 1 root root 301 2021-11-23 audit.xml -rw-r--r--. 1 root root 320 2021-11-23 bacula-client.xml -rw-r--r--. 1 root root 346 2021-11-23 bacula.xml -rw-r--r--. 1 root root 429 2021-11-23 bb.xml -rw-r--r--. 1 root root 339 2021-11-23 bgp.xml -rw-r--r--. 1 root root 275 2021-11-23 bitcoin-rpc.xml -rw-r--r--. 1 root root 307 2021-11-23 bitcoin-testnet-rpc.xml -rw-r--r--. 1 root root 281 2021-11-23 bitcoin-testnet.xml -rw-r--r--. 1 root root 244 2021-11-23 bitcoin.xml -rw-r--r--. 1 root root 410 2021-11-23 bittorrent-lsd.xml -rw-r--r--. 1 root root 294 2021-11-23 ceph-mon.xml -rw-r--r--. 1 root root 329 2021-11-23 ceph.xml -rw-r--r--. 1 root root 168 2021-11-23 cfengine.xml
Poniżej znajduje się zawartość przykładowego pliku usługi:
[user@server10 ~]$ cat /usr/lib/firewalld/services/nfs.xml <?xml version="1.0" encoding="utf-8"?> <service> <short>NFS4</short> <description>The NFS4 protocol is used to share files via TCP networking. You will need to have the NFS tools installed and properly configure your NFS server for this option to be useful.</description> <port protocol="tcp" port="2049"/> </service>
20.2. Zarządzanie ruchem sieciowym w firewalld
Do zarządzania ruchem sieciowym posłużymy się poleceniem firewall-cmd. Wymagana ono uprawnień superużytkownika aby móc coś zmienić w zaporze. To polecenie posiada dużą ilość różnych opcji, jednak nie ma sensu ich tu przytaczać. Poznamy je w trakcie wykonywania przykładów z tego podrozdziału.
20.2.1. Sprawdzenie status zapory sieciowej
Sprawdzenia statusu zapory sieciowej możemy dokonać na dwa sposóby: mozemy wydać polecenie firewall-cmd z odpowiednią opcją lub sprawdzić status jednostki systemd firewalld.service. Poniżej znajdują się wyniki działania obu tych poleceń:
[user@server10 ~]$ sudo systemctl status firewalld.service [sudo] hasło użytkownika user: ● firewalld.service - firewalld - dynamic firewall daemon Loaded: loaded (/usr/lib/systemd/system/firewalld.service; enabled; vendor preset: enabled) Active: active (running) since Thu 2022-08-04 08:47:25 CEST; 2h 55min ago Docs: man:firewalld(1) Main PID: 720 (firewalld) Tasks: 4 (limit: 5891) Memory: 46.3M CPU: 7.278s CGroup: /system.slice/firewalld.service └─720 /usr/bin/python3 -s /usr/sbin/firewalld --nofork --nopid sie 04 08:47:24 server10.example.com systemd[1]: Starting firewalld - dynamic firewall daemon... sie 04 08:47:25 server10.example.com systemd[1]: Started firewalld - dynamic firewall daemon. [user@server10 ~]$ sudo firewall-cmd --state running
20.2.2. Dodowanie usług, portów oraz zarządzanie strefami
Zanim jednak zaczniemy dodwać usługi i porty wyświetlimy sobie domyślną strefę, a do tego posłuży opcja --get-default-zone polecenia firewall-cmd:
[user@server10 ~]$ sudo firewall-cmd --get-default-zone [sudo] hasło użytkownika user: public
Aby zmiany dokonane w zaporze zostały na stałe, należy każdą zmianę poprzedzić opcją --permanent. Usługi możemy dodwać za pomocą opcji --add-service. Podczas zapisywania opcji polecenia firewall-cmd możemy posłużyć się klawiszem Tab w celu autouzupełnienia. W ramach przykładu dodałem usługę http do domyślniej strefy.
[user@server10 ~]$ sudo firewall-cmd --permanent --add-service=http success
Aby ta reguła zadziałała firewalld musi ponownie wczytać plik strefy, aby to wymusić wydajemy polecenie firewall-cmd wraz opcją --reload.
[user@server10 ~]$ sudo firewall-cmd --reload [sudo] hasło użytkownika user: success
Za pomocą opcji --list-services, możemy wyświetlić reguły skonfigurowane do wskazanych usług:
[user@server10 ~]$ sudo firewall-cmd --list-services cockpit dhcpv6-client http ssh
Jak możemy zauważyć dodana usługa znajduje się na liście reguł.
Dodawanie portów wygląda podobnie do dodawania usług jednak używa się opcji --add-port=. Po podaniu portu należy również wskazać po ukośniku (/) protokół TCP czy UDP. Opcja ta pozwala również na podanie zakresu portów. Za pomocą poniższego polecenia dodałem porty TCP od 5901 do 5910, do strefy (--zone=) internal.
[user@server10 ~]$ sudo firewall-cmd --permanent --add-port=5901-5910/tcp --zone=internal [sudo] hasło użytkownika user: success
Za pomocą opcji --list-ports, możemy wyswietlić zasady skonfigurowane pod konkretne porty. Natomiast za pomocą opcji --zone możemy zarządzać innymi strefami.
[user@server10 ~]$ sudo firewall-cmd --list-ports --zone=internal 5901-5910/tcp
Za pomocą opcji --set-default-zone= możemy ustawić dowolną strefę jako tę domyślną dla naszego systemu:
[user@server10 ~]$ sudo firewall-cmd --set-default-zone=internal [sudo] hasło użytkownika user: success
20.2.3. Usuwanie portów oraz usług
Aby wycofać wcześniej wykonywane zmiany należy użyć opcji --remove-service= lub --remove-port=. Usunę na początku regułę odpowiedzialną za otworzenie zakresu portów z poprzedniego przykładu.
[user@server10 ~]$ sudo firewall-cmd --permanent --remove-port=5901-5910/tcp success [user@server10 ~]$ sudo firewall-cmd --reload success [user@server10 ~]$ sudo firewall-cmd --list-ports
Opcja --remove-port również pozwala na podanie zakresu. Również w tym przypadku wymagane jest podanie protokołu.
Teraz usunę również usługę HTTP, którą dodałem na początku, pamiętając o tym, że public to nie jest już moją domyślną strefą.
[user@server10 ~]$ sudo firewall-cmd --permanent --remove-service=http --zone=public success [user@server10 ~]$ sudo firewall-cmd --reload success [user@server10 ~]$ sudo firewall-cmd --list-services --zone=public cockpit dhcpv6-client ssh
Na koniec przywrócę moją domyślną strefę.
[user@server10 ~]$ sudo firewall-cmd --set-default-zone=public success [user@server10 ~]$ sudo firewall-cmd --get-default-zone public
20.2.4. Efektywność zapory firewalld
W tym przykładzie sprawdzimy sobie w jaki sposób zapora działa w praktyce. A przetestujemy to sobie usuwając regułę pozwalającą na połączenie się przez SSH na jednej z maszyn.
Czynności rozpoczynamy od ustalenia domyślnej strefy oraz czy występuje w niej usługa SSH.
[user@server10 ~]$ sudo firewall-cmd --get-default-zone public [user@server10 ~]$ sudo firewall-cmd --list-services cockpit dhcpv6-client ssh
Jak widzimy reguła SSH znajduje się na liście usług. Za pomocą opcji --remove-service= możemy usunąć tą regułę.
[user@server10 ~]$ sudo firewall-cmd --permanent --remove-service=ssh [sudo] hasło użytkownika user: success [user@server10 ~]$ sudo firewall-cmd --reload success [user@server10 ~]$ sudo firewall-cmd --list-services cockpit dhcpv6-client
Próba połączenia z tą maszyną z innej nie dochodzi do skutku.
[user@server20 ~]$ ssh server10 ssh: connect to host server10 port 22: No route to host
Aby zakończyć to ćwiczenie, ten przykład, dodajmy z powrotem regułę SSH do domyślnej strefy i spróbujmy się połączyć ponownie.
[user@server10 ~]$ sudo firewall-cmd --permanent --add-service=ssh success [user@server10 ~]$ sudo firewall-cmd --reload success [user@server10 ~]$ sudo firewall-cmd --list-services cockpit dhcpv6-client ssh
Tym razem próba kończy się powodzeniem.
[user@server20 ~]$ ssh server10 user@server10's password: Activate the web console with: systemctl enable --now cockpit.socket Register this system with Red Hat Insights: insights-client --register Create an account or view all your systems at https://red.ht/insights-dashboard Last login: Thu Aug 4 09:03:57 2022 from 192.168.122.7 [user@server10 ~]$
Ćwiczenie 1: Dodawanie usługi do zapory
Jako użytkownik z możliwością podniesienia uprawnień, na maszynie oznaczonej jako server10, dodaj na stałe regułę dla usługi HTTPS i aktywuj ją (--reload). Potwierdź wykonanie zadania wyświetlając plik strefy oraz za pomocą odpowiedniej opcji polecenia firewall-cmd.
Ćwiczenie 2: Dodawanie zakresu portów do zapory
Jako użytkownik z możliwością podniesienia uprawnień, na maszynie oznaczonej jako server10, dodaj zakres portów 8000-8005 UDP do strefy trusted i aktywuj go (--reload). Potwierdź wykonanie zadania wyświetlając plik strefy oraz za pomocą odpowiedniej opcji polecenia firewall-cmd.
Podsumowanie
W tym rodziale poruszyliśmy temat zapory sieciowej. Dowiedzieliśmy się jak ona działa oraz co realizuje jej funkcję w RHEL 9. Poznaliśmy podstawy teoretyczne oprogramowania firewalld oraz poznaliśmy najczęściej stosowane polecenia za pomocą pokazanych w tym rozdziale przykładów. W następnym rozdziale zapoznamy się mechanizmem SELinux.
21. Security Enchanced Linux
Security Enchanced Linux (SELinux) decyduje o tym co kto może zrobić w systemie. Ten mechanizm tworzy kolejną warstwę bezpieczeństwa ponad klasycznymi zabezpieczeniami jakie poznaliśmy do tej pory. Podstawowym celem SELinux jest możliwe jak największe zmniejszenie wpływu na system w momencie wystąpienia w nim nieuprawnionego dostępu.
21. Podstawy teoretyczne SELinux
SELinux jest implementacją mechanizmu MAC (Mandatory Access Control), który jest zintegrowany z jądrem Linuksa. MAC ogranicza możliwości dostępu podmiotu (użytkownik lub proces) do obiektu (pliki, katalogi, systemu plików, urządzenia, połączenia/interfejsy sieciowe, porty, potoki oraz gniazda). Dlatego też w przypadku wykorzystania podatności na przykład na serwerze WWW, atakujący będzie mieć wpływ tylko na pliki, do których miał dostęp ten proces.
Do zapewnienia kontroli, mechanizm MAC wykorzystuje zbiory zasad autoryzacyjnych zwanych polityką do sprawdzenia atrybutów podmiotu kiedy stara się on o dostęp do obiektu i decyduje czy udzielić tego dostępu. Atrybutu są zapisane w postaci kontekstu (lub etykiet) i dotyczą zarówno podmiotów jak i obiektów. Decyzje dokonane przez SELinux są zapisywane w specjalnym rodzaju pamięci podręcznej nazwanej AVC (Access Vector Control). W momencie gdy dochodzić do decyzji SELinux sprawdza tę pamięć podręczną czy nie udzielał już temu podmiotowi dostępu do tego obiektu. Jeśli tak obecną decyzje bazuje na tej podjętej wcześniej przez co nie musi on rozważać wszystkich możliwych zasad polityki wobec tej próby dostępu.
21.1.1. Pojęcia związane z SELinux
Aby obeznać się chociaż w podstawowym stopniu z SELinux należy poznać kilka pojęć, które będą używane podczas przedstawiania teorii tego mechanizmu ale również przykładów oraz ćwiczeń.
- Podmiot - każdy proces oraz użytkownik, który jest w stanie uzyskać dostęp do obiektu. Na przykład system_u - użytkownik systemu SELinux czy unconfined_u stosowany dla podmiotów, które nie są związane z polityką SELinux. Podmiot SELinux znajduje się w pierwszym polu kontekstu.
- Objekt - zasób systemowy, od plików po gniazda. Obiekty mogą zostać przestawione jako object_r - obiekt ogólny, system_r - obiekt systemowy albo unconfined_r - obiekt niezwiązny z SELinux.
- Dostęp - akcja dokonywana przez podmiot na obiekcie. W ramach dostępu możemy wyróżnić tworzenie, odczyt, modyfikację pliku, wyświetlenie zawartości katalogu czy próba dostępu do portu albo gniazda.
- Polityka - Zbiór zasad mający wpływ na cały system. Polityka jest wykorzystywana do analizy atrybutów podmiotów oraz obiektów. Na podstawie polityki SELinux dokonuje decyzji czy pozwolić podmiotowi na dostęp lub interakcje z obiektem. Jeśli brakuje pasującej zasady, wówczas domyślną decyzją jest odmowa. SELinux dostarczany jest wraz z dwoma standardowymi preconfigurowanymi politykami targeted oraz MLS, gdzie targeted wskazuje, że każdy ukierunkowany proces uruchamiany jest w ograniczonej domenie oraz każdy nieukierunkowany proces uruchomiony jest w nieograniczonej domenie. Na przykład SELinux umieszcza zalogowanego użytkownika w nieograniczonej domenie, a proces serwera WWW domyślnie w domenie ograniczonej. Każdy podmiot działający w domenie nieograniczonej jest większym żagrożniem niż ten, który działa w domenie ograniczonej.
- Kontekst - lub etykieta, jest to znacznik przechowywujący atrybuty. Każdy element w ujęciu SELinux posiada przypisany kontekst, który składa się z użytkownika SELinux, roli, domeny (czy też typu) oraz poziomu. SELinux, korzysta z konktekstu podczas podejmowania decyzji o przydzieleniu dostępu.
- Etykietowanie - mapowanie plików wraz z kontekstem.
- Użytkownik SELinux - predefiniowany w polityce użytkownik SELinux autoryzowany do określonego zbioru reguł. W polityce znajdują się mapowania użytkowników systemu na użytkowników SELinux, aby ograniczać ich możliwości. Użytkownik określa jakie role oraz domeny lub typy mogą zostać przypisane do procesu lub pliku . Jeśli użytkownik systemu będzie mieć przypisanego użytkownika user_u, nie będzie mógł wówczas uruchomić żadnego programu znajdującego się w swoim katalogu domowym oraz korzystać z takich poleceń jak su czy sudo.
- Rola - określa czy podmiot ma możliwość dostępu do domeny. Użytkownicy SELinux są autoryzowani do ról, natomiast role do domen oraz typów. Każdy podmiot ma określoną role aby odseparować procesy systemowe od procesów użytkowników. Podmioty mogą zmienić swoje role, aby zwiększyć dostęp do innych domen. Przykładowymi rola są: user_r - dla zwykłych użytkowników, sysadm_r - dla administratorów oraz system_r, dla procesów zaincjowanych pod tą rola. Rola zajmuje drugie pole kontekstu.
- Typ egzekwowania - identyfikuje oraz ogranicza możliwość dostępu procesów do domen oraz plików do typów. Odwołuje się do kontekstu podmiotów oraz obiektów.
- Typ - grupa obiektów bazująca na jednolitości wymagań bezpieczeństwa. Pliki oraz katalogi na podstawie wspólnych wymagań zabezpieczeń mogą zostać zgrupowane w jeden typ. Na przykład user_home_t dla obiektów znajdujących się w katalogach domowych użytkowników, czy usr_t dla większości obiektów znajdujących się w katalogach /usr.
- Domena - określa dostęp jaki posiada proces. Procesy ze wspólnymi wymogami bezpieczeństwa mogą zostać zgrupowane do jednej określonej domeny, przez co ich działania mogą zostać w niej ograniczone. Dla przykładu proces systemd działa w domenie unit_t a firewalld w firewalld_t. Typ lub domena znajdują się na trzecim polu kontekstu.
- Poziom bezpieczeństwa - poziom bezpieczńswa może być ujęty w dwóch rodzajach MLS (Multi-Level Security) lub MCS (Multi-Category Security). Poziom ten składa się z dwóch czynników: wrażliwości oraz kategorii Kategorie mogą być definiowane za pomocą pojedynczych wartości lub zakresów np. c0.c4 co oznacza kategorie od c0 do c4. Od RHEL 8 w polityce ukierunkowanej wymusza użycie rodzaju MCS, który określa tylko jeden poziom wrażliwości jakim jest s0 oraz 1024 kategorie od 0 do 1023.
21.1.2. Kontekst SELinux użytkowników
Za pomocą opcji -Z polecenie id możemy poznać kontekst SELinux użytkowników.
[user@server10 ~]$ id -Z unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
W polu użytkownika SELinux jego nazwa to
unconfined_u
co oznacza, że ma
nieograniczone możliwości. Superużytkownik również przypisanego ma
tego samego użytkownika. Pomimo tego SELinux dostarcza
siedemiu swoich użytkowników ograniczających wpływ
zwykłych użytkowników na system. Aby wyświetlić ich nazwy musimy
zainstalować pakiet setools-console.
[user@server10 ~]$ sudo seinfo -u [sudo] hasło użytkownika user: Users: 8 guest_u root staff_u sysadm_u system_u unconfined_u user_u xguest_u
Jak możemy zauwazyć unconfined_u
również jest jednym z użytkowników SELinux dla tego też mówimy
o siedmiu. Przypisanie go użytkownikom systemu wynika
z mapowania w polityce, a te możemy podejrzeć za pomocą polecenia
semanage wraz z pod poleceniem login oraz
opcją -l.
[user@server10 ~]$ sudo semanage login -l Login Użytkownik SELinuksa Zakres MLS/MCS Usługa __default__ unconfined_u s0-s0:c0.c1023 * root unconfined_u s0-s0:c0.c1023 *
W pierwszej kolumnie Login
znajdują
się nazwy użytkowników systemowych. Wartość
_default_
tyczy się wszystkich
zwykłych użytkowników.
21.1.3. Kontekst procesów
Za pomocą opcji -Z znanego już polecenia ps, możemy wyświetlić kontekst SELinux procesów. Ponizej znajduje się przykład:
[user@server10 ~]$ ps -eZ LABEL PID TTY TIME CMD system_u:system_r:init_t:s0 1 ? 00:00:01 systemd ...
W polu LABEL
znajduje się kontekst
SELinux. Podmiotem w tym przypadku jest użytkownik
SELinux system_u
(mapowany do superużytkownika), rolą, rola systemowa -
system_r
z typem ochrony nałożonym
przez domenę init_t
i poziomem
bepzieczeństwa wskazywanym przez s0
.
Każdy niechroniony proces działa w domenie unconfined_t.
21.1.4. Kontekst SELinux plików
Pliki oraz katalogi to obiekty SELinux one również posiadają kontekst, który może zostać wyświetlony za pomocą opcji -Z polecenia ls. Poniżej znajdują się atrybuty oraz kontekst dla pliku /etc/passwd.
[user@server10 ~]$ ls -lZ /etc/passwd -rw-r--r--. 1 root root system_u:object_r:passwd_file_t:s0 1764 08-03 08:46 /etc/passwd
Ten plik posiada rolę przeznaczoną dla zwykłych obiektów
(object_r
) oraz typ o nazwie
passwd_file_t
. Kontekst wszystkich
plików w systemie składowany jest dwóch plikach file_context
oraz file_context.local w katalogu
/etc/selinux/targeted/context/files. Kontekst może zostać
zmieniony za pomocą polecenia semanage.
21.1.5. Zachowanie kontekstu SELinux podczas zarządzania plikami
Domyślnie kopiując pliki z jednego katalogu do drugiego kontekst SELinux, zostanie odziedziczony z katalogu nadrzędnego, taka sama zasada tyczy się nadpisywania plików, wówczas plik źródłowy otrzyma kontekst SELinux od pliku, który został nadpisany. Aby zachować kontekst SELinux należy użyć opcji --preserve wraz z wartością context.
Przenoszenie nie ma wpływu na kontekst SELinux. Kontekst pozostaje w nienaruszonym stanie.
Jeśli istnieje potrzeba aby zachować kontekst SELinux w archiwach tar to należy użyć opcji --selinux.
Przetestujemy sobie część tych przypadków podczas przykładów.
21.1.6. Kontekst SELinux portów sieciowych
SELinux definiuje atrybuty bezpieczeństwa dla każdego rozdzaju obiektu w tym i dla portów. Typy (w ujęciu SELinux) dla portów możemy podejrzeć za pomocą polecenia semanage wraz z podpoleceniem port oraz opcją -l.
[user@rhel90 ~]$ sudo semanage port -l Typ portu SELinuksa Protokół Numer portu ftp_data_port_t tcp 20 ftp_port_t tcp 21, 989, 990 ftp_port_t udp 989, 990 http_port_t tcp 80, 81, 443, 488, 8008, 8009, 8443, 9000 ssh_port_t tcp 22
Wyjście prezentowane jest kolumnach, w przypadku portów spotykamy się z typem, tak jak w przypadku plików. Domyślnie SELinux pozwala na nasłuchiwanie usługom tylko na określonych przez typy portach.
21.1.7. Zmiana domeny SELinux
SELinux pozwala procesom na zmianę domeny, aby mogły uruchomić aplikację, która może działać tylko w jednej określonej domenie. Tego typu zachowanie jest oczywiście poparte regułami w polityce, które wspierają tego typu działania. Zmiana domeny możliwa jest za pomocą uprawnienia entrypoint, które kontroluje taką możliwość. Najprostszym tego przykładem jest zmiana hasła.
SELinux w swojej polityce posiada zasady, dzięki którym proces działający w domenie passwd_t może modyfikować plik z typem shadow_t. W tej polityce istnieje także uprawnienie entrypoint w domenie passwd_exec_t. Dzięki czemu polecenie passwd może modyfikować plik /etc/shadow, gdzie tak naprawdę nikt nie ma żadnych klasycznych uprawnień. Poniżej znajdują się atrybut wraz kontekstem zarówno polecenia passwd oraz pliku /etc/shadow.
[user@server10 ~]$ ls -lZ /usr/bin/passwd -rwsr-xr-x. 1 root root system_u:object_r:passwd_exec_t:s0 32648 2021-08-10 /usr/bin/passwd [user@server10 ~]$ ls -lZ /etc/shadow ----------. 1 root root system_u:object_r:shadow_t:s0 1368 08-03 08:47 /etc/shadow
21.1.8. Wartości logiczne SELinux
Wartości logiczne SELinux są używane jako przełączniki włączające lub wyłączające pozwolenie na wykonanie pewnej akcji. W ujęciu polityki przełączają one zasady bez potrzeby ich pownownego wczytywania. Za pomocą tych wartości możemy pozwolić aby anonimowi użytkownicy FTP mogli zapisywać na serwerze dane. Wszyskie te wartości są złożone w katalogu /sys/fs/selinux/booleans. Poniżej znajduje się fragment listingu tego katalogu, w systemie takim jak RHEL znajduje się wiele tych wartości
[user@server10 ~]$ ls -l /sys/fs/selinux/booleans/ | head razem 0 -rw-r--r--. 1 root root 0 08-06 09:07 abrt_anon_write -rw-r--r--. 1 root root 0 08-06 09:07 abrt_handle_event -rw-r--r--. 1 root root 0 08-06 09:07 abrt_upload_watch_anon_write -rw-r--r--. 1 root root 0 08-06 09:07 antivirus_can_scan_system -rw-r--r--. 1 root root 0 08-06 09:07 antivirus_use_jit -rw-r--r--. 1 root root 0 08-06 09:07 auditadm_exec_content -rw-r--r--. 1 root root 0 08-06 09:07 authlogin_nsswitch_use_ldap -rw-r--r--. 1 root root 0 08-06 09:07 authlogin_radius -rw-r--r--. 1 root root 0 08-06 09:07 authlogin_yubikey ...
Nazwa kazdego pliku odpowiada nazwie wartości używanej do zmiany jej stanu. Jeśli na podstawie nazwy nie możemy wywnioskować do czego służy podana wartość, to możemy zainstalować pakiet selinux-policy-doc i wyszukać odpowiednią stronę podręcznika podając nazwę wartości poleceniu man po opcji -K.
Możemy przeglądać wartości logiczne i zmieniać ich stan tymczasowo co nię będzie miało wpływu na politykę lub na stałe, wówczas te będzie musiało mieć już swoje odzwierciedlenie w polityce.
21.2. Zarządzanie SELinux
Zarządzanie SELinux to wiele zadań obejmujących aktywację mechanizmu, zmianę jego stanu operacyjnego, aktualizacje kontekstu zarówno podmiotów jak i obiektów oraz przełączanie wartości logicznych. W tym celu w RHEL znajduje się wiele narzędzi, które możemy wykorzystać do tego celu.
21.2.1. Polecenia zarządzające
RHEL dostarcza wiele poleceń, dzięki którym możemy realizować nasze zadania związane z SELinux. Wiele z nich odpowiada za konkretne czynności, jednak jedno semanage pozwala na zrealizowanie tych zadań dobierając odpowiednie podpolecenie. Innym poleceniem, na które należy zwrócić uwagę jest chcon, które pozwala na zmianę contekstu obiektu oraz restorcon, które przywraca kontekst z bazy (plików wymienionych w poprzednim podrozdziale, podczas omawiania kontektu plików). Poniżej znajdują się przykłady, dzięki którym poznamy jak należy zarządzać SELinux w praktyce oraz niezbędne do tego polecenia.
21.2.2. Zmiana stanu operacyjnego SELinux
Stan operacyjny tego mechanizmu możemy zmienić, zmieniając wartość jednej z dyrektyw w pliku konfigracyjny SELinux. W tym pliku możemy również wyłączyć ten mechanizm. Na poniższym przykładzie znajduje się jego zawartość:
[user@server10 ~]$ cat /etc/selinux/config # This file controls the state of SELinux on the system. # SELINUX= can take one of these three values: # enforcing - SELinux security policy is enforced. # permissive - SELinux prints warnings instead of enforcing. # disabled - No SELinux policy is loaded. # See also: # https://docs.fedoraproject.org/en-US/quick-docs/getting-started-with-selinux/ #getting-started-with-selinux-selinux-states-and-modes # # NOTE: In earlier Fedora kernel builds, SELINUX=disabled would also # fully disable SELinux during boot. If you need a system with SELinux # fully disabled instead of SELinux running with no policy loaded, you # need to pass selinux=0 to the kernel command line. You can use grubby # to persistently set the bootloader to boot with selinux=0: # # grubby --update-kernel ALL --args selinux=0 # # To revert back to SELinux enabled: # # grubby --update-kernel ALL --remove-args selinux # SELINUX=enforcing # SELINUXTYPE= can take one of these three values: # targeted - Targeted processes are protected, # minimum - Modification of targeted policy. Only selected processes are protected. # mls - Multi Level Security protection. SELINUXTYPE=targeted
Zachowanie SELinux możemy kontrolować za pomocą dyrektywy
SELINUX
. Dyrektwa może przyjmować
takie wartości jak:
- enforcing - wymuszając tym samym stosowanie polityki względem podmiotów.
- permissive - w tym przypadku SELinux nie będzie wymuszać stosowania polityki, ale jej naruszenia będą rejestrowane.
- disabled - wyłączenie ładowania polityki, co powoduje, że działanie SELinux nie będzie mieć wpływu na system.
Inna wartością kontrolujcą ten mechanizm jest dyrektywa
SELINUXTYPE
wymuszająca typ polityki.
Domyślnie stosowaną jest polityka ukierunkowana
(targeted
). Pozostałe wartości
znajdują się w komentarzu nad dyrektywą.
Do uzyskania informacji na temat działania SELinux możemy skorzystać z polecenia getenforce.
[user@server10 ~]$ sudo getenforce [sudo] hasło użytkownika user: Enforcing
Tymczasem do chwilowej zmiany stanu tego mechanizmu możemy użyć polecenia setenforce.
[user@server10 ~]$ sudo setenforce usage: setenforce [ Enforcing | Permissive | 1 | 0 ] [user@server10 ~]$ sudo setenforce 0 [user@server10 ~]$ sudo getenforce Permissive
Przy czym do wyboru mamy tylko Enforcing
(1
) lub
Permissive
(0
).
Aby jednak na stałe zmienić stan operacyjny SELinux musimy zmienić to pliku konfiguracyjnym a następnie uruchomić ponownie system.
Odnośnie egzaminu
Jeśli zajdzie taka potrzeba możemy przełączać się między stanami
operacyjnymi, aby na przykład rozwiązać problem z usługą.
Po rozwiązaniu problemów, możemy powrócić do normalnego stanu.
21.2.3. Sprawdzanie stanu SELinux
Z pomocą polecenia sestats, mozemy sprawdzić stan mechanizmu SELinux oraz wyświetlić kilka dodatkowych informacji na jego temat.
[user@server10 ~]$ sestatus SELinux status: enabled SELinuxfs mount: /sys/fs/selinux SELinux root directory: /etc/selinux Loaded policy name: targeted Current mode: enforcing Mode from config file: enforcing Policy MLS status: enabled Policy deny_unknown status: allowed Memory protection checking: actual (secure) Max kernel policy version: 33
Z informacji zwracanych przez to polecenie możemy wywnioskować w jakim
trybie działa SELinux
(Current mode:
) oraz rodzaj używanej
polityki (Loaded policy name:
).
Używając opcji -v możemy wyświetlić kontekst, niektórych plików oraz procesów. Są one zapisane w pliku /etc/sestatus.conf.
21.2.4. Modyfikowanie kontekstu SELinux plików
Do modyfikowania kontekstu słuzy polecenie chcon. Chcąc zmienić użytkownika SELinux używamy opcji -u, do zmiany typu wykorzystujemy opcję -t. Jeśli zmiany mają być rekurencyjne wówczas należy uzyć opcji -R. Na poniższym przykładzie zobrazowałem to zmieniając kontekst katalogu /tmp/testsedir1 w którym znajdował się plik testsefile2.
[user@server10 ~]$ ls -ldZ /tmp/testsedir1/ drwxr-xr-x. 2 user user unconfined_u:object_r:user_tmp_t:s0 25 08-06 12:34 /tmp/testsedir1/ [user@server10 ~]$ ls -lZ /tmp/testsedir1/testsefile2 -rw-r--r--. 1 user user unconfined_u:object_r:user_tmp_t:s0 0 08-06 12:34 /tmp/testsedir1/testsefile2 [user@server10 ~]$ sudo chcon -v -u user_u -t public_content_t /tmp/testsedir1 -R [sudo] hasło użytkownika user: zmiana kontekstu bezpieczeństwa '/tmp/testsedir1/testsefile2' zmiana kontekstu bezpieczeństwa '/tmp/testsedir1' [user@server10 ~]$ ls -ldZ /tmp/testsedir1/ drwxr-xr-x. 2 user user user_u:object_r:public_content_t:s0 25 08-06 12:34 /tmp/testsedir1/ [user@server10 ~]$ ls -lZ /tmp/testsedir1/testsefile2 -rw-r--r--. 1 user user user_u:object_r:public_content_t:s0 0 08-06 12:34 /tmp/testsedir1/testsefile2
Jak możemy zauważyć na powyższym przykładzie zmieniliśmy typ oraz użytkownika SELinux.
21.2.5. Dodwanie oraz zatwierdzanie kontekstu plików SELinux
Aby zatwierdzić zmieniony kontekst plików należy dodać go do bazy kontekstów. Do tego posłużymy się poleceniem semanage wraz z podpoleceniem fcontext, za pomocą opcji -a wskazujemy akcje dodania nowego kontekstu, opcja -s wskazuje na użytkownika SELinux, opcja -t wskazuje na typ w tym przypadku. Na końcu podajemy ścieżkę do pliku lub katalogu. Jeśli zmiany mają obejmować katalog wraz z jego zawartością to wówczas należy użyć wyrażenia regularnego: (/.*)? w ścieżce katalogu. Teraz dodam zmiany z wcześniejszego podrozdziału do bazy.
[user@server10 ~]$ sudo semanage fcontext -a -s user_u -t public_content_t '/tmp/testsedir1(/.*)?' [sudo] hasło użytkownika user: [user@server10 ~]$ sudo semanage fcontext -Cl fcontext SELinuksa typ Kontekst /tmp/testsedir1(/.*)? all files user_u:object_r:public_content_t:s0
Za pomocą opcji -Cl wyświetliłem ostatnie zmiany w bazie kontekstów plików SELinux. Teraz jeśli zmienimy kontekst tego katalogu lub któregoś z zawartych w nim plików to będziemy mogli powrócić do poprzedniego stanu za pomocą polecenia restorecon bazując na wpisie w bazie danych, który dodaliśmy we wcześniejszym przykładzie. Aby to za prezentować zmienię teraz kontekst zarówno katalogu jak i jego zawartości.
[user@server10 ~]$ ls -ldZ /tmp/testsedir1/ drwxr-xr-x. 2 user user user_u:object_r:public_content_t:s0 25 08-06 12:34 /tmp/testsedir1/ [user@server10 ~]$ ls -lZ /tmp/testsedir1/testsefile2 -rw-r--r--. 1 user user user_u:object_r:public_content_t:s0 0 08-06 12:34 /tmp/testsedir1/testsefile2 [user@server10 ~]$ sudo chcon -v -u user_u -t usr_t /tmp/testsedir1 -R zmiana kontekstu bezpieczeństwa '/tmp/testsedir1/testsefile2' zmiana kontekstu bezpieczeństwa '/tmp/testsedir1' [user@server10 ~]$ ls -ldZ /tmp/testsedir1/ drwxr-xr-x. 2 user user user_u:object_r:usr_t:s0 25 08-06 12:34 /tmp/testsedir1/ [user@server10 ~]$ ls -lZ /tmp/testsedir1/testsefile2 -rw-r--r--. 1 user user user_u:object_r:usr_t:s0 0 08-06 12:34 /tmp/testsedir1/testsefile2 [user@server10 ~]$ sudo restorecon -Rv /tmp/testsedir1/ Relabeled /tmp/testsedir1 from user_u:object_r:usr_t:s0 to user_u:object_r:public_content_t:s0 Relabeled /tmp/testsedir1/testsefile2 from user_u:object_r:usr_t:s0 to user_u:object_r:public_content_t:s0 [user@server10 ~]$ ls -ldZ /tmp/testsedir1/ drwxr-xr-x. 2 user user user_u:object_r:public_content_t:s0 25 08-06 12:34 /tmp/testsedir1/ [user@server10 ~]$ ls -lZ /tmp/testsedir1/testsefile2 -rw-r--r--. 1 user user user_u:object_r:public_content_t:s0 0 08-06 12:34 /tmp/testsedir1/testsefile2
Opcja -R
polecenia restorecon
włącza rekurencję, natomiast -v
włącza wyświetlanie komunikatów diagnostycznych.
Odnośnie egzaminu:
Podczas zmiany kontekstu plików oraz katalogów warto korzystać z
polecenia semanage oraz restorecon aby dodawać
kontekst do bazy a następnie przywrócić go na pliku. Przez co
będziemy mieć pewność że zmiany z pewnością przetrwają ponowne
uruchomienie serwera.
21.2.6. Dodawanie i usuwanie portów sieciowych w ujęciu SELinux
Jak mogliśmy się dowiedzieć domyślnie SELinux pozwala na nasłuchiwanie tylko na określonych typami portach więc jeśli nasza usługa musi nasłuchiwać na inny niż te w określonym type musimy dodać ten port do mechanizmu SELinux.
Dodawnie portów możemy zrealizować za pomocą polecenia semanage, ale na początku określimy typ portu SELinux. Za pomocą podpolecenia port wraz z opcją -l możemy wylistować wszystkie porty wraz z protokołami oraz typami portów. Załóżmy, że chcę dodać port do usługi http, wówczas możemy wyszukać portów powiązanych z tą usługą za pomocą polecenie grep.
[user@server10 ~]$ sudo semanage port -l | grep 'http' [sudo] hasło użytkownika user: http_cache_port_t tcp 8080, 8118, 8123, 10001-10010 http_cache_port_t udp 3130 http_port_t tcp 80, 81, 443, 488, 8008, 8009, 8443, 9000 pegasus_http_port_t tcp 5988 pegasus_https_port_t tcp 5989
Potrzebny port dodam do typu
http_port_t
.
[user@server10 ~]$ sudo semanage port -at http_port_t -p tcp 8010 [user@server10 ~]$ sudo semanage port -l | grep 'http_port_t' http_port_t tcp 8010, 80, 81, 443, 488, 8008, 8009, 8443, 9000
Aby dodać port użyłem podpolecenia
port
wraz z opcjami
-at
, które
nakazują dodanie portu oraz wskaznie na typ portu SELinux.
Następnie po opcji -p podałem protokół oraz numer portu.
Na koniec wyświetliłem jeszce ten typ portu, aby sprawdzić czy zmiany
zostały zatwierdzone.
Jeśli port przestanie nam być potrzebny możemy go usunąć, za pomocą opcji -d oraz opcji -p po której podajemy protokół i numer portu. Teraz usunę ten port, który wcześniej dodałem.
[user@server10 ~]$ sudo semanage port -d -p tcp 8010 [sudo] hasło użytkownika user: [user@server10 ~]$ sudo semanage port -l | grep 'http_port_t' http_port_t tcp 80, 81, 443, 488, 8008, 8009, 8443, 9000
Jak możemy zauważyć nie ma już portu 8010 na początku listy
przydzielonej do typu http_port_t
.
Odnośnie egzaminu
Aby korzystać z niestandarowych portów dla usług należy dodać je do
typów tych usług w SELinux.
21.2.7. Zachowanie kontekstu SELinux podczas kopiowania
Aby zachować kontekst SELinux dla kopiowanych plików, należy użyć opcji --preserve=context polecenia cp. W tym podrozdziale sobie to zobrazujemy. Nasz plik testowy w katalogu /tmp/testsedir1 prezentuje się z następującymi atrybutami:
[user@server10 ~]$ ls -lZ /tmp/testsedir1/testsefile2 -rw-r--r--. 1 user user user_u:object_r:public_content_t:s0 0 08-06 12:34 /tmp/testsedir1/testsefile2
Teraz jeśli przekopiuje go z pomocą polecenia cp do katalogu /var/local jego atrybuty będą prezentować się w następujący sposób.
[user@server10 ~]$ ls -ldZ /var/local/testsefile2 -rw-r--r--. 1 root root unconfined_u:object_r:var_t:s0 0 08-06 14:36 /var/local/testsefile2
Jak widzimy kontekst uległ zmianie. Jeśli jest to dla nas ważne z pewnych względów, to aby temu zapobiec należy używać opcji --preserve=context. Teraz usunę wcześniej skopiowany plik następnie skopiuje go jeszcze raz tym raz wykorzystując do tego wspomnianą opcję.
[user@server10 ~]$ sudo cp --preserve=context /tmp/testsedir1/testsefile2 /var/local/ [user@server10 ~]$ ls -ldZ /var/local/testsefile2 -rw-r--r--. 1 root root user_u:object_r:public_content_t:s0 0 08-06 14:40 /var/local/testsefile2
Jak widzimy, w tym przypadku kontekst nie uległ zmianie. Ta opcja tyczy się wyłącznie kopiowania, ponieważ przenoszenie nie zmienia kontekstu.
[user@server10 ~]$ sudo mv /tmp/testsedir1/testsefile2 /var/local/ [user@server10 ~]$ ls -ldZ /var/local/testsefile2 -rw-r--r--. 1 user user user_u:object_r:public_content_t:s0 0 08-06 12:34 /var/local/testsefile2
21.2.8. Zmiana wartości logicznych SELinux
Zabierając się za zmianę wartości logicznych SELinux warto, na początku upewnić się jaki stan mają wartości. Możemy to zrobić za pomocą trzech różnych narzędzi. Na potrzeby przykładu wybrałem wartość use_nfs_home_dirs. Poniżej znajdują się trzy możliwe sposoby na sprawdzenie stanu tej wartości.
[user@server10 ~]$ sudo semanage boolean -l | grep 'use_nfs_home_dirs' use_nfs_home_dirs (wyłączone,wyłączone) Allow use to nfs home dirs [user@server10 ~]$ sudo getsebool -a | grep 'use_nfs_home_dirs' use_nfs_home_dirs --> off [user@server10 ~]$ sudo sestatus -b | grep 'use_nfs_home_dirs' use_nfs_home_dirs off
Najlepszym sposóbem wydaje mi się, że jest użycie pierwszego polecenia, gdyż domyślnie zwraca więcej informacji. W nawiasie wyjścia tego polecenia możemy zauważyć dwa stany pierwszy z nich to stan obecny, natomiast drugi to stan pobrany z polityki.
Aby zmienić stan wartości logicznej należy użyć polecenia setsebool, jako argument to polecenie przyjmuje nazwę wartości oraz stan, w tym przypadku 0 lub 1.
[user@server10 ~]$ sudo setsebool use_nfs_home_dirs 1 [sudo] hasło użytkownika user: [user@server10 ~]$ sudo semanage boolean -l | grep 'use_nfs_home_dirs' use_nfs_home_dirs (włączone,wyłączone) Allow use to nfs home dirs
Teraz ta wartość jest włączona, ale jeśli uruchomie komputer ponownie, to wartość wróci do stanu określonego w polityce. Jeśli chcemy aby, zmiany były trwałe należy dodać do wcześniej użytego polecenia opcję -P.
[user@server10 ~]$ sudo setsebool -P use_nfs_home_dirs 1 [user@server10 ~]$ sudo semanage boolean -l | grep 'use_nfs_home_dirs' use_nfs_home_dirs (włączone,włączone) Allow use to nfs home dirs
Teraz stan wartości został ustawiony na stałe.
21.2.9. Monitorowanie naruszeń SELinux
Nie zależnie od trybu działania SELinux, generuje ostrzeżenia i zapisuje je za pomocą demona auditd do pliku /var/log/audit/audit.log lub przy użyciu rsyslog do pliku /var/log/messages jeśli demon audit jest niedostępny. Ostrzeżenia generowane są podczas odmowy dostępu i zapisywane wraz z odpowiednimi informacjami w wyżej wymienionych plikach. SELinux analizuje te ostrzeżenia w celach identyfikacji powodu odmowy dostępu. Wyniki tych analiz są zapisywane wraz z możliwymi rekomendacjami jak naprawić napotkamy problem.
Za pomocą polecenia sealert wraz z opcją -a możemy sprawdzić podany plik pod kątem występowania ostrzeżeń. Jeśli takowe wstąpią zostanie nam zwrócony na ten temat raport.
[user@server10 ~]$ sudo sealert -a /var/log/audit/audit.log 100% done found 0 alerts in /var/log/audit/audit.log
W moim systemie niestety brak alertów.
Ćwiczenie 1: Zmiana trybu operacyjnego SELinux
Jako użytkownik z możliwością podniesienia uprawnień na maszynie oznaczonej jako server1 wyłącz SELinux z poziomu pliku konfiguracyjnego, następnie uruchom ponownie komputer i sprawdź stan operacyjny SELinux. Następnie przywróć go z powrotem do trybu enforcing i znów uruchom ponownie komputer. Potwierdź zmianę trybu za pomocą odpowiedniego polecenia.
Ćwiczenie 2: Modyfikacja kontekstu plików
Jako użytkownik z możliwością podniesienia uprawnień na maszynie oznaczonej jako server1. Utwórz w katalogu /tmp katalog d1 zawierający podkatalog d2. Następnie zmień rekurencyjnie kontekst katalogu /tmp/d1 ustawiając typ SELinux etc_t. Potwierdź to następnie dodaj zmiany bazy kontekstów.
Ćwiczenie 3: Dodawanie portów
Jako użytkownik z możliwością podniesienia uprawnień na maszynie oznaczonej jako server1, dodaj port 8010 do typu SELinux dla usługi HTTP. Potwierdź wykonanie tej czynności.
Ćwiczenie 4: Kopiowanie plików z zachowaniem kontekstu
Jako użytkownik z możliwością podniesienia uprawnień na maszynie oznaczonej jako server1, utworz plik o nazwie sef2 w katalogu /tmp, wyświetl jego kontekst. Skopiuj go do katalogu /usr z zachowaniem kontekstu, ponownie wyświetl kontekst pliku w katalogu /usr aby upewnić się, że kontekst rzeczywiście się nie zmienił.
Ćwiczenia 5: Zmiana stanu wartości logicznej SELinux
Jako użytkownik z możliwością podniesienia uprawnień na maszynie oznaczonej jako server1, wyświetl stan wartości logicznej ssh_use_tcpd za pomocą polecenia getsebool oraz sestatus. Użyj odpowiedniego polecenia aby zmienić jej stan. Potwierdź to, wyświetlając go na wszystkie trzy sposoby.
Podsumowanie
Ten rozdział został poswięcony w pełni podstawom znajomości oraz obsługi mechanizmu SELinux. Poznaliśmy podstawy teoretyczne łącznie wymaganą do rozeznania w temacie terminologią. W dalszej części rozdzialu zapoznaliśmy się w jaki sposób możemy manipulować elementami tego mechanizmu w praktyce. Na koniec poznaliśmy metodę na monitorowanie ostrzeżeń generowanych przez SELinux. W następnym rozdziale zapoznamy się z podstawami tworzenia skryptów powłoki.
22. Skrypty powłoki
Skrypty powłoki są to listy poleceń zapisywane w jednym pliku tekstowym. Polecenia zapisane w skryptach są najzwyklejszymi poleceniami, tak jakbyśmy chcieli wykonać je z poziomu wiersza polecenia. Skrypty służą głównie automatyzacji nudnych oraz powtarzalnych zadań, na przykład w systemie należy utworzyć konta dla 100 użytkowników. Skrypty składają się z trzech głownych składników: poleceń/instrukcji, konstrukcji kontroli (tj. konstrukcji warunkowych oraz pętli) i komentarzy, które służą wyłącznie opisowi tego co się dzieje w skrypcie i nie biorą udziału w jego interpretacji. Skrypt powłoki są interpretowane przez powłokę, która jest uruchamiana wraz uruchomieniem skryptu. Rozwijane są użyte w skryptach wyrażania a polecenia są uruchamiane po kolei, jedno po drugim tak jak wpisywalibyśmy je ręczenie. W przypadku błędów powłoka zwróci odpowiedni komunikat oraz numer linii, w której ten błąd wystąpił.
22.1. Podstawy skryptów powłoki
Jeśli spytamy się kogo kolwiek jak jest najlepsza metoda nauki jakiegoś języka programowania, zapewne usłyszymy kilka zdań, które można streścić do: czytaj, zrozum, pisz, powtórz. Tak może być i w tym przypadku. Obecnie skrypty powłoki BASH uznawane są branży IT jako podstawowe narzędzie do automatyzacji i konstrukcje używane do budowy skryptów uznaje się za język programowania. Zatem zaczniemy od czegoś prostego, skryptu który wpisze nam podstawowe informacje o systemie.
[user@server10 ~]$ cat -n /usr/local/bin/sys_info.sh 1 #!/bin/bash 2 3 # Ten skrypt ma nazwe sys_info.sh i został napisany przez xf0r3m 8 sierpnia 2022 4 # Ten skrypt powinien znajdować się w katalogu /usr/local/bin 5 # Ten skrypt wyświetla podstawowe informacje o systemie: 6 7 echo "Podstawowe informacje o systemie:"; 8 echo "================================"; 9 echo; 10 echo "Nazwa komputera, informacje o sprzęcie oraz systemie operacyjnym:"; 11 /usr/bin/hostnamectl; 12 echo; 13 echo "Obecnie w systemie zalogowani są następujący użytkownicy:"; 14 /usr/bin/who;
Na początku każdego skryptu znajduje się nagłówek, w którym jest
ścieżka, wskazująca na program interpretera zawartości skryptu.
Nagłówek zaczyna się od specjalnego typu kometarza jakim jest
shebang (#!). W tym przypadku jest
wskazaniem na program bash
w katalogu
/bin
. W ten sposób wskazujemy, że
zawartością tego pliku będzie skrypt powłoki BASH. Kolejnymi
elementami skryptu są komentarze (zwykłe). Komentarz poprzedzony jest
tylko i wyłącznie krzyżykiem (#), w komentarzach
najczęściej umieszczane są wyjaśnienia bardziej skomplikowanych
konstrukcji lub toku myślenia programisty. Na początku skryptu
umieszcza się bardziej informacyjne treści jak nazwę skryptu, imię,
nazwisko, bądź pseudomnim autora; date jego wytworzenia; domyślną
lokalizacje; krótki opis co on robi oraz przykłady użycia. W dalszej
części przykładu znajdują się już właściwe polecenia. Polecenie
echo
służy do wypisywania na
stdout tego co zostanie podane jako argument polecenia. W
skryptach to polecenie służy do wyświetlania informacji w terminalu.
Później znajdują się polecenia, które odpowiadają za czynności, do
których skrypt został stworzony. Zwrócimy uwagę na to, że
są one zapisane w postaci plików, które rzeczywiście z tego polecenia
są odpowiedzialne. Ten zapis zapewnia, że napewno zostanie uruchmiony
ten program, a nie np. jakiś alias lub polecenie wbudowane.
hostnamectl
uruchomiony bez żadnych
argumentów, zwróci podsumowanie na temat używanego sprzętu oraz
systemu operacyjnego. Natomiast polecenie
who
wyświetla zalogowanych
użytkowników.
Dobrym miejscem na nasze skrypty jest katalog /usr/local/bin. Prze co będzie nam łatwiej je uruchamiać, ponieważ ten katalog znajduje się w ścieżce wyszukiwania poleceń każdego użytkownika. Niestety zapis do tego katalogu wymaga podniesienia uprawnień. Po zapisaniu takie skryptu jeśli zwrócimy uwagę na jego atrybuty, brakuje w nich bitu wykonania a on jest niezbędny aby można było taki program uruchomić.
[user@server10 ~]$ ls -l /usr/local/bin/sys_info.sh -rw-r--r--. 1 root root 494 08-08 08:38 /usr/local/bin/sys_info.sh
Bit nadamy każdej z grupie, żebyśmy mogli uruchomić go jako zwykły użytkownik. Do nadania bitu użyjemy polecenie chmod.
[user@server10 ~]$ sudo chmod +x /usr/local/bin/sys_info.sh [user@server10 ~]$ ls -l /usr/local/bin/sys_info.sh -rwxr-xr-x. 1 root root 494 08-08 08:38 /usr/local/bin/sys_info.sh
Teraz wszyscy mogą uruchomić ten plik, a z racji tego iż znajduje się on na ścieżce wyszukiwania poleceń wystarczy, że podamy w wierszu polecenia nazwę pliku.
[user@server10 ~]$ sys_info.sh Podstawowe informacje o systemie: ================================ Nazwa komputera, informacje o sprzęcie oraz systemie operacyjnym: Static hostname: server10.example.com Icon name: computer-vm Chassis: vm 🖴 Machine ID: 301347671a7c47a5934351c451479d32 Boot ID: bb68cbe389874bebaa4cf60693187c89 Virtualization: kvm Operating System: Red Hat Enterprise Linux 9.0 (Plow) CPE OS Name: cpe:/o:redhat:enterprise_linux:9::baseos Kernel: Linux 5.14.0-70.13.1.el9_0.x86_64 Architecture: x86-64 Hardware Vendor: Red Hat Hardware Model: KVM Obecnie w systemie zalogowani są następujący użytkownicy: user pts/0 2022-08-08 08:28 (192.168.122.1)
22.1.1. Debugowanie skryptu
Jeśli w skrypcie występuje jakiś problem możemy uruchomić go w trybie debugowania. Taki tryb dostępny jest albo poprzez dodanie do nagłówka skryptu opcji -x lub uruchomienia skryptu za pomocą polecenia bash wraz z opcją -x. W tym trybie będą wyświetlane wykonywane koleno polecenia wraz z rozwinięciami wyrażeń, czy przypisywane wartości zmiennym. Osobiście jako, że BASH jest moim podstawowym językiem to uważam, że ta opcja jest szczególnie przydatna oczywiście w bardziej zaawansowanych skryptach. Poniżej znajduje się wcześniej analizowany skrypt uruchomiony w trybie debugowania.
[user@server10 ~]$ bash -x /usr/local/bin/sys_info.sh + echo 'Podstawowe informacje o systemie:' Podstawowe informacje o systemie: + echo ================================ ================================ + echo + echo 'Nazwa komputera, informacje o sprzęcie oraz systemie operacyjnym:' Nazwa komputera, informacje o sprzęcie oraz systemie operacyjnym: + /usr/bin/hostnamectl Static hostname: server10.example.com Icon name: computer-vm Chassis: vm 🖴 Machine ID: 301347671a7c47a5934351c451479d32 Boot ID: bb68cbe389874bebaa4cf60693187c89 Virtualization: kvm Operating System: Red Hat Enterprise Linux 9.0 (Plow) CPE OS Name: cpe:/o:redhat:enterprise_linux:9::baseos Kernel: Linux 5.14.0-70.13.1.el9_0.x86_64 Architecture: x86-64 Hardware Vendor: Red Hat Hardware Model: KVM + echo + echo 'Obecnie w systemie zalogowani są następujący użytkownicy:' Obecnie w systemie zalogowani są następujący użytkownicy: + /usr/bin/who user pts/0 2022-08-08 08:28 (192.168.122.1)
Linie oznaczone plusem, są poleceniami zapisanymi w skrypcie. Pod nimi znajduje się wynik działania tego polecenia.
22.1.2. Zmienne
Jak pamiętamy albo nie z rozdziału o powłoce BASH, dostępne są dwa rodzaje zmiennych. Zmienne powłoki nazywane także zmiennymi prywatnymi lub lokalnymi, mogą być wykorzystywane w skryptach, nie tylko w obsłudze wiersza polecenia. W skryptach możemy również uzyskać dostęp do zmiennych środowiskowych.
[user@server10 ~]$ cat -n /usr/local/bin/use_var.sh 1 #!/bin/bash 2 3 echo "Ustawienie zmiennej powłoki"; 4 echo "==========================="; 5 SYSNAME="server10.example.com"; 6 echo "Nazwa komputera tej maszyny to: $SYSNAME";
W powyższym skrypcie utworzyłem jedną zmienną której nadałem przedstawioną wartość a następnie odwołałem się do niej w poleceniu echo. Warto tutaj też wspomnieć o tym, że każdy skrypt uruchamiany jest jako oddzielny proces powłoki BASH - uruchamiany jest w podpowłoce. Zmienne zdefiniowane w skrypcie nie będą dostępne, kiedy skończy on swoje działanie (chyba że do wykonania skryptu użyjemy polecenia source).
Dostęp do zmiennych środowiskowych wymaga jedynie odwołnia się do nich.
[user@server10 ~]$ cat -n /usr/local/bin/pre_env.sh 1 #!/bin/bash 2 3 echo "Lokalizacja mojej powłoki znajduje się: "; 4 echo $SHELL; 5 echo "Jestem zalogowany w systemie jako: $LOGNAME";
W bardziej zaawansowanych skryptach pożądane jest aby przechować wynik działania jakiegoś polecenia lub polecenia potokowego w zmiennej, żeby można było go użyć do różnych celów. Wynik działania tego polecenia może trafić do zmiennej za sprawą podstawienia polecenia. Poniżej znajduje się skrypt, w którym pokazano dwa sposoby na podstawienie polecenia do zmiennej.
[user@server10 ~]$ cat -n /usr/local/bin/cmd_out.sh 1 #!/bin/bash 2 3 SYSNAME=$(hostname); 4 KERNVER=`uname -r`; 5 6 echo "Nazwa komputera to: $SYSNAME"; 7 echo "Wersja jądra to: $KERNVER";
Jak widzimy podstawienie polecenia możemy dokonać na dwa sposoby
za pomocą nawiasów poprzedzonych znakiem dolara ($())
lub za pomocą ukośnego apostrofu (``). Ten skrypt
przechowuje w nazwę komputera w zmiennej
SYSNAME
oraz wersję jądra w zmiennej
KERNVER
. Te informacje zostały
zdefiniowane w zmiennych za pomocą mecanizmu podstawienia polecenia,
następnie zostały on wyświetlone przy użyciu polecenia echo.
22.1.3. Parametry powłoki
Chcąc przekazać jakieś informacje do skryptu z zewnątrz, możemy wykorzystać mechanizm parametrów powłoki. Wywołując jakieś polecenie w wierszu polecenia, zazwyczaj zapisujemy jego nazwę. To jest parametr powłoki. Wśrod parametrów powłoki możemy wyróżnić takie rzeczy jak zmienne, parametry specjalne oraz parametry pozycjne. Na potrzeby tego materiału zajmiemy się tylko parametrami pozycyjnymi oraz obsługującymi je parametrami specjalnymi. Nazwa polecenia lub skryptu jest pierwszym parametrem pozycyjnym. Każdy kolejny argument zapisany po nazwie polecenia to kolejny parametr pozycyjny. Parametry pozycyjne są liczone od zera. Możemy odwołać się do nich podając po znaku dolara numer parametru. Parametrów pozycyjnych może być wiele. Przy czym, aby odwołać się do parametru powyżej 9 należy umieść numer parametru w nawiasach klamrowych np. (${11}). Poniżej znajduje się skrypt oraz jego wywołanie, który obrazuje przekazanie parametrów do skryptu.
[user@server10 ~]$ cat -n /usr/local/bin/cmd_line_arg.sh 1 #!/bin/bash 2 3 echo "Do skryptu wprowadzono $# argumenty pozycyjne"; 4 echo "Są nimi kolejno: $*"; 5 echo "Pierwszym argument jest: $1"; 6 echo "Identyfikator powłoki uruchamiającej ten skrypt to: $$"; [user@server10 ~]$ /usr/local/bin/cmd_line_arg.sh test test2 test3 1 2 3 4 5 6 7 8 9 0 Do skryptu wprowadzono 13 argumenty pozycyjne Są nimi kolejno: test test2 test3 1 2 3 4 5 6 7 8 9 0 Pierwszym argument jest: test Identyfikator powłoki uruchamiającej ten skrypt to: 1874
W skrypcie odwołano się do drugiego parametru pozycjnego, czyli do argumentu o numerze 1 (linia: 5). W skrypcie użyto parametrów specjalnych takich jak: liczba przekazanych argumentów pozycyjnych - ($#); wszystkie przekazane argumenty - ($*) oraz numer PID podpowłoki, która jest odpowiedzialna za wykonanie tego skryptu - ($$).
Chcąc używać po kolei parametrów pozycyjnych, musimy tak też je zapisać w skrypcie, a co jeśli ilość tych zmiennych nie będzie nam znana. W tym przypadku wówczas możemy przesuwać wszystkie parametry o jeden w lewo. Jeśli użyjemy wartość drugiego parametru pozycjnego ($1) i nie będzie nam już ona potrzebna, możemy użyć polecenia shift, które przesunie wszystkie parametry o jeden w lewo (domyślnie, ponieważ polecenie to przyjmuje argument w postaci liczby, o ile wartości przesunąć parametry). Dlatego też wartość trzeciego parametru przejdzie na drugą pozycję, czwartego na trzecią itd. Po użyciu tego polecenia oryginalna wartość drugie parametru zostanie utracona. Poniżej znajduje się skrypt, w którym zobrazowano działanie tego polecenia.
[user@server10 ~]$ cat -n /usr/local/bin/cmd_line_arg_shift.sh 1 #!/bin/bash 2 3 echo "Do skryptu wprowadzono $# argumenty pozycyjne"; 4 echo "Są nimi kolejno: $*"; 5 echo "Pierwszym argument jest: $1"; 6 echo "Identyfikator powłoki uruchamiającej ten skrypt to: $$"; 7 shift; 8 echo "Nowym pierszym argumentem po pierwszym przesunięciu jest: $1"; 9 shift; 10 echo "Nowym pierwszy argumentem po drugim przesunięciu jest: $1";
Jak widzimy przy użyciu polecenia shift
nie musimy używać innych odwołań do parametrów poza odwołaniem do
drugiego (parametr o numerze 1).
22.2. Konstrukcje logiczne w skryptach powłoki
Konstrukcje logiczne nie tylko w skryptach powłoki mają za zadanie warunkować na podstawie wyrażeń logicznych wykonanie pewnych bloków kodu. Konstrukcje logiczne kontolują przepływ wykonania poleceń w skryptach. W BASH możemy spotkać z dwoma kontrukcjami logicznymi: konstrukcją if-then-fi oraz konstrukcją case. Omawianie konstrukcji case wychodzi poza ramy tego materiału, wiec skupimy się tylko if-then-fi i jej rozszerzeniach, ale najpierw zaczniemy od przedstawienia czym są kody wyjściowe oraz wyrażenia warunkowe.
22.2.1. Kody wyjściowe
Każde polecenie uruchomione w powłoce po zakończeniu pracy, nie ważne czy pomyślnie, czy nie zwraca do powłoki tzw. exit code - kod wyjściowy. Możemy użyć tych kodów w wyrażeniach warunkowych aby mieć pewność, że działanie polecenia uruchomionego w poprzedniej linii zakończyło się sukcesem i można kontynuować wykonywanie przez skrypt kolejnych zadań. Kod wyjściowy poprzedniego polecenia znajduje się w specjalnym parametrze powłoki $?.
[user@server10 ~]$ pwd /home/user [user@server10 ~]$ echo $? 0 [user@server10 ~]$ man Jakiej strony podręcznika potrzebujesz? For example, try 'man man'. [user@server10 ~]$ echo $? 1
Pierwsze polecenie, którego wykonanie zakończyło sie sukcesem zwróciło
kod wyjściowy 0
. Natomiast w przypadku
polecenia man
przy którym zapomniałem
o podaniu argumentu zwróciło wartość 1
.
W przypadku zastrzeżeń co do poprawnego wykonania zwracanym kodem
wyjściowym jest najczęściej wartość niezerowa, nie zawsze jest to 1.
Te wartości mogą być różne i zależne od programu.
Dlaczego mówie o kodach wyjściowych w przypadku konstrukcji logicznych, otóż powody są dwa. Można użyć kodów wyjściowych do budowania warunków, oraz konstrukcja if-then-fi podejmuje decyzje na podstawie kodu wyjściowego wyrażenia warunkowego. Zatem jeśli wyrażenie zwróci 0, to wówczas wykona się blok kodu zapisany po instrukcji then.
22.2.2. Wyrażenia warunkowe
Zadaniem wyrażenia warunkowego jest obliczenie równania logicznego. Na przykład czy: 3 < 4. Wynikiem takiego równia jest 1, czyli prawda, jeśli odwrócimy operandy równiania wówczas wówczas otrzymamy 0 czyli fałsz. Kiedy wyrażenie warunkowe obliczy prawdę wówczas zwraca kod wyjścia równy 0, a w przeciwnym wypadku jest 1. Elementami powłoki odpowiedzialnymi za wyrażenia warukowe jest polecenie test oraz rozszerzenie nawiasu kwadratowego ([]) i to tego rozszerzenia będziemy używać w konstrukcjach warunkowych. Na stronie podręcznika polecenia BASH w sekcji CONDITIONAL EXPRESSIONS znajdują się wszystkie dostępne operatory wyrażeń warunkowych jakie możemy użyć w skryptach.
Odnośnie egzaminu
Bardzo ważna jest dobra znajomość instrukcji logicznych oraz ich
operatorów.
22.2.3. Konstrukcja if-then-fi
Za pomocą konstrukcji if-then-fi możemy warunkować na podstawie kodu wyjściowego wykonanie poleceń zapisanych w konstrukcji. Poniżej znajduje się przykładowy skrypt zawierający tę konstrukcję.
[user@server10 ~]$ cat -n /usr/local/bin/if_then_fi.sh 1 #!/bin/bash 2 3 if [ $# -ne 2 ]; then 4 echo "Błąd. Nie poprawna liczba podanych argumentów"; 5 echo "Użycie $0 plik_zrodlowy plik docelowy"; 6 exit 2; 7 fi 8 echo "Skrypt zakończył swoje działanie";
Konstrukcję rozpocznamy od słowa kluczowego if następnie podajemy polecenie lub wyrażenie warunkowe, którego kod wyjściowy będzie decydować czy wykonać polecenia zawarte po słowie klczowym then na przykładzie są to linie od 4 do 6. Konstrukcja kończy się słowem kluczowym fi, które musi być zawarte inaczej próba uruchomienia takiego skryptu zakończy się błędem. Jako ciekawostkę podam, że blok zawarty po słowie then konczy się poleceniem exit, dzięki któremu możemy zakończyć działanie skryptu z określonym kodem wyjściowym.
Na zamieszczonym przykładzie użyłem do przedstawienia warunku
rozszerzenia nawiasu kwadratowego, w ktorym sprawdzam czy podano
dokładnie dwa paramentry pozycjne, operator którego użyłem
-ne
, który sprawdza czy lewy operand
jest nierówny prawemu. Jeśli tak, to kod wyjściowy warunku będzie
równy 0 i dojdzie do wykonania poleceń, co tym przypadku oznacza, że
podaliśmy jeden lub więcej niż dwa parametry pozycyjne podczas
uruchamiania tego skryptu.
22.2.4. Konstrukcja if-then-else-fi
Ta konstrukcja jest rozszerzeniem standardowej konstrukcji if. Zawiera ona dodatkowy blok else, który będzie wykonywany w momencie gdy kod wyjściowy warunku/polecenia będzie niezerowy.
[user@server10 ~]$ cat -n /usr/local/bin/if_then_else_fi.sh 1 #!/bin/bash 2 3 if [ $1 -gt 0 ]; then 4 echo "$1 jest wartością dodatnią"; 5 else 6 echo "$1 jest wartością ujemną"; 7 fi
W tym przypadku warunek w postaci rozszerzenia nawiasów kwadartowych
(najpopularniejsza forma warunków w skryptach powłoki) sprawdza czy
wartość podana jako drugi parametr pozycyjny jest większa od 0. Jeśli
tak, to wykonane zostanie polecenie znajdujące się w po słowie
then
a jeśli nie to polecenie po
słowie kluczowym else
.
22.2.5. Konstrukcja if-then-elif-fi
Rozszerzenie konstrukcji if o słowo kluczowe elif pozwala na zdefiniowane kolejnego warunku. W przypadku konstrukcji if-then-elif-fi, warunków możebyć nieskończeniei wiele i dodatkowo możemy zakończyć całą konstrukcję blokiem else.
[user@server10 ~]$ cat -n /usr/local/bin/if_then_elif_fi.sh 1 #!/bin/bash 2 3 if [ $1 -gt 0 ]; then 4 echo "$1 jest dodatnią wartością."; 5 elif [ $1 -lt 0 ]; then 6 echo "$1 jest ujemną wartością."; 7 elif [ $1 -eq 0 ]; then 8 echo "Podana wartość to 0."; 9 else 10 echo "Podano wartość, która nie jest cyfrą"; 11 fi
Na powyższym przykładzie drugi parametr pozycyjny poddawany jest wielu warunkom. Początkowy warunek sprawdza czy jest on większy od 0 (operator -gt), następnie czy może jest mniejszy od 0 (operator -lt) i ostatni czy jest on równy 0 (operator -eq). W bloku else znajduje się komunikat mówiący, że podana wartość nie jest liczbą, będzie on wykonywany gdy jako argument podamy literę lub znak specjalny. Podczas uruchomienia tego skryptu wraz z literowym argumentem możemy zauważyć błąd. Ten błąd jest generowany z tego względu, iż wymienione wyżej operatory są przeznaczone dla liczb całkowitych, a litera jest znakiem.
22.3. Konstrukcje pętli
Za pomocą konstrukcji pętli możemy wykonywać ten sam blok poleceń dla określonych, zmienianych w trakcie działania bloku pętli zmiennych. Zmienne w trakcie działania pętli najczęściej są iterowane - ich wartość zmienia się o jeden lub o jakąś stałą określoną wartość. W BASH-u dostępne są trzy rodzaje pętli: for-do-done, while-do-done oraz until-do-done. W tym materiale skupimy się tylko na pętli for-do-done.
22.3.1. Konstrukcja pętli for-do-done
Pętla for jest inną pętlą niż te dwie pozostałe, gdyż działa ona na określonej liście wartości, które są kolejno przypisywane zmiennej pętli. Pętla działa do momentu, aż wyczerpią się wszystkie elementy na liście. Poniżej znajduje się przykład skryptu w którym użyłem pętli for.
[user@server10 ~]$ cat -n /usr/local/bin/for_do_done.sh 1 #!/bin/bash 2 3 count=0; 4 for LETTER in {A..Z}; do 5 count=$((count + 1)); 6 echo "$count literą alfabetu jest [${LETTER}]"; 7 done
Pętla zaczyna się od słowa kluczowego
for
następnie zapisywana jest zmienna
pętli (LETTER
) po słowie kluczowym
in
występuje lista elementów, na
której operuje pętla ({A..Z}
) zwróćmy
uwagę na to, iż możemy definiować tutaj zakresy co pokazano na
przykładzie. Dla celów tego skryptu jeszcze przed pętlą utworono
zmienną, która jest w tym przypadku jej licznikiem. Jest ona bowiem
iterowana na początku bloku pętli, za pomocą wyrażenia arytmetycznego
($(())), w tym wyrażeniu nie odwołujemy się do
zmiennej tylko podajemy jej nazwę. Odwołanie nastąpi automatycznie
podczas interpretacji tego wyrażenia. Następnie wyświetlany jest
komunikat, zawierający licznik oraz zmienną pętli. Pętla wypisze
wszystkie litery alfabetu łacińskiego, poprzedzając je numerem w
kolejności.
Aby lepiej zobrazować sobie działanie pętli możemy uruchomić ten skrypt w trybie debugowania.
Ćwiczenie 1: Poprawienie skryptu
Jako użytkownik z możliwością podniesienia uprawnień na maszynie oznaczonej jako server10. Popraw skrypt z podrozdziału o konstrukcji if-then-elif-fi, tak aby nie wyświetlał błędu. Możesz posłużyć się stroną podręcznika powłoki BASH oraz trybem debugowania.
Podsumowanie
W tym rozdziale poznaliśmy podstawy tworzenie skryptów powłoki. Dowiedziliśmy się jaką budowę ma skrypt powłoki oraz poznaliśmy ich podstawowe elementy. Poznaliśmy konstrukcje warunkowe oraz prostą konstrukcję pętli jąką jest pętla for. Jeśli domyślnie nie korzystamy z powłoki BASH przestawione tutaj przykłady po drobnych przeróbkach będą działać na pozostałych powłokach Uniksa. W następnym już ostatnim rozdziale zapoznamy się z mechanizmem konteneryzacji dostępnym w RHEL.
23. Kontenery
Kontener to sposób na uruchomienie aplikacji w odrębnym środowisku dzięki czemu, może ona działać i wykonywać swoje zadania bez wpływu na inne procesy przy zachowaniu jak największej oszczędności zasobów systemu. Kontenery dostarczają do systemu właściwą aplikację wraz cały środowiskiem niezbędnym do jej działania, wygląda ona tak samo jakby była zainstalowana na fizycznym serwerze. Aplikacja uruchamiana w kontenerze nazywana jest aplikacją konteneryzowaną.
Kontenery do swojego działania wykorzystują funkcje jądra Linux, takie jak grupy kontrolne (przydzielanie zasobów procesom), przestrzeń nazw (udostępnienie zasobów systemowych takich jak interfejsy sieciowe) oraz moduł seccomp i SELinux, które odpowiadają za kontrolowanie dostępu procesów. Wykorzystując te komponenty kontenery zapewniają w pełni kontrolowane środowisko o wysokim stopniu bezpieczeństwa.
Korzystanie z kontenerów przynosi ze sobą wiele korzyści takich jak izolacja aplikacji w kontenerach, małe powiązanie z system w którym kontener działa, niezależność kontenerów wobec siebie czy mniejsze obciążenie systemu. Korzyści jest naprawdę bardzo dużo, dlatego też konterneryzacja wypiera wirtualizację, ale oczywiście to wszystko zależy od konkretnego przypadku.
Przy wyborze miejsca docelowego dla konternerów możemy zastanawiać się nad fizycznym serwerem albo maszyną wirtualna. Korzystanie z maszyn wirtualnych wprowadza dodatkową warstwę hipernadzorcy, który je kontroluje. W przypadku jeśli kontenery mają swiadczyć usługi, mogą on spokojnie rezydować na fizycznym serwerze, bez dodatkowych komplikacji. Więc wybór wydaje się dość łatwy.
Kontenery są rozprowadzane na zasadzie obrazów (ang. images) zawierających całe środowisko określonej aplikacji, dzięki czemu może poprawnie pracować w izolowanym środowisku. Mechnizmy konteneryzacji dostarczane wraz z RHEL, przestrzegają zasad Inicjatywy Otwartych Kontenerów - OCI, dzięki czemu użytkownicy mogą tworzyć obrazy o przemysłowych standardach. Do zarządzania obrazami OCI wykorzystywane są takie narzędzia Docker oraz dostarczany wraz z Red Hat podman. Obrazy OCI korzystają z kontroli wersji, tak więc możemy skorzystać z niekoniecznie najnowszej wersji, a pobrany obraz może być wykorzystywany w więcej niż jednym kontenerze.
Obrazy konternerów przechowywane są w rejestrach. Rejestry mogą być prywatne i aby pobrać obraz należy się zalgować lub mogą być ogólno dostępne, publiczne i każdy może pobierać z nich obrazy. W internecie dostępnych jest kilka rejestrów, z czego tylko trzy z nich wykorzystuje się w RHEL: Red Hat Container Catalog występujący w dwóch różnych rejestrach oraz Docker Hub. Przyczym tylko Docker Hub jest rejestrem publicznym. Obrazy posiadają swoje nazewnictwo, nazwane FQIN (ang. Full Qualified Image Name). Ta nazwa składa się czterech części:
- Nazwy rejestru
- Nazwy właściciela/Nazwy organizacji
- Nazwy repozytorium
- Wersji (opcjonalnie)
Po złożeniu tych elementów ścieżka może wyglądać w następujący sposób: nazwa_rejestru/nazwa_organizacji/nazwa_repozytorium:wersja.
Kontenery mogą być uruchamiane za równo przez superużytkownika - mowimy wtedy o kontenerach uprzywilejowanych oraz przez zwykłych użytkowników - wówczas mówi o kontenerach nieuprzywilejowanych. Główną różnicą jest brak możlwości mapowania portów (przekierowania) poniżej portu 1024. Warto dodać, że uruchamianie kontenerów uprzywilejowanych może powodować potencjalne problemy z bezpieczeństwem w systemie. Kontenery nieuprzywilejowanene dają możliwość interakcji z nimi z poziomu superużytkownika i jeśli nie będzie takiej potrzeby lepiej korzystać z tego rodzaju kontenerów.
23.1. Praca z obrazami oraz kontenerami
Do pracy z kontenerami RHEL dostarcza dwa narzędzia: wspomniany już wcześniej podman oraz skopeo. Przyczym wszystkie czynności będą operać się na wykorzystaniu polecenia podman. Polecenie skopeo posłuży nam tylko do pobrania bardziej szczegółowych informacji na temat dostępnego w rejestrze obrazu. W tym ostatnim rodziale skupimy się na praktyce. Jeśli będzie trzeba coś dopowiedzieć, zostanie to dopisane podczas omawiania danej kwestii. Do rozpoczęcia pracy z konterami, potrzebujemy oprogramowania oraz dostępu do rejestrów Red Hat. Najlepiej więc zarejestrować tę instalację systemu na koncie firmy Red Hat, wtedy bez problemu będziemy mogli zaktualizować system a następnie zainstalować potrzebne oprogramowanie.
23.1.1. Rejestrowanie systemu Red Hat
Za pomocą konsoli wirtualne również możemy zarejestrować system w sieci Red Hat, do tego służy polecenie subscription-manager wraz z podpoleceniem register. Polecenie to wydajemy z podniesieniem uprawnień. Do rejestracji potrzebna jest nazwa użytkownika (login) podawany podczas logowania do Red Hat, podajemy ją po opcji --username. Na poniższym przykładzie przedstawiam składnie polecenia oraz zwracane przez nie informacje
[xf0r3m@primeb450 ~]$ sudo subscription-manager register --username Registering to: subscription.rhsm.redhat.com:443/subscription Password: The system has been registered with ID: 12d0865f-3b78-4ce3-93db-b836b50ef879 The registered system name is: primeb450.morketsmerke.net
Moja nazwa użytkownika została ocenzurowana na tym przykładzie, także
po opcji --username
znajduje się
login do sieci Red Hat. Poprawność rejestracji możemy
sprawdzić za pomocą polecenia attach.
Poniżej pokazałem jak to wygląda w przypadku mojego serwera.
[xf0r3m@primeb450 ~]$ sudo subscription-manager attach [sudo] password for xf0r3m: All installed products are covered by valid entitlements. No need to update subscriptions at this time. Installed Product Current Status: Product Name: Red Hat Enterprise Linux for x86_64 Status: Subscribed
Teraz możemy korzystać z repozytoriów sieci Red Hat i na początek radzę zaktualizować system. Jeśli będziemy korzystać z tego systemu w celach innych niż testy jego i jego możliwości oraz zawartości, możemy podłączyć ten system już podczas instalacji.
[xf0r3m@primeb450 ~]$ sudo dnf update [sudo] password for xf0r3m: Updating Subscription Management repositories. Red Hat Enterprise Linux 9 for x86_64 - BaseOS (RPMs) 2.5 MB/s | 3.6 MB 00:01 Red Hat Enterprise Linux 9 for x86_64 - AppStream (RPMs) 6.1 MB/s | 9.2 MB 00:01 Dependencies resolved. ...
23.1.2. Instalacja oprogramowania kontenerów
Moduły RHEL 9 nie są jeszcze dostępne. Pojawią się dopiero w kolejnym mniejszym wydaniu (9.1), ale w repozytoriach znajduje się pakiet, który wraz z zależnościami odpowiada za obsługę kontenerów w tej wersji systemu Red Hat. Tym pakietem jest container-tools.
[xf0r3m@primeb450 ~]$ sudo dnf install container-tools [sudo] password for xf0r3m: Updating Subscription Management repositories. Red Hat Enterprise Linux 9 for x86_64 - BaseOS (RPMs) 8.2 kB/s | 4.1 kB 00:00 Red Hat Enterprise Linux 9 for x86_64 - AppStream (RPMs) 10 kB/s | 4.1 kB 00:00 Dependencies resolved. ============================================================================================================================ Package Architecture Version Repository Size ============================================================================================================================ Installing: container-tools noarch 1-10.el9 rhel-9-for-x86_64-appstream-rpms 8.7 k Installing dependencies: podman-docker noarch 2:4.1.1-1.el9_0 rhel-9-for-x86_64-appstream-rpms 42 k podman-remote x86_64 2:4.1.1-1.el9_0 rhel-9-for-x86_64-appstream-rpms 8.1 M python3-podman noarch 3:4.0.0-1.el9 rhel-9-for-x86_64-appstream-rpms 171 k python3-pyxdg noarch 0.27-3.el9 rhel-9-for-x86_64-appstream-rpms 108 k python3-toml noarch 0.10.2-6.el9 rhel-9-for-x86_64-appstream-rpms 46 k skopeo x86_64 2:1.8.0-4.el9_0 rhel-9-for-x86_64-appstream-rpms 6.7 M toolbox x86_64 0.0.99.3-3.el9_0 rhel-9-for-x86_64-appstream-rpms 2.2 M udica noarch 0.2.6-4.el9 rhel-9-for-x86_64-appstream-rpms 54 k Transaction Summary ============================================================================================================================ Install 9 Packages Total download size: 17 M Installed size: 65 M Is this ok [y/N]:
Teraz w systemie dostępne będą takie narzędzia jak podman oraz skopeo.
23.1.3. Polecenie podman
Polecenie podman jest podstawowym polecenień związanym z obsługą kontenerów na RHEL. Za jego pomocą będziemy wykonywać wiekszość czynności związanych z kontenerami. Poniżej znajdują się najczęściej wykorzystywane podpolecenia.
- images - wyświetla listę pobranych obrazów.
- pull - pobiera wskazany obraz z rejestru na dysk
- rmi - usuwa wskazany obraz.
- search - poszukuje obrazów pasujących do podanego słowa kluczowego.
- attach - podłącza powłokę pod uruchomiony kontener.
- exec - wykonuje polecenie na uruchomionym kontenerze.
- generate - generuje plik, np. jednostki systemd pozwalający na kontrolę kontenera jakby był zwykłą usługą.
- ps - wyświetla listę działających kontenerów, dodanie opcji -a, wyświetli listę zatrzymanych kontenerów.
- rm - usuwa kontenery.
- run - uruchamiana (instaluje) kontenery, jesli obraz kontenera nie istnieje na dysku zostanie pobrany z rejestru. To podpolecenie posiada kilka opcji, które będziemy poznawać podczas omawiania konkretnych przypadków uruchamiania kontenerów.
- start/stop/restart - podstawowe czynności wykonywane na konternerach, takie uruchomienie, zatrzymanie czy ponowne uruchomienie.
Odnośnie egzaminu:
Zrozumienie przedstawionych wyżej podpoleceń oraz swobodne używanie
polecenia podman jest kluczowe do wykonania zadań związanych
z kontenerami.
23.1.4. Polecenie skopeo
Polecenie skopeo służy do obsługi obrazów zarówno tych znajdujących się na dysku, jak i tych, które znajdują się w rejestrach. Nie mniej jednak w tym materiale skupimy się tylko na jednym podpoleceniu jakim jest podpoleceniem inspect, które zwraca szczegóły na temat obrazu.
23.1.5. Plik registries.conf
W pliku registries.conf przechowywane są adresy rejestrów, z których możemy pobierać obrazy kontenerów. Plik znajduje się w katalogu /etc/containers jest on plikem globalnym, a każdy z użytkowników może przychowywać swoją kopię pliku w katalogu ~/.config/containers, ustawienia zawarte w plikach użytkowników nadpisują te wartości z pliku globalnego, co może być przydatne w przypadku kontenerów nieuprzywilejowanych. Poniżej znajduje się zawartości tego pliku:
[xf0r3m@primeb450 ~]$ grep -v '^#' /etc/containers/registries.conf unqualified-search-registries = ["registry.access.redhat.com", "registry.redhat.io", "docker.io"] short-name-mode = "enforcing"
Plik zawiera masę komentarzy wyjaśniających wiele rzeczy. Nas jednak będzie interesować wyłącznie pierwsza linia zawierająca adresy rejestrów. W momencie poszukiwania obrazu polecenie podman odpytuje rejestry w zapisanej kolejności. Oczywiście jeśli jest taka potrzeba możemy dopisać swoje prywatne rejestry do tego pliku.
Odnośnie egzaminu:
Podczas egzaminu nie będzie dostępu do sieci, więc prawdopodbnie będzie
trzeba ustawić rejestr prywatny znajdujący się w sieci egzaminacyjnej.
23.1.6. Informacje nt. konfiguracji kontenerów w systemie
Pierwszą czynnością jaką poznamy odnośnie kontenerów jest sprawdzenie konfiguracji programu podman, możemy zrealizować to za pomocą podpolecenia info. Poniżej znajduje się fragment wyniku działania tego polecenia:
[xf0r3m@primeb450 ~]$ podman info host: arch: amd64 buildahVersion: 1.26.2 cgroupControllers: - memory - pids cgroupManager: systemd cgroupVersion: v2 conmon: package: conmon-2.1.2-2.el9_0.x86_64 path: /usr/bin/conmon version: 'conmon version 2.1.2, commit: 1ed53517f446a779f9d0edafe090ce821a41e255' cpuUtilization: idlePercent: 99.94 systemPercent: 0.02 userPercent: 0.04 cpus: 8 distribution: distribution: '"rhel"' version: "9.0" eventLogger: journald hostname: primeb450.morketsmerke.net ...
Polecenie to zwraca masę informacji od architektury przez informacje o zużyciu procesora, informacje o dystrybucji po informacje na temat pakietów odpowiedzialnych za kontenery w systemie oraz miejsce składowania obrazów. Warto wspomnieć że te informację mogą się różnić kiedy wydamy to polecenie z sudo, wówczas te informacje będą dotyczyć konfiguracji globalnej, przeznaczonej dla kontenerów uprzywilejowanych.
Po za tymi informacjami możemy za pomocą podpolecenia version zwrócić wersję polecenia podman oraz kilku dostarczanych wraz z nim składników.
[xf0r3m@primeb450 ~]$ podman version Client: Podman Engine Version: 4.1.1 API Version: 4.1.1 Go Version: go1.17.12 Built: Wed Jul 27 16:26:10 2022 OS/Arch: linux/amd64
23.2. Zarządzanie obrazami
Jedną z podstawowych czynności jakie możemy wykonać w obrębie kontenerów jest zarządzanie obrazami, czyli: wyszukanie, sprawdzenie szczegółów, pobranie oraz jego usunięcie. Tym zajmiemy się w tym podrozdziale.
Za pomocą polecenia podman z podpoleceniem search wyszukamy kontenera systemu bazodanowego MySQL.
[xf0r3m@primeb450 ~]$ podman search mysql registry.redhat.io/rhel8/mysql-80 This container image provides a containerize... registry.redhat.io/rhel9/mysql-80 rhcc_registry.access.redhat.com_rhel9/mysql-...
Te dwa obrazy wydają się najbardziej trafne. Opisy możemy rozwinąć
dodając opcję --no-trunc. W pierwszej kolumnie wyjścia tego
polecenia znajduje się FQIN w drugiej zaś opis obrazu. Obraz
jest przeznaczony dla rhel9
co możemy
wywnioskować po napisie znajującym się w drugiej części nazwy obrazu.
Aby poznać więcej szczegółów na temat tego obrazu posłużymy się
poleceniem skopeo wraz podpoleceniem inspect.
To polecenie przyjmuje jako argument FQIN poprzedzonym
wskazaniem protokołu Docker (docker://).
Poniżej znajdują się informacje jakie udało się uzyskać poleceniu
skopeo na temat tego obrazu.
[xf0r3m@primeb450 ~]$ skopeo inspect docker://registry.redhat.io/rhel9/mysql-80 FATA[0000] Error parsing image name "docker://registry.redhat.io/rhel9/mysql-80": unable to retrieve auth token: invalid username/password: unauthorized: Please login to the Red Hat Registry using your Customer Portal credentials. Further instructions can be found here: https://access.redhat.com/RegistryAuthentication
Jeśli rejestrowaliśmy system za pomocą polecenia subscription-manager potrzebne może być zalogowanie się za do rejestrów. Logowania dokonujemy za pomocą polecenia podman wraz podpolecenie login oraz polecenia skopeo wraz podpoleceniem login, przy czym przy poleceniu skopeo należy podać adres rejestru.
[xf0r3m@primeb450 ~]$ sudo podman login [sudo] password for xf0r3m: Username: Password: Login Succeeded! [xf0r3m@primeb450 ~]$ skopeo login registry.redhat.io Username: Password: Login Succeeded!
Polecenia zapytaja nas o nazwę użytkownika sieci Red Hat oraz o hasło. Moja nazwa użytkownika została ocenzurowana. Teraz powinniśmy otrzymać interesujące nas informacje na temat żądanego obrazu.
[xf0r3m@primeb450 ~]$ skopeo inspect docker://registry.redhat.io/rhel9/mysql-80 { "Name": "registry.redhat.io/rhel9/mysql-80", "Digest": "sha256:e6dbbce33d195df0380cb5b0207167be1ba45e4fe1229e50fc9d769b928e5cb7", "RepoTags": [ "1-190-source", "1-197-source", "1-190.1655192188-source", "1-206", "1", "1-206-source", "1-190.1655192188", "1-197", "1-190", "latest" ...
Na przykładzie znajduje się tylko fragment, ale to polecenie zwraca
bardzo dużo przydatnych informacji, na przykład przy kluczu
RepoTags
znajdują się dostępne wersje
tego obrazu jakie możemy pobrać podając je pod dwukropku na końcu
FQIN, domyślnie pobieraną wersją jest latest.
Inną ciekawą wartością jest klucz usage, który zwraca nam
całe polecenie, za pomocą którego możemy uruchomić ten kontener.
Za pomocą podpolecenia pull polecenia podman możemy pobrać wybrany przez nas obraz. To polecenie wymaga podania FQIN jako argumentu. Poniżej znajduje się wynik działania tego polecenia:
[xf0r3m@primeb450 ~]$ podman pull registry.redhat.io/rhel9/mysql-80 Trying to pull registry.redhat.io/rhel9/mysql-80:latest... Getting image source signatures Checking if image destination supports signatures Copying blob a021685edffe done Copying blob c6e5292cfd5f done Copying blob bf30f05a2532 done Copying blob f540faa799cb done Copying config 536612cfc7 done Writing manifest to image destination Storing signatures 536612cfc795266464d7828ff38ab12c44a55620174a769243d4cf31edadc8db
A tak przezentuje się obraz na liście obrazów polecenia podman:
[xf0r3m@primeb450 ~]$ podman images REPOSITORY TAG IMAGE ID CREATED SIZE registry.redhat.io/rhel9/mysql-80 latest 536612cfc795 7 days ago 558 MB
Aby poznać szczegóły pobranego już obrazu należy skorzystać z
podpolecenia inspect polecenia podman. Jako argument
wystarczy że podamy ostatni człon FQIN w tym przypadku będzie
to: mysql-80
.
[xf0r3m@primeb450 ~]$ podman inspect mysql-80 [ { "Id": "536612cfc795266464d7828ff38ab12c44a55620174a769243d4cf31edadc8db", "Digest": "sha256:e6dbbce33d195df0380cb5b0207167be1ba45e4fe1229e50fc9d769b928e5cb7", "RepoTags": [ "registry.redhat.io/rhel9/mysql-80:latest" ], ...
Jeśli obraz nie będzie nam już potrzebny możemy usunąć go z dysku za pomocą podpolecenia rmi polecenia podman. Podobnie jak w przypadku podpolecenia inspect wystarczy, że podamy ostatnią część FQIN.
[xf0r3m@primeb450 ~]$ podman rmi mysql-80 Untagged: registry.redhat.io/rhel9/mysql-80:latest Deleted: 536612cfc795266464d7828ff38ab12c44a55620174a769243d4cf31edadc8db
Aby potwierdzić usunięcie obrazu możemy jeszcze raz wyświetlić ich listę.
[xf0r3m@primeb450 ~]$ podman images REPOSITORY TAG IMAGE ID CREATED SIZE
23.3. Podstawy zarządzania kontenerami
Po opanowaniu obsługi obrazów przyszedł czas na pierwszy kontakt z kontenerami. Kontenery działają tak długo, jak działa aplikacja dla której są zbudowane. Trzeba sobie to wyjaśnić. Kontenery możemy podzielić na te nazwane oraz te bez nazw. Kontenery bez nazwy są jednorazowe i czesto usuwane po wykonaniu swojego zadania. Nie mniej jednak w tym pod rozdziale zajmiemy się zarówno jednym i drugim. Dla kontenerów na nazwanych wybrałem najnowszą wersję obrazu UBI czyli uniwersalnej bazy, która służy jako podstawa dla innych kontenerów zawierających już aplikacje.
23.3.1. Zarządzanie konterami nazwanymi
Aby uruchomić swój pierwszy kontenery należy na początku upewnić się, że w systemie w katalogu /etc nie znajduje się katalog docker. Jego obecność może powodować problemy z uprawnieniami.
[xf0r3m@primeb450 ~]$ ls -l /etc/docker ls: cannot access '/etc/docker': No such file or directory
Kiedy tego katalogu nie ma w systemie możemy przejść do uruchomienia kontenera za pomocą poniższego polecenia.
[xf0r3m@primeb450 ~]$ podman run -it --name rhel9-base-os ubi9 Resolved "ubi9" as an alias (/etc/containers/registries.conf.d/001-rhel-shortnames.conf) Trying to pull registry.access.redhat.com/ubi9:latest... Getting image source signatures Checking if image destination supports signatures Copying blob bf30f05a2532 done Copying blob c6e5292cfd5f done Copying config 168c58a383 done Writing manifest to image destination Storing signatures [root@baf4f328600d /]#
Za pomocą podpolecenia run
uruchomiłem
kontener w trybie interaktywnym (-it
).
Kontener nazwałem za pomocą opcji
--name
,
został on zbudowany w oparciu o obraz
ubi9
, czyli obraz bazowy RHEL
9. Nazwa obrazu została podana w krótkiej wersji, bez FQIN.
W przypadku innych kontenerów niż tez zbudowane na UBI
nie zaleca się używania tej formy przekazywania nazw obrazów. Polecenie
samo rozwiązało FQIN na podstawie informacji zawartych w
pliku
/etc/containers/registries.conf.d/001-rhel-shortnames.conf
.
Po pobraniu obrazu oraz uruchomieniu na jego podstawie kontenera,
została na zwrócona powłoka wewnątrz kontenera. W celach testowych
możemy wykonać kilka podstawowych poleceń:
[root@baf4f328600d /]# ls afs bin boot dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var [root@baf4f328600d /]# pwd / [root@baf4f328600d /]# whoami root [root@baf4f328600d /]# cat /etc/redhat-release Red Hat Enterprise Linux release 9.0 (Plow) [root@baf4f328600d /]# cat /etc/os-release NAME="Red Hat Enterprise Linux" VERSION="9.0 (Plow)" ID="rhel" ID_LIKE="fedora" VERSION_ID="9.0" PLATFORM_ID="platform:el9" PRETTY_NAME="Red Hat Enterprise Linux 9.0 (Plow)" ANSI_COLOR="0;31" LOGO="fedora-logo-icon" CPE_NAME="cpe:/o:redhat:enterprise_linux:9::baseos" HOME_URL="https://www.redhat.com/" DOCUMENTATION_URL="https://access.redhat.com/documentation/red_hat_enterprise_linux/9/" BUG_REPORT_URL="https://bugzilla.redhat.com/" REDHAT_BUGZILLA_PRODUCT="Red Hat Enterprise Linux 9" REDHAT_BUGZILLA_PRODUCT_VERSION=9.0 REDHAT_SUPPORT_PRODUCT="Red Hat Enterprise Linux" REDHAT_SUPPORT_PRODUCT_VERSION="9.0"
W znaku zachęty, w miejscu nazwy hosta znajduje się ciąg znaków przedstawiających identyfikator kontenera. Jeśli opuścimy powłokę kontenera, zostanie on zatrzymany ponieważ wykonane zostało jego domyślne zadaniem jakim była obsługa procesu powłoki. Zatem tego kontenera trzeba szukać na liście zatrzymanych kontenerów.
[root@baf4f328600d /]# exit exit [xf0r3m@primeb450 ~]$ podman ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES baf4f328600d registry.access.redhat.com/ubi9:latest /bin/bash 14 minutes ago Exited (0) 9 seconds ago rhel9-base-os [xf0r3m@primeb450 ~]$
Kontener ten możemy włączy ponownie, za pomocą podpolecenia start oraz nazwy kontenera.
[xf0r3m@primeb450 ~]$ podman start rhel9-base-os rhel9-base-os [xf0r3m@primeb450 ~]$ podman ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES baf4f328600d registry.access.redhat.com/ubi9:latest /bin/bash 16 minutes ago Up 3 seconds ago rhel9-base-os
Na kontenerach możemy wykonywać polecenia, bez podłączania się do ich powłoki, temu celowi służy podpolecenie exec. Wymaga ono podania nazwy uruchomionego kontenera oraz polecenia.
[xf0r3m@primeb450 ~]$ podman exec rhel9-base-os cat /etc/redhat-release Red Hat Enterprise Linux release 9.0 (Plow)
Jeśli jednak chcielibyśmy podłączyć się do powłoki kontenera, to wówczas należy użyć podpolecenia attach wraz z nazwą kontenera.
[xf0r3m@primeb450 ~]$ podman ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES baf4f328600d registry.access.redhat.com/ubi9:latest /bin/bash 18 minutes ago Up 2 minutes ago rhel9-base-os [xf0r3m@primeb450 ~]$ podman attach rhel9-base-os [root@baf4f328600d /]#
Po opuszczeniu powłoki, kontener zostanie zatrzymany. Jeśli nie potrzebujemy już w systemie kontenerów, możemy je usunąć za pomocą podpolecenia rm, przy czym należy upewnić się, że kontener jest zatrzymany inaczej polecenie niepowiedzie się.
[xf0r3m@primeb450 ~]$ podman ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES [xf0r3m@primeb450 ~]$ podman rm rhel9-base-os baf4f328600dad7e8fce03d854a6c4e480453679181f97233dccee5ea5a9e5dc [xf0r3m@primeb450 ~]$ podman ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
Za pomocą pierwszego wywołania podpolecenia ps upewniłem się, że kontener nie jest uruchomiony, następnie za pomocą podpolecenia rm usunąłem kontener. Za pomocą podpolecenia ps z opcją -a sprawdziłem czy kontener jest rzeczywiście usunięty.
23.3.2. Zarządzanie kontenerami bez nazw
Zarządzanie kontenerami bez nazw, jest znacznie prostsze, ponieważ może zostać sprowadzone do jednego polecenia. Poniżej przedstawiłem w jaki sposób można uruchomić kontener bez nazwy, aby wykonał proces do które został stworzony następnie został usunięty z systemu.
[xf0r3m@primeb450 ~]$ podman run --rm docker.io/library/hello-world Trying to pull docker.io/library/hello-world:latest... Getting image source signatures Copying blob 2db29710123e done Copying config feb5d9fea6 done Writing manifest to image destination Storing signatures Hello from Docker! This message shows that your installation appears to be working correctly. To generate this message, Docker took the following steps: 1. The Docker client contacted the Docker daemon. 2. The Docker daemon pulled the "hello-world" image from the Docker Hub. (amd64) 3. The Docker daemon created a new container from that image which runs the executable that produces the output you are currently reading. 4. The Docker daemon streamed that output to the Docker client, which sent it to your terminal. To try something more ambitious, you can run an Ubuntu container with: $ docker run -it ubuntu bash Share images, automate workflows, and more with a free Docker ID: https://hub.docker.com/ For more examples and ideas, visit: https://docs.docker.com/get-started/ [xf0r3m@primeb450 ~]$ podman ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES [xf0r3m@primeb450 ~]$ podman ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
Kontener zwrócił informacje powitalną podobnego systemu kontenerów jakim jest Docker, następnie został usunięty co zostało potwierdzone za pomocą dwóch ostatnich poleceń na przykładzie.
23.4. Zaawansowane zarządzanie kontenerami
Po poznaniu podstaw, możemy przejść do bardziej zaawansowanych czynności wykonywanych na kontenerach, takich jak mapowanie portów, przekazywanie zmiennych środowiskowych, katalogu hostującej maszyny czy zarządania kontenerami z poziomu systemd.
23.4.1. Mapowanie portów hosta na porty kontenera
Odnośnie egzaminu:
Podczas wykonywania tej czynność, należy pamiętać o bardzo ważnej
rzeczy. Mianowicie, kontenery nieuprzywilejowane nie mogą mapować
portów na porty hosta poniżej 1024 portu.
Mapowanie portów spowoduje, że jaki kolwiek ruch sieciowy, który będzie skierowany do określonego portu hosta zostanie przekierowny do portu kontenera. Tą czynność wykonuje się poprzez użycie opcji -p podpolecenia run. Rozważmy poniższym przykład.
Na początek pobiorę obraz serwera HTTP.
[xf0r3m@primeb450 ~]$ podman pull registry.redhat.io/rhel9/httpd-24 Trying to pull registry.redhat.io/rhel9/httpd-24:latest... Getting image source signatures ...
Następnie na podstawie tego obrazu przygotuje nazwany kontener z mapowaniem portów.
[xf0r3m@primeb450 ~]$ podman run -d -p 8080:80 --name rhel9-http-map registry.redhat.io/rhel9/httpd-24 cdb3fe727ec39de7323da49bb230f2dc22bdc51da43bc48e9218d2eeb09b166b [xf0r3m@primeb450 ~]$ podman ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES cdb3fe727ec3 registry.redhat.io/rhel9/httpd-24:latest /usr/bin/run-http... 3 seconds ago Up 4 seconds ago 0.0.0.0:8080->80/tcp rhel9-http-map
Za pomocą -d
kontener zostaje
odłączony od terminala i kontynuje pracę w tle. Przyczym ma to
zastosowanie wyłącznie w przypadku programów, które oczekują na
połączenia od innych np. demonów.
Teraz ruch przychodzący na port 8080 hosta zostanie
przekierowany do kontenera. Mapowania widać w kolumnie
PORTS
. Mapowania możemy zobrazować
lepiej za pomocą podpolecenia port polecenia podman,
przy czym to podpolecenie wymaga podania nazwy kontenera.
[xf0r3m@primeb450 ~]$ podman port rhel9-http-map 80/tcp -> 0.0.0.0:8080
Na koniec usunąłem ten kontener, za pomocą poniższych poleceń.
[xf0r3m@primeb450 ~]$ podman stop rhel9-http-map rhel9-http-map [xf0r3m@primeb450 ~]$ podman rm rhel9-http-map cdb3fe727ec39de7323da49bb230f2dc22bdc51da43bc48e9218d2eeb09b166b
23.4.2. Przekazywanie zmiennych środowiskowych do kontenerów
Nie które z konteneryzowanych aplikacji wymagają podania od użytkownika pewnych parametrów do uruchomienia. Te parametry przekazuje się za pomocą zmiennych środowiskowych, a są one przezkazywane za pomocą opcji -e podpolecenia run.
Odnośnie egzaminu:
Warto dodać, że przekazanie każdej wartości do kontenera wymaga podania
opcji -e.
Dobrze obrazuje to poniższy przykład.
[xf0r3m@primeb450 ~]$ podman run -dt -e VAR1="test1" -e VAR2="test2" --name rhel9-cont-env ubi9 13a244c2d73d2d604591ebbdf2112e222392f3f046b90e220e55397888cae80a [xf0r3m@primeb450 ~]$ podman exec rhel9-cont-env env TERM=xterm container=oci VAR1=test1 VAR2=test2 PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin HOME=/root
Za pomocą opcji -dt
umożliwiłem
działanie powłoki w tle (głownym procesem obrazów UBI jest
powłoka). Przy użyciu opcji -e
przekazałem do kontenera przedstawione na przykładzie zmienne
środowiskowe. W drugim poleceniu używając podpolecenia
exec
uruchomiłem na kontenerze
polecenie env
, które zwraca zmienne
środowiskowe. Jak wskazuje wynik działania tego polecenia, przekazane
przez nas wartości są obecne w środowisku kontenera jako zmienne
środowiskowe. Teraz możemy zatrzymać i usunąć ten kontener.
[xf0r3m@primeb450 ~]$ podman stop rhel9-cont-env rhel9-cont-env [xf0r3m@primeb450 ~]$ podman rm rhel9-cont-env 13a244c2d73d2d604591ebbdf2112e222392f3f046b90e220e55397888cae80a
23.4.3. Konfigurowanie miejsca na dane dla kontenerów
Kontenery działają tak długo, jak długo działa główny proces. Kiedy on kończy swoje działanie, tak i kontener zostaje zatrzymany. Zatrzymanie albo restart kontenera powodują utratę wszystkich wytworzonych przez niego danych. Jeśli te dane mogą być potrzebne, to należy zaopatrzyć kontenery w miejsce gdzie będą mogły je składować. Takim miejscem może być katalog znajdujący się gdzieś na hoście.
Odnośnie egzaminu:
Konfigurując taki katalog należy pamiętać o trzech czynnościach jakie
należy wykonać: 1. Odpowiednie uprawnienia, w przykładach będę stosować
raczej pełnych uprawnień, tj. 777; 2. Prawo własności, jeśli jest to
kontener nieuprzywilejowany to włascicielem oraz grupą, do której ten
katalog należy powinien być użytkownik, który uruchamia kontener;
3. Właściwy typ pliku SELinux, tej wartości nie trzeba
konfigurować ręcznie, wystarczy że podamy na koniec wartości
przekazywania katalogu
opcję :Z, spowoduje ona samodzielne przypisanie
odpowiedniego kontesktu SELinux.
Chcąc zobrazować jak może wyglądać takie przekazanie katalogu. Czynności należy rozpocząć od utworzenia katalogu, nadania mu odpowiednich uprawnień oraz prawa własności.
[xf0r3m@primeb450 ~]$ sudo mkdir /host_dir [sudo] password for xf0r3m: [xf0r3m@primeb450 ~]$ sudo chmod 777 /host_dir/ [xf0r3m@primeb450 ~]$ sudo chown xf0r3m:xf0r3m /host_dir/
Następnie uruchomie kontener przekazując ten katalog jako katalog /container_dir w głównym systemie plików kontenera.
[xf0r3m@primeb450 ~]$ podman run -dt --name rhel9-persistent-data -v /host_dir:/container_dir:Z ubi9 96e45fa0558c0d2da216de2c91747aae1fc177301ea58eb81571f200f8022fb2
Za pomocą opcji -v
dokonujemy
przekazania katalogu do kontenera. Zwróćmy uwagę na dodatkową opcję
:Z
, powoduje ona dobranie
odpowiedniego kontekstu SELinux. Teraz podłącze się pod
kontener aby sprawdzić uprawnienia przekazanego katalogu, kontekst
SELinux oraz to czy możemy przechowywać w nim dane.
[root@96e45fa0558c /]# ls -l total 0 dr-xr-xr-x. 2 root root 6 Aug 9 2021 afs lrwxrwxrwx. 1 root root 7 Aug 9 2021 bin -> usr/bin dr-xr-xr-x. 2 root root 6 Aug 9 2021 boot drwxrwxrwx. 2 root root 6 Aug 11 11:52 container_dir ... [root@96e45fa0558c /]# cd container_dir/ [root@96e45fa0558c container_dir]# echo "This is a test message!" > test_file.txt [root@96e45fa0558c container_dir]# ls -ldZ /container_dir drwxrwxrwx. 2 root root system_u:object_r:container_file_t:s0:c417,c733 27 Aug 11 11:55 /container_dir [root@96e45fa0558c container_dir]# ls -lZ /container_dir/ total 4 -rw-r--r--. 1 root root system_u:object_r:container_file_t:s0:c417,c733 24 Aug 11 11:55 test_file.txt
Jak możemy zauważyć na powyższym przykładzie katalog przekazany do
kontenera znajduje się w katalogu głównym tak jak to zostało zapisane
podczas jego utworzenia. Następnie sprawdziłem czy da się utworzyć
jakiś plik z zawartością w tym katalogu. Po wydaniu polecenia
echo
powłoka nie zwróciła żadnego
błędu więc można było przypuszczać, że zapis do pliku powiódł się.
Na koniec jeszcze sprawdziłem konteskt SELinux. Po zamknięciu
powłoki, sprawdziłem czy utworzony plik znajduje się w katalogu
przeznaczonym dla kontenera oraz plik posiada wcześniej zapisaną
zawartość. Możemy się o tym przekonać analizując poniższy przykład:
[xf0r3m@primeb450 ~]$ ls -l /host_dir/ total 4 -rw-r--r--. 1 xf0r3m xf0r3m 24 Aug 11 13:55 test_file.txt [xf0r3m@primeb450 ~]$ cat /host_dir/test_file.txt This is a test message!
Jak widzimy wszystko zadziałało. Teraz możemy usunąć ten kontener.
23.4.4. Kontrolowanie kontenerów przez systemd
Jeśli konterów w systemie jest bardzo wiele, łatwiej jest nimi zarządać za pomocą programu typu init, jakim jest systemd. Za pomocą podpolecenia generate polecenia podman, możemy wygenerować pliki jednostki usługi, dla każdego kontenera i zarządzać nimi jak usługami. Tego typu funkcja ma jedną bardzo ważną cechę przez co jest dość mocno wykorzystywana, mianowicie automatyczne uruchomienie kontenerów podczas startu systemu. Przy okazji tego zagadnienia również zauważymy różnicę między kontenerami nieuprzywilejowanymi oraz uprzyprzywilejowanymi, ponieważ przekazanie ich kontroli do systemd wygląda nieco inaczej.
Kontenery uprzywilejowane:
Na początku konfiguracji potrzebujemy kontenera. Utwórzmy prosty kontener na bazie UBI.
[xf0r3m@primeb450 ~]$ sudo podman run -dt --name rhel9-cont-systemd ubi9 [sudo] password for xf0r3m: Resolved "ubi9" as an alias (/etc/containers/registries.conf.d/001-rhel-shortnames.conf) Trying to pull registry.access.redhat.com/ubi9:latest... Getting image source signatures Checking if image destination supports signatures Copying blob bf30f05a2532 done Copying blob c6e5292cfd5f done Copying config 168c58a383 done Writing manifest to image destination Storing signatures d9ef99614a37c58d55edbca805cbc4da5bd99dae9c1674ed3c336893dbe901d6
Nie ma się co dziwić jeśli polecenie to pobierze jeszcze raz obraz. Wynika to z tego, że konfiguracja kontenerów nieuprzywilejowanych i tych uprzywilejowanych jest zupełnie inna, te kontenery również mają oddzielny katalog, który przechowuje ich obrazy. Po utworzeniu katalogu generujemy plik jednostki, zapisujemy go katalogu konfiguracji lokalnej /etc/systemd/system.
sudo podman generate systemd --new rhel9-cont-systemd | sudo tee /etc/systemd/system/rhel9-cont-systemd.service
Podpolecenie generate wymaga podania typu generowanego pliku
w tym przypadku jest systemd
. Użyłem
tutaj również opcji --new
, co powoduje
za każdym startem utworzenie nowego kontenera. Wynik musiałem
przepuścić przez polecenie tee
,
ponieważ przy użyciu operatora przekierowania nie damy rady zapisać
nic w tej
lokalizacji. Po utworzeniu tego pliku możemy załadować plik jednostki
i kontrolować kontener z poziomu systemd.
[xf0r3m@primeb450 ~]$ sudo systemctl daemon-reload [sudo] password for xf0r3m: [xf0r3m@primeb450 ~]$ sudo systemctl enable --now rhel9-cont-systemd.service Created symlink /etc/systemd/system/default.target.wants/rhel9-cont-systemd.service → /etc/systemd/system/rhel9-cont-systemd.service. [xf0r3m@primeb450 ~]$ sudo systemctl status rhel9-cont-systemd.service --no-pager ● rhel9-cont-systemd.service - Podman container-d9ef99614a37c58d55edbca805cbc4da5bd99dae9c1674ed3c336893dbe901d6.service Loaded: loaded (/etc/systemd/system/rhel9-cont-systemd.service; enabled; vendor preset: disabled) Active: active (running) since Thu 2022-08-11 14:44:32 CEST; 12s ago Docs: man:podman-generate-systemd(1) Process: 9123 ExecStartPre=/bin/rm -f /run/rhel9-cont-systemd.service.ctr-id (code=exited, status=0/SUCCESS) Main PID: 9294 (conmon) Tasks: 2 (limit: 48032) Memory: 980.0K CPU: 246ms CGroup: /system.slice/rhel9-cont-systemd.service └─9294 /usr/bin/conmon --api-version 1 -c fa9a83e06b6c9b75b64c69d80925b67e6d7458f3de5d78075b180bb2da0156fb -u fa9a83e06… [xf0r3m@primeb450 ~]$ sudo podman ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES fa9a83e06b6c registry.access.redhat.com/ubi9:latest /bin/bash 37 seconds ago Up 37 seconds ago rhel9-cont-systemd
Teraz możemy kontenery zatrzymywać oraz uruchamiać ponownie z poziomu polecenia systemctl. Zatrzymanie kontenera z tego poziomu spowoduje jego usunięcie z systemu. Utworzony plik usługi można traktować wówczas jako pliki szablonu dla kontenerów.
Kontenery nieuprzywilejowane:
W przypadku tego rodzaju kontenerów sprawa się dodatkowo komplikuje z powodu tego, iż kontenery są zatrzymywane w momencie wylogowania się użytkownika. Jednak w tym przypadku stosuje się sztuczkę, która powoduje pojawienia się użytkownika jeśli tylko jest potrzebny. Ta metoda nazywana jest lingering. Inną komplikacją jest fakt, że do obsługi systemd z poziomu zwykłego użytkownika, musi być on zalogowany albo fizycznie, albo za pomocą SSH, nie może być to przełączony użytkownik za pomocą poleceń sudo lub su.
Czynności tym razem zaczniemy od utworzenia katalogu ~/.config/systemd/user oraz włączenia lingeringu.
[xf0r3m@primeb450 ~]$ mkdir -p ~/.config/systemd/user [xf0r3m@primeb450 ~]$ loginctl enable-linger
Lingering włącza się za pomocą pojedynczego polecenia, wiec nie jest jakoś zbytnio skomplikowane, a naprawdę robi robotę. Teraz możemy przejść do utworzenia kontenera.
[xf0r3m@primeb450 ~]$ podman run -dt --name rhel9-unpriv-cont-systemd ubi9 fbe3ab11d3728470f1fcd38f07b99bd7e151ac2fc0c4a6a8dad85c486c3bce60
Tego przykładu chyba nie muszę tłumaczyć. Teraz wygeneruje plik jednostki dla tego kontenera w utworzonym wcześniej katalogu.
podman generate systemd --new rhel9-unpriv-cont-systemd > ~/.config/systemd/user/rhel9-unpriv-cont-systemd.service
Teraz mogłem użyć przekierowania, ponieważ cały czas działam w obrębie
tych samych uprawnień. Teraz załaduje plik jednostki i uruchomię
nowy kontener, tutaj też użyłem opcji
--new
.
[xf0r3m@primeb450 ~]$ systemctl --user daemon-reload [xf0r3m@primeb450 ~]$ systemctl --user enable --now rhel9-unpriv-cont-systemd.service Created symlink /home/xf0r3m/.config/systemd/user/default.target.wants/rhel9-unpriv-cont-systemd.service → /home/xf0r3m/.config/systemd/user/rhel9-unpriv-cont-systemd.service. [xf0r3m@primeb450 ~]$ systemctl --user status rhel9-unpriv-cont-systemd.service --no-pager ● rhel9-unpriv-cont-systemd.service - Podman container-fbe3ab11d3728470f1fcd38f07b99bd7e151ac2fc0c4a6a8dad85c486c3bce60.service Loaded: loaded (/home/xf0r3m/.config/systemd/user/rhel9-unpriv-cont-systemd.service; enabled; vendor preset: disabled) Active: active (running) since Thu 2022-08-11 15:02:52 CEST; 31s ago Docs: man:podman-generate-systemd(1) Process: 9876 ExecStartPre=/bin/rm -f /run/user/1000/rhel9-unpriv-cont-systemd.service.ctr-id (code=exited, status=0/SUCCESS) Main PID: 9914 (conmon) Tasks: 3 (limit: 48032) Memory: 1.4M CPU: 211ms CGroup: /user.slice/user-1000.slice/user@1000.service/app.slice/rhel9-unpriv-cont-systemd.service ├─9910 /usr/bin/slirp4netns --disable-host-loopback --mtu=65520 --enable-sandbox --enable-seccomp --enable-ipv6 -c -e 3… └─9914 /usr/bin/conmon --api-version 1 -c 73435f815694db611703dca5e48b52321f95849de15e6ac3cd2859f469a2d116 -u 73435f815… [xf0r3m@primeb450 ~]$ podman ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 73435f815694 registry.access.redhat.com/ubi9:latest /bin/bash 42 seconds ago Up 43 seconds ago rhel9-unpriv-cont-systemd
Jak widzimy na przykładzie kontener został uruchomiony, teraz uruchomie go ponownie za pomocą polecenia systemctl.
[xf0r3m@primeb450 ~]$ systemctl --user restart rhel9-unpriv-cont-systemd.service [xf0r3m@primeb450 ~]$ podman ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 810555dd08f1 registry.access.redhat.com/ubi9:latest /bin/bash 3 seconds ago Up 4 seconds ago rhel9-unpriv-cont-systemd [xf0r3m@primeb450 ~]$ systemctl --user restart rhel9-unpriv-cont-systemd.service && podman ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 433ac061577e registry.access.redhat.com/ubi9:latest /bin/bash Less than a second ago Up Less than a second ago rhel9-unpriv-cont-systemd
Różne identyfikatory kontenerów w pierwszej kolumnie, wyjścia polecenia
podman ps
wskazuje, że za każdym
ponownym aktywowaniem jednostki, tworzony jest nowy kontener. Po
wylogowaniu i zalogowaniu się ponownie, kontener nadal działa, co
oznacza, że lingering jest dobrze skonfigurowany.
[xf0r3m@primeb450 ~]$ exit logout Connection to 192.168.8.7 closed. [xf0r3m@latitude-e5270 ~]$ ssh 192.168.8.7 xf0r3m@192.168.8.7's password: Activate the web console with: systemctl enable --now cockpit.socket Register this system with Red Hat Insights: insights-client --register Create an account or view all your systems at https://red.ht/insights-dashboard Last login: Thu Aug 11 08:37:43 2022 from 192.168.8.168 [xf0r3m@primeb450 ~]$ podman ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 433ac061577e registry.access.redhat.com/ubi9:latest /bin/bash 3 minutes ago Up 3 minutes ago rhel9-unpriv-cont-systemd
Ćwiczenie 1: Utwórzenie laboratorium kontenerów
Na fizycznym komputerze lub maszynie wirtualne, zainstaluj system RHEL 9, zarejestruj go w sieci Red Hat podczas instalacji oraz utwórz użytkownika z uprawnieniami administratora. Po zainstalowaniu systemu zaktualizuj go i zainstaluj niezbędne oprogramowanie do obsługi kontenerów w systemie. Wykonanie tego ćwiczenia jest niezbędne do wykonania pozostałych.
Ćwiczenie 2: Nazwany kontener z mapowaniem portów
W laboratorium kontenerów, utworz uprzywilejowany kontener z mapowaniem portu 80:8080 oraz dowolną nazwą. Do tworzenia kontenera wykorzystaj obraz UBI dla RHEL 7. Wykonaj kilka poleceń takich jak: ls, pwd, df, cat /etc/redhat-release oraz cat /etc/os-release. Sprawdź mapowanie portów. Nie usuwaj jeszcze tego kontenera.
Ćwiczenie 3: Kontener bez nazwy z przekazanymi zmiennymi
W laboratorium kontenerów, na podstawie UBI dla RHEL 8 utwórz nieuprzywilejowany kontener bez nazwy z przekazaniem dwóch zmiennych VAR1="lab1" oraz VAR2="lab2". Działanie kontenera powinno polegać na wyświetleniu zmiennych środowiskowych, a kontener powinien zostać usunięty po skończeniu zadania. Na koniec usuń także obraz UBI dla RHEL 8.
Ćwiczenie 4: Kontener ze stałym miejscem przechowywania
W laboratorium kontenerów, utwórz katalog o nazwie /host_perm1 wraz z plikiem str1 przeznaczony na stałe miejsce dla danych kontenera uprzywilejowanego, następnie na podstawie UBI dla RHEL 9 utwórz kontener o nazwie priv-cont-str przekazując do niego ten katalog pod punkt montowania /cont_perm1. Przez powłokę kontenera sprawdź uprawnienia przekazanego katalogu oraz obecność pliku, następnie utwórz w nim dodatkowy podkatalog. Opuść powłokę kontenera i na hoście sprawdź obecność utworzonego podkatalogu. Na koniec usuń kontener oraz utworzony na potrzeby tego ćwiczenia katalog.
Ćwiczenie 5: Kontener z przekazywaniem portów, zmiennymi oraz stałym miejscem przechowywania
W laboratorium kontenerów, utworz katalog o nazwie /host_perm2 na stałe miejsce przechowywania dla kontenera nieuprzywilejowanego, na podstawie UBI dla RHEL 9 utwórz kontener o nazwie rootless-adv-cont w trybie interaktywym przekaż do niego dwie zmienne HISTSIZE=100 oraz MYNAME=RedHat zmapuj port hosta 9000 na port 8080 kontenera, przekaż wcześniej utworzony katalog pod punkt montowania /cont_perm2, sprawdź zmienne oraz punkt montowania, następie opuść powłokę i sprawdź czy mapowanie portów było prawidłowe. Nie usuwaj tego kontenera jeszcze.
Ćwiczenie 6: Konfigracja kontroli systemd nad kontenerami uprzywilejowanymi
Korzystając z kontenera z ćwiczenia drugiego, w laboratorium kontenerów skonfiguruj kontrolę tego kontenera przez systemd. Aby potwierdzić działanie konfiguracji zrestartuj system.
Ćwiczenie 7: Konfigracja kontroli systemd nad kontenerami nieuprzywilejowanymi
Korzystając z kontenera z ćwiczenia piątego, w laboratorum kontenerów skonfiguruj kontrolę tego kontenera przez systemd, zwróć uwagę na to iż jest to kontener nieuprzywilejowany. Aby potwierdzić działanie konfiguracji zrestartuj system.
Podsumowanie
W tym ostatnim już rozdziale zapoznaliśmy się technikami kontenerów w RHEL. Poznalismy niezbędną wiedzę teoretyczną oraz narzędzia potrzebne w praktyce. Poznaliśmy wiele przypadków praktycznej obsługi kontenerów, od przekazywania portów do przekazania kontroli nad konterami do programu typu init, jakim jest systemd zapoznaliśmy się też z konfiguracją plików jednostek użytkownika. Ten rozdział zamyka ten materiał. Jeśli chcemy więcej technologii Red Hat, możemy przystąpić kolejnego certyfikatu po zdaniu RHCSA. Powodzenia!