0 Obsługa systemu LINUX (cz. 3)
Tomasz Zaworski edited this page 2020-11-15 02:28:24 +01:00
  1. Skrypty
  2. Procesy
  3. Potoki
  4. Wyrażenia regularne
  5. Zadania domowe

Skrypty

Skrypt to plik tekstowy zawierający w kolejnych wierszach polecenia powłoki.

Plik skrypt.sh

echo ===================================================
ps
echo ===================================================
ls

Powyższy skrypt uruchamiamy przekazując go jako argument do interpretera bash.

bash skrypt.sh

Jeżeli w pierwszym wierszu skryptu umieścimy tekst:

#!/bin/bash

oraz nadamy plikowi atrybut wykonywalny:

chmod +x skrypt.sh

to będzie można go uruchamiać tak, jak zwykłe programy:

./skrypt.sh

W skryptach można korzystać z instrukcji warunkowych if, pętli while oraz innych konstrukcji odpowiedzialnych za sterowanie przebiegiem wykonania skryptu. Instrukcje te zostały opisane w sekcji Compound Commands podręcznika użytkownika powłoki.

man bash

Zadanie 1

Stwórz skrypt loop.sh, który będzie w pętli wypisywać wiadomość co 10 sekund.

#!/bin/bash
while true; do
    // tu dodaj wypisanie wiadomości i czekanie 10 sekund
done

Procesy

Każdy proces (wykonywany w systemie program) posiada numer, który go jednoznacznie identyfikuje (process identifier, PID).

Identyfikatory procesów uruchomionych w systemie można wyświetlić korzystając z polecenia ps.

Zadanie 2

Wyświetl wszystkie procesy uruchomione w systemie. Zapoznaj się z przełącznikami -a, -u, -x.

Zadanie 3

Uruchom komendę sleep 100 W innym terminalu znajdź identyfikator uruchomionego procesu.

Procesy w tle

Proces może być uruchomiony na pierwszym planie w terminalu lub w tle.

Aby uruchomić polecenie w tle należy dodać do niego &. Np. sleep 10 &, aby przywrócić dany proces na pierwszy plan należy użyć komendy fg.

Zadanie 4

Uruchom program sleep z parametrem 10 w tle.

Zadanie 5

Przywróć uruchomiony proces na pierwszy plan.

Sygnały

Procesom można przekazywać sygnały, które wpływają na ich działanie. Sygnały stanowią podstawową formę komunikacji procesu z systemem operacyjnym. W większości przypadków otrzymanie sygnału przez proces kończy się jego zamknięciem, jednakże są sygnały, które programy wykorzystują.

Do często używanych sygnałów należą:

  • SIGTERM - zakończenie procesu
  • SIGKILL - "zabicie" procesu
  • SIGSTOP - zatrzymanie procesu
  • SIGCONT - wznowienie zatrzymanego procesu
  • SIGALRM - sygnał wysysłany do programu, gdy minie ustalony czas. Wykorzystywany przez timer w C.
  • SIGUSR1 - sygnał zarezerwowany dla użytkownika. Programista może zaimplementować zachowanie programu na ten sygnał.

Sygnały przekazujemy procesom korzystając z polecenia kill.

Listę zdefiniowanych w systemie sygnałów oraz ich numery można uzyskać przy użyciu polecenia kill -l.

Znaczenie poszczególnych sygnałów można odczytać z odp. strony podręcznika użytkownika

man 7 signal

Zadanie 6

Uruchom loop.sh, po czym przerwij jego działanie wciskając Ctrl+C. Co się dzieje po naciśnięciu Ctrl+C?

Zadanie 7

Uruchom loop.sh po czym zatrzymaj jego wykonanie przy pomocy Ctrl+Z. Co się dzieje po naciśnięciu Ctrl+Z?

Zadanie 8

Znajdź indentyfikator procesu uruchomionego w poprzednim zadaniu.

Zadanie 9

Uruchom po raz kolejny ./loop.sh w tle.

Zadanie 10

Korzystając z polecenia jobs -l wyświetl zadania uruchomione w bieżącej sesji.

Zadanie 11

Korzystając z polecenia bg wznów wykonanie w tle procesu, który został zawieszony.

Zadanie 12

Korzystając z polecenia kill zawieś działanie pierwszego z wykonywanych w tle procesów loop.sh, wysyłając do niego sygnał STOP.

Zadanie 13

Korzystając z polecenia kill zakończ działanie drugiego z wykonywanych w tle procesów loop.sh, wysyłając do niego sygnał TERM.

Zadanie 14

Wznów zawieszony process loop.sh wysyłając do niego sygnał CONT.

Zadanie 15

Zakończ process loop.sh wysyłając do niego sygnał KILL.

Potoki

Potoki nienazwane

Standardowy strumień wyjścia jednego polecenia można przekazać na wejście kolejnego korzystając z operatora | (ang. pipe, pol. potok).

echo Hello World | wc

1       2      12

Potoki nazwane

Standardowy strumień wyjścia można przekazać na wejście innego procesu wykorzystując także mechanizm potoków nazwanych (ang. named pipes).

Potok nazwany tworzymy korzystając z polecenia mkfifo:

mkfifo np1

Potok nazwany jest plikiem (specjalnego rodzaju), który jest widoczny gdy wywołujemy polecenie ls.

Sposób działania potoków nazwanych można sprawdzić uruchamiając w jednym oknie terminala polecenie:

wc < np1

a w drugim:

echo Hello World > np1
Zadanie 16

Zapisz plik (https://marcing.faculty.wmi.amu.edu.pl/plwiki.txt.gz) w bieżącym katalogu. Plik zawiera fragment polskiej Wikipedii skompresowany programem gzip.

Wyrażenia regularne

Wprowadzenie

Podstawową metodą definiowania łańcuchów znaków są wyrażenia regularne. Każde wyrażenie regularne definiuje zbiór łańcuchów znaków, które je spełniają.

Podstawowym wyrażeniem regularnym jest pojedynczy znak, np. a. Wyrażenie to definiuje zbiór ciągów znaków {a}. Wyrażenia regularne można można łączyć. Konkatenacja (sklejenie) dwóch wyrażeń regularnych dopasuje konkatenacje dwóch słów, pierwsze dopasowane do pierwszego wyrażenia, a drugie do drugiego. Np. wyrażenie (ab)(cde) dopasuje wyraz abcde. Kolejnym podstawowym elementem jest alternatywa (lub). Wyrażenie (ab)|(bcd) dopasuje 2 wyrazy, ab i bcd.

Uwaga:

Alternatywa łączy słabiej niż konkatenacja zatem wyrażenie ab|cde, będzie interpretowane jako (ab)|(cde).

Kolejnym ważnym elementem wyrażeń regularnych są znaki początku i końca łańcucha. Służą do tego znaki specjalne ^ (początek), $ (koniec). Przydaje się się to na przykład w poleceniu grep, przypadku gdy chcemy dopasować początek lub koniec linii. Znak . jest znakiem specjalnych i dopasowuje jeden dowolny znak.

Klasy znaków

Aby skrócić zapis do składni wyrażeń regularnych zostały dodane klasy znaków. [abcd] jest równoważne a|b|c|d. Dodatkowo różne rozszerzenia definiują inne klasy znaków. Dodatkowo jeżeli doda się ^ na początku klasy znaków zrobi to negację tej klasy (wszystkie znaki oprócz podanych). Można również używać zakresów znaków np. a-z, A-Z, 0-9, itp.

Przykłady:
POSIX class Podobne do Znaczenie
[:upper:] [A-Z] Duże litery
[:lower:] [a-z] Małe litery
[:alpha:] [[:upper:][:lower:]] Litery
[:alnum:] [[:alpha:][:digit:]] Litery i cyfry
[:digit:] [0-9] Cyfry
[:xdigit:] [0-9A-Fa-f] Cyfry w systemie szesnastkowym
[:punct:] [.,!?:…] Znaki interpunkcyjne
[:blank:] [ \t] Spacja i tabulator
[:space:] [ \t\n\r\f\v] Białe znaki
[:cntrl:] Znaki kontrolne ASCII
[:graph:] [^ \t\n\r\f\v] Znaki drukowanle
[:print:] [^\t\n\r\f\v] Znaki drukowanle i białe znaki

Wyrażenie [[:upper:]] dopasuje dowolną dużą literę.

Operatory powtórzenia

Wyrażenie regularn mogą zawierać operatory powtórzenia, które określają ile razy musi wystąpić dany znak lub grupa znaków (lub inne wyrażenie regularne). Do takich operatorów należą:

Operator Znaczenie
? 0 lub 1 raz
+ co najmniej 1 raz
* 0 lub więcej razy
{n,m} conajmniej n, ale nie więcej niż m, ten operator jest dostępny w rozszerzonych wyrażeniach regularnych

Np. .* dopasuje dowolny ciąg znaków

Znaki specjalne

Wszystkie podane powyżej operatory stanowią znaki specjalne. Aby próbować dopasować takie znaki należy przed nimi postawić znak ucieczki (\).

Np. Wyrażenie \.* dopasuje wyrażenie, które zawiera dowolną liczbę kropek.


Zadanie 17

Wykorzystując polecenia wc i zcat sprawdź ile słów i wierszy zawiera plik plwiki.txt.gz.

Zadanie 18

Korzystając z polecenia grep znajdź w pliku plwiki.txt.gz wiersze zawierające adresy url artykułów.

Zadanie 19

Korzystając z przedstawionych powyżej poleceń sprawdź ile plik plwiki.txt.gz zawiera artykułów.

Zadanie 20

Korzystając z programu grep usuń z plwiki.txt.gz puste wiersze, wynik skompresuj programem gzip i zapisz w pliku plwiki.noempty.gz.

Zadanie 21

Korzystając z poleceń grep i sed wydobądź z plwiki.txt.gz urle artykułów i zapisz je w pliku urls.txt.

cat urls.txt

http://pl.wikipedia.org/wiki?curid=2
http://pl.wikipedia.org/wiki?curid=4
...
Zadanie 22

Korzystając z polecenia sed zastąp tagi postaci

<doc id="2" url="http://pl.wikipedia.org/wiki?curid=2" title="AWK">

tagami postaci

=== AWK ===

oraz usuń tagi </doc>.

Wynik skompresuj i zapisz w pliku plwiki.notags.gz.

Zadanie 23

Otocz wszystkie liczby występujące w pliku zadania.txt podwójnymi nawiasami kwadratowymi, np. 1, 2, 11, 12. Zapisz wynik w pliku liczby.txt.

Zadanie 24

Korzystając z polecenia tr zamień wielkie litery w plwiki.txt.gz na małe, skompresuj wynik i zapisz w plwiki.lc.gz.

Zadanie 25

Korzystając z polecenia cut wydobądź z pliku /etc/passwd nazwy użytkowników systemu.

Zadanie 26

Korzystając z poleceń ps, sort oraz uniq sprawdź ile procesów jest uruchomionych przez poszczególnych użytkowników systemu.

Zadanie 27

Zastosuj polecenie cut oraz head lub tail razem z programami z poprzedniego zadania do wyznaczenia loginów trzech użytkowników z największą liczbą uruchomionych procesów.

Zadania domowe

Zadanie domowe 1

Korzystając z potoków utwórz polecenie, które dla każdej powłoki systemowej wyświetli liczbę użytkowników, dla których dana powłoka jest domyślną (odp. informacje można znaleźć w pliku /etc/passwd).

Lista powinna być posortowana nierosnąco.

Zapisz to polecenie w pliku defshells.sh.

Przykładowe wyjście:

 13 /bin/bash
  6 /sbin/nologin
  1 /usr/sbin/nologin
Zadanie domowe 2

Zaimplementuj skrypt ubij.sh, który zakończy działanie wszystkich procesów o zadanej nazwie.

Przykład wywołania:

./ubij.sh loop.sh
Zadanie domowe 3

Zaimplementuj skrypt freq.sh, który dla tekstu przekazanego na wejściu zwróci na wyjściu listę frekwencyjną, tj. dla każdego słowa w tekście wypisze liczbę jego wystąpień.

Wyjście powinno składać się z par postaci

slowo 234
nastepneslowo 211
kolejneslowo 201

Słowa powinny zostać posortowane w kolejności od największej do najmniejszej liczby wystąpień.

Przetestuj działanie skryptu na plwiki.txt.gz.

Na potrzeby tego zadania należy przyjąć, że słowem jest dowolny ciąg znaków złożony z liter.

Zadanie domowe 4

Wykonaj ćwiczenia zawarte na stronie https://regexone.com/ (spróbuj rozwiązać też zadania dodatkowe).