Moduł 2

Materiały do zajęć z Systemów operacyjnych prowadzonych na Wydziale Matematyki i Informatyki Uniwersytetu im. Adama Mickiewicza w Poznaniu.

« Wróć do spisu materiałów

Uprawnienia do plików i katalogów

Systemy uniksopodobne wywodzą się z systemu Unix, którego głównym założeniem była możliwość współdzielenia zasobów przez użytkowników. Wymusiło to wprowadzenie mechanizmów ochrony dostępów do elementów takich jak pliki, katalogi, czy urządzenia.

Jednym z popularniejszych powiedzeń związanych z systemami uniksopodobnymi jest: wszystko jest plikiem. Konstrukcja systemu sprawia, że rzeczywiste pliki z danymi, katalogi, ale także urządzenia fizyczne, takie jak modemy, dyski, klawiatury czy drukarki, oraz wirtualne, takie jak konsole wirtualne, są dostępne w strukturze plików. Korzystanie z nich (np. zapis do pliku, pisanie przy użyciu klawiatury, wyświetlenie danych w konsoli, wydruk dokumentu) opiera się na przesłaniu strumienia bajtów do odpowiedniego pliku.

Od tej pory pod pojęciem pliku rozumieć będziemy element struktury plików, będący regularnym plikiem, katalogiem, ale też dowolnym innym elementem, do którego można się odwoływać jak do pliku. Jeśli wymagane będzie rozróżnienie, zostanie to wyraźnie zaznaczone.

Korzystanie z elementów struktury plików wymaga od użytkownika posiadania odpowiednich uprawnień. Spójrzmy na przykładowy efekt wywołania polecenia ls -l:

total 36
-rw-rw---- 1 adam   studenci     52 Jul 30 18:17 ges
lrw----rw- 1 tomasz studenci     11 Jul 30 18:17 kaczka
drwx-w---- 2 piotr  doktorzy   4096 Jul 30 18:18 kon
drwx--x--x 2 adam   magistrzy  4096 Jul 30 18:16 krowa
drwx--x--x 2 adam   pracownicy 4096 Jul 30 18:16 malpa
drwx---r-- 2 tomasz doktorzy   4096 Jul 30 18:16 slon
drwx-wx-w- 2 tomasz magistrzy  4096 Jul 30 18:16 swinia
-rw----rwx 1 adam   pracownicy 3893 Jul 30 18:17 zebra
-rw--w---- 1 stefan studenci    384 Jul 30 18:17 zyrafa

Opcja -l polecenia ls umożliwia nam uzyskanie dostępu do rozbudowanych informacji o plikach znajdujących się w katalogu, na którym operujemy, opisujących kolejno:

Jak czytać uprawniania?

W systemach uniksopodobnych wyróżniamy następujące typy plików:

Pierwszy znak opisu uprawnień określa rodzaj pliku. Pozostałych 9 znaków opisuje uprawnienia do pliku nadane, odpowiednio, właścicielowi pliku, członkom grupy związanej z plikiem i innym użytkownikom. Mogą oni, niezależnie od siebie, posiadać prawa do:

pliku. Zbiór pełnych uprawnień do pliku opisujemy ciągiem rwx, a jeśli któreś z uprawnień nie występuje, jego symbol zastąpiony jest znakiem -. Tym samym możemy opisać zbiór uprawnień do pliku w jeden z następujących sposobów: ---, r--, -w-, --x, rw-, r-x, -wx lub rwx.

O ile w przypadku regularnych plików dość intuicyjnie można zrozumieć znaczenie poszczególnych uprawnień, o tyle w przypadku katalogów uprawnienia te należy interpretować następująco:

  • prawo odczytu (r) daje możliwość odczytania katalogu, to znaczy wypisania zawartości tego katalogu,
  • prawo zapisu (w) daje możliwość tworzenia, modyfikacji i usuwania elementów wewnątrz tego katalogu, jeśli istnieje prawo wykonania (x), inaczej nie ma znaczenia,
  • prawo wykonania (x) daje możliwość dostępu do katalogu i plików znajdujących się wewnątrz.

Spójrz raz jeszcze na efekt działania programu ls:

total 36
-rw-rw---- 1 adam   studenci     52 Jul 30 18:17 ges
-rw----rw- 1 tomasz studenci     11 Jul 30 18:17 kaczka
drwx-w---- 2 piotr  doktorzy   4096 Jul 30 18:18 kon
drwx--x--x 2 adam   magistrzy  4096 Jul 30 18:16 krowa
drwx--x--x 2 adam   pracownicy 4096 Jul 30 18:16 malpa
drwx---r-- 2 tomasz doktorzy   4096 Jul 30 18:16 slon
drwx-wx-w- 2 tomasz magistrzy  4096 Jul 30 18:16 swinia
-rw----rwx 1 adam   pracownicy 3893 Jul 30 18:17 zebra
-rw--w---- 1 stefan studenci    384 Jul 30 18:17 zyrafa

Określ, które elementy listy są katalogami, a które plikami. Następnie odpowiedz na pytanie, jakie uprawnienia do poszczególnych pozycji listy będzie miał:

  • użytkownik adam, będący członkiem grupy studenci,
  • użytkownik tomasz, będący członkiem grup doktorzy i pracownicy,
  • użytkownik piotr, będący członkiem grupy magistrzy,
  • użytkownik stefan, będący członkiem grup pracownicy oraz magistrzy,

Jakie musiały być uprawnienia do każdego z katalogów nadrzędnych, aby możliwe było uzyskanie zaprezentowanej listy?

Zobacz odpowiedź

Każdy z katalogów nadrzędnych musiał mieć prawo do wykonania, a katalog, którego zawartość odczytujemy, także prawo do odczytu. Jeśli katalog, którego zawartość odczytujemy nie ma praw do wykonania, a jedynie do odczytu, wówczas możemy wypisać listę elementów tego katalogu, ale nie uzyskamy dostępu do informacji innych niż nazwy elementów znajdujących się wewnątrz.

W momencie zalogowania się w konsoli wirtualnej lub przez interfejs pseudoterminala, zalogowanemu użytkownikowi nadawane są odpowiednie uprawnienia (w szczególności własność) do odpowiedniego pliku, reprezentującego to urządzenie.

Zaloguj się do serwera lts.wmi.amu.edu.pl, korzystając z protokołu ssh. Sprawdź nazwę swojego terminala (who), a następnie zweryfikuj i zinterpretuj uprawnienia do plików w katalogu /dev/pts.

Tak naprawdę uprawnienia do plików mogą być o wiele bardziej rozbudowane. Zaawansowane listy dostępu do plików można tworzyć i analizować przy użyciu programów setfacl oraz getfacl. Fakt, że takie listy obowiązują w przypadku wybranego pliku, można rozpoznać po dodatkowym symbolu +, znajdującym się za opisem uprawnień do wybranego pliku.

Czasem zdarza się też, że zamiast symbolu x, oznaczającego uprawnienia do wykonania pliku, obserwuje się symbol s lub S (w przypadku uprawnień właściciela i grupy) oraz t lub T (w przypadku innych użytkowników). Symbole te są związane ze specjalnymi uprawnieniami do plików i katalogów, w tym z tak zwanym sticky bit. Więcej informacji można znaleźć na stronach:

Zmiana uprawnień – polecenie chmod

Uprawnienia do plików można modyfikować przy użyciu polecenia chmod, przy czym na taki przywilej może sobie pozwolić jedynie właściciel pliku i superużytkownik root.

Utwórz w swoim katalogu domowym plik o nazwie sop.txt oraz katalog o nazwie sop. Wykonaj następujące polecenia i sprawdź uzyskane efekty:

$ chmod u-x sop
$ chmod g=rw,o+r sop sop.txt
$ chmod u+X sop sop.txt
$ chmod g=rwx sop.txt
$ chmod u+X sop sop.txt
$ chmod go-r sop sop.txt

Jak działa uprawnienie X? Korzystając z przedstawionej wyżej notacji symbolicznej:

  1. odbierz grupie uprawnienia do wykonania pliku sop.txt,
  2. wykonując jedno polecenie, dodaj grupie i innym użytkownikom prawo do odczytu pliku sop.txt oraz katalogu sop,
  3. odbierz właścicielowi prawo wykonania pliku sop.txt.

Zobacz odpowiedź

Uprawnienie X obejmuje tylko katalogi oraz pliki, które posiadają już jakiekolwiek prawo do wykonywania.

Sprawdź, czy polecenia cp oraz mv zachowują domyślnie uprawnienia do plików i katalogów. Jeśli nie, to jak sobie z tym poradzić?

Zobacz odpowiedź

Polecenie mv zachowuje uprawnienia, a polecenie cp nie. Aby to zmienić, należy wywołać polecenie cp z opcją -p.

Jak już zauważyliśmy, uprawnienia opisuje się oddzielnie dla właściciela (user), grupy (group) oraz innych użytkowników (other). Jeśli rozpatrzyć uprawnienia jako trzybitowe liczby, moglibyśmy zauważyć następującą zależność:

UprawnieniaBinarnieÓsemkowo
---0000
--x0011
-w-0102
-wx0113
r--1004
r-x1015
rw-1106
rwx1117

Uprawnienia do pliku możemy więc zapisać w postaci ciągu trzech cyfr ósemkowych (lub po prostu trzycyfrowej liczby ósemkowej).

Zapisz uprawnienia do plików z listingu

total 36
-rw-rw---- 1 adam   studenci     52 Jul 30 18:17 ges
-rw----rw- 1 tomasz studenci     11 Jul 30 18:17 kaczka
drwx-w---- 2 piotr  doktorzy   4096 Jul 30 18:18 kon
drwx--x--x 2 adam   magistrzy  4096 Jul 30 18:16 krowa
drwx--x--x 2 adam   pracownicy 4096 Jul 30 18:16 malpa
drwx---r-- 2 tomasz doktorzy   4096 Jul 30 18:16 slon
drwx-wx-w- 2 tomasz magistrzy  4096 Jul 30 18:16 swinia
-rw----rwx 1 adam   pracownicy 3893 Jul 30 18:17 zebra
-rw--w---- 1 stefan studenci    384 Jul 30 18:17 zyrafa

w postaci ciągu ósemkowej. Przykładowo, rw-rw---- można zapisać równoważnie jako 660.

Korzystając z notacji liczbowej, nadaj uprawnienia rw-r---- do pliku tekstowego sop.txt. W tym celu wykonaj polecenie

$ chmod 640 sop.txt

Analogicznie, nadaj:

  1. uprawnienia rwxrwxr-- do pliku sop.txt,
  2. uprawnienia r-x-wx-wx do pliku sop.txt,
  3. uprawnienia -w---x--- do pliku sop.txt,
  4. uprawnienia r-x------ do katalogu sop,

Utwórz w katalogu sop pliki a i b oraz katalog c, wewnątrz którego utwórz plik d. W tym celu nadaj sobie odpowiednie uprawnienia do katalogu sop. Wykonując jednokrotnie polecenie chmod, nadaj innym użytkownikom (other) prawo odczytu wszystkich elementów tej struktury oraz prawo wykonania tylko do katalogów w tej strukturze. Skorzystaj z opcji -R polecenia chmod.

Zobacz odpowiedź

$ chmod -R o=rX sop

W wyniku działania pewnego polecenia otrzymano na wyjściu następujący ciąg znaków:

drwx------ 6 adam ludzie 4096 Oct  8 16:11 muchomorek/
  1. Podaj pełną treść polecenia, które mogło zwrócić taki wynik. Załóż, że element o nazwie muchomorek znajduje się w bieżącym katalogu roboczym.
  2. Jakie polecenie należy wykonać, aby dodać członkom grupy ludzie prawo do odczytu i wykonania elementu muchomorek, a pozostałym użytkownikom prawo do jego odczytu? Zaproponuj co najmniej dwa rozwiązania wykorzystujące notację liczbową i symboliczną.

Zmiana właściciela – polecenia chown i chgrp

Każdy użytkownik systemu posiada swoją unikalną nazwę (login) oraz jedną grupę (group), z którą jest związany. Ponadto, każdy użytkownik może być przypisany do dowolnej liczby innych grup i traktowany jak ich członek.

Korzystając z polecenia id dowiedz się, jakich grup jesteś członkiem.

Gdy plik jest tworzony, system nadaje status właściciela temu kontu, które go utworzyło. Przypisuje też do pliku główną grupę związaną z właścicielem. Użytkownik posiadający uprawnienia superużytkownika (root) może zmienić właściciela dowolnego pliku przy użyciu polecenia chown oraz grupę związaną z plikiem przy użyciu polecenia chgrp. W nowszych systemach program chown pozwala na jednoczesną zmianę właściciela i grupy.

Dlaczego tylko użytkownik root może zmienić właściciela pliku?

Zapoznaj się z konstrukcją poleceń chown oraz chgrp. Jeśli masz dostęp do komputera, na którym możesz uzyskać uprawnienia użytkownika root, przetestuj działanie tych poleceń.

Wiemy już, że użytkownik może być członkiem wielu grup, a uprawnienia do plików mogą być związane z członkostwem w grupie przypisanej do nich. Nic nie stoi więc na przeszkodzie, aby utworzyć w systemie wiele grup i, operując uprawnieniami, uzależnić dostęp do pewnych zasobów systemowych (np. drukarek, urządzeń audio itp.) od członkostwa w danej grupie. To dosyć częste podejście.

Domyślne uprawnienia – umask

Kiedy tworzony jest katalog, domyślnie przypisywane są do niego uprawnienia 777. W przypadku plików jest to 666, ponieważ uprawnienia do wykonywania plików powinny być zawsze nadawane ręcznie. Polecenie umask pozwala na ustawienie maski dopełnień mmm, dzięki której domyślne uprawnienia będą równe 777 & ~mmm dla katalogów i 666 & ~mmm dla pozostałych plików.

Wykonując polecenie

$ umask

określ, jaka maska dopełnień jest stosowana dla katalogów i plików tworzonych przez Ciebie.

Jeśli maska dopełnień jest równa 014, to uprawnienia do nowo tworzonych katalogów będą równe

777 & ~014 = 111111111 & ~000001100
           = 111111111 & 111110011
           = 111110011
           = 763

a do plików

666 & ~014 = 110110110 & ~000001100
           = 110110110 & 111110011
           = 110110010
           = 662

Określ, jakie będą uprawnienia do nowo utworzonych plików i katalogów, jeśli maska dopełnień jest równa: 000, 022, 777 lub 002.

Wykonując polecenie

$ umask 002

zmień stosowaną maskę dopełnień na 002. Sprawdź, w jaki sposób wpływa to na uprawnienia do tworzonych plików i katalogów.

Sprawdź, co się stanie, jeśli wykonasz polecenia

$ umask u=,go=wx
$ umask u+r

Jaka maska będzie stosowana po pierwszym, a jaka po drugim wywołaniu? Jakie wnioski można z tego wynieść?

W ramach eksperymentu utworzono katalog zwirek. Okazało się, że domyślne uprawnienia do niego są równe r-xrw---x.

  1. Jaki będzie efekt wywołania polecenia umask?
  2. Jakie polecenie należy wykonać, aby domyślne uprawnienia do nowo tworzonych katalogów były równe rwxr-xr--?

Dowiązania

Do każdego elementu, w momencie tworzenia go w danym systemie plików, przypisuje się rekord zwany inode (ang. index node, i-węzeł). Rekord ten zawiera informacje o pliku, w tym te zwiazane z jego położeniem na fizycznym nośniku, takim jak partycja dysku twardego. Poszczególne i-węzły są związane z jednoznacznie identyfikującą je liczbą, zwaną numerem i-węzła. Katalog jest plikiem (bo wszystko jest plikiem...) zawierającym listę elementów w postaci <nazwa, numer i-węzła>. Nazwa pliku lub katalogu odnosi się więc do określonego węzła w określonym systemie plików.

I-węzeł zawiera wiele informacji o pliku – najkrócej można powiedzieć, że wszystkie, poza jego nazwą i zawartością. Szczegółowe omówienie tych zagadnień jednak znacząco wykracza poza materiał tego przedmiotu.[1]

Korzystając z opcji -i polecenia ls, poznaj numery i-węzłów, do których odwołują się pliki w Twoim katalogu domowym.

[1] Osoby zainteresowane mogą przeczytać więcej na temat struktury i-węzła na stronie https://pl.wikipedia.org/wiki/I-węzeł.

Dowiązania stałe

Jako że element katalogu jest uporzadkowanym zbiorem elementów postaci <nazwa, numer i-węzła>, nic nie stoi na przeszkodzie, aby z dwóch miejsc wewnątrz danego systemu plików odwoływać się do tego samego i-węzła. Takie odwołanie nazywamy dowiązaniem stałym (ang. hard link). Właściciel pliku (lub superużytkownik) może je utworzyć przy pomocy polecenia ln.

Zapoznaj się z dokumentacją polecenia ln. Następnie utwórz w swoim katalogu domowym plik a.txt oraz dowiązanie stałe do związanego z nim i-węzła – nazwij je b.txt. Sprawdź, jak zmieniła się liczba dowiązań stałych wyświetlana przy obu plikach po wywołaniu polecenia ls -l.

Sprawdź, jak zmieni się zawartość:

  1. pliku a.txt, jeśli zmienisz zawartość pliku b.txt,
  2. pliku b.txt, jeśli zmienisz zawartość pliku a.txt.

Dlaczego tak jest?

Sprawdź, jak zmienią się uprawnienia:

  1. do pliku a.txt, jeśli zmienisz uprawnienia do pliku b.txt,
  2. do pliku b.txt, jeśli zmienisz uprawnienia do pliku a.txt.

Dlaczego tak jest?

Usuwanie pliku w systemie plików opartym na i-węzłach to nic innego jak usunięcie dowiązania stałego do pliku (stąd usuwanie plików określa się niekiedy pojęciem unlink).

Utwórz w swoim katalogu domowym dowolny katalog. Dlaczego są do niego dwa dowiązania stałe? Jak zmieni się liczba dowiązań stałych do katalogu, jeśli w jego wnętrzu utworzysz: (a) plik, (b) katalog? Dlaczego tak jest?

Spróbuj utworzyć dowiazanie stałe do wybranego katalogu. Czy jest to możliwe? Sprawdź w dokumentacji programu ln, jak to zrobić i kto może wykonać taką operację.

Dowiązania symboliczne

Użytkownicy systemów z rodziny Windows przyzwyczajeni są do skrótów, które odwołują się do elementów zlokalizowanych w dowolnym miejscu struktury plików. W systemach uniksopodobnych rolę skrótów przejmują dowiązania symboliczne. Dowiązanie takie jest plikiem zawierającym ścieżkę do elementu docelowego.

Korzystając z opcji -s polecenia ln utwórz w swoim katalogu domowym dowiązanie symboliczne do pliku /etc/passwd i nazwij je dowiazanie. Czy możesz utworzyć dowiązanie stałe do tego samego pliku? Dlaczego?

Po wyświetleniu szczegółowej listy plików w katalogu domowym okaże się, że plik dowiazanie ma rozmiar 11 bajtów. Od czego zależy ten rozmiar? Utwórz kilka dowiązań symbolicznych (z wykorzystaniem ścieżek względnych i bezwzględnych) i porównaj otrzymane wyniki.

Utwórz dowiązanie symboliczne do dowolnego katalogu. Spróbuj zmienić nań katalog roboczy wykorzystując polecenie cd. W jaki sposób zachowuje się powłoka?

Zobacz odpowiedź

Powłoka traktuje dowiązanie symboliczne tak jak element istniejący w systemie plików.

Sprawdź, jakie uprawnienia posiadasz do utworzonych dowiązań symbolicznych. Jak zinterpretować te uprawnienia? Jak się do tego ma maska ustawiona przy użyciu polecenia umask?

Zobacz odpowiedź

Uprawnienia do utworzonych dowiązań symbolicznych są równe 777, aby pokryć wszelkie potencjalne uprawnienia elementu docelowego. Odwołanie się do dowiązania symbolicznego, do którego nie mamy prawa odczytu, zakończy się niepowodzeniem, nawet jeśli posiadamy odpowiednie uprawnienia do elementu docelowego.

Spróbuj utworzyć dowiązanie symboliczne do elementu, który nie istnieje. Czy jest to możliwe?

Zobacz odpowiedź

Tak, chociaż powłoka może zwrócić na to uwagę, np. kolorując na czerwono nazwę tego dowiązania na szczegółowej liście elementów zawartych w katalogu.

Wejście i wyjście

Kiedy w systemie uniksopodobnym uruchamiany jest program, tworzone są trzy kanały komunikacji pomiędzy tym programem a środowiskiem, w którym jest on uruchamiany (zwykle terminalem). Kanały te to:

Relacja pomiędzy programem a powyższymi strumieniami zaprezentowana została na poniższym rysunku.

Gdy program uruchamia się, otwierany jest kanał komunikacji pomiędzy nim a standardowymi strumieniami. Program odwołuje się do nich przez unikalny identyfikator, będący liczbą całkowitą. Identyfikator ten nazywamy deskryptorem pliku. Po uruchomieniu programu zdefiniowane są trzy deskryptory plików:

  • 0, dla strumienia stdin,
  • 1, dla strumienia stdout,
  • 2, dla strumienia stderr.

Sprawdź, do czego odwołują się pliki urządzeń: /dev/stdin, /dev/stdout oraz /dev/stderr.

Sprawdź, jak działają funkcje systemowe języka C: open, read oraz write. Co zwraca funkcja open? W jaki sposób deskryptor pliku wiąże się z funkcjami read oraz write?

Domyślnie, zarówno standardowe wejście, jak i oba wyjścia związane są z terminalem (konsolą lub wirtualną konsolą). W praktyce oznacza to, że do strumienia standardowego wejścia trafią wszystkie znaki wprowadzane za pomocą klawiatury,* a każdy znak przesłany przez program do standardowego strumienia wyjścia lub strumienia błędów zostanie wyświetlony w terminalu.

* Zaawansowani użytkownicy zdają sobie pewnie sprawę z tego, że to stwierdzenie nie jest do końca poprawne. W rzeczywistości większość programów powłoki buforuje dane przed przesłaniem ich do standardowego wejścia, czekając na znak końca linii lub końca pliku.

Potoki i polecenie tee

Czasem zachodzi potrzeba, aby standardowe wyjście jednego z programów było traktowane jako standardowe wejście drugiego. Idea ta została zwizualizowana na poniższym rysunku. Taki przepływ danych nazywamy potokiem.

W powłoce Bash potok wprowadza się przy użyciu symbolu |.

Korzystając z mechanizmu potokowania, wyświetl przy pomocy programu less (poznanego przy okazji eksplorowania podręczników programów) szczegółową listę elementów znajdujących się w katalogu /etc. W tym celu wykonaj polecenie:

$ ls -l /etc | less

Mechanizm potokowania nie czeka na zakończenie działania jednego programu przed uruchomieniem drugiego. Tak naprawdę przepływ danych pomiędzy odpowiednimi strumieniami stdout oraz stdin odbywa się w czasie rzeczywistym (buforowanym linia po linii, podobnie jak w przypadku standardowego wejścia z klawiatury). Łatwo to zweryfikować wykonując polecenie:

$ for I in {1..50}; do echo $I; sleep 0.2; done | less

Wśród ciekawych programów związanych z obsługą potoków warto wymienić program o nazwie tee. Jego działanie jest następujące: dane ze standardowego wejścia przesyła on do standardowego wyjścia, zapisując je po drodze we wskazanym pliku.

Zmodyfikuj polecenie z poprzedniego ćwiczenia tak, aby lista elementów z katalogu /etc została dodatkowo zapisana w pliku lista-etc w Twoim katalogu domowym.

Zobacz odpowiedź

$ ls -l /etc | tee lista-etc | less

Łączenie plików – polecenia cat i tac

Polecenie cat wypisuje przez standardowy strumień wyjścia, bajt po bajcie, zawartość plików, których nazwy przekazane są do niego jako argumenty. Jeśli polecenie cat zostanie wywołane bez argumentów, wypisuje przez standardowy strumień wyjścia dane ze standardowego strumienia wejścia.

Wykonaj polecenie:

$ cat ~/lista-etc /etc/passwd

Zweryfikuj otrzymane efekty.

Wywołaj polecenie cat bez argumentów. Wprowadź kilka wierszy tekstu – każdy z nich zakończ wciśnięciem klawisza Enter. Wprowadzanie danych zakończ kombinacją klawiszy Ctrl + D (znak końca pliku). W jaki sposób zachowuje się program cat?

Polecenie tac ma działanie zbliżone do cat z tą różnicą, że wiersze plików, których nazwy przekazane są jako argumenty, wypisuje w odwrotnej kolejności (a więc od ostatniego do pierwszego). Jeśli polecenie tac zostanie wywołane bez argumentów, wypisze ono dane ze standardowego wejścia począwszy od ostatniego wiersza.

Wykonaj polecenie:

$ tac ~/lista-etc /etc/passwd

Zweryfikuj otrzymane efekty.

Wywołaj polecenie tac bez argumentów. Wprowadź kilka wierszy tekstu – każdy z nich zakończ wciśnięciem klawisza Enter. Wprowadzanie danych zakończ kombinacją klawiszy Ctrl + D (znak końca pliku). W jaki sposób zachowuje się program tac? Dlaczego, w przeciwieństwie do programu cat, dane są wysyłane do standardowego wyjścia dopiero po natrafieniu przez program tac na znak końca pliku?

Czy istnieje istotna różnica pomiędzy wywołaniami poniższych poleceń?

$ cat /etc/passwd | tac
$ tac /etc/passwd | cat
$ tac /etc/passwd

Polecenia head, tail, sort, grep w potokach

Istnieje cała gama programów, które wypisują na standardowym wyjściu przetworzoną lub przefiltrowaną zawartość wskazanych plików lub danych ze standardowego wejścia (takie programy nazywamy filtrami). Ta ostatnia własność ma dość praktyczne znaczenie w połączeniu z mechanizmem potoków.

O zachowaniu wymienionych dalej programów będziemy mówić w kontekście operowania na danych pochodzących ze standardowego wejścia. Każdy z nich radzi sobie jednak równie dobrze z plikami – wystarczy podać ich nazwy jako argumenty.

Program head wypisuje 10 pierwszych linii ze standardowego wejścia. Przydatne opcje:

-c XXwypisz XX pierwszych bajtów
-n XXwypisz XX pierwszych linii
-c -XXwypisz wszystkie poza ostatnimi XX bajtami
-n -XXwypisz wszystkie poza ostatnimi XX liniami

Czy istnieje istotna różnica pomiędzy wywołaniami poniższych poleceń?

$ cat ~/lista-etc | head -n 5
$ head -n 5 ~/lista-etc
$ head ~/lista-etc -n 5

Wypisz:

  1. cztery pierwsze linie pliku ~/.bash_history,
  2. pierwszych 13 bajtów pliku ~/lista-etc,
  3. wszystkie poza ostatnimi dwoma liniami pliku /etc/passwd.

Program tail wypisuje 10 ostatnich linii ze standardowego wejścia. Przydatne opcje:

-c XXwypisz XX ostatnich bajtów
-n XXwypisz XX ostatnich linii
-c -XXwypisz wszystkie poza pierwszymi XX bajtami
-n -XXwypisz wszystkie poza pierwszymi XX liniami
-c +XXwypisz wszystkie bajty, począwszy od XX-tego
-n +XXwypisz wszystkie linie, począwszy od XX-tej
-faktualizuj wynik w miarę jak dane spływają do standardowego wejścia

Wypisz czwartą i piątą linię pliku ~/lista-etc. Zaproponuj kilka dróg do otrzymania pożądanego efektu.

Zobacz odpowiedź

$ cat lista-etc | head -n 5 | tail -n 2
$ head -n 5 lista-etc | tail -n 2

Jaki będzie efekt wywołania polecenia

$ head -n -2 plik | tail -n +3

gdzie plik jest dowolnym plikiem?

Czy istnieje istotna różnica pomiędzy wywołaniami poniższych poleceń?

$ tail -n 5 -f ~/lista-etc
$ tail --lines=5 --follow ~/lista-etc
$ tail --lines=5 -f ~/lista-etc

Program sort sortuje alfabetycznie (w kolejności rosnącej) linie tekstu ze standardowego wejścia. Przydatne opcje:

-ftraktuj małe i wielkie litery równoważnie
-ntraktuj linie jak liczby
-Rposortuj linie losowo
-rsortuj malejąco
-k Xprzy sortowaniu uwzględniaj dane od X-tej kolumny
-k X,Yprzy sortowaniu uwzględniaj dane z kolumn o indeksach od X do Y
-t Xtraktuj X jako separator kolumn

Wypisz informacje o ośmiu największych elementach, znajdujących się bezpośrednio w Twoim katalogu domowym.

Zobacz odpowiedź

$ ls -l ~ | tail -n +2 | sort -k 5 -nr | head -n 8

Jaki będzie efekt wywołania polecenia

$ ls -l | tail -n +2 | sort -k 2 -n -r | head -n 3

w dowolnym katalogu?

Program grep wypisuje na wyjściu tylko te linie ze standardowego wejścia, które odpowiadają zadanemu wyrażeniu regularnemu. Przydatne opcje:

-itraktuj małe i wielkie litery równoważnie
-vwypisuj na wyjściu tylko te linie, które nie spełniają zadanego wyrażenia regularnego
-wwypisuj na wyjściu tylko te linie, które zawierają słowo spełniające zadane wyrażenie regularne
-cwypisz na wyjściu liczbę linii spełniających wyrażenie
-qnic nie wypisuj i zwróć 0 w chwili znalezienia dopasowania

Zasady konstrukcji wyrażeń regularnych:

.dowolny znak, poza znakiem nowej linii
^początek linii
$koniec linii
[abc]dowolny z wyliczonych znaków
[a-z]dowolny znak ze zbioru
[^0-9]dowolny znak z dopełnienia zbioru
[abc]*ciąg znaków a, b i c dowolnej długości (również pusty)
[abc]+ciąg znaków a, b i c dowolnej niezerowej długości
[abc]?maksymalnie jednokrotne wystąpienie elementu a, b lub c
[abc]\{n\}ciąg znaków a, b i c długości n
[abc]\{n,\}ciąg znaków a, b i c długości co najmniej n
[abc]\{,m\}ciąg znaków a, b i c długości co najwyżej m
[abc]\{n,m\}ciąg znaków a, b i c długości od n do m
\|alternatywa
\( \)nawiasy grupujące

Jaki będzie efekt działania poniższego polecenia?

$ ls -l ~ | grep '^drwx\(r..\)\{2\}.*[a-zA-Z]\{5\}\(ry\|op\)$'

Wykonaj poniższe zadania. Posłuż się poznanymi dotąd poleceniami i metodami.

  1. Odpowiedz, ile elementów znajdujących się w katalogu /dev jest dowiązaniami symbolicznymi?
  2. Plik ~/.bash_history zawiera historię wykonywanych poleceń w kolejności od najdawniej wykonanego. Wypisz, począwszy od najświeższego, 3 wykonane ostatnio polecenia rozpoczynające się od słowa cat lub ls.
    Uwaga: zawartość pliku ~/.bash_history jest aktualizowana w momencie zakończenia sesji konsoli. Można to jednak zrobić ręcznie, wykonując polecenie history -a.
  3. Wyświetl, posortowaną malejąco według nazw, szczegółową listę ośmiu największych elementów znajdujących się w katalogu /bin.
  4. Posortuj szczegółową listę elementów z katalogu /etc malejąco według liczby dowiązań stałych. Jeśli dwa lub więcej elementów ma taką samą liczbę dowiązań stałych, powinny być posortowane według rozmiaru malejąco. Uwzględnij tylko te elementy, które mogą być odczytane przez osoby inne niż właściciel i członkowie wskazanej grupy.

Zobacz odpowiedź

  1. $ ls -l /dev | tail -n +2 | grep '^l' | wc -l
  2. $ tac .bash_history | grep '^\(cat\|ls\)' | head -n 3
  3. $ ls -l /bin | tail -n +2 | sort -k5 -rn | head -n8 | sort -k9 -r
  4. $ ls -l /etc | tail -n +2 | sort -rn -k2 -k5 | grep '^.\{7\}r'

Przeadresowywanie wejścia/wyjścia

Jak już wiemy, w momencie uruchamiania programu tworzone są trzy kanały komunikacyjne pomiędzy nim a środowiskiem, w którym jest wykonywany. Są to stdin (o numerze 0), stdout (o numerze 1) oraz stderr (o numerze 2). I choć domyślnie każdy z tych kanałów prowadzi do pliku urządzenia terminala, możemy – korzystając z funkcjonalności powłoki – przekierować (przeadresować) wejście/wyjście, wskazując inny plik. Służą do tego metasymbole powłoki: >, >>, < oraz <<. Pierwsze dwa służą do przekierowywania wyjścia, kolejne zaś do przeadresowywania wejścia.

Konstrukcja N> pozwala przekierować dane wyjściowe związane z deskryptorem pliku o numerze N do dowolnego innego pliku w systemie. Jeśli N nie jest określone, przyjmuje się, że wynosi 1 (a więc jest związane z stdout). Jeśli plik docelowy nie istnieje, zostanie utworzony, jeśli zaś istnieje, zostanie nadpisany.

Wykonaj w swoim katalogu domowym następujące polecenia:

$ ls -la 1> wynik.txt
$ ls -l > wynik.txt

Skomentuj efekty.

Wykonaj w swoim katalogu domowym następujące polecenie:

$ ls -l | sort -k 5 -n | head -n 5 > wynik.txt

Skomentuj efekty.

Korzystając z polecenia cat i przeadresowania wyjścia, utwórz w swoim katalogu domowym plik o dowolnej treści.

Łatwo się domyślić, że przekierowania danych przesyłanych do pliku określonego deskryptorem o numerze 2 (a więc stderr) można dokonać korzystając z konstrukcji 2>.

Wykonaj w swoim katalogu domowym następujące polecenia:

$ cat /etc/shadow > wynik.txt
$ cat /etc/shadow > wynik.txt > wynikb.txt
$ cat /etc/shadow 2> wynik.txt
$ cat /etc/shadow /etc/passwd > wynik.txt 2> wynik.err
$ cat /etc/shadow /etc/passwd 1> wynik.txt 2> wynik.err
$ cat /etc/shadow /etc/passwd 2> wynik.err 1> wynik.txt

Skomentuj efekty.

Aby przekierować jednocześnie wszystkie dane wychodzące z programu, niezależnie od tego, z którym deskryptorem pliku są związane, można skorzystać z konstrukcji &>.

Wykonaj w swoim katalogu domowym następujące polecenia:

$ cat /etc/shadow /etc/passwd 1> wynik.txt 2> wynik.err
$ cat /etc/shadow /etc/passwd &> wynik.txt

Skomentuj efekty.

Przesyłać dane można też pomiędzy plikami związanymi z różnymi deskryptorami. Wymaga to jednak poprzedzenia numeru deskryptora docelowego znakiem &.

Wykonaj w swoim katalogu domowym następujące polecenia:

$ cat /etc/shadow /etc/passwd 2>1
$ cat /etc/shadow /etc/passwd 2>&1
$ cat /etc/shadow /etc/passwd 2>&1 > wynik.txt
$ cat /etc/shadow /etc/passwd 2>&1 1> wynik.txt
$ cat /etc/shadow /etc/passwd 1> wynik.txt 2>&1

Skomentuj efekty.

Zobacz odpowiedź

Polecenie cat /etc/shadow /etc/passwd 2>&1 > wynik.txt wypisuje na ekranie błąd, podczas gdy cat /etc/shadow /etc/passwd 1> wynik.txt 2>&1 przekierowuje wyjście zgodnie z oczekiwaniami.

Korzystając z metasymbolu powłoki < możemy przekierować dane z dowolnego pliku do wejścia programu.

Wykonaj w swoim katalogu domowym następujące polecenia:

$ cat < /etc/passwd
$ cat 0< /etc/passwd
$ cat < /etc/shadow
$ cat < /etc/shadow 2> wynik.err
$ cat 2> wynik.err < /etc/shadow

Skomentuj efekty. Co, według Twojej intuicji, oznacza konstrukcja 0<?

Zastosowanie konstrukcji N> do przeadresowania wyjścia związanego z deskryptorem o numerze N powodowało, że plik docelowy był nadpisywany. Zastosowanie w całości analogicznej konstrukcji N>> powoduje, że dane wyjściowe zostaną dopisane na końcu wskazanego pliku, chyba że ten nie istnieje – wówczas zostanie utworzony.

Wykonaj w swoim katalogu domowym następujące polecenia:

$ ls ~ > lista.txt
$ ls /home >> lista.txt

Skomentuj efekty.

Wynik działania polecenia ls będzie się różnił w zależności od tego, czy dane będą wypisywane w terminalu, czy przekierowane do pliku (lub innego programu przez mechanizm potokowania). Wynika to z faktu, że mechanizm przekierowania wejścia/wyjścia modyfikuje docelowe pliki związane z danymi deskryptorami. Tym samym program może weryfikować, czy dany deskryptor odwołuje się do pliku terminala.

W przypadku mechanizmu potokowania, dane wyjściowe przesyłane są do kolejnego programu w potoku za pośrednictwem pliku tymczasowego typu gniazdowego (ang. socket), a nie terminala. Dlatego też polecenia

$ ls
$ ls | cat

dadzą inne rezultaty.

Konstrukcja << nie działa tak, jak można by się spodziewać. Dowiedz się, jakie znaczenie ma ten metasymbol i przetestuj jego działanie.

Podpowiedź: https://en.wikipedia.org/wiki/Here_document.

Dowiedz się, jakie znaczenie ma metasymbol <<< i przetestuj jego działanie.

Zobacz odpowiedź

Metasymbol <<< pozwala traktować przekazany ciąg znaków jako standardowe wejście.

Mechanizm przeadresowywania wyjścia pozwala także na przekazywanie wyjścia do innego terminala (bo terminal też jest plikiem).

Zaloguj się do dwóch terminali i odnajdź związane z nimi pliki w katalogu /dev. W jednej z konsol uruchom program cat, w drugiej wykonaj dowolne polecenie, a wynik przekieruj do pierwszej z konsol. Czy istnieje różnica pomiędzy zastosowaniem przekierowania z użyciem metasymbolu >> a >?

Kilka przypatnych poleceń

Program bc to proste narzędzie do wykonywania operacji arytmetycznych. Obsługuje wiele operatorów matematycznych, w tym operatory arytmetyczne i logiczne, funkcji matematycznych, instrukcji warunkowych i pętli. Konstrukcja wyrażeń jest zbliżona do tej znanej z języka C.

Korzystając z programu bc z opcją -l (dołącza biblioteki matematyczne), oblicz (z dokładnością do 10 miejsc po przecinku) wartość wyrażenia $e^{\sqrt{7}-1}+5e$.

Zobacz odpowiedź

scale=10; e(sqrt(7)-1)+5*e(1)

Korzystając z programu bc z opcją -l, oblicz wartość liczby $\pi$ z dokładnością do 1000 miejsc po przecinku. Wykorzystaj fakt, że $\frac{\pi}{4} = \arctan(1)$.

Zobacz odpowiedź

scale=1000; a(1)*4

Program cal pozwala na wyświetlenie kalendarza w formie tekstowej.

Zapoznaj się z podręcznikiem programu cal. Następnie wyświetl:

  1. kalendarz na rok 2016,
  2. kalendarz trójdzielny dla miesiąca grudnia (listopad 2015, grudzień 2015 i styczeń 2016),
  3. kalendarz dla bieżącego miesiąca i trzech poprzednich oraz pięciu kolejnych miesięcy.

Zobacz odpowiedź

(a) $ cal -y 2016, (b) $ cal -3 -d 2015-11, (c) $ cal -A 5 -B 3.

Program clear pozwala na oczyszczenie ekranu.

Przetestuj działanie programu clear.

Dowiedz się, jak działa program clear. W tym celu możesz sprawdzić, przekierowując potokiem do programu hexdump dane ze standardowego wyjścia programu clear, jakie znaki specjalne wypisuje on na wyjściu.

Program date pozwala wyświetlić lub ustawić datę systemową. Przydatne opcje:

-d "X"nadpisz bieżącą datę datą X
-s "X"ustaw bieżący czas na X
-uużywaj czasu UTC

Program obsługuje też wiele możliwości formatowania wyjścia, z którymi można się zapoznać w jego dokumentacji.

Wykonaj następujące polecenia:

$ date
$ date -d '2 Nov'
$ date -d '2 Nove'
$ date -d '2 Nov 2013'
$ date -d 'Nov 2 2014'
$ date -d '2 Jan 2017 10:54'
$ date -d 'Jan 2 2017 10:54:12'

Zastanów się nad efektami.

Korzystając z formatowania wyjścia, wyświetl datę zgodnie ze wzorami

Dzisiaj jest 215. dzien roku.
20150803152847
Biezacy rok to 20 stuleci i 15 lat.

Zobacz odpowiedź

$ date +"Dzisiaj jest %j. dzien roku."
$ date +"%Y%m%d%H%M%S"
$ date +"Biezacy rok to %C stuleci i %y lat."

Ile sekund minęło od 12 stycznia 2013 r., godz. 10:23:17, do 10 września 2014 r., godz. 11:12:43?

Zobacz odpowiedź

52357766

$ echo `date -d "2014-09-10 11:12:43" +"%s"` - \
       `date -d "2013-01-12 10:23:17" +"%s"` | bc

Procesy

Na początku poprzednich ćwiczeń dowiedzieliśmy się już, co się dzieje, zanim rozpocznie się sesja powłoki i że w momencie poprawnego zalogowania uruchamiany jest program powłoki (np. bash). W systemach uniksopodobnych panuje hierarchiczna struktura procesów. Oznacza to, że każdy proces (program) ma dokładnie jednego rodzica (proces, który go wywołał), a procesem-korzeniem całej struktury jest init.

W praktyce oznacza to, że każdy program uruchamiany z poziomu powłoki staje się jej podprocesem, a jeśli ten uruchamia kolejne procesy, drzewo procesów się rozrasta.

Użytkownik systemu może dotrzeć do listy procesów uruchomionych aktualnie w systemie. W zależności od jego konfiguracji, może się okazać, że lista ta jest ograniczona jedynie do procesów, których właścicielem jest zalogowany użytkownik. Tak jest, procesy – podobnie jak pliki – mają właścicieli.

Polecenia ps i pstree

Program ps służy do wyświetlania listy aktualnie uruchomionych procesów. Obsługuje ono zarówno uniksowy (ze znakiem -), jak i pochodzący z BSD (bez znaku -) sposób przekazywania opcji. W przypadku tego programu stosuje się powszechnie styl BSD. Wynika to z faktu, że program ps nie przyjmuje argumentów innych niż opcje. Ważniejsze z nich to:

awyświetla tylko procesy związane z jakimś terminalem lub wszystkie procesy, jeśli połączone z opcją x
xwyświetla tylko procesy bieżącego użytkownika lub wszystkie procesy, jeśli połączone z opcją a
uwyświetl listę procesów w sposób szczegółowy

Serwer lts.wmi.amu.edu.pl nie pozwala uzyskać dostępu do informacji o procesach innych użytkowników. Należy więc obejść się smakiem.

Korzystając z dokumentacji programu ps dowiedz się, na czym polega notacja uniksowa, BSD i GNU związana z przekazywaniem opcji do programu. Gdzie spotkaliśmy się wcześniej z tym podziałem?

Rozpocznij kilka sesji powłoki na lokalnym komputerze lub za pośrednictwem protokołu ssh. Uruchom jakieś programy (np. less lub sleep), a następnie sprawdź działanie przedstawionych wyżej opcji programu ps wykonując polecenia:

$ ps
$ ps a
$ ps au
$ ps aux

Korzystając z polecenia pstree można obejrzeć drzewo procesów, a więc zależności pomiędzy poszczególnymi procesami aktualnie uruchomionymi w systemie.

Zapoznaj się z poleceniem pstree. Przetestuj jego działanie. Wybierz samodzielnie, korzystając z dokumentacji programu, kilka opcji i sprawdź ich działanie w praktyce.

Sygnały, procesy w tle i na pierwszym planie

Każdy program uruchomiony w powłoce wykonuje się w tej powłoce na pierwszym planie (to znaczy absorbuje powłokę). Kiedy uruchamiamy program cat, wchodzi on z nami w interakcję na poziomie powłoki. Dopóki nie zakończy się jego działanie, nie możemy wykorzystać powłoki w inny sposób, np. aby uruchomić inny program.

W rzeczywistości zdecydowana większość programów obsługuje poprawnie tak zwane sygnały, które wpływają na zachowanie programu. Szczegóły dotyczące tej tematyki będą poruszane na wykładzie, nas jednak interesuje to, że z poziomu powłoki możemy takie sygnały wysłać.

Gdy program się wykonuje w powłoce, możemy wysłać do niego sygnał SIGINT (interrupt), korzystając z kombinacji klawiszy Ctrl + C (oznaczanej jako ^C). Sygnał ten oznacza, że program powinien przerwać wykonywane zadanie i zakończyć się niezwłocznie. Podobnie, korzystając z kombinacji klawiszy Ctrl + Z (^Z), możemy wysłać do programu sygnał SIGSTP (stop), który powoduje wstrzymanie programu i powrót do powłoki. Proces taki nie kończy się jednak.

Uruchom dowolny program (np. cat), a następnie wciśnij kombinację klawiszy Ctrl + C. Sprawdź, jaki będzie efekt wywołania polecenia ps. Podobny eksperyment wykonaj dla kombinacji klawiszy Ctrl + Z. Zinterpretuj wyniki.

Można kontynuować wykonywanie wstrzymanego procesu. Polecenie fg powoduje, że ostatni wstrzymany proces powróci do powłoki i będzie w niej kontynuowany. Polecenie bg powoduje zaś, że ostatni wstrzymany proces zostanie przywrócony w tle. Polecenie jobs pozwala zobaczyć listę aktualnie wykonywanych programów wraz z ich statusami.

Wykonaj następujące czynności i zaobserwuj efekty:

$ sleep 100
^Z
$ sleep 90
^Z
$ sleep 80
^Z
$ jobs
$ bg
$ jobs
$ fg %1
^C
$ jobs
$ fg
^C

Co oznacza polecenie fg %1? Wywołaj polecenie jobs, gdy wykonywanie polecenia sleep 80 zakończy się. Wywołaj je ponownie. Co się stało?

Zobacz odpowiedź

Przy pierwszym wywołaniu polecenia jobs po zakończeniu procesu z listy, wyświetli się informacja o jego zakończeniu (Done).

Proces można od razu uruchomić w tle. Wystarczy zakończyć jego wywołanie znakiem &.

Uruchom w tle program sleep z argumentem 240. W tym celu wykonal polecenie

$ sleep 240 &

Sprawdź, co się stało, korzystając z poleceń ps, pstree oraz jobs. Przenieś uruchomiony program na pierwszy plan i zakończ, wysyłając sygnał SIGINT.

Zabijanie procesów – polecenia kill i killall

Każdy proces w momencie uruchomienia otrzymuje nazwę oraz swój indywidualny i niepowtarzalny numer. Numer ten nazywamy identyfikatorem procesu i oznaczamy skrótem PID.

Korzystając z programu ps dowiedz się, jakie identyfikatory mają aktualnie uruchomione programy.

Program kill pozwala wysłać sygnał do programów o wskazanych identyfikatorach. Domyślnie jest to sygnał SIGTERM.

Dowiedz się, jakie inne sygnały można przesłać do programu za pomocą programu kill i jak to zrobić.

Zobacz odpowiedź

<pid> [...]
    Send signal to every <pid> listed.
-<signal>
-s <signal>

Uruchom w tle program sleep z argumentem 240. Dowiedz się, jaki identyfikator ma utworzony proces, a następnie zakończ go używając polecenia kill.

Polecenie killall pozwala na zakończenie procesu o określonej nazwie, przekazanej jako argument.

Uruchom w tle program sleep z argumentem 240. Wykonaj następujące polecenia:

$ killall sle
$ killall sleep

Zaobserwuj efekty. Czy polecenie $ killall sle* zadziała tak, jak można się spodziewać?

Polecenie time

Program time pozwala zmierzyć czas wykonywania polecenia.

Korzystając z programu time dowiedz się, jak wiele czasu potrzebuje komputer na wykonanie polecenia

$ ls -la /etc

Zinterpretuj wartości real, user oraz sys.

Zobacz odpowiedź

Czas sys okresla czas procesora związany z wykonywaniem operacji na poziomie jądra, user ten związany z wykonywaniem operacji poza jądrem, a real rzeczywisty czas od rozpoczęcia do zakończenia wykonywania programu.

W oparciu o rozwiązanie poprzedniego ćwiczenia, skonstruuj polecenie, które na standardowym wyjściu wypisuje wyłącznie rzeczywisty czas wykonania badanego polecenia w sekundach, na przykład:

0.015

Upewnij się, że polecenie będzie działać poprawnie również gdy badane polecenie będzie się wykonywać ponad minutę.

Zobacz odpowiedź

$ TIMEFORMAT='%E'
$ time "ls" &> /dev/null