Linuks (ogólnie un*xy) jest z założenia systemem wieloużytkownikowym, czyli na
raz może być na nim zalogowanych wielu użytkowników (zdaje się do 32000).
Wieloużytkownikowość pociąga za sobą wielozadaniowość (każdy user chce coś
robić). Jak jednak użyć tej wielce użytecznej cechy Linuksa? To teoretycznie
zależy od używanej powłoki, w praktyce jednak większość shelli stosuje tę samą
konwencję. Opiszę jednak szczegóły odwołując się do basha (chyba
najpopularniejsza, a na pewno ja sam jej używam).
Pierwszą sprawą, jaką powinieneś poznać, to sposoby kończenia programu. Nie
mam tu na myśli kończenia przez wybór odpowiedniej opcji z menu programu, bo
nie zawsze program musi mieć menu (choćby taki napisany przez ciebie). Przede
wszystkim jest kombinacja klawiszy ^C (tak jest oznaczane Ctrl+C w zapisie,
jakim będę się tu posługiwał). Ta kombinacja powoduje wyjście z programu.
Jeśli chcesz zatrzymać program na chwilę, możesz wcisnąć ^Z. Zobaczysz linię w
stylu
[1]+ Stopped nazwa-programu
To jest linijka statusu zadań, możesz ją powtórnie przywołać poleceniem
jobs (to jest wbudowana komenda basha). Liczba w nawiasie
kwadratowym to numer zadania (bo może być ich kilka), który jest użyteczny dla
niektórych komend wbudowanych. Jest unikalny na danej konsoli, ale na innych
konsolach już nie możesz się odwoływać przez ten numer. Dalej jest status
pracy (zatrzymana, pracuje, zakończona i parę innych) i komenda, jaką praca
została uruchomiona. No to teraz przydałaby się komenda przywracająca zadanie
na pierwszy plan (tzw foreground): fg. Podane bez argumentów
fg przywraca pracę, która ostatnio była aktywna (to ta z plusem
koło numeru pracy, przedostatnia zaś ma minus). Jeśli chcesz przywrócić pracę
o konkretnym numerze, to za argument fg podaj właśnie ten numer:
fg 14 przywróci pracę z numerem 14 (fg - przywróci
przedostatnią). Możesz też odesłać pracę w tło, jeśli nie chcesz, żeby
zajmowała ci terminal, na przykład kopiowanie dużego pliku. Możesz w tym
momencie podawać inne polecenia, równolegle z tamtym zadaniem. Do takiego
tricku służy bg, które działa identycznie jak fg (z
dokładnością do tego, że odsyła pracę w tło, tzw. background). A jeśli
chcesz wysłać pracę w tło od razu, nie usypiając jej kombinacją ^Z, to na
końcu polecenia dodaj znaczek & (przykład:
cp duzy-plik nowa-lokacja &).
Procesy mogą zmieniać swój status w trakcie wykonywania, na przykład proces
wykonywany w tle może zacząć czekać na wejście z klawiatury (wtedy jest
zatrzymywany, aż do przejścia na foreground) albo jakiś proces może się
skończyć. Takie zmiany są sygnalizowane komunikatem wypisywanym tuż przed
znakiem zachęty (znaczy wtedy, gdy ma być wypisany na nowo, czyli po wydaniu
komendy).
Jeszcze zostało polecenie kill. Nazwa wskazuje na to, że tak można
zabić jakiś program. Owszem, choć polecenie raczej wysyła do programu sygnał
o określonym numerze. Domyślnie jest to sygnał 15, oznaczany nazwą
SIGTERM. Jest to dobry sygnał, w większości sytuacji powoduje miękkie
zakończenie programu. Jednak program może przechwytywać pewne sygnały
(dokładnie to program może przechwycić wszystkie sygnały poza dwoma), albo
może będziesz chciał wysłać inny sygnał (na przykład przy pisaniu
programu).
Podstawowe zastosowanie polecenia: kill 1234 lub kill
%2. Pierwsze zabije proces o identyfikatorze 1234 (identyfikator, czyli
PID, to numer przydzielony procesowi przez system, jest on unikalny w skali
sesji), w drugim przypadku kill zabije zadanie drugie z listy
procesów uśpionych i działających w tle. Do wysyłania sygnałów innych niż
SIGTERM służą opcje: kill -s SIGTERM <proces> wysyła
sygnał SIGTERM do procesu <proces> (oczywiście tutaj wpisujesz
numer zadania albo PID); kill -n 15 <proces> lub kill
-15 <proces> wysyła sygnał numer 15 do procesu <proces>.
Jeśli chcesz listę sygnałów, wpisz kill -l.
Wiesz teraz, jak wysyłać sygnały, ale nie wiesz, które wysyłać. Ogólnie,
sygnał 15 SIGTERM standardowo kończy zadanie, sygnał 2 SIGINT to
sygnał posłany przy wciśnięciu ^C, 20 SIGTSTP jest wysyłany po
wciśnięciu ^Z, natomiast sygnały 9 SIGKILL i 19 SIGSTOP są
nieprzechwytywalne z założenia, dzięki czemu zawsze możesz zastopować/zabić
proces (to jest słynne polecenie: kill -9, zabija
bezwarunkowo).
Uwaga dotycząca różnych systemów operacyjnych: sygnały SIGSTOP i SIGTSTP mogą
mieć inne numery, ale na pewno te same nazwy.
Jeszcze przydałoby się wiedzieć, do jakiego procesu wysłać SIGKILL :-)
Jednym z najpopularniejszych poleceń do zarządzania procesami (w tym ich
kończenia) jest top (table of processes). Nie potrzebuje żadnych
parametrów. Po uruchomieniu dostajesz spis procesów, który prawdopodobnie nie
mieści się na ekranie. Przyznaję się bez bicia, że nie potrafię przewijać tej
listy. Ale możesz sobie ograniczyć wyświetlane procesy do aktywnych (literka
i, komenda typu włącz/wyłącz) albo do konkretnego użytkownika
(literka u, po której wpisujesz nazwę usera). Wychodzisz wciskając
q. Uwaga: top zdaje się nie występować na Solarisie.
Drugim popularnym poleceniem jest ps. To z kolei jest chyba na
każdym un*xie. ps po prostu wypisuje procesy. Domyślnie listuje
zadania z aktualnej konsoli. Żeby wylistować wszystkie zadania użytkownika
wpisz ps -u <login>. Do wylistowania wszystkie zadania (nie
tylko twoje) służy ps -A. Ja sam często stosuję ps -Af,
dostaję wtedy zamiast samej nazwy procesu pełne polecenie, jakim został proces
uruchomiony.
Możesz uruchamiać kilka poleceń na raz, oddzielając je średnikiem. W zasadzie odpalą się jedno po drugim. Jeśli chcesz je uruchomić jednocześnie, to oddizel je znaczkiem &. Tak, tym samym, który służy do puszczania procesu w tle (do tego przecież się sprowadza uruchomienie współbieżne dwóch lub więcej programów). Są jeszcze bardziej zaawansowane sposoby uruchamiania sekwencji programów, ale te opiszę w zasadzie pod koniec koorsu (bo tam dopiero się przydadzą).
Jeszcze słówko nie do końca o wielozadaniowości, ale czasem przydatne. Jeśli uruchomisz jakiś program, który nic nie chce wypisywać na ekranie (np. ed lub cat), to prawdopodobnie odpaliłeś program czekający na dane ze standardowego wejścia (później wyjaśnię, o co chodzi). Często wystarczy wcisnąć ^D, żeby program się zakończył. Otóż ^D to znaczek używany przy przesyłaniu danych na oznaczenie końca strumienia danych. Gdy program czekający na wejście otrzyma taki znaczek, to kończy pobieranie danych. Wtedy nie ma żadnych danych do operowania na nich, więc się kończy. Spróbuj tego również z shellem :-).