Linux jest systemem wielozadaniowym, który umożliwia wykonywanie wielu poleceń jednocześnie. Egzekucja polecenia jest identyfikowana przez system przy pomocy numeru identyfikacyjnego PID przypisanego każdemu procesowi, który jest egzekwowany (egzekucja polecenia uruchamia proces). System otrzymując od użytkownika polecenie, uruchamia je, czekając na jego zakończenie. O takim poleceniu mówimy, że jest pierwszoplanowe (foreground). Terminal jest zablokowany do momentu zakończenia zadania. Wyobraźmy sobie (a nie jest to bynajmniej rzadkie), że wykonanie naszego polecenia (np. polecenia find) może trwać wiele minut (są zadania, które trwają wiele godzin). Rzecz jasna możemy zalogować się na innej konsoli wirtualnej i tam możemy uruchamiać kolejne zadania. Innym sposobem postępowania z „długotrwałymi” zadaniami jest uruchamianie ich w tle. Zadanie uruchamiamy jako drugoplanowe wpisując na końcu linii poleceń znak ampresand & .
Objaśnijmy raz jeszcze mechanizm, który opisaliśmy powyżej: powłoka systemu operacyjnego otrzymując od użytkownika polecenie uruchamia je i czeka na zakończenie jego egzekucji. Tego typu proces nazywamy zadaniem pierwszoplanowym. Uruchamianie poleceń, skryptów pierwszoplanowych nazywa się w języku programistów – domyślnymi, nie jest to najszczęśliwszy termin, gdyż wprowadza wiele zamieszania, szczególnie u początkujących informatyków, dlatego w naszym podręczniku będziemy używali terminu: zadania pierwszoplanowe.
Zauważmy, że wprowadziliśmy przed chwilą nowy termin, którego definicji czytelnik jeszcze nie zna, chodzi o termin: zadanie. Jaka jest różnica miedzy procesem i zadaniem ?
Takie terminy jak właśnie proces czy program lub skrypt mają swoje konkretne znaczenie techniczne i są precyzyjnie osadzone w kontekście budowy i funkcjonowania systemu operacyjnego. Termin zadanie jest natomiast terminem organizacyjno-technicznym, ponieważ jest on powiązany z pracą użytkownika systemu. Na przykład uruchomienie edytora tekstowego vi jest konkretnym procesem w systemie, ale też jednocześnie zadaniem użytkownika, który realizuje swój cel – napisanie tekstu. Innymi słowy można zadanie określić jako zlecenie systemowi przez użytkownika określonego działania. Użytkownik patrzy i ocenia system operacyjny (ale także np. język programowania) przez pryzmat możliwych do wykonania zadań. Zadanie jest zazwyczaj równoważne z pojedynczym procesem, ale na potrzeby wykonania zadania system operacyjny może uruchomić dodatkowe procesy. Termin zadanie nie ma definicji ściśle technicznej – jak program czy proces – i dlatego może być on używany w innych kontekstach.
Wiemy już, że niektóre zadania mogą być wykonywane bardzo długo (można je nazwać zadaniami „długotrwałymi”), dlatego Linux dysponuje mechanizmem ich uruchamiania w tzw. tle lub uruchamiania ich jako zadań drugoplanowych. Zadania pierwszoplanowe w danej chwili na konkretnej konsoli wirtualnej, możemy uruchomić jedno, natomiast zadań drugoplanowych wiele. Wiemy już, że zadanie drugoplanowe uruchamiamy wpisując na końcu linii poleceń znak ampersand &. Odpowiednimi poleceniami – z którymi zapoznamy się w tym rozdziale - możemy również przenosić zadania z planu pierwszego na drugi lub odwrotnie. Aby zobaczyć zadania działające w danym momencie w tle czyli jako zadania drugoplanowe musimy użyć polecenia jobs . Polecenie to posiada następujące opcje:
-l → wyświetlamy także numer PID procesów
-p → wyświetlamy tylko numery PID procesów
-n → pozwala na wyświetlenie tylko zawieszonych zadań
Przykład: wiemy z rozdziału II, że polecenie ls –R / wyświetla na ekranie wszystkie katalog i pliki w systemie operacyjnym, a z tego wniosek, ze zapełnione ekrany wyświetlane są bardzo długo. Wykonajmy to polecenie, a następnie zatrzymajmy jego egzekucje przy pomocy klawiszy CTRL+Z.
$ ls -R /
Z^
W tej chwili wiemy, że zawiesiliśmy wykonywanie polecenia ls –R /, jeżeli wykonamy w tej chwili polecenie jobs , to rezultaty jego będą następujące:
$ jobs
[1]+ Stopped ls –R /
Liczba w nawiasie kwadratowym (w tym przypadku [1]) oznacza numer zadania użytkownika. Korzystając z tego numeru, użytkownik może odwoływać się do zadania użytkownika w poleceniach fg , bg i kill , które będą poniżej wyjaśnione. Jednak w tej chwili wykonajmy polecenie ls –R / w tle. Jak to zrobić ? Rezultat polecenia – czyli wyświetlające się stronice informacji – umieśćmy w pliku rezultat korzystając z mechanizmu przekierowania, a na końcu polecenia wystukajmy znak & :
$ ls –R / > rezultat &
[1] 456
Liczba 456 oznacza identyfikator procesu PID w systemie. PID jest najczęściej wykorzystywany w poleceniu kill, które omówimy w następnym podrozdziale. Wiemy także że identyfikator (numer) procesu możemy poznać stosując polecenie jobs z opcją –l. Proces zatrzymany (ang – stopped ) kombinacja klawiszy CTRL + Z może być wznowiony. Do ponownego uruchomienia zatrzymanego zadania na pierwszym planie używamy polecenia fg. Do ponownego uruchomienia zatrzymanego zadania na drugim planie – czyli w tzw. tle – używamy polecenia bg.
Przez ponowne uruchomienie – i jest to bardzo ważna uwaga – rozumiemy sytuacje, w której proces rozpoczyna kontynuacje zadania od miejsca, w którym został zatrzymany.
Jak już powiedzieliśmy zadanie działające w tle można przenieść na pierwszy plan za pomocą polecenia fg . Składnia polecenia fg pozwala odwołać się do zadania za pomocą znaku % i numeru zadania. Przykładowo poniższa sekwencja rozpoczyna egzekucje polecenia ls –R / w tle:
$ ls –R / &
[5] 4321
$
$ fg %5
$ ls –R /
Odwrotnością polecenia fg jest polecenie bg. Pozwala ono na przeniesienie zadania uruchomionego na pierwszym planie na drugi plan. Jednak aby to zrobić trzeba przy pomocy kombinacji klawiszy CTRL + Z zawiesić zadanie, w ten sposób przywracamy znak gotowości i możliwość wystukania nowego polecenia.
Jak już wiemy kiedy proces zostanie rozpoczęty, domyślnie działa na tzw. pierwszy planie. Na pierwszym planie staje się jedynym zadaniem, które użytkownik może wykonywać. Kiedy użytkownik wydaje na przykład polecenie ls –l /, wyniki pojawiają się na jego terminalu, a użytkownik nie może wydać innego polecenia, zanim ls –l / nie zakończy swego działania.
Aby uruchomić proces w tle wystarczy umieścić na końcu polecenia znak & - pozwala to na jednoczesne wykonywanie więcej niż jednego polecenia. Można również wydać polecenie sleep , które wstrzymuje wykonywanie polecenia w tle na określona ilość sekund.
$ sleep 180 &
[10] 4010
$
Liczba pojawiająca się w nawiasie to liczba zadań w danej chwili wykonywanych w tle. Liczba po niej – w tym przypadku 4010 – to identyfikator procesu PID tego zadania.
Umieszczenie zadania w tle pozwala użytkownikowi kontynuować i rozpoczynać inne procesy, to znaczy daje mu możliwość zarządzania procesami wywoływanymi głownie przez niego samego. Jeśli musimy zaczekać na zakończenie jednego procesu przed rozpoczęciem kolejnego procesu to używamy do tego celu polecenia wait , który w połączeniu z PID procesu, może przerwać przetwarzanie do zakończenia określonego procesu. Na przykład:
$ sleep 360 &
[6] 5432
$
$ wait 5432 # znak gotowości $ nie wraca, o ile 5432 to prawidłowy Identyfikator PID
Jeszcze jeden mechanizm związany z egzekucją poleceń i związanych z nimi procesów jest niezwykle istotny dla pracy programisty, otóż procesy mogą kontynuować swoją prace nawet po odłączeniu się (wylogowaniu z maszyny). Polecenie które pozwala po wylogowaniu się kontynuacje wykonywania procesów, nazywa się nohup.
$ nohup dzien
4321
Nazwa nohup jest skrótem od słów „no hung up” – nie rozłączaj. Polecenie zapobiega zakończeniu procesu w momencie wylogowania użytkownika. Komunikaty które są tworzone w trakcie wykonywania tego polecenia skierowane są do pliku o nazwie nohup.out, który można obejrzeć w celu sprawdzenia wyniku działania polecenia.
Zarządzanie procesami i zadaniami Rozdział 7.1 Darmowy kurs Linux